From 0d9f871a4f7c478fdf3f7b699d74e77506e978a4 Mon Sep 17 00:00:00 2001 From: dotnet format Date: Thu, 27 Aug 2020 20:18:47 +0200 Subject: [PATCH] #2128: Reformat the whole code base. --- .../MonoCecilDebugInfoProvider.cs | 34 +- .../CorrectnessTestRunner.cs | 50 +- ICSharpCode.Decompiler.Tests/DataFlowTest.cs | 2 + .../DisassemblerPrettyTestRunner.cs | 8 +- .../Helpers/CodeAssert.cs | 60 +- .../Helpers/RemoveCompilerAttribute.cs | 14 +- .../Helpers/SdkUtility.cs | 122 +- .../Helpers/Tester.VB.cs | 39 +- .../Helpers/Tester.cs | 191 +- .../ILPrettyTestRunner.cs | 11 +- .../Output/CSharpAmbienceTests.cs | 5 +- .../PdbGenerationTestRunner.cs | 18 +- .../PrettyTestRunner.cs | 20 +- .../ProjectDecompiler/TargetFrameworkTests.cs | 2 + .../RoundtripAssembly.cs | 86 +- .../Semantics/ConversionTests.cs | 8 +- .../Semantics/ExplicitConversionTest.cs | 8 +- .../Semantics/OverloadResolutionTests.cs | 18 +- .../TestAssemblyResolver.cs | 4 +- .../TestCases/Correctness/Async.cs | 129 +- .../TestCases/Correctness/Capturing.cs | 60 +- .../TestCases/Correctness/Comparisons.cs | 16 +- .../Correctness/CompoundAssignment.cs | 22 +- .../TestCases/Correctness/ControlFlow.cs | 56 +- .../TestCases/Correctness/Conversions.cs | 77 +- .../TestCases/Correctness/DecimalFields.cs | 2 +- .../Correctness/DeconstructionTests.cs | 24 +- .../Correctness/FloatingPointArithmetic.cs | 3 +- .../TestCases/Correctness/Generics.cs | 6 +- .../TestCases/Correctness/InitializerTests.cs | 60 +- .../TestCases/Correctness/LINQRaytracer.cs | 15 +- .../TestCases/Correctness/Loops.cs | 103 +- .../TestCases/Correctness/MemberLookup.cs | 26 +- .../TestCases/Correctness/MiniJSON.cs | 202 +- .../TestCases/Correctness/NullPropagation.cs | 2 +- .../TestCases/Correctness/NullableTests.cs | 49 +- .../Correctness/OverloadResolution.cs | 3 +- .../Correctness/PropertiesAndEvents.cs | 8 +- .../TestCases/Correctness/Switch.cs | 69 +- .../TestCases/Correctness/TrickyTypes.cs | 4 +- .../Correctness/UndocumentedExpressions.cs | 10 +- .../TestCases/Correctness/UnsafeCode.cs | 8 +- .../TestCases/Correctness/Using.cs | 70 +- .../TestCases/Correctness/ValueTypeCall.cs | 45 +- .../TestCases/Correctness/YieldReturn.cs | 232 +- .../TestCases/ILPretty/CS1xSwitch_Debug.cs | 55 +- .../TestCases/ILPretty/CS1xSwitch_Release.cs | 55 +- .../TestCases/ILPretty/FSharpLoops_Debug.cs | 21 +- .../TestCases/ILPretty/FSharpLoops_Release.cs | 21 +- .../TestCases/ILPretty/FSharpUsing_Debug.cs | 18 +- .../TestCases/ILPretty/FSharpUsing_Release.cs | 18 +- .../TestCases/ILPretty/Issue1047.cs | 3 +- .../TestCases/ILPretty/Issue1454.cs | 3 +- .../TestCases/ILPretty/Issue1681.cs | 2 +- .../TestCases/ILPretty/Issue1918.cs | 13 +- .../TestCases/ILPretty/Issue646.cs | 3 +- .../TestCases/ILPretty/Issue684.cs | 25 +- .../TestCases/ILPretty/Issue959.cs | 3 +- .../TestCases/ILPretty/SequenceOfNestedIfs.cs | 21 +- .../TestCases/ILPretty/Unsafe.cs | 25 +- .../TestCases/Pretty/Async.cs | 43 +- .../TestCases/Pretty/AsyncForeach.cs | 12 +- .../TestCases/Pretty/AsyncStreams.cs | 16 +- .../TestCases/Pretty/AsyncUsing.cs | 12 +- .../TestCases/Pretty/CheckedUnchecked.cs | 18 +- .../Pretty/CompoundAssignmentTest.cs | 64 +- .../Pretty/CustomAttributeConflicts.cs | 5 +- .../Pretty/CustomShortCircuitOperators.cs | 41 +- .../TestCases/Pretty/CustomTaskType.cs | 37 +- .../TestCases/Pretty/DeconstructionTests.cs | 6 +- .../TestCases/Pretty/DelegateConstruction.cs | 67 +- .../TestCases/Pretty/DynamicTests.cs | 32 +- .../TestCases/Pretty/ExceptionHandling.cs | 232 +- .../TestCases/Pretty/ExpressionTrees.cs | 15 +- .../TestCases/Pretty/FixProxyCalls.cs | 10 +- .../TestCases/Pretty/Generics.cs | 3 +- .../TestCases/Pretty/InitializerTests.cs | 15 +- .../TestCases/Pretty/InlineAssignmentTest.cs | 21 +- .../TestCases/Pretty/Issue1080.cs | 3 +- .../TestCases/Pretty/LiftedOperators.cs | 179 +- .../TestCases/Pretty/LocalFunctions.cs | 47 +- .../TestCases/Pretty/Lock.cs | 6 +- .../TestCases/Pretty/Loops.cs | 299 ++- .../TestCases/Pretty/NativeInts.cs | 9 +- .../TestCases/Pretty/NullPropagation.cs | 18 +- .../TestCases/Pretty/OutVariables.cs | 6 +- .../TestCases/Pretty/PInvoke.cs | 2 +- .../TestCases/Pretty/QualifierTests.cs | 3 +- .../TestCases/Pretty/QueryExpressions.cs | 6 +- .../TestCases/Pretty/ReduceNesting.cs | 304 ++- .../TestCases/Pretty/RefLocalsAndReturns.cs | 21 +- .../TestCases/Pretty/ShortCircuit.cs | 156 +- .../TestCases/Pretty/Switch.cs | 368 +++- .../TestCases/Pretty/SwitchExpressions.cs | 21 +- .../TestCases/Pretty/ThrowExpressions.cs | 3 +- .../TestCases/Pretty/TupleTests.cs | 12 +- .../TestCases/Pretty/TypeAnalysisTests.cs | 3 +- .../TestCases/Pretty/TypeMemberTests.cs | 2 +- .../TestCases/Pretty/UnsafeCode.cs | 63 +- .../TestCases/Pretty/Using.cs | 36 +- .../TestCases/Pretty/UsingVariables.cs | 6 +- .../TestCases/Pretty/ValueTypes.cs | 11 +- .../TestCases/Pretty/YieldReturn.cs | 187 +- ...eScalarReplacementOfAggregates.Expected.cs | 26 +- ...AggressiveScalarReplacementOfAggregates.cs | 58 +- .../Ugly/NoDecimalConstants.Expected.cs | 2 +- .../Ugly/NoForEachStatement.Expected.cs | 19 +- .../TestCases/Ugly/NoForEachStatement.cs | 6 +- .../TestCases/VBPretty/Async.cs | 2 +- .../TestCases/VBPretty/Select.cs | 8 +- .../TestCases/VBPretty/VBCompoundAssign.cs | 6 +- .../TestTraceListener.cs | 5 +- .../TypeSystem/TypeSystemLoaderTests.cs | 86 +- .../TypeSystem/TypeSystemTestCase.cs | 86 +- .../UglyTestRunner.cs | 20 +- .../Util/BitSetTests.cs | 7 +- .../Util/IntervalTests.cs | 11 +- .../Util/LongSetTests.cs | 2 + .../VBPrettyTestRunner.cs | 11 +- ICSharpCode.Decompiler/CSharp/Annotations.cs | 87 +- .../CSharp/CSharpDecompiler.cs | 486 +++-- ICSharpCode.Decompiler/CSharp/CallBuilder.cs | 593 +++-- .../CSharp/ExpressionBuilder.cs | 1464 +++++++++---- .../CSharp/OutputVisitor/CSharpAmbience.cs | 109 +- .../OutputVisitor/CSharpFormattingOptions.cs | 44 +- .../OutputVisitor/CSharpOutputVisitor.cs | 679 ++++-- .../OutputVisitor/FormattingOptionsFactory.cs | 46 +- .../GenericGrammarAmbiguityVisitor.cs | 20 +- .../CSharp/OutputVisitor/ITokenWriter.cs | 1 + .../InsertMissingTokensDecorator.cs | 57 +- .../OutputVisitor/InsertParenthesesVisitor.cs | 148 +- .../InsertRequiredSpacesDecorator.cs | 117 +- .../OutputVisitor/InsertSpecialsDecorator.cs | 56 +- .../OutputVisitor/TextWriterTokenWriter.cs | 168 +- .../ProjectDecompiler/IProjectFileWriter.cs | 1 + .../ProjectDecompiler/IProjectInfoProvider.cs | 1 + .../ProjectFileWriterDefault.cs | 42 +- .../ProjectFileWriterSdkStyle.cs | 59 +- .../ProjectDecompiler/TargetFramework.cs | 20 +- .../ProjectDecompiler/TargetServices.cs | 22 +- .../WholeProjectDecompiler.cs | 132 +- .../CSharp/RequiredNamespaceCollector.cs | 163 +- .../Resolver/AliasNamespaceResolveResult.cs | 4 +- .../CSharp/Resolver/AliasTypeResolveResult.cs | 4 +- .../CSharp/Resolver/AwaitResolveResult.cs | 1 + .../CSharp/Resolver/CSharpConversions.cs | 415 ++-- .../Resolver/CSharpInvocationResolveResult.cs | 50 +- .../CSharp/Resolver/CSharpOperators.cs | 652 +++--- .../CSharp/Resolver/CSharpResolver.cs | 1409 +++++++----- .../CSharp/Resolver/CastResolveResult.cs | 4 +- .../DynamicInvocationResolveResult.cs | 15 +- .../Resolver/DynamicMemberResolveResult.cs | 7 +- .../CSharp/Resolver/LambdaResolveResult.cs | 46 +- ICSharpCode.Decompiler/CSharp/Resolver/Log.cs | 22 +- .../CSharp/Resolver/MemberLookup.cs | 384 ++-- .../Resolver/MethodGroupResolveResult.cs | 101 +- .../CSharp/Resolver/OverloadResolution.cs | 276 ++- .../CSharp/Resolver/TypeInference.cs | 497 +++-- .../CSharp/SequencePointBuilder.cs | 134 +- .../CSharp/StatementBuilder.cs | 341 ++- .../CSharp/Syntax/AstNode.cs | 164 +- .../CSharp/Syntax/AstNodeCollection.cs | 73 +- .../CSharp/Syntax/AstType.cs | 87 +- .../CSharp/Syntax/CSharpModifierToken.cs | 32 +- .../CSharp/Syntax/CSharpTokenNode.cs | 52 +- .../CSharp/Syntax/CSharpUtil.cs | 65 +- .../CSharp/Syntax/ComposedType.cs | 103 +- .../CSharp/Syntax/DepthFirstAstVisitor.cs | 1929 +++++++++-------- .../CSharp/Syntax/DocumentationReference.cs | 52 +- .../Expressions/AnonymousMethodExpression.cs | 74 +- .../AnonymousTypeCreateExpression.cs | 55 +- .../Expressions/ArrayCreateExpression.cs | 44 +- .../Expressions/ArrayInitializerExpression.cs | 78 +- .../CSharp/Syntax/Expressions/AsExpression.cs | 44 +- .../Expressions/AssignmentExpression.cs | 92 +- .../Expressions/BaseReferenceExpression.cs | 24 +- .../Expressions/BinaryOperatorExpression.cs | 108 +- .../Syntax/Expressions/CastExpression.cs | 46 +- .../Syntax/Expressions/CheckedExpression.cs | 48 +- .../Expressions/ConditionalExpression.cs | 48 +- .../Expressions/DefaultValueExpression.cs | 46 +- .../Syntax/Expressions/DirectionExpression.cs | 45 +- .../Syntax/Expressions/ErrorExpression.cs | 18 +- .../CSharp/Syntax/Expressions/Expression.cs | 44 +- .../Expressions/IdentifierExpression.cs | 38 +- .../Syntax/Expressions/IndexerExpression.cs | 54 +- .../InterpolatedStringExpression.cs | 1 + .../Expressions/InvocationExpression.cs | 56 +- .../CSharp/Syntax/Expressions/IsExpression.cs | 36 +- .../Syntax/Expressions/LambdaExpression.cs | 44 +- .../Expressions/MemberReferenceExpression.cs | 68 +- .../Expressions/NamedArgumentExpression.cs | 38 +- .../Syntax/Expressions/NamedExpression.cs | 40 +- .../Expressions/NullReferenceExpression.cs | 34 +- .../Expressions/ObjectCreateExpression.cs | 72 +- .../Expressions/ParenthesizedExpression.cs | 40 +- .../Expressions/PointerReferenceExpression.cs | 46 +- .../Syntax/Expressions/PrimitiveExpression.cs | 58 +- .../Syntax/Expressions/QueryExpression.cs | 442 ++-- .../Syntax/Expressions/SizeOfExpression.cs | 48 +- .../Expressions/StackAllocExpression.cs | 40 +- .../Expressions/ThisReferenceExpression.cs | 24 +- .../Syntax/Expressions/ThrowExpression.cs | 30 +- .../Syntax/Expressions/TupleExpression.cs | 1 + .../Syntax/Expressions/TypeOfExpression.cs | 48 +- .../Expressions/TypeReferenceExpression.cs | 26 +- .../Expressions/UnaryOperatorExpression.cs | 70 +- .../Syntax/Expressions/UncheckedExpression.cs | 46 +- .../Expressions/UndocumentedExpression.cs | 65 +- .../CSharp/Syntax/FunctionPointerType.cs | 25 +- .../CSharp/Syntax/GeneralScope/Attribute.cs | 34 +- .../Syntax/GeneralScope/AttributeSection.cs | 122 +- .../CSharp/Syntax/GeneralScope/Comment.cs | 50 +- .../CSharp/Syntax/GeneralScope/Constraint.cs | 31 +- .../GeneralScope/DelegateDeclaration.cs | 44 +- .../GeneralScope/ExternAliasDeclaration.cs | 36 +- .../GeneralScope/NamespaceDeclaration.cs | 7 +- .../GeneralScope/PreProcessorDirective.cs | 62 +- .../Syntax/GeneralScope/TypeDeclaration.cs | 51 +- .../GeneralScope/TypeParameterDeclaration.cs | 49 +- .../GeneralScope/UsingAliasDeclaration.cs | 68 +- .../Syntax/GeneralScope/UsingDeclaration.cs | 74 +- .../CSharp/Syntax/IAnnotatable.cs | 80 +- .../CSharp/Syntax/IAstVisitor.cs | 40 +- .../CSharp/Syntax/Identifier.cs | 82 +- .../IdentifierExpressionBackreference.cs | 6 +- .../CSharp/Syntax/MemberType.cs | 83 +- .../CSharp/Syntax/Modifiers.cs | 46 +- .../CSharp/Syntax/PatternMatching/AnyNode.cs | 6 +- .../Syntax/PatternMatching/AnyNodeOrNull.cs | 7 +- .../Syntax/PatternMatching/Backreference.cs | 8 +- .../CSharp/Syntax/PatternMatching/Choice.cs | 13 +- .../CSharp/Syntax/PatternMatching/INode.cs | 6 +- .../CSharp/Syntax/PatternMatching/Match.cs | 35 +- .../Syntax/PatternMatching/NamedNode.cs | 8 +- .../Syntax/PatternMatching/OptionalNode.cs | 10 +- .../CSharp/Syntax/PatternMatching/Pattern.cs | 32 +- .../CSharp/Syntax/PatternMatching/Repeat.cs | 16 +- .../CSharp/Syntax/PrimitiveType.cs | 57 +- ICSharpCode.Decompiler/CSharp/Syntax/Role.cs | 26 +- ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs | 90 +- .../CSharp/Syntax/SimpleType.cs | 90 +- .../Syntax/Statements/BlockStatement.cs | 76 +- .../Syntax/Statements/BreakStatement.cs | 28 +- .../Syntax/Statements/CheckedStatement.cs | 42 +- .../Syntax/Statements/ContinueStatement.cs | 30 +- .../Syntax/Statements/DoWhileStatement.cs | 56 +- .../Syntax/Statements/EmptyStatement.cs | 26 +- .../Syntax/Statements/ExpressionStatement.cs | 32 +- .../Syntax/Statements/FixedStatement.cs | 50 +- .../CSharp/Syntax/Statements/ForStatement.cs | 54 +- .../Syntax/Statements/ForeachStatement.cs | 56 +- .../CSharp/Syntax/Statements/GotoStatement.cs | 124 +- .../Syntax/Statements/IfElseStatement.cs | 62 +- .../Syntax/Statements/LabelStatement.cs | 32 +- .../CSharp/Syntax/Statements/LockStatement.cs | 44 +- .../Syntax/Statements/ReturnStatement.cs | 44 +- .../CSharp/Syntax/Statements/Statement.cs | 44 +- .../Syntax/Statements/SwitchStatement.cs | 148 +- .../Syntax/Statements/ThrowStatement.cs | 46 +- .../Syntax/Statements/UncheckedStatement.cs | 42 +- .../Syntax/Statements/UnsafeStatement.cs | 32 +- .../VariableDeclarationStatement.cs | 46 +- .../Syntax/Statements/WhileStatement.cs | 46 +- .../Syntax/Statements/YieldBreakStatement.cs | 36 +- .../Syntax/Statements/YieldReturnStatement.cs | 42 +- .../CSharp/Syntax/SyntaxExtensions.cs | 3 +- .../CSharp/Syntax/SyntaxTree.cs | 50 +- .../CSharp/Syntax/TextLocation.cs | 60 +- .../CSharp/Syntax/TokenRole.cs | 29 +- .../CSharp/Syntax/TupleAstType.cs | 3 +- .../CSharp/Syntax/TypeMembers/Accessor.cs | 49 +- .../TypeMembers/ConstructorDeclaration.cs | 121 +- .../TypeMembers/DestructorDeclaration.cs | 38 +- .../Syntax/TypeMembers/EntityDeclaration.cs | 70 +- .../TypeMembers/EnumMemberDeclaration.cs | 26 +- .../Syntax/TypeMembers/EventDeclaration.cs | 87 +- .../Syntax/TypeMembers/FieldDeclaration.cs | 27 +- .../TypeMembers/FixedFieldDeclaration.cs | 32 +- .../TypeMembers/FixedVariableInitializer.cs | 48 +- .../Syntax/TypeMembers/IndexerDeclaration.cs | 55 +- .../Syntax/TypeMembers/MethodDeclaration.cs | 56 +- .../Syntax/TypeMembers/OperatorDeclaration.cs | 255 +-- .../TypeMembers/ParameterDeclaration.cs | 51 +- .../Syntax/TypeMembers/PropertyDeclaration.cs | 42 +- .../Syntax/TypeMembers/VariableInitializer.cs | 86 +- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 1014 ++++++--- .../CSharp/Transforms/AddCheckedBlocks.cs | 127 +- .../AddXmlDocumentationTransform.cs | 32 +- .../Transforms/CombineQueryExpressions.cs | 56 +- .../Transforms/ContextTrackingVisitor.cs | 57 +- .../CSharp/Transforms/CustomPatterns.cs | 33 +- .../Transforms/DecimalConstantTransform.cs | 14 +- .../CSharp/Transforms/DeclareVariables.cs | 215 +- .../Transforms/EscapeInvalidIdentifiers.cs | 16 +- .../CSharp/Transforms/FixNameCollisions.cs | 33 +- .../CSharp/Transforms/FlattenSwitchBlocks.cs | 4 +- .../Transforms/IntroduceExtensionMethods.cs | 68 +- .../Transforms/IntroduceQueryExpressions.cs | 301 +-- .../Transforms/IntroduceUnsafeModifier.cs | 43 +- .../Transforms/IntroduceUsingDeclarations.cs | 121 +- .../Transforms/NormalizeBlockStatements.cs | 49 +- .../Transforms/PatternStatementTransform.cs | 201 +- .../CSharp/Transforms/PrettifyAssignments.cs | 29 +- .../Transforms/RemoveCLSCompliantAttribute.cs | 7 +- .../ReplaceMethodCallsWithOperators.cs | 145 +- .../CSharp/Transforms/TransformContext.cs | 1 + ...ransformFieldAndConstructorInitializers.cs | 61 +- .../CSharp/TranslatedExpression.cs | 291 ++- .../CSharp/TranslatedStatement.cs | 1 + .../TypeSystem/AliasNamespaceReference.cs | 15 +- .../TypeSystem/CSharpTypeResolveContext.cs | 25 +- .../MemberTypeOrNamespaceReference.cs | 26 +- .../CSharp/TypeSystem/ResolvedUsingScope.cs | 103 +- .../SimpleTypeOrNamespaceReference.cs | 24 +- .../TypeSystem/TypeOrNamespaceReference.cs | 22 +- .../CSharp/TypeSystem/UsingScope.cs | 64 +- .../DebugInfo/AsyncDebugInfo.cs | 3 +- .../DebugInfo/DebugInfoGenerator.cs | 32 +- .../DebugInfo/PortablePdbWriter.cs | 86 +- ICSharpCode.Decompiler/DecompileRun.cs | 14 +- ICSharpCode.Decompiler/DecompilerException.cs | 57 +- ICSharpCode.Decompiler/DecompilerSettings.cs | 320 ++- .../Disassembler/DisassemblerHelpers.cs | 113 +- .../DisassemblerSignatureTypeProvider.cs | 29 +- .../Disassembler/ILParser.cs | 7 +- .../Disassembler/ILStructure.cs | 55 +- .../Disassembler/MethodBodyDisassembler.cs | 172 +- .../Disassembler/OpCodeInfo.cs | 18 +- .../Disassembler/ReflectionDisassembler.cs | 538 +++-- .../GetPotentiallyNestedClassTypeReference.cs | 27 +- .../Documentation/IdStringMemberReference.cs | 15 +- .../Documentation/IdStringProvider.cs | 120 +- .../Documentation/XmlDocLoader.cs | 50 +- .../Documentation/XmlDocumentationElement.cs | 60 +- .../Documentation/XmlDocumentationProvider.cs | 210 +- .../FlowAnalysis/ControlFlowNode.cs | 43 +- .../FlowAnalysis/DataFlowVisitor.cs | 213 +- .../FlowAnalysis/DefiniteAssignmentVisitor.cs | 73 +- .../FlowAnalysis/Dominance.cs | 61 +- .../ReachingDefinitionsVisitor.cs | 108 +- ICSharpCode.Decompiler/IL/BlockBuilder.cs | 97 +- .../IL/ControlFlow/AsyncAwaitDecompiler.cs | 549 +++-- .../IL/ControlFlow/AwaitInCatchTransform.cs | 85 +- .../IL/ControlFlow/AwaitInFinallyTransform.cs | 35 +- .../IL/ControlFlow/ConditionDetection.cs | 152 +- .../IL/ControlFlow/ControlFlowGraph.cs | 43 +- .../ControlFlow/ControlFlowSimplification.cs | 85 +- .../IL/ControlFlow/DetectPinnedRegions.cs | 265 ++- .../IL/ControlFlow/ExitPoints.cs | 80 +- .../IL/ControlFlow/LoopDetection.cs | 191 +- .../IL/ControlFlow/StateRangeAnalysis.cs | 68 +- .../IL/ControlFlow/SwitchAnalysis.cs | 158 +- .../IL/ControlFlow/SwitchDetection.cs | 138 +- .../IL/ControlFlow/SymbolicExecution.cs | 55 +- .../IL/ControlFlow/YieldReturnDecompiler.cs | 433 ++-- .../IL/ILAstWritingOptions.cs | 12 +- .../IL/ILInstructionExtensions.cs | 1 + ICSharpCode.Decompiler/IL/ILReader.cs | 541 +++-- ICSharpCode.Decompiler/IL/ILTypeExtensions.cs | 38 +- ICSharpCode.Decompiler/IL/ILVariable.cs | 54 +- ICSharpCode.Decompiler/IL/InstructionFlags.cs | 2 +- .../IL/InstructionOutputExtensions.cs | 269 ++- ICSharpCode.Decompiler/IL/Instructions.cs | 664 ++++-- .../Instructions/BinaryNumericInstruction.cs | 43 +- .../IL/Instructions/Block.cs | 58 +- .../IL/Instructions/BlockContainer.cs | 65 +- .../IL/Instructions/Branch.cs | 24 +- .../IL/Instructions/CallIndirect.cs | 15 +- .../IL/Instructions/CallInstruction.cs | 28 +- .../IL/Instructions/Comp.cs | 33 +- .../CompoundAssignmentInstruction.cs | 76 +- .../IL/Instructions/Conv.cs | 51 +- .../IL/Instructions/DeconstructInstruction.cs | 65 +- .../DeconstructResultInstruction.cs | 4 +- .../IL/Instructions/DynamicInstructions.cs | 25 +- .../IL/Instructions/ExpressionTreeCast.cs | 4 +- .../IL/Instructions/ILFunction.cs | 82 +- .../IL/Instructions/ILInstruction.cs | 254 ++- .../IL/Instructions/ILVariableCollection.cs | 46 +- .../IL/Instructions/IfInstruction.cs | 23 +- .../IL/Instructions/InstructionCollection.cs | 105 +- .../IL/Instructions/LdFlda.cs | 16 +- .../IL/Instructions/LdLen.cs | 6 +- .../IL/Instructions/Leave.cs | 21 +- .../IL/Instructions/MatchInstruction.cs | 68 +- .../IL/Instructions/MemoryInstructions.cs | 20 +- .../IL/Instructions/NullableInstructions.cs | 14 +- .../IL/Instructions/PatternMatching.cs | 146 +- .../IL/Instructions/SimpleInstruction.cs | 23 +- .../IL/Instructions/StLoc.cs | 2 +- .../IL/Instructions/StringToInt.cs | 9 +- .../IL/Instructions/SwitchInstruction.cs | 57 +- .../IL/Instructions/TryInstruction.cs | 101 +- .../IL/Instructions/UnaryInstruction.cs | 3 +- .../IL/Instructions/UsingInstruction.cs | 6 +- ICSharpCode.Decompiler/IL/Patterns/AnyNode.cs | 7 +- .../IL/Patterns/ListMatch.cs | 38 +- ICSharpCode.Decompiler/IL/Patterns/Match.cs | 33 +- .../IL/PointerArithmeticOffset.cs | 37 +- ICSharpCode.Decompiler/IL/SemanticHelper.cs | 20 +- ICSharpCode.Decompiler/IL/SlotInfo.cs | 8 +- .../IL/Transforms/AssignVariableNames.cs | 339 ++- .../IL/Transforms/BlockTransform.cs | 14 +- .../CachedDelegateInitialization.cs | 16 +- .../IL/Transforms/CombineExitsTransform.cs | 2 +- .../IL/Transforms/CopyPropagation.cs | 59 +- .../IL/Transforms/DeconstructionTransform.cs | 94 +- .../IL/Transforms/DelegateConstruction.cs | 87 +- .../DetectCatchWhenConditionBlocks.cs | 24 +- .../IL/Transforms/DynamicCallSiteTransform.cs | 82 +- .../DynamicIsEventAssignmentTransform.cs | 16 +- .../Transforms/EarlyExpressionTransforms.cs | 25 +- .../IL/Transforms/ExpressionTransforms.cs | 300 ++- .../IL/Transforms/FixLoneIsInst.cs | 22 +- .../IL/Transforms/FixRemainingIncrements.cs | 22 +- .../IL/Transforms/HighLevelLoopTransform.cs | 134 +- .../IL/Transforms/IILTransform.cs | 3 +- .../IL/Transforms/ILExtraction.cs | 18 +- .../IL/Transforms/ILInlining.cs | 216 +- .../IL/Transforms/IndexRangeTransform.cs | 244 ++- .../IL/Transforms/InlineReturnTransform.cs | 16 +- .../IntroduceDynamicTypeOnLocals.cs | 16 +- .../IntroduceNativeIntTypeOnLocals.cs | 16 +- .../IntroduceRefReadOnlyModifierOnLocals.cs | 10 +- .../IL/Transforms/LocalFunctionDecompiler.cs | 209 +- .../IL/Transforms/LockTransform.cs | 29 +- .../IL/Transforms/NamedArgumentTransform.cs | 40 +- .../IL/Transforms/NullCoalescingTransform.cs | 17 +- .../IL/Transforms/NullPropagationTransform.cs | 156 +- .../IL/Transforms/NullableLiftingTransform.cs | 310 ++- .../IL/Transforms/ProxyCallReplacer.cs | 22 +- .../IL/Transforms/ReduceNestingTransform.cs | 136 +- .../IL/Transforms/RemoveDeadVariableInit.cs | 41 +- .../IL/Transforms/SplitVariables.cs | 81 +- .../IL/Transforms/StatementTransform.cs | 32 +- .../IL/Transforms/Stepper.cs | 9 +- .../Transforms/SwitchOnNullableTransform.cs | 31 +- .../IL/Transforms/SwitchOnStringTransform.cs | 366 +++- .../Transforms/TransformArrayInitializers.cs | 206 +- .../IL/Transforms/TransformAssignment.cs | 305 ++- ...ransformCollectionAndObjectInitializers.cs | 115 +- .../Transforms/TransformDisplayClassUsage.cs | 221 +- .../IL/Transforms/TransformExpressionTrees.cs | 331 ++- .../IL/Transforms/TupleTransform.cs | 18 +- .../Transforms/UserDefinedLogicTransform.cs | 109 +- .../IL/Transforms/UsingTransform.cs | 78 +- .../Metadata/AssemblyReferences.cs | 24 +- .../Metadata/CodeMappingInfo.cs | 3 +- .../Metadata/CustomAttributeDecoder.cs | 37 +- ICSharpCode.Decompiler/Metadata/Dom.cs | 1 + .../Metadata/DotNetCorePathFinder.cs | 84 +- .../DotNetCorePathFinderExtensions.cs | 90 +- ICSharpCode.Decompiler/Metadata/ILOpCodes.cs | 4 +- .../Metadata/LightJson/JsonArray.cs | 16 +- .../Metadata/LightJson/JsonObject.cs | 27 +- .../Metadata/LightJson/JsonValue.cs | 229 +- .../Serialization/JsonParseException.cs | 3 +- .../LightJson/Serialization/JsonReader.cs | 128 +- .../LightJson/Serialization/TextScanner.cs | 64 +- .../Metadata/MetadataExtensions.cs | 78 +- .../Metadata/MetadataTokenHelpers.cs | 14 +- .../Metadata/MethodSemanticsLookup.cs | 17 +- .../Metadata/OperandType.cs | 3 +- ICSharpCode.Decompiler/Metadata/PEFile.cs | 22 +- .../Metadata/SignatureBlobComparer.cs | 29 +- .../Metadata/UniversalAssemblyResolver.cs | 124 +- ICSharpCode.Decompiler/NRExtensions.cs | 24 +- ICSharpCode.Decompiler/Output/IAmbience.cs | 19 +- ICSharpCode.Decompiler/Output/ITextOutput.cs | 1 + .../Output/PlainTextOutput.cs | 42 +- .../Output/TextOutputWriter.cs | 10 +- .../Output/TextTokenWriter.cs | 119 +- ICSharpCode.Decompiler/SRMExtensions.cs | 206 +- ICSharpCode.Decompiler/SRMHacks.cs | 13 +- .../Semantics/AmbiguousResolveResult.cs | 6 +- .../Semantics/ArrayAccessResolveResult.cs | 7 +- .../Semantics/ArrayCreateResolveResult.cs | 7 +- .../Semantics/ByReferenceResolveResult.cs | 11 +- .../Semantics/ConstantResolveResult.cs | 9 +- .../Semantics/Conversion.cs | 172 +- .../Semantics/ConversionResolveResult.cs | 13 +- .../Semantics/ErrorResolveResult.cs | 10 +- .../Semantics/ForEachResolveResult.cs | 13 +- .../InterpolatedStringResolveResult.cs | 1 + .../Semantics/InvocationResolveResult.cs | 19 +- .../Semantics/LocalResolveResult.cs | 18 +- .../Semantics/MemberResolveResult.cs | 36 +- .../Semantics/NamedArgumentResolveResult.cs | 15 +- .../Semantics/NamespaceResolveResult.cs | 9 +- .../Semantics/OperatorResolveResult.cs | 15 +- .../Semantics/ResolveResult.cs | 19 +- .../Semantics/SizeOfResolveResult.cs | 5 +- .../Semantics/ThisResolveResult.cs | 4 +- .../Semantics/TupleResolveResult.cs | 1 + .../Semantics/TypeIsResolveResult.cs | 3 +- .../Semantics/TypeOfResolveResult.cs | 5 +- .../Semantics/TypeResolveResult.cs | 2 +- .../Semantics/UnknownMemberResolveResult.cs | 31 +- ICSharpCode.Decompiler/Solution/ProjectId.cs | 3 +- .../Solution/SolutionCreator.cs | 48 +- .../TypeSystem/Accessibility.cs | 24 +- .../TypeSystem/ApplyAttributeTypeVisitor.cs | 129 +- .../TypeSystem/ArrayType.cs | 51 +- .../TypeSystem/AssemblyQualifiedTypeName.cs | 19 +- .../TypeSystem/ByReferenceType.cs | 27 +- .../TypeSystem/ComHelper.cs | 8 +- .../TypeSystem/DecompilerTypeSystem.cs | 55 +- .../TypeSystem/FullTypeName.cs | 89 +- .../TypeSystem/GenericContext.cs | 8 +- .../TypeSystem/IAssembly.cs | 15 +- .../TypeSystem/IAttribute.cs | 3 +- .../TypeSystem/ICodeContext.cs | 2 +- .../TypeSystem/ICompilation.cs | 15 +- .../TypeSystem/IDecompilerTypeSystem.cs | 1 + ICSharpCode.Decompiler/TypeSystem/IEntity.cs | 10 +- ICSharpCode.Decompiler/TypeSystem/IEvent.cs | 2 +- ICSharpCode.Decompiler/TypeSystem/IField.cs | 4 +- .../TypeSystem/IFreezable.cs | 2 +- .../TypeSystem/IInterningProvider.cs | 18 +- ICSharpCode.Decompiler/TypeSystem/IMember.cs | 16 +- ICSharpCode.Decompiler/TypeSystem/IMethod.cs | 8 +- .../TypeSystem/INamedElement.cs | 6 +- .../TypeSystem/INamespace.cs | 18 +- .../TypeSystem/IParameter.cs | 10 +- .../TypeSystem/IProperty.cs | 4 +- .../TypeSystem/ISupportsInterning.cs | 2 +- ICSharpCode.Decompiler/TypeSystem/ISymbol.cs | 4 +- ICSharpCode.Decompiler/TypeSystem/IType.cs | 38 +- .../TypeSystem/ITypeDefinition.cs | 12 +- .../TypeSystem/ITypeParameter.cs | 19 +- .../TypeSystem/ITypeReference.cs | 14 +- .../TypeSystem/IVariable.cs | 4 +- .../Implementation/AbstractFreezable.cs | 33 +- .../TypeSystem/Implementation/AbstractType.cs | 58 +- .../Implementation/AbstractTypeParameter.cs | 148 +- .../Implementation/AttributeListBuilder.cs | 94 +- .../Implementation/BaseTypeCollector.cs | 20 +- .../Implementation/CustomAttribute.cs | 23 +- .../Implementation/DecimalConstantHelper.cs | 12 +- .../DefaultAssemblyReference.cs | 20 +- .../Implementation/DefaultAttribute.cs | 15 +- .../Implementation/DefaultParameter.cs | 28 +- .../Implementation/DefaultTypeParameter.cs | 10 +- .../Implementation/DefaultVariable.cs | 16 +- .../Implementation/DummyTypeParameter.cs | 77 +- .../TypeSystem/Implementation/FakeMember.cs | 5 +- .../Implementation/GetClassTypeReference.cs | 40 +- .../Implementation/GetMembersHelper.cs | 193 +- .../Implementation/KnownAttributes.cs | 5 +- .../Implementation/KnownTypeCache.cs | 12 +- .../Implementation/LocalFunctionMethod.cs | 5 +- .../Implementation/MergedNamespace.cs | 52 +- .../Implementation/MetadataEvent.cs | 6 +- .../Implementation/MetadataField.cs | 66 +- .../Implementation/MetadataMethod.cs | 115 +- .../Implementation/MetadataNamespace.cs | 13 +- .../Implementation/MetadataParameter.cs | 33 +- .../Implementation/MetadataProperty.cs | 42 +- .../Implementation/MetadataTypeDefinition.cs | 209 +- .../Implementation/MetadataTypeParameter.cs | 70 +- .../Implementation/MinimalCorlib.cs | 7 +- .../Implementation/NestedTypeReference.cs | 22 +- .../NullabilityAnnotatedType.cs | 20 +- .../TypeSystem/Implementation/PinnedType.cs | 8 +- .../Implementation/SimpleCompilation.cs | 41 +- .../Implementation/SpecializedEvent.cs | 19 +- .../Implementation/SpecializedField.cs | 14 +- .../Implementation/SpecializedMember.cs | 109 +- .../Implementation/SpecializedMethod.cs | 88 +- .../Implementation/SpecializedProperty.cs | 17 +- .../Implementation/SyntheticRangeIndexer.cs | 14 +- .../Implementation/TypeParameterReference.cs | 36 +- .../Implementation/TypeWithElementType.cs | 14 +- .../TypeSystem/Implementation/UnknownType.cs | 23 +- .../TypeSystem/InheritanceHelper.cs | 80 +- .../TypeSystem/IntersectionType.cs | 61 +- .../TypeSystem/KnownTypeReference.cs | 28 +- .../TypeSystem/MetadataModule.cs | 214 +- .../TypeSystem/ModifiedType.cs | 8 +- .../TypeSystem/NormalizeTypeVisitor.cs | 40 +- .../TypeSystem/NullableType.cs | 14 +- .../TypeSystem/ParameterListComparer.cs | 44 +- .../TypeSystem/ParameterizedType.cs | 121 +- .../TypeSystem/PointerType.cs | 29 +- .../TypeSystem/ReflectionHelper.cs | 185 +- .../ReflectionNameParseException.cs | 12 +- .../TypeSystem/SimpleTypeResolveContext.cs | 20 +- .../TypeSystem/SpecialType.cs | 23 +- ICSharpCode.Decompiler/TypeSystem/TaskType.cs | 24 +- .../TypeSystem/TopLevelTypeName.cs | 47 +- .../TypeSystem/TupleType.cs | 90 +- ICSharpCode.Decompiler/TypeSystem/TypeKind.cs | 10 +- .../TypeSystem/TypeParameterSubstitution.cs | 100 +- .../TypeSystem/TypeProvider.cs | 24 +- .../TypeSystem/TypeSystemExtensions.cs | 94 +- .../TypeSystem/TypeUtils.cs | 66 +- .../TypeSystem/TypeVisitor.cs | 11 +- .../TypeSystem/VarArgInstanceMethod.cs | 34 +- ICSharpCode.Decompiler/Util/BitSet.cs | 103 +- ICSharpCode.Decompiler/Util/BusyManager.cs | 20 +- .../Util/CSharpPrimitiveCast.cs | 952 +++++--- ICSharpCode.Decompiler/Util/CacheManager.cs | 8 +- .../Util/CallbackOnDispose.cs | 7 +- .../Util/CollectionExtensions.cs | 92 +- ICSharpCode.Decompiler/Util/EmptyList.cs | 40 +- ICSharpCode.Decompiler/Util/GraphVizGraph.cs | 22 +- ICSharpCode.Decompiler/Util/Interval.cs | 49 +- ICSharpCode.Decompiler/Util/KeyComparer.cs | 16 +- ICSharpCode.Decompiler/Util/LazyInit.cs | 2 +- ICSharpCode.Decompiler/Util/LongDict.cs | 12 +- ICSharpCode.Decompiler/Util/LongSet.cs | 114 +- .../Util/MultiDictionary.cs | 45 +- ICSharpCode.Decompiler/Util/Platform.cs | 3 +- ICSharpCode.Decompiler/Util/ProjectedList.cs | 34 +- .../Util/ReferenceComparer.cs | 4 +- .../Util/ResXResourceWriter.cs | 84 +- ICSharpCode.Decompiler/Util/ResourcesFile.cs | 145 +- ICSharpCode.Decompiler/Util/TreeTraversal.cs | 48 +- ICSharpCode.Decompiler/Util/UnicodeNewline.cs | 254 ++- ICSharpCode.Decompiler/Util/UnionFind.cs | 6 +- ILSpy.AddIn/AssemblyFileFinder.cs | 31 +- .../Commands/AssemblyReferenceForILSpy.cs | 1 + .../Commands/NuGetReferenceForILSpy.cs | 11 +- ILSpy.AddIn/Commands/OpenCodeItemCommand.cs | 55 +- ILSpy.AddIn/Commands/OpenILSpyCommand.cs | 24 +- .../Commands/OpenProjectOutputCommand.cs | 7 +- ILSpy.AddIn/Commands/OpenReferenceCommand.cs | 26 +- ILSpy.AddIn/Commands/ProjectItemForILSpy.cs | 2 + .../Commands/ProjectReferenceForILSpy.cs | 23 +- ILSpy.AddIn/ILSpyAddInPackage.cs | 28 +- ILSpy.AddIn/ILSpyInstance.cs | 25 +- ILSpy.AddIn/SyntaxNodeExtensions.cs | 1588 +++++++------- ILSpy.AddIn/Utils.cs | 47 +- ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs | 27 +- .../Cases/AttachedEvent.xaml.cs | 2 +- .../Cases/CustomControl.cs | 4 +- .../Mocks/AvalonDock.cs | 6 +- ILSpy.BamlDecompiler/Baml/BamlContext.cs | 43 +- ILSpy.BamlDecompiler/Baml/BamlDocument.cs | 9 +- ILSpy.BamlDecompiler/Baml/BamlNode.cs | 48 +- ILSpy.BamlDecompiler/Baml/BamlReader.cs | 43 +- ILSpy.BamlDecompiler/Baml/BamlRecords.cs | 459 ++-- ILSpy.BamlDecompiler/Baml/BamlWriter.cs | 21 +- ILSpy.BamlDecompiler/Baml/KnownMembers.cs | 6 +- ILSpy.BamlDecompiler/Baml/KnownThings.cs | 23 +- ILSpy.BamlDecompiler/Baml/KnownTypes.cs | 6 +- ILSpy.BamlDecompiler/BamlElement.cs | 19 +- ILSpy.BamlDecompiler/BamlResourceEntryNode.cs | 61 +- .../BamlResourceNodeFactory.cs | 6 +- .../Blocks/ConstructorParametersHandler.cs | 10 +- .../Handlers/Blocks/DocumentHandler.cs | 10 +- .../Handlers/Blocks/ElementHandler.cs | 13 +- .../Handlers/Blocks/KeyElementStartHandler.cs | 13 +- .../Handlers/Blocks/PropertyArrayHandler.cs | 10 +- .../Handlers/Blocks/PropertyComplexHandler.cs | 10 +- .../Blocks/PropertyDictionaryHandler.cs | 10 +- .../Handlers/Blocks/PropertyListHandler.cs | 10 +- .../Handlers/Records/AssemblyInfoHandler.cs | 6 +- .../Handlers/Records/AttributeInfoHandler.cs | 6 +- .../Handlers/Records/ConnectionIdHandler.cs | 9 +- .../ConstructorParameterTypeHandler.cs | 10 +- .../Records/ContentPropertyHandler.cs | 9 +- .../Handlers/Records/DefAttributeHandler.cs | 10 +- .../Records/DefAttributeKeyStringHandler.cs | 13 +- .../Records/DefAttributeKeyTypeHandler.cs | 13 +- .../Records/DeferableContentStartHandler.cs | 10 +- .../Records/LineNumberAndPositionHandler.cs | 6 +- .../Handlers/Records/LinePositionHandler.cs | 6 +- .../Handlers/Records/LiteralContentHandler.cs | 10 +- .../Records/OptimizedStaticResourceHandler.cs | 34 +- .../Handlers/Records/PIMappingHandler.cs | 6 +- .../PresentationOptionsAttributeHandler.cs | 10 +- .../Handlers/Records/PropertyCustomHandler.cs | 84 +- .../Handlers/Records/PropertyHandler.cs | 10 +- .../Records/PropertyTypeReferenceHandler.cs | 16 +- .../Records/PropertyWithConverterHandler.cs | 6 +- .../Records/PropertyWithExtensionHandler.cs | 37 +- .../PropertyWithStaticResourceIdHandler.cs | 13 +- .../Records/StaticResourceIdHandler.cs | 4 +- .../Records/StaticResourceStartHandler.cs | 1 + .../Handlers/Records/TextHandler.cs | 15 +- .../Records/TextWithConverterHandler.cs | 6 +- .../Handlers/Records/TypeInfoHandler.cs | 9 +- .../Handlers/Records/XmlnsPropertyHandler.cs | 23 +- ILSpy.BamlDecompiler/IHandlers.cs | 40 +- ILSpy.BamlDecompiler/IRewritePass.cs | 6 +- .../Properties/AssemblyInfo.cs | 2 +- .../Rewrite/AttributeRewritePass.cs | 25 +- .../Rewrite/ConnectionIdRewritePass.cs | 41 +- .../Rewrite/DocumentRewritePass.cs | 15 +- .../Rewrite/MarkupExtensionRewritePass.cs | 65 +- .../Rewrite/XClassRewritePass.cs | 16 +- ILSpy.BamlDecompiler/Xaml/NamespaceMap.cs | 13 +- ILSpy.BamlDecompiler/Xaml/XamlExtension.cs | 30 +- .../Xaml/XamlPathDeserializer.cs | 167 +- ILSpy.BamlDecompiler/Xaml/XamlProperty.cs | 25 +- ILSpy.BamlDecompiler/Xaml/XamlResourceKey.cs | 37 +- ILSpy.BamlDecompiler/Xaml/XamlType.cs | 33 +- ILSpy.BamlDecompiler/Xaml/XamlUtils.cs | 33 +- ILSpy.BamlDecompiler/XamlContext.cs | 59 +- ILSpy.BamlDecompiler/XamlDecompiler.cs | 16 +- ILSpy.BamlDecompiler/XmlnsDictionary.cs | 62 +- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 229 +- ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs | 10 +- ILSpy.ReadyToRun/ReadyToRunOptions.cs | 37 +- .../MemberImplementsInterfaceAnalyzerTests.cs | 12 +- .../Analyzers/MethodUsesAnalyzerTests.cs | 8 +- .../Analyzers/TypeUsedByAnalyzerTests.cs | 2 + ILSpy.Tests/Stub.cs | 3 +- ILSpy/AboutPage.cs | 133 +- ILSpy/Analyzers/AnalyzeCommand.cs | 34 +- ILSpy/Analyzers/AnalyzerContext.cs | 8 +- ILSpy/Analyzers/AnalyzerEntityTreeNode.cs | 13 +- ILSpy/Analyzers/AnalyzerScope.cs | 75 +- ILSpy/Analyzers/AnalyzerSearchTreeNode.cs | 26 +- ILSpy/Analyzers/AnalyzerTreeNode.cs | 7 +- ILSpy/Analyzers/AnalyzerTreeView.cs | 29 +- .../Builtin/AttributeAppliedToAnalyzer.cs | 51 +- .../Builtin/EventImplementedByAnalyzer.cs | 7 +- .../Builtin/EventOverriddenByAnalyzer.cs | 13 +- .../Analyzers/Builtin/FieldAccessAnalyzer.cs | 65 +- .../MemberImplementsInterfaceAnalyzer.cs | 4 +- .../Builtin/MethodImplementedByAnalyzer.cs | 7 +- .../Builtin/MethodOverriddenByAnalyzer.cs | 13 +- .../Analyzers/Builtin/MethodUsedByAnalyzer.cs | 67 +- ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs | 59 +- .../Builtin/MethodVirtualUsedByAnalyzer.cs | 43 +- .../Builtin/PropertyImplementedByAnalyzer.cs | 7 +- .../Builtin/PropertyOverriddenByAnalyzer.cs | 13 +- .../Builtin/TypeExposedByAnalyzer.cs | 31 +- .../Builtin/TypeExtensionMethodsAnalyzer.cs | 10 +- .../Builtin/TypeInstantiatedByAnalyzer.cs | 48 +- ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs | 55 +- ILSpy/Analyzers/IAnalyzer.cs | 1 + .../RemoveAnalyzeContextMenuEntry.cs | 6 +- .../TreeNodes/AnalyzedAccessorTreeNode.cs | 3 +- .../TreeNodes/AnalyzedEventTreeNode.cs | 13 +- .../TreeNodes/AnalyzedFieldTreeNode.cs | 7 +- .../TreeNodes/AnalyzedMethodTreeNode.cs | 7 +- .../TreeNodes/AnalyzedModuleTreeNode.cs | 7 +- .../TreeNodes/AnalyzedPropertyTreeNode.cs | 7 +- .../TreeNodes/AnalyzedTypeTreeNode.cs | 7 +- ILSpy/App.xaml.cs | 89 +- ILSpy/AssemblyList.cs | 90 +- ILSpy/AssemblyListManager.cs | 48 +- ILSpy/AvalonEdit/ITextMarker.cs | 40 +- ILSpy/AvalonEdit/TextMarkerService.cs | 146 +- ILSpy/CommandLineArguments.cs | 12 +- ILSpy/Commands/BrowseBackCommand.cs | 1 + ILSpy/Commands/BrowseForwardCommand.cs | 1 + ILSpy/Commands/CheckForUpdatesCommand.cs | 6 +- ILSpy/Commands/CommandWrapper.cs | 3 +- .../CopyFullyQualifiedNameContextMenuEntry.cs | 4 +- ILSpy/Commands/DecompileAllCommand.cs | 33 +- ILSpy/Commands/DecompileCommand.cs | 11 +- ILSpy/Commands/DecompileInNewViewCommand.cs | 18 +- ILSpy/Commands/DisassembleAllCommand.cs | 51 +- ILSpy/Commands/ExitCommand.cs | 2 +- ILSpy/Commands/ExportCommandAttribute.cs | 16 +- ILSpy/Commands/GeneratePdbContextMenuEntry.cs | 28 +- ILSpy/Commands/ILSpyCommands.cs | 1 + ILSpy/Commands/IProtocolHandler.cs | 1 + ILSpy/Commands/OpenCommand.cs | 5 +- ILSpy/Commands/OpenFromGacCommand.cs | 2 +- ILSpy/Commands/Pdb2XmlCommand.cs | 10 +- ILSpy/Commands/RefreshCommand.cs | 5 +- .../RemoveAssembliesWithLoadErrors.cs | 9 +- ILSpy/Commands/SaveCodeContextMenuEntry.cs | 25 +- ILSpy/Commands/SaveCommand.cs | 3 +- ILSpy/Commands/SearchMsdnContextMenuEntry.cs | 15 +- ILSpy/Commands/SelectPdbContextMenuEntry.cs | 11 +- ILSpy/Commands/ShowCFGContextMenuEntry.cs | 8 +- ILSpy/Commands/ShowDebugSteps.cs | 2 +- ILSpy/Commands/SimpleCommand.cs | 3 +- ILSpy/Commands/SortAssemblyListCommand.cs | 12 +- ILSpy/ContextMenuEntry.cs | 49 +- ILSpy/Controls/BoolToVisibilityConverter.cs | 2 +- ILSpy/Controls/CustomDialog.cs | 30 +- ILSpy/Controls/ExtensionMethods.cs | 16 +- ILSpy/Controls/GridViewColumnAutoSize.cs | 46 +- ILSpy/Controls/MarkupExtensions.cs | 19 +- ILSpy/Controls/ResourceObjectTable.xaml.cs | 4 +- ILSpy/Controls/ResourceStringTable.xaml.cs | 4 +- ILSpy/Controls/SearchBox.cs | 76 +- ILSpy/Controls/SortableGridViewColumn.cs | 99 +- ILSpy/DebugInfo/DebugInfoUtils.cs | 40 +- ILSpy/DebugInfo/PortableDebugInfoProvider.cs | 26 +- ILSpy/DecompilationOptions.cs | 12 +- ILSpy/Docking/ActiveTabPageConverter.cs | 1 + ILSpy/Docking/CloseAllDocumentsCommand.cs | 1 + ILSpy/Docking/DockLayoutSettings.cs | 24 +- ILSpy/Docking/DockWorkspace.cs | 43 +- ILSpy/Docking/PaneCollection.cs | 1 + ILSpy/Docking/PaneStyleSelector.cs | 1 + ILSpy/Docking/PaneTemplateSelector.cs | 3 +- ILSpy/EntityReference.cs | 1 + ILSpy/ExtensionMethods.cs | 25 +- ILSpy/FilterSettings.cs | 38 +- ILSpy/GuessFileType.cs | 101 +- ILSpy/ILSpySettings.cs | 62 +- ILSpy/ILSpyTraceListener.cs | 37 +- ILSpy/ISmartTextOutput.cs | 8 +- ILSpy/Images/Images.cs | 58 +- ILSpy/Languages/CSharpBracketSearcher.cs | 246 ++- .../CSharpHighlightingTokenWriter.cs | 64 +- ILSpy/Languages/CSharpILMixedLanguage.cs | 38 +- ILSpy/Languages/CSharpLanguage.cs | 180 +- ILSpy/Languages/CSharpLexer.cs | 432 ++-- ILSpy/Languages/ILAstLanguage.cs | 37 +- ILSpy/Languages/ILLanguage.cs | 51 +- ILSpy/Languages/Language.cs | 79 +- ILSpy/Languages/Languages.cs | 10 +- ILSpy/LoadedAssembly.cs | 146 +- ILSpy/LoadedAssemblyExtensions.cs | 4 +- ILSpy/LoadedNugetPackage.cs | 23 +- ILSpy/MainWindow.xaml.cs | 404 ++-- ILSpy/Metadata/CoffHeaderTreeNode.cs | 1 + .../CorTables/AssemblyRefTableTreeNode.cs | 9 +- .../CorTables/ClassLayoutTableTreeNode.cs | 11 +- .../CorTables/ConstantTableTreeNode.cs | 9 +- .../CorTables/CustomAttributeTableTreeNode.cs | 9 +- .../CorTables/DeclSecurityTableTreeNode.cs | 9 +- .../CorTables/EventMapTableTreeNode.cs | 11 +- .../Metadata/CorTables/EventTableTreeNode.cs | 9 +- .../CorTables/ExportedTypeTableTreeNode.cs | 11 +- .../CorTables/FieldLayoutTableTreeNode.cs | 9 +- .../CorTables/FieldMarshalTableTreeNode.cs | 9 +- .../CorTables/FieldRVATableTreeNode.cs | 9 +- .../Metadata/CorTables/FieldTableTreeNode.cs | 10 +- ILSpy/Metadata/CorTables/FileTableTreeNode.cs | 9 +- .../GenericParamConstraintTableTreeNode.cs | 16 +- .../CorTables/GenericParamTableTreeNode.cs | 13 +- .../CorTables/ImplMapTableTreeNode.cs | 11 +- .../CorTables/InterfaceImplTableTreeNode.cs | 11 +- .../ManifestResourceTableTreeNode.cs | 9 +- .../CorTables/MemberRefTableTreeNode.cs | 9 +- .../CorTables/MethodImplTableTreeNode.cs | 9 +- .../CorTables/MethodSemanticsTableTreeNode.cs | 9 +- .../CorTables/MethodSpecTableTreeNode.cs | 18 +- .../Metadata/CorTables/MethodTableTreeNode.cs | 13 +- .../CorTables/ModuleRefTableTreeNode.cs | 15 +- .../Metadata/CorTables/ModuleTableTreeNode.cs | 9 +- .../CorTables/NestedClassTableTreeNode.cs | 11 +- .../Metadata/CorTables/ParamTableTreeNode.cs | 15 +- .../CorTables/PropertyMapTableTreeNode.cs | 11 +- .../CorTables/PropertyTableTreeNode.cs | 9 +- .../CorTables/StandAloneSigTableTreeNode.cs | 9 +- .../CorTables/TypeDefTableTreeNode.cs | 14 +- .../CorTables/TypeRefTableTreeNode.cs | 18 +- .../CorTables/TypeSpecTableTreeNode.cs | 17 +- ILSpy/Metadata/DataDirectoriesTreeNode.cs | 1 + ILSpy/Metadata/DataGridCustomTextColumn.cs | 3 +- ILSpy/Metadata/DebugMetadataTreeNode.cs | 1 + .../CustomDebugInformationTableTreeNode.cs | 34 +- .../DebugTables/DocumentTableTreeNode.cs | 9 +- .../DebugTables/ImportScopeTableTreeNode.cs | 14 +- .../DebugTables/LocalConstantTableTreeNode.cs | 10 +- .../DebugTables/LocalScopeTableTreeNode.cs | 14 +- .../DebugTables/LocalVariableTableTreeNode.cs | 10 +- .../MethodDebugInformationTableTreeNode.cs | 19 +- .../StateMachineMethodTableTreeNode.cs | 12 +- ILSpy/Metadata/DosHeaderTreeNode.cs | 1 + ILSpy/Metadata/FlagsFilterControl.xaml.cs | 23 +- ILSpy/Metadata/FlagsTooltip.xaml.cs | 7 +- ILSpy/Metadata/Helpers.cs | 29 +- ILSpy/Metadata/HexFilterControl.xaml.cs | 1 + ILSpy/Metadata/MetadataProtocolHandler.cs | 4 +- ILSpy/Metadata/MetadataTableTreeNode.cs | 1 + ILSpy/Metadata/MetadataTableViews.xaml.cs | 3 +- ILSpy/Metadata/MetadataTreeNode.cs | 1 + ILSpy/Metadata/OptionalHeaderTreeNode.cs | 1 + ILSpy/NativeMethods.cs | 62 +- ILSpy/NavigationHistory.cs | 19 +- ILSpy/NavigationState.cs | 1 + ILSpy/Options/DecompilerSettingsPanel.xaml.cs | 29 +- ILSpy/Options/DisplaySettings.cs | 72 +- ILSpy/Options/DisplaySettingsPanel.xaml.cs | 44 +- ILSpy/Options/MiscSettings.cs | 24 +- ILSpy/Options/MiscSettingsPanel.xaml.cs | 2 +- ILSpy/Options/OptionsDialog.xaml.cs | 37 +- ILSpy/Properties/AssemblyInfo.template.cs | 6 +- ILSpy/Search/AbstractEntitySearchStrategy.cs | 25 +- ILSpy/Search/AbstractSearchStrategy.cs | 63 +- ILSpy/Search/AssemblySearchStrategy.cs | 10 +- ILSpy/Search/LiteralSearchStrategy.cs | 87 +- ILSpy/Search/MemberSearchStrategy.cs | 49 +- ILSpy/Search/MetadataTokenSearchStrategy.cs | 28 +- ILSpy/Search/NamespaceSearchStrategy.cs | 7 +- ILSpy/Search/ResourceSearchStrategy.cs | 4 +- ILSpy/Search/SearchPane.cs | 115 +- ILSpy/Search/SearchResult.cs | 7 +- ILSpy/SessionSettings.cs | 32 +- ILSpy/SolutionWriter.cs | 58 +- ILSpy/TaskHelper.cs | 22 +- ILSpy/TextView/AvalonEditTextOutput.cs | 101 +- ILSpy/TextView/BracketHighlightRenderer.cs | 7 +- ILSpy/TextView/CaretHighlightAdorner.cs | 15 +- ILSpy/TextView/DecompilerTextView.cs | 439 ++-- ILSpy/TextView/DocumentationUIBuilder.cs | 128 +- ILSpy/TextView/FoldingCommands.cs | 15 +- .../TextView/OutputLengthExceededException.cs | 2 +- ILSpy/TextView/ReferenceElementGenerator.cs | 23 +- ILSpy/TextView/UIElementGenerator.cs | 8 +- ILSpy/TreeNodes/AssemblyListTreeNode.cs | 61 +- ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs | 34 +- ILSpy/TreeNodes/AssemblyTreeNode.cs | 111 +- ILSpy/TreeNodes/BaseTypesEntryNode.cs | 7 +- ILSpy/TreeNodes/BaseTypesTreeNode.cs | 6 +- ILSpy/TreeNodes/DerivedTypesEntryNode.cs | 15 +- ILSpy/TreeNodes/DerivedTypesTreeNode.cs | 16 +- ILSpy/TreeNodes/EventTreeNode.cs | 8 +- ILSpy/TreeNodes/FieldTreeNode.cs | 6 +- ILSpy/TreeNodes/ILSpyTreeNode.cs | 52 +- ILSpy/TreeNodes/MethodTreeNode.cs | 6 +- ILSpy/TreeNodes/ModuleReferenceTreeNode.cs | 14 +- ILSpy/TreeNodes/NamespaceTreeNode.cs | 13 +- ILSpy/TreeNodes/PropertyTreeNode.cs | 5 +- ILSpy/TreeNodes/ReferenceFolderTreeNode.cs | 11 +- ILSpy/TreeNodes/ResourceListTreeNode.cs | 10 +- .../ResourceNodes/CursorResourceEntryNode.cs | 15 +- .../ResourceNodes/IconResourceEntryNode.cs | 14 +- .../ImageListResourceEntryNode.cs | 7 +- .../ResourceNodes/ImageResourceEntryNode.cs | 12 +- .../ResourceNodes/ResourceEntryNode.cs | 15 +- .../ResourceNodes/ResourceTreeNode.cs | 20 +- .../ResourceNodes/ResourcesFileTreeNode.cs | 89 +- .../ResourceNodes/XamlResourceNode.cs | 21 +- .../ResourceNodes/XmlResourceNode.cs | 28 +- ILSpy/TreeNodes/ThreadingSupport.cs | 64 +- ILSpy/TreeNodes/TypeTreeNode.cs | 49 +- ILSpy/ViewModels/AssemblyListPaneModel.cs | 1 + .../ManageAssemblyListsViewModel.cs | 73 +- ILSpy/ViewModels/PaneModel.cs | 24 +- ILSpy/ViewModels/TabPageModel.cs | 42 +- ILSpy/Views/CreateListDialog.xaml.cs | 3 +- ILSpy/Views/DebugSteps.xaml.cs | 28 +- ILSpy/Views/ManageAssemblyLIstsDialog.xaml.cs | 1 + ILSpy/Views/NugetPackageBrowserDialog.xaml.cs | 3 +- ILSpy/Views/OpenFromGacDialog.xaml.cs | 13 +- SharpTreeView/Converters.cs | 4 +- SharpTreeView/EditTextBox.cs | 18 +- SharpTreeView/ExtensionMethods.cs | 10 +- SharpTreeView/FlatListTreeNode.cs | 198 +- SharpTreeView/GeneralAdorner.cs | 23 +- SharpTreeView/InsertMarker.cs | 2 +- SharpTreeView/LinesRenderer.cs | 29 +- .../Properties/GlobalAssemblyInfo.cs | 4 +- SharpTreeView/SharpGridView.cs | 8 +- SharpTreeView/SharpTreeNode.cs | 387 ++-- SharpTreeView/SharpTreeNodeCollection.cs | 86 +- SharpTreeView/SharpTreeNodeView.cs | 82 +- SharpTreeView/SharpTreeView.cs | 320 ++- SharpTreeView/SharpTreeViewAutomationPeer.cs | 2 +- SharpTreeView/SharpTreeViewItem.cs | 55 +- .../SharpTreeViewItemAutomationPeer.cs | 23 +- SharpTreeView/SharpTreeViewTextSearch.cs | 44 +- SharpTreeView/TreeFlattener.cs | 62 +- SharpTreeView/TreeTraversal.cs | 21 +- TestPlugin/ContextMenuCommand.cs | 9 +- TestPlugin/CustomLanguage.cs | 11 +- TestPlugin/CustomOptionPage.xaml.cs | 28 +- TestPlugin/MainMenuCommand.cs | 3 +- 963 files changed, 37032 insertions(+), 21983 deletions(-) diff --git a/ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs b/ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs index 9f79d0c73..b0d53022d 100644 --- a/ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs +++ b/ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs @@ -28,6 +28,7 @@ using ICSharpCode.Decompiler.Util; using Mono.Cecil; using Mono.Cecil.Pdb; + using SRM = System.Reflection.Metadata; namespace ICSharpCode.Decompiler.PdbProvider @@ -38,11 +39,13 @@ namespace ICSharpCode.Decompiler.PdbProvider public unsafe MonoCecilDebugInfoProvider(PEFile module, string pdbFileName, string description = null) { - if (module == null) { + if (module == null) + { throw new ArgumentNullException(nameof(module)); } - if (!module.Reader.IsEntireImageAvailable) { + if (!module.Reader.IsEntireImageAvailable) + { throw new ArgumentException("This provider needs access to the full image!"); } @@ -51,18 +54,22 @@ namespace ICSharpCode.Decompiler.PdbProvider var image = module.Reader.GetEntireImage(); this.debugInfo = new Dictionary SequencePoints, IList Variables)>(); using (UnmanagedMemoryStream stream = new UnmanagedMemoryStream(image.Pointer, image.Length)) - using (var moduleDef = ModuleDefinition.ReadModule(stream)) { + using (var moduleDef = ModuleDefinition.ReadModule(stream)) + { moduleDef.ReadSymbols(new PdbReaderProvider().GetSymbolReader(moduleDef, pdbFileName)); - foreach (var method in module.Metadata.MethodDefinitions) { + foreach (var method in module.Metadata.MethodDefinitions) + { var cecilMethod = moduleDef.LookupToken(MetadataTokens.GetToken(method)) as MethodDefinition; var debugInfo = cecilMethod?.DebugInformation; if (debugInfo == null) continue; IList sequencePoints = EmptyList.Instance; - if (debugInfo.HasSequencePoints) { + if (debugInfo.HasSequencePoints) + { sequencePoints = new List(debugInfo.SequencePoints.Count); - foreach (var point in debugInfo.SequencePoints) { + foreach (var point in debugInfo.SequencePoints) + { sequencePoints.Add(new SequencePoint { Offset = point.Offset, StartLine = point.StartLine, @@ -74,10 +81,12 @@ namespace ICSharpCode.Decompiler.PdbProvider } } var variables = new List(); - foreach (var scope in debugInfo.GetScopes()) { + foreach (var scope in debugInfo.GetScopes()) + { if (!scope.HasVariables) continue; - foreach (var v in scope.Variables) { + foreach (var v in scope.Variables) + { variables.Add(new Variable(v.Index, v.Name)); } } @@ -90,7 +99,8 @@ namespace ICSharpCode.Decompiler.PdbProvider public IList GetSequencePoints(SRM.MethodDefinitionHandle handle) { - if (!debugInfo.TryGetValue(handle, out var info)) { + if (!debugInfo.TryGetValue(handle, out var info)) + { return EmptyList.Instance; } @@ -99,7 +109,8 @@ namespace ICSharpCode.Decompiler.PdbProvider public IList GetVariables(SRM.MethodDefinitionHandle handle) { - if (!debugInfo.TryGetValue(handle, out var info)) { + if (!debugInfo.TryGetValue(handle, out var info)) + { return EmptyList.Instance; } @@ -109,7 +120,8 @@ namespace ICSharpCode.Decompiler.PdbProvider public bool TryGetName(SRM.MethodDefinitionHandle handle, int index, out string name) { name = null; - if (!debugInfo.TryGetValue(handle, out var info)) { + if (!debugInfo.TryGetValue(handle, out var info)) + { return false; } diff --git a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs index ac9c66bf6..ab47ccec7 100644 --- a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs @@ -21,7 +21,9 @@ using System.CodeDom.Compiler; using System.IO; using System.Linq; using System.Runtime.CompilerServices; + using ICSharpCode.Decompiler.Tests.Helpers; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests @@ -38,7 +40,8 @@ namespace ICSharpCode.Decompiler.Tests .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any()) .Select(m => m.Name) .ToArray(); - foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) { + foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) + { if (file.Extension == ".txt" || file.Extension == ".exe" || file.Extension == ".config") continue; var testName = Path.GetFileNameWithoutExtension(file.Name); @@ -213,7 +216,8 @@ namespace ICSharpCode.Decompiler.Tests { CompilerOptions compiler = CompilerOptions.UseDebug; AssemblerOptions asm = AssemblerOptions.None; - if (force32Bit) { + if (force32Bit) + { compiler |= CompilerOptions.Force32Bit; asm |= AssemblerOptions.Force32Bit; } @@ -237,7 +241,8 @@ namespace ICSharpCode.Decompiler.Tests { CompilerOptions compiler = CompilerOptions.UseRoslyn | CompilerOptions.UseDebug; AssemblerOptions asm = AssemblerOptions.None; - if (force32Bit) { + if (force32Bit) + { compiler |= CompilerOptions.Force32Bit; asm |= AssemblerOptions.Force32Bit; } @@ -247,7 +252,8 @@ namespace ICSharpCode.Decompiler.Tests [Test] public void UnsafeCode([ValueSource("defaultOptions")] CompilerOptions options) { - if (options.HasFlag(CompilerOptions.UseMcs)) { + if (options.HasFlag(CompilerOptions.UseMcs)) + { Assert.Ignore("Decompiler bug with mono!"); } RunCS(options: options); @@ -274,7 +280,8 @@ namespace ICSharpCode.Decompiler.Tests [Test] public void YieldReturn([ValueSource("defaultOptions")] CompilerOptions options) { - if (options.HasFlag(CompilerOptions.UseMcs)) { + if (options.HasFlag(CompilerOptions.UseMcs)) + { Assert.Ignore("Decompiler bug with mono!"); } RunCS(options: options); @@ -301,7 +308,8 @@ namespace ICSharpCode.Decompiler.Tests [Test] public void MiniJSON([ValueSource("defaultOptions")] CompilerOptions options) { - if (options.HasFlag(CompilerOptions.UseMcs)) { + if (options.HasFlag(CompilerOptions.UseMcs)) + { Assert.Ignore("Decompiler bug with mono!"); } RunCS(options: options); @@ -313,11 +321,13 @@ namespace ICSharpCode.Decompiler.Tests string testOutputFileName = testName + Tester.GetSuffix(options) + ".exe"; CompilerResults outputFile = null, decompiledOutputFile = null; - try { + try + { outputFile = Tester.CompileCSharp(Path.Combine(TestCasePath, testFileName), options, outputFileName: Path.Combine(TestCasePath, testOutputFileName)); string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options)); - if (forceRoslynRecompile || options.HasFlag(CompilerOptions.UseMcs)) { + if (forceRoslynRecompile || options.HasFlag(CompilerOptions.UseMcs)) + { // For second pass, use roslyn instead of mcs. // mcs has some compiler bugs that cause it to not accept ILSpy-generated code, // for example when there's unreachable code due to other compiler bugs in the first mcs run. @@ -332,12 +342,14 @@ namespace ICSharpCode.Decompiler.Tests "); } decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options); - + Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile); - + Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile)); Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly)); - } finally { + } + finally + { if (outputFile != null) outputFile.TempFiles.Delete(); if (decompiledOutputFile != null) @@ -352,7 +364,8 @@ namespace ICSharpCode.Decompiler.Tests string testOutputFileName = testName + Tester.GetSuffix(options) + ".exe"; CompilerResults outputFile = null, decompiledOutputFile = null; - try { + try + { outputFile = Tester.CompileVB(Path.Combine(TestCasePath, testFileName), options, outputFileName: Path.Combine(TestCasePath, testOutputFileName)); string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options)); @@ -362,7 +375,9 @@ namespace ICSharpCode.Decompiler.Tests Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile)); Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly)); - } finally { + } + finally + { if (outputFile != null) outputFile.TempFiles.Delete(); if (decompiledOutputFile != null) @@ -375,16 +390,19 @@ namespace ICSharpCode.Decompiler.Tests string outputFile = null; CompilerResults decompiledOutputFile = null; - try { + try + { outputFile = Tester.AssembleIL(Path.Combine(TestCasePath, testFileName), asmOptions); string decompiledCodeFile = Tester.DecompileCSharp(outputFile, Tester.GetSettings(options)); decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options); - + Tester.RunAndCompareOutput(testFileName, outputFile, decompiledOutputFile.PathToAssembly, decompiledCodeFile); Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile)); Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly)); - } finally { + } + finally + { if (decompiledOutputFile != null) decompiledOutputFile.TempFiles.Delete(); } diff --git a/ICSharpCode.Decompiler.Tests/DataFlowTest.cs b/ICSharpCode.Decompiler.Tests/DataFlowTest.cs index 8c49c3949..cfe14be75 100644 --- a/ICSharpCode.Decompiler.Tests/DataFlowTest.cs +++ b/ICSharpCode.Decompiler.Tests/DataFlowTest.cs @@ -22,9 +22,11 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; + using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.TypeSystem; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests diff --git a/ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs index ce002b835..bc7010982 100644 --- a/ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs @@ -23,7 +23,9 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.Tests.Helpers; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests @@ -40,8 +42,10 @@ namespace ICSharpCode.Decompiler.Tests .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any()) .Select(m => m.Name) .ToArray(); - foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) { - if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase)) { + foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) + { + if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase)) + { var testName = file.Name.Split('.')[0]; Assert.Contains(testName, testNames); } diff --git a/ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs b/ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs index 84150206a..a364f43a1 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs @@ -2,9 +2,12 @@ using System.Collections.Generic; using System.IO; using System.Linq; + using DiffLib; + using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Helpers @@ -19,7 +22,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers public static void AreEqual(string input1, string input2, string[] definedSymbols = null) { var diff = new StringWriter(); - if (!CodeComparer.Compare(input1, input2, diff, CodeComparer.NormalizeLine, definedSymbols)) { + if (!CodeComparer.Compare(input1, input2, diff, CodeComparer.NormalizeLine, definedSymbols)) + { Assert.Fail(diff.ToString()); } } @@ -35,32 +39,40 @@ namespace ICSharpCode.Decompiler.Tests.Helpers collection1, collection2, new CodeLineEqualityComparer(normalizeLine) ); var alignedDiff = Diff.AlignElements(collection1, collection2, diffSections, new StringSimilarityDiffElementAligner()); - + bool result = true; int line1 = 0, line2 = 0; const int contextSize = 10; int consecutiveMatches = contextSize; var hiddenMatches = new List(); - - foreach (var change in alignedDiff) { - switch (change.Operation) { + + foreach (var change in alignedDiff) + { + switch (change.Operation) + { case DiffOperation.Match: AppendMatch($"{++line1,4} {++line2,4} ", change.ElementFromCollection1.Value); break; case DiffOperation.Insert: string pos = $" {++line2,4} "; - if (ShouldIgnoreChange(change.ElementFromCollection2.Value)) { + if (ShouldIgnoreChange(change.ElementFromCollection2.Value)) + { AppendMatch(pos, change.ElementFromCollection2.Value); - } else { + } + else + { AppendDelta(pos, " + ", change.ElementFromCollection2.Value); result = false; } break; case DiffOperation.Delete: pos = $"{++line1,4} "; - if (ShouldIgnoreChange(change.ElementFromCollection1.Value)) { + if (ShouldIgnoreChange(change.ElementFromCollection1.Value)) + { AppendMatch(pos, change.ElementFromCollection1.Value); - } else { + } + else + { AppendDelta(pos, " - ", change.ElementFromCollection1.Value); result = false; } @@ -73,7 +85,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers break; } } - if (hiddenMatches.Count > 0) { + if (hiddenMatches.Count > 0) + { diff.WriteLine(" ..."); } @@ -82,10 +95,13 @@ namespace ICSharpCode.Decompiler.Tests.Helpers void AppendMatch(string pos, string code) { consecutiveMatches++; - if (consecutiveMatches > contextSize) { + if (consecutiveMatches > contextSize) + { // hide this match hiddenMatches.Add(pos + " " + code); - } else { + } + else + { diff.WriteLine(pos + " " + code); } } @@ -93,10 +109,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers void AppendDelta(string pos, string changeType, string code) { consecutiveMatches = 0; - if (hiddenMatches.Count > contextSize) { + if (hiddenMatches.Count > contextSize) + { diff.WriteLine(" ..."); } - for (int i = Math.Max(0, hiddenMatches.Count - contextSize); i < hiddenMatches.Count; i++) { + for (int i = Math.Max(0, hiddenMatches.Count - contextSize); i < hiddenMatches.Count; i++) + { diff.WriteLine(hiddenMatches[i]); } hiddenMatches.Clear(); @@ -132,11 +150,16 @@ namespace ICSharpCode.Decompiler.Tests.Helpers { line = line.Trim(); var index = line.IndexOf("//", StringComparison.Ordinal); - if (index >= 0) { + if (index >= 0) + { return line.Substring(0, index); - } else if (line.StartsWith("#", StringComparison.Ordinal)) { + } + else if (line.StartsWith("#", StringComparison.Ordinal)) + { return string.Empty; - } else { + } + else + { return line; } } @@ -151,7 +174,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers { public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia) { - if (trivia.IsKind(SyntaxKind.DisabledTextTrivia)) { + if (trivia.IsKind(SyntaxKind.DisabledTextTrivia)) + { return default(SyntaxTrivia); // delete } return base.VisitTrivia(trivia); diff --git a/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs b/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs index 049533a7f..efdd021d3 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/RemoveCompilerAttribute.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; + using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Transforms; @@ -13,12 +14,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers var section = (AttributeSection)attribute.Parent; SimpleType type = attribute.Type as SimpleType; if (section.AttributeTarget == "assembly" && - (type.Identifier == "CompilationRelaxations" || type.Identifier == "RuntimeCompatibility" || type.Identifier == "SecurityPermission" || type.Identifier == "PermissionSet" || type.Identifier == "AssemblyVersion" || type.Identifier == "Debuggable" || type.Identifier == "TargetFramework")) { + (type.Identifier == "CompilationRelaxations" || type.Identifier == "RuntimeCompatibility" || type.Identifier == "SecurityPermission" || type.Identifier == "PermissionSet" || type.Identifier == "AssemblyVersion" || type.Identifier == "Debuggable" || type.Identifier == "TargetFramework")) + { attribute.Remove(); if (section.Attributes.Count == 0) section.Remove(); } - if (section.AttributeTarget == "module" && type.Identifier == "UnverifiableCode") { + if (section.AttributeTarget == "module" && type.Identifier == "UnverifiableCode") + { attribute.Remove(); if (section.Attributes.Count == 0) section.Remove(); @@ -64,9 +67,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers { public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) { - if (namespaceDeclaration.Name == "My") { + if (namespaceDeclaration.Name == "My") + { namespaceDeclaration.Remove(); - } else { + } + else + { base.VisitNamespaceDeclaration(namespaceDeclaration); } } diff --git a/ICSharpCode.Decompiler.Tests/Helpers/SdkUtility.cs b/ICSharpCode.Decompiler.Tests/Helpers/SdkUtility.cs index d25d076c3..1b669ec3a 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/SdkUtility.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/SdkUtility.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.IO; + using Microsoft.Win32; namespace ICSharpCode.Decompiler.Tests.Helpers @@ -25,10 +26,13 @@ namespace ICSharpCode.Decompiler.Tests.Helpers { static string GetPathFromRegistry(string key, string valueName) { - using (RegistryKey installRootKey = Registry.LocalMachine.OpenSubKey(key)) { - if (installRootKey != null) { + using (RegistryKey installRootKey = Registry.LocalMachine.OpenSubKey(key)) + { + if (installRootKey != null) + { object o = installRootKey.GetValue(valueName); - if (o != null) { + if (o != null) + { string r = o.ToString(); if (!string.IsNullOrEmpty(r)) return r; @@ -37,14 +41,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers } return null; } - + static string GetPathFromRegistryX86(string key, string valueName) { - using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) { - using (RegistryKey installRootKey = baseKey.OpenSubKey(key)) { - if (installRootKey != null) { + using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) + { + using (RegistryKey installRootKey = baseKey.OpenSubKey(key)) + { + if (installRootKey != null) + { object o = installRootKey.GetValue(valueName); - if (o != null) { + if (o != null) + { string r = o.ToString(); if (!string.IsNullOrEmpty(r)) return r; @@ -54,107 +62,115 @@ namespace ICSharpCode.Decompiler.Tests.Helpers } return null; } - + #region InstallRoot Properties - + static string netFrameworkInstallRoot = null; /// /// Gets the installation root of the .NET Framework (@"C:\Windows\Microsoft.NET\Framework\") /// public static string NetFrameworkInstallRoot { get { - if (netFrameworkInstallRoot == null) { + if (netFrameworkInstallRoot == null) + { netFrameworkInstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "InstallRoot") ?? string.Empty; } return netFrameworkInstallRoot; } } - + static string netSdk20InstallRoot = null; /// /// Location of the .NET 2.0 SDK install root. /// public static string NetSdk20InstallRoot { get { - if (netSdk20InstallRoot == null) { + if (netSdk20InstallRoot == null) + { netSdk20InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "sdkInstallRootv2.0") ?? string.Empty; } return netSdk20InstallRoot; } } - + static string windowsSdk60InstallRoot = null; /// /// Location of the .NET 3.0 SDK (Windows SDK 6.0) install root. /// public static string WindowsSdk60InstallRoot { get { - if (windowsSdk60InstallRoot == null) { + if (windowsSdk60InstallRoot == null) + { windowsSdk60InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0", "InstallationFolder") ?? string.Empty; } return windowsSdk60InstallRoot; } } - + static string windowsSdk60aInstallRoot = null; /// /// Location of the Windows SDK Components in Visual Studio 2008 (.NET 3.5; Windows SDK 6.0a). /// public static string WindowsSdk60aInstallRoot { get { - if (windowsSdk60aInstallRoot == null) { + if (windowsSdk60aInstallRoot == null) + { windowsSdk60aInstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0a", "InstallationFolder") ?? string.Empty; } return windowsSdk60aInstallRoot; } } - + static string windowsSdk61InstallRoot = null; /// /// Location of the .NET 3.5 SDK (Windows SDK 6.1) install root. /// public static string WindowsSdk61InstallRoot { get { - if (windowsSdk61InstallRoot == null) { + if (windowsSdk61InstallRoot == null) + { windowsSdk61InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.1", "InstallationFolder") ?? string.Empty; } return windowsSdk61InstallRoot; } } - + static string windowsSdk70InstallRoot = null; /// /// Location of the .NET 3.5 SP1 SDK (Windows SDK 7.0) install root. /// public static string WindowsSdk70InstallRoot { get { - if (windowsSdk70InstallRoot == null) { + if (windowsSdk70InstallRoot == null) + { windowsSdk70InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0", "InstallationFolder") ?? string.Empty; } return windowsSdk70InstallRoot; } } - + static string windowsSdk71InstallRoot = null; /// /// Location of the .NET 4.0 SDK (Windows SDK 7.1) install root. /// public static string WindowsSdk71InstallRoot { get { - if (windowsSdk71InstallRoot == null) { + if (windowsSdk71InstallRoot == null) + { windowsSdk71InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1", "InstallationFolder") ?? string.Empty; } return windowsSdk71InstallRoot; } } - + static string windowsSdk80InstallRoot = null; /// /// Location of the .NET 4.5 SDK (Windows SDK 8.0) install root. /// public static string WindowsSdk80NetFxTools { get { - if (windowsSdk80InstallRoot == null) { + if (windowsSdk80InstallRoot == null) + { windowsSdk80InstallRoot = GetPathFromRegistryX86(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools", "InstallationFolder") ?? string.Empty; } return windowsSdk80InstallRoot; @@ -167,53 +183,71 @@ namespace ICSharpCode.Decompiler.Tests.Helpers /// public static string WindowsSdk461NetFxTools { get { - if (WindowsSdk461InstallRoot == null) { + if (WindowsSdk461InstallRoot == null) + { WindowsSdk461InstallRoot = GetPathFromRegistryX86(@"SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\NETFXSDK\4.6.1\WinSDK-NetFx40Tools", "InstallationFolder") ?? string.Empty; } return WindowsSdk461InstallRoot; } } #endregion - + /// /// Searches all the .net sdk bin folders and return the path of the /// exe from the latest sdk. /// /// The EXE to search for. /// The path of the executable, or null if the exe is not found. - public static string GetSdkPath(string exeName) { + public static string GetSdkPath(string exeName) + { string execPath; - if (!string.IsNullOrEmpty(WindowsSdk461NetFxTools)) { + if (!string.IsNullOrEmpty(WindowsSdk461NetFxTools)) + { execPath = Path.Combine(WindowsSdk461NetFxTools, exeName); - if (File.Exists(execPath)) { return execPath; } + if (File.Exists(execPath)) + { return execPath; } } - if (!string.IsNullOrEmpty(WindowsSdk80NetFxTools)) { + if (!string.IsNullOrEmpty(WindowsSdk80NetFxTools)) + { execPath = Path.Combine(WindowsSdk80NetFxTools, exeName); - if (File.Exists(execPath)) { return execPath; } + if (File.Exists(execPath)) + { return execPath; } } - if (!string.IsNullOrEmpty(WindowsSdk71InstallRoot)) { + if (!string.IsNullOrEmpty(WindowsSdk71InstallRoot)) + { execPath = Path.Combine(WindowsSdk71InstallRoot, "bin\\" + exeName); - if (File.Exists(execPath)) { return execPath; } + if (File.Exists(execPath)) + { return execPath; } } - if (!string.IsNullOrEmpty(WindowsSdk70InstallRoot)) { + if (!string.IsNullOrEmpty(WindowsSdk70InstallRoot)) + { execPath = Path.Combine(WindowsSdk70InstallRoot, "bin\\" + exeName); - if (File.Exists(execPath)) { return execPath; } + if (File.Exists(execPath)) + { return execPath; } } - if (!string.IsNullOrEmpty(WindowsSdk61InstallRoot)) { + if (!string.IsNullOrEmpty(WindowsSdk61InstallRoot)) + { execPath = Path.Combine(WindowsSdk61InstallRoot, "bin\\" + exeName); - if (File.Exists(execPath)) { return execPath; } + if (File.Exists(execPath)) + { return execPath; } } - if (!string.IsNullOrEmpty(WindowsSdk60aInstallRoot)) { + if (!string.IsNullOrEmpty(WindowsSdk60aInstallRoot)) + { execPath = Path.Combine(WindowsSdk60aInstallRoot, "bin\\" + exeName); - if (File.Exists(execPath)) { return execPath; } + if (File.Exists(execPath)) + { return execPath; } } - if (!string.IsNullOrEmpty(WindowsSdk60InstallRoot)) { + if (!string.IsNullOrEmpty(WindowsSdk60InstallRoot)) + { execPath = Path.Combine(WindowsSdk60InstallRoot, "bin\\" + exeName); - if (File.Exists(execPath)) { return execPath; } + if (File.Exists(execPath)) + { return execPath; } } - if (!string.IsNullOrEmpty(NetSdk20InstallRoot)) { + if (!string.IsNullOrEmpty(NetSdk20InstallRoot)) + { execPath = Path.Combine(NetSdk20InstallRoot, "bin\\" + exeName); - if (File.Exists(execPath)) { return execPath; } + if (File.Exists(execPath)) + { return execPath; } } return null; } diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs index 55f0f5a3e..01bd5be2b 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs @@ -7,6 +7,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; + using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.VisualBasic; using Microsoft.VisualBasic; @@ -18,17 +19,20 @@ namespace ICSharpCode.Decompiler.Tests.Helpers public static CompilerResults CompileVB(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null) { List sourceFileNames = new List { sourceFileName }; - foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)""")) { + foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)""")) + { sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value))); } var preprocessorSymbols = GetPreprocessorSymbols(flags).Select(symbol => new KeyValuePair(symbol, 1)).ToList(); - if (flags.HasFlag(CompilerOptions.UseRoslyn)) { + if (flags.HasFlag(CompilerOptions.UseRoslyn)) + { var parseOptions = new VisualBasicParseOptions(preprocessorSymbols: preprocessorSymbols, languageVersion: LanguageVersion.Latest); var syntaxTrees = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f)); var references = defaultReferences.Value; - if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) { + if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) + { references = references.Concat(visualBasic.Value); } var compilation = VisualBasicCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName), @@ -42,17 +46,23 @@ namespace ICSharpCode.Decompiler.Tests.Helpers CompilerResults results = new CompilerResults(new TempFileCollection()); results.PathToAssembly = outputFileName ?? Path.GetTempFileName(); var emitResult = compilation.Emit(results.PathToAssembly); - if (!emitResult.Success) { + if (!emitResult.Success) + { StringBuilder b = new StringBuilder("Compiler error:"); - foreach (var diag in emitResult.Diagnostics) { + foreach (var diag in emitResult.Diagnostics) + { b.AppendLine(diag.ToString()); } throw new Exception(b.ToString()); } return results; - } else if (flags.HasFlag(CompilerOptions.UseMcs)) { + } + else if (flags.HasFlag(CompilerOptions.UseMcs)) + { throw new NotSupportedException("Cannot use mcs for VB"); - } else { + } + else + { var provider = new VBCodeProvider(new Dictionary { { "CompilerVersion", "v4.0" } }); CompilerParameters options = new CompilerParameters(); options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library); @@ -60,23 +70,28 @@ namespace ICSharpCode.Decompiler.Tests.Helpers options.CompilerOptions += (flags.HasFlag(CompilerOptions.UseDebug) ? " /debug" : ""); options.CompilerOptions += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : ""); options.CompilerOptions += " /optioninfer+ /optionexplicit+"; - if (preprocessorSymbols.Count > 0) { + if (preprocessorSymbols.Count > 0) + { options.CompilerOptions += " /d:" + string.Join(",", preprocessorSymbols.Select(p => $"{p.Key}={p.Value}")); } - if (outputFileName != null) { + if (outputFileName != null) + { options.OutputAssembly = outputFileName; } options.ReferencedAssemblies.Add("System.dll"); options.ReferencedAssemblies.Add("System.Core.dll"); options.ReferencedAssemblies.Add("System.Xml.dll"); - if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) { + if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) + { options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll"); } CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray()); - if (results.Errors.Cast().Any(e => !e.IsWarning)) { + if (results.Errors.Cast().Any(e => !e.IsWarning)) + { StringBuilder b = new StringBuilder("Compiler error:"); - foreach (var error in results.Errors) { + foreach (var error in results.Errors) + { b.AppendLine(error.ToString()); } throw new Exception(b.ToString()); diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index 6bc3c6a9f..731d55a93 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -28,18 +28,21 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; + using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; + using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Text; using Microsoft.CSharp; using Microsoft.DiaSymReader.Tools; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Helpers @@ -81,20 +84,25 @@ namespace ICSharpCode.Decompiler.Tests.Helpers string ilasmPath = Path.Combine(Environment.GetEnvironmentVariable("windir"), @"Microsoft.NET\Framework\v4.0.30319\ilasm.exe"); string outputFile = Path.Combine(Path.GetDirectoryName(sourceFileName), Path.GetFileNameWithoutExtension(sourceFileName)); string otherOptions = " "; - if (options.HasFlag(AssemblerOptions.Force32Bit)) { + if (options.HasFlag(AssemblerOptions.Force32Bit)) + { outputFile += ".32"; otherOptions += "/32BitPreferred "; } - if (options.HasFlag(AssemblerOptions.Library)) { + if (options.HasFlag(AssemblerOptions.Library)) + { outputFile += ".dll"; otherOptions += "/dll "; - } else { + } + else + { outputFile += ".exe"; otherOptions += "/exe "; } - if (options.HasFlag(AssemblerOptions.UseDebug)) { + if (options.HasFlag(AssemblerOptions.UseDebug)) + { otherOptions += "/debug "; } @@ -121,10 +129,12 @@ namespace ICSharpCode.Decompiler.Tests.Helpers public static string Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions) { - if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler)) { + if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler)) + { using (var peFileStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read)) using (var peFile = new PEFile(sourceFileName, peFileStream)) - using (var writer = new StringWriter()) { + using (var writer = new StringWriter()) + { var metadata = peFile.Metadata; var output = new PlainTextOutput(writer); ReflectionDisassembler rd = new ReflectionDisassembler(output, CancellationToken.None); @@ -186,7 +196,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers } static readonly string coreRefAsmPath = new DotNetCorePathFinder(TargetFrameworkIdentifier.NETCoreApp, new Version(3, 1)).GetReferenceAssemblyPath(".NETCoreApp, Version = v3.1"); - + static readonly string refAsmPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2"); static readonly string thisAsmPath = Path.GetDirectoryName(typeof(Tester).Assembly.Location); @@ -217,7 +227,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers static IEnumerable GetDefaultReferences() { - foreach (var reference in Directory.EnumerateFiles(coreRefAsmPath, "*.dll")) { + foreach (var reference in Directory.EnumerateFiles(coreRefAsmPath, "*.dll")) + { yield return MetadataReference.CreateFromFile(reference); } } @@ -231,16 +242,20 @@ namespace ICSharpCode.Decompiler.Tests.Helpers public static List GetPreprocessorSymbols(CompilerOptions flags) { var preprocessorSymbols = new List(); - if (flags.HasFlag(CompilerOptions.UseDebug)) { + if (flags.HasFlag(CompilerOptions.UseDebug)) + { preprocessorSymbols.Add("DEBUG"); } - if (flags.HasFlag(CompilerOptions.Optimize)) { + if (flags.HasFlag(CompilerOptions.Optimize)) + { preprocessorSymbols.Add("OPT"); } - if (flags.HasFlag(CompilerOptions.ReferenceCore)) { + if (flags.HasFlag(CompilerOptions.ReferenceCore)) + { preprocessorSymbols.Add("NETCORE"); } - if (flags.HasFlag(CompilerOptions.UseRoslyn)) { + if (flags.HasFlag(CompilerOptions.UseRoslyn)) + { preprocessorSymbols.Add("ROSLYN"); preprocessorSymbols.Add("CS60"); preprocessorSymbols.Add("CS70"); @@ -252,12 +267,17 @@ namespace ICSharpCode.Decompiler.Tests.Helpers preprocessorSymbols.Add("VB14"); preprocessorSymbols.Add("VB15"); - if (flags.HasFlag(CompilerOptions.Preview)) { + if (flags.HasFlag(CompilerOptions.Preview)) + { preprocessorSymbols.Add("CS90"); } - } else if (flags.HasFlag(CompilerOptions.UseMcs)) { + } + else if (flags.HasFlag(CompilerOptions.UseMcs)) + { preprocessorSymbols.Add("MCS"); - } else { + } + else + { preprocessorSymbols.Add("LEGACY_CSC"); preprocessorSymbols.Add("LEGACY_VBC"); } @@ -267,28 +287,35 @@ namespace ICSharpCode.Decompiler.Tests.Helpers public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null) { List sourceFileNames = new List { sourceFileName }; - foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)""")) { + foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)""")) + { sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value))); } var preprocessorSymbols = GetPreprocessorSymbols(flags); - if (flags.HasFlag(CompilerOptions.UseRoslyn)) { + if (flags.HasFlag(CompilerOptions.UseRoslyn)) + { var parseOptions = new CSharpParseOptions( preprocessorSymbols: preprocessorSymbols.ToArray(), languageVersion: flags.HasFlag(CompilerOptions.Preview) ? Microsoft.CodeAnalysis.CSharp.LanguageVersion.Preview : Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp8 ); var syntaxTrees = sourceFileNames.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, path: f, encoding: Encoding.UTF8)); - if (flags.HasFlag(CompilerOptions.ReferenceCore)) { + if (flags.HasFlag(CompilerOptions.ReferenceCore)) + { syntaxTrees = syntaxTrees.Concat(new[] { SyntaxFactory.ParseSyntaxTree(targetFrameworkAttributeSnippet) }); } IEnumerable references; - if (flags.HasFlag(CompilerOptions.ReferenceCore)) { + if (flags.HasFlag(CompilerOptions.ReferenceCore)) + { references = coreDefaultReferences.Value; - } else { + } + else + { references = defaultReferences.Value; } - if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) { + if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) + { references = references.Concat(visualBasic.Value); } var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(sourceFileName), @@ -306,41 +333,54 @@ namespace ICSharpCode.Decompiler.Tests.Helpers if (flags.HasFlag(CompilerOptions.GeneratePdb)) pdbName = Path.ChangeExtension(outputFileName, ".pdb"); var emitResult = compilation.Emit(results.PathToAssembly, pdbName); - if (!emitResult.Success) { + if (!emitResult.Success) + { StringBuilder b = new StringBuilder("Compiler error:"); - foreach (var diag in emitResult.Diagnostics) { + foreach (var diag in emitResult.Diagnostics) + { b.AppendLine(diag.ToString()); } throw new Exception(b.ToString()); } return results; - } else if (flags.HasFlag(CompilerOptions.UseMcs)) { + } + else if (flags.HasFlag(CompilerOptions.UseMcs)) + { CompilerResults results = new CompilerResults(new TempFileCollection()); results.PathToAssembly = outputFileName ?? Path.GetTempFileName(); string testBasePath = RoundtripAssembly.TestDir; - if (!Directory.Exists(testBasePath)) { + if (!Directory.Exists(testBasePath)) + { Assert.Ignore($"Compilation with mcs ignored: test directory '{testBasePath}' needs to be checked out separately." + Environment.NewLine + $"git clone https://github.com/icsharpcode/ILSpy-tests \"{testBasePath}\""); } string mcsPath = Path.Combine(testBasePath, @"mcs\2.6.4\bin\gmcs.bat"); string otherOptions = " -unsafe -o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+ " : "- "); - if (flags.HasFlag(CompilerOptions.Library)) { + if (flags.HasFlag(CompilerOptions.Library)) + { otherOptions += "-t:library "; - } else { + } + else + { otherOptions += "-t:exe "; } - if (flags.HasFlag(CompilerOptions.UseDebug)) { + if (flags.HasFlag(CompilerOptions.UseDebug)) + { otherOptions += "-g "; } - if (flags.HasFlag(CompilerOptions.Force32Bit)) { + if (flags.HasFlag(CompilerOptions.Force32Bit)) + { otherOptions += "-platform:x86 "; - } else { + } + else + { otherOptions += "-platform:anycpu "; } - if (preprocessorSymbols.Count > 0) { + if (preprocessorSymbols.Count > 0) + { otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" "; } @@ -364,35 +404,43 @@ namespace ICSharpCode.Decompiler.Tests.Helpers Console.WriteLine("errors: " + errorTask.Result); Assert.AreEqual(0, process.ExitCode, "mcs failed"); return results; - } else { + } + else + { var provider = new CSharpCodeProvider(new Dictionary { { "CompilerVersion", "v4.0" } }); CompilerParameters options = new CompilerParameters(); options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library); options.CompilerOptions = "/unsafe /o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+" : "-"); string debugOption = " /debug"; - if (flags.HasFlag(CompilerOptions.GeneratePdb)) { + if (flags.HasFlag(CompilerOptions.GeneratePdb)) + { debugOption += ":full"; options.IncludeDebugInformation = true; } options.CompilerOptions += (flags.HasFlag(CompilerOptions.UseDebug) ? debugOption : ""); options.CompilerOptions += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : ""); - if (preprocessorSymbols.Count > 0) { + if (preprocessorSymbols.Count > 0) + { options.CompilerOptions += " /d:" + string.Join(";", preprocessorSymbols); } - if (outputFileName != null) { + if (outputFileName != null) + { options.OutputAssembly = outputFileName; } options.ReferencedAssemblies.Add("System.dll"); options.ReferencedAssemblies.Add("System.Core.dll"); options.ReferencedAssemblies.Add("System.Xml.dll"); options.ReferencedAssemblies.Add("Microsoft.CSharp.dll"); - if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) { + if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic)) + { options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll"); } CompilerResults results = provider.CompileAssemblyFromFile(options, sourceFileNames.ToArray()); - if (results.Errors.Cast().Any(e => !e.IsWarning)) { + if (results.Errors.Cast().Any(e => !e.IsWarning)) + { StringBuilder b = new StringBuilder("Compiler error:"); - foreach (var error in results.Errors) { + foreach (var error in results.Errors) + { b.AppendLine(error.ToString()); } throw new Exception(b.ToString()); @@ -403,13 +451,19 @@ namespace ICSharpCode.Decompiler.Tests.Helpers internal static DecompilerSettings GetSettings(CompilerOptions cscOptions) { - if (cscOptions.HasFlag(CompilerOptions.UseRoslyn)) { - if (cscOptions.HasFlag(CompilerOptions.Preview)) { + if (cscOptions.HasFlag(CompilerOptions.UseRoslyn)) + { + if (cscOptions.HasFlag(CompilerOptions.Preview)) + { return new DecompilerSettings(CSharp.LanguageVersion.Latest); - } else { + } + else + { return new DecompilerSettings(CSharp.LanguageVersion.CSharp8_0); } - } else { + } + else + { return new DecompilerSettings(CSharp.LanguageVersion.CSharp5); } } @@ -421,7 +475,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers List embeddedTexts = new List(); List syntaxTrees = new List(); - foreach (KeyValuePair file in sourceFiles) { + foreach (KeyValuePair file in sourceFiles) + { var sourceText = SourceText.From(file.Value, new UTF8Encoding(false), SourceHashAlgorithm.Sha256); syntaxTrees.Add(SyntaxFactory.ParseSyntaxTree(sourceText, parseOptions, file.Key)); embeddedTexts.Add(EmbeddedText.FromSource(file.Key, sourceText)); @@ -437,11 +492,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers deterministic: true )); using (FileStream peStream = File.Open(assemblyName + ".dll", FileMode.OpenOrCreate, FileAccess.ReadWrite)) - using (FileStream pdbStream = File.Open(assemblyName + ".pdb", FileMode.OpenOrCreate, FileAccess.ReadWrite)) { + using (FileStream pdbStream = File.Open(assemblyName + ".pdb", FileMode.OpenOrCreate, FileAccess.ReadWrite)) + { var emitResult = compilation.Emit(peStream, pdbStream, options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: assemblyName + ".pdb"), embeddedTexts: embeddedTexts); - if (!emitResult.Success) { + if (!emitResult.Success) + { StringBuilder b = new StringBuilder("Compiler error:"); - foreach (var diag in emitResult.Diagnostics) { + foreach (var diag in emitResult.Diagnostics) + { b.AppendLine(diag.ToString()); } throw new Exception(b.ToString()); @@ -490,7 +548,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers { if (settings == null) settings = new DecompilerSettings(); - using (var file = new FileStream(assemblyFileName, FileMode.Open, FileAccess.Read)) { + using (var file = new FileStream(assemblyFileName, FileMode.Open, FileAccess.Read)) + { var module = new PEFile(assemblyFileName, file, PEStreamOptions.PrefetchEntireImage); var resolver = new UniversalAssemblyResolver(assemblyFileName, false, module.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchMetadata); @@ -526,13 +585,16 @@ namespace ICSharpCode.Decompiler.Tests.Helpers Assert.AreEqual(0, result1, "Exit code != 0; did the test case crash?" + Environment.NewLine + error1); Assert.AreEqual(0, result2, "Exit code != 0; did the decompiled code crash?" + Environment.NewLine + error2); - if (output1 != output2 || error1 != error2) { + if (output1 != output2 || error1 != error2) + { StringBuilder b = new StringBuilder(); b.AppendLine($"Test {testFileName} failed: output does not match."); - if (decompiledCodeFile != null) { + if (decompiledCodeFile != null) + { b.AppendLine($"Decompiled code in {decompiledCodeFile}:line 1"); } - if (error1 != error2) { + if (error1 != error2) + { b.AppendLine("Got different error output."); b.AppendLine("Original error:"); b.AppendLine(error1); @@ -541,25 +603,30 @@ namespace ICSharpCode.Decompiler.Tests.Helpers b.AppendLine(error2); b.AppendLine(); } - if (output1 != output2) { + if (output1 != output2) + { string outputFileName = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(testFileName)); File.WriteAllText(outputFileName + ".original.out", output1); File.WriteAllText(outputFileName + ".decompiled.out", output2); int diffLine = 0; string lastHeader = null; Tuple errorItem = null; - foreach (var pair in output1.Replace("\r", "").Split('\n').Zip(output2.Replace("\r", "").Split('\n'), Tuple.Create)) { + foreach (var pair in output1.Replace("\r", "").Split('\n').Zip(output2.Replace("\r", "").Split('\n'), Tuple.Create)) + { diffLine++; - if (pair.Item1 != pair.Item2) { + if (pair.Item1 != pair.Item2) + { errorItem = pair; break; } - if (pair.Item1.EndsWith(":", StringComparison.Ordinal)) { + if (pair.Item1.EndsWith(":", StringComparison.Ordinal)) + { lastHeader = pair.Item1; } } b.AppendLine($"Output differs; first difference in line {diffLine}"); - if (lastHeader != null) { + if (lastHeader != null) + { b.AppendLine(lastHeader); } b.AppendLine($"{outputFileName}.original.out:line {diffLine}"); @@ -573,12 +640,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers internal static void RepeatOnIOError(Action action, int numTries = 5) { - for (int i = 0; i < numTries - 1; i++) { - try { + for (int i = 0; i < numTries - 1; i++) + { + try + { action(); return; - } catch (IOException) { - } catch (UnauthorizedAccessException) { + } + catch (IOException) + { + } + catch (UnauthorizedAccessException) + { // potential virus scanner problem } Thread.Sleep(10); diff --git a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs index 383c6c1d7..487ee8be1 100644 --- a/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs @@ -20,7 +20,9 @@ using System; using System.IO; using System.Linq; using System.Runtime.CompilerServices; + using ICSharpCode.Decompiler.Tests.Helpers; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests @@ -37,8 +39,10 @@ namespace ICSharpCode.Decompiler.Tests .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any()) .Select(m => m.Name) .ToArray(); - foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) { - if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase)) { + foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) + { + if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase)) + { var testName = file.Name.Split('.')[0]; Assert.Contains(testName, testNames); Assert.IsTrue(File.Exists(Path.Combine(TestCasePath, testName + ".cs"))); @@ -243,7 +247,8 @@ namespace ICSharpCode.Decompiler.Tests static void CopyFSharpCoreDll() { - lock (copyLock) { + lock (copyLock) + { if (File.Exists(Path.Combine(TestCasePath, "FSharp.Core.dll"))) return; string fsharpCoreDll = Path.Combine(TestCasePath, "..\\..\\..\\ILSpy-tests\\FSharp\\FSharp.Core.dll"); diff --git a/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs b/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs index 898852b39..f729215c4 100644 --- a/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs +++ b/ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs @@ -19,11 +19,13 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.Output; using ICSharpCode.Decompiler.Tests.TypeSystem; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; + using NUnit.Framework; using static ICSharpCode.Decompiler.Output.ConversionFlags; @@ -47,7 +49,8 @@ namespace ICSharpCode.Decompiler.Tests.Output ITypeDefinition GetDefinition(Type type) { - if (type == null) { + if (type == null) + { throw new ArgumentNullException(nameof(type)); } diff --git a/ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs b/ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs index 6077d6c15..81a3d6277 100644 --- a/ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PdbGenerationTestRunner.cs @@ -6,14 +6,17 @@ using System.Reflection.PortableExecutable; using System.Runtime.CompilerServices; using System.Text; using System.Xml.Linq; + using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Tests.Helpers; using ICSharpCode.Decompiler.TypeSystem; + using Microsoft.CodeAnalysis.CSharp; using Microsoft.DiaSymReader.Tools; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests @@ -58,17 +61,21 @@ namespace ICSharpCode.Decompiler.Tests var moduleDefinition = new PEFile(peFileName); var resolver = new UniversalAssemblyResolver(peFileName, false, moduleDefinition.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchEntireImage); var decompiler = new CSharpDecompiler(moduleDefinition, resolver, new DecompilerSettings()); - using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, testName + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite)) { + using (FileStream pdbStream = File.Open(Path.Combine(TestCasePath, testName + ".pdb"), FileMode.OpenOrCreate, FileAccess.ReadWrite)) + { pdbStream.SetLength(0); PortablePdbWriter.WritePdb(moduleDefinition, decompiler, new DecompilerSettings(), pdbStream, noLogo: true); pdbStream.Position = 0; using (Stream peStream = File.OpenRead(peFileName)) - using (Stream expectedPdbStream = File.OpenRead(pdbFileName)) { - using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(pdbFileName, ".xml"), false, Encoding.UTF8)) { + using (Stream expectedPdbStream = File.OpenRead(pdbFileName)) + { + using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(pdbFileName, ".xml"), false, Encoding.UTF8)) + { PdbToXmlConverter.ToXml(writer, expectedPdbStream, peStream, options); } peStream.Position = 0; - using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(xmlFile, ".generated.xml"), false, Encoding.UTF8)) { + using (StreamWriter writer = new StreamWriter(Path.ChangeExtension(xmlFile, ".generated.xml"), false, Encoding.UTF8)) + { PdbToXmlConverter.ToXml(writer, pdbStream, peStream, options); } } @@ -83,7 +90,8 @@ namespace ICSharpCode.Decompiler.Tests private void ProcessXmlFile(string fileName) { var document = XDocument.Load(fileName); - foreach (var file in document.Descendants("file")) { + foreach (var file in document.Descendants("file")) + { file.Attribute("checksum").Remove(); file.Attribute("embeddedSourceLength").Remove(); file.ReplaceNodes(new XCData(file.Value.Replace("\uFEFF", ""))); diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index c2dca9b37..03897a4c1 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -21,7 +21,9 @@ using System.CodeDom.Compiler; using System.IO; using System.Linq; using System.Runtime.CompilerServices; + using ICSharpCode.Decompiler.Tests.Helpers; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests @@ -38,9 +40,11 @@ namespace ICSharpCode.Decompiler.Tests .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any()) .Select(m => m.Name) .ToArray(); - foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) { + foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) + { if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase) - || file.Extension.Equals(".cs", StringComparison.OrdinalIgnoreCase)) { + || file.Extension.Equals(".cs", StringComparison.OrdinalIgnoreCase)) + { var testName = file.Name.Split('.')[0]; Assert.Contains(testName, testNames); } @@ -533,22 +537,26 @@ namespace ICSharpCode.Decompiler.Tests { var csFile = Path.Combine(TestCasePath, testName + ".cs"); var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".exe"; - if (cscOptions.HasFlag(CompilerOptions.Library)) { + if (cscOptions.HasFlag(CompilerOptions.Library)) + { exeFile = Path.ChangeExtension(exeFile, ".dll"); } // 1. Compile CompilerResults output = null; - try { + try + { output = Tester.CompileCSharp(csFile, cscOptions, exeFile); - } finally { + } + finally + { if (output != null) output.TempFiles.Delete(); } // 2. Decompile var decompiled = Tester.DecompileCSharp(exeFile, decompilerSettings ?? Tester.GetSettings(cscOptions)); - + // 3. Compile CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray()); } diff --git a/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs b/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs index d484714f8..c92f49c57 100644 --- a/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs +++ b/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs @@ -17,7 +17,9 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests diff --git a/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs b/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs index 2a1b99130..fade0cf68 100644 --- a/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs +++ b/ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs @@ -23,12 +23,15 @@ using System.Linq; using System.Reflection.PortableExecutable; using System.Text.RegularExpressions; using System.Threading; + using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Tests.Helpers; + using Microsoft.Build.Locator; using Microsoft.Win32; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests @@ -38,7 +41,7 @@ namespace ICSharpCode.Decompiler.Tests { public static readonly string TestDir = Path.GetFullPath(Path.Combine(Tester.TestCasePath, "../../ILSpy-tests")); static readonly string nunit = Path.Combine(TestDir, "nunit", "nunit3-console.exe"); - + [Test] public void Cecil_net45() { @@ -54,9 +57,12 @@ namespace ICSharpCode.Decompiler.Tests [Test] public void NewtonsoftJson_pcl_debug() { - try { + try + { RunWithTest("Newtonsoft.Json-pcl-debug", "Newtonsoft.Json.dll", "Newtonsoft.Json.Tests.dll", useOldProjectFormat: true); - } catch (CompilationFailedException) { + } + catch (CompilationFailedException) + { Assert.Ignore("Cannot yet re-compile PCL projects."); } } @@ -148,14 +154,16 @@ namespace ICSharpCode.Decompiler.Tests void RunInternal(string dir, string fileToRoundtrip, Action testAction, LanguageVersion languageVersion, string snkFilePath = null, bool useOldProjectFormat = false) { - if (!Directory.Exists(TestDir)) { + if (!Directory.Exists(TestDir)) + { Assert.Ignore($"Assembly-roundtrip test ignored: test directory '{TestDir}' needs to be checked out separately." + Environment.NewLine + - $"git clone https://github.com/icsharpcode/ILSpy-tests \"{TestDir}\""); + $"git clone https://github.com/icsharpcode/ILSpy-tests \"{TestDir}\""); } string inputDir = Path.Combine(TestDir, dir); string decompiledDir = inputDir + "-decompiled"; string outputDir = inputDir + "-output"; - if (inputDir.EndsWith("TestCases")) { + if (inputDir.EndsWith("TestCases")) + { // make sure output dir names are unique so that we don't get trouble due to parallel test execution decompiledDir += Path.GetFileNameWithoutExtension(fileToRoundtrip) + "_" + languageVersion.ToString(); outputDir += Path.GetFileNameWithoutExtension(fileToRoundtrip) + "_" + languageVersion.ToString(); @@ -163,16 +171,20 @@ namespace ICSharpCode.Decompiler.Tests ClearDirectory(decompiledDir); ClearDirectory(outputDir); string projectFile = null; - foreach (string file in Directory.EnumerateFiles(inputDir, "*", SearchOption.AllDirectories)) { - if (!file.StartsWith(inputDir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) { + foreach (string file in Directory.EnumerateFiles(inputDir, "*", SearchOption.AllDirectories)) + { + if (!file.StartsWith(inputDir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) + { Assert.Fail($"Unexpected file name: {file}"); } string relFile = file.Substring(inputDir.Length + 1); Directory.CreateDirectory(Path.Combine(outputDir, Path.GetDirectoryName(relFile))); - if (relFile.Equals(fileToRoundtrip, StringComparison.OrdinalIgnoreCase)) { + if (relFile.Equals(fileToRoundtrip, StringComparison.OrdinalIgnoreCase)) + { Console.WriteLine($"Decompiling {fileToRoundtrip}..."); Stopwatch w = Stopwatch.StartNew(); - using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) { + using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) + { PEFile module = new PEFile(file, fileStream, PEStreamOptions.PrefetchEntireImage); var resolver = new TestAssemblyResolver(file, inputDir, module.Reader.DetectTargetFrameworkId()); resolver.AddSearchDirectory(inputDir); @@ -182,25 +194,29 @@ namespace ICSharpCode.Decompiler.Tests var projectGuid = Guid.Parse("{127C83E4-4587-4CF9-ADCA-799875F3DFE6}"); var settings = new DecompilerSettings(languageVersion); - if (useOldProjectFormat) { + if (useOldProjectFormat) + { settings.UseSdkStyleProjectFormat = false; } var decompiler = new TestProjectDecompiler(projectGuid, resolver, settings); - if (snkFilePath != null) { + if (snkFilePath != null) + { decompiler.StrongNameKeyFile = Path.Combine(inputDir, snkFilePath); } decompiler.DecompileProject(module, decompiledDir); Console.WriteLine($"Decompiled {fileToRoundtrip} in {w.Elapsed.TotalSeconds:f2}"); projectFile = Path.Combine(decompiledDir, module.Name + ".csproj"); } - } else { + } + else + { File.Copy(file, Path.Combine(outputDir, relFile)); } } Assert.IsNotNull(projectFile, $"Could not find {fileToRoundtrip}"); - + Compile(projectFile, outputDir); testAction(outputDir); } @@ -208,19 +224,25 @@ namespace ICSharpCode.Decompiler.Tests static void ClearDirectory(string dir) { Directory.CreateDirectory(dir); - foreach (string subdir in Directory.EnumerateDirectories(dir)) { - for (int attempt = 0; ; attempt++) { - try { + foreach (string subdir in Directory.EnumerateDirectories(dir)) + { + for (int attempt = 0; ; attempt++) + { + try + { Directory.Delete(subdir, true); break; - } catch (IOException) { + } + catch (IOException) + { if (attempt >= 10) throw; Thread.Sleep(100); } } } - foreach (string file in Directory.EnumerateFiles(dir)) { + foreach (string file in Directory.EnumerateFiles(dir)) + { File.Delete(file); } } @@ -228,9 +250,9 @@ namespace ICSharpCode.Decompiler.Tests static string FindMSBuild() { string vsPath = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.VisualStudioSetup }) - .OrderByDescending(i => i.Version) + .OrderByDescending(i => i.Version) .FirstOrDefault() - ?.MSBuildPath; + ?.MSBuildPath; if (vsPath == null) throw new InvalidOperationException("Could not find MSBuild"); return Path.Combine(vsPath, "msbuild.exe"); @@ -247,16 +269,20 @@ namespace ICSharpCode.Decompiler.Tests info.EnvironmentVariables.Remove("Configuration"); info.EnvironmentVariables.Remove("Platform"); Console.WriteLine($"\"{info.FileName}\" {info.Arguments}"); - using (var p = Process.Start(info)) { + using (var p = Process.Start(info)) + { Regex errorRegex = new Regex(@"^[\w\d.\\-]+\(\d+,\d+\):"); string suffix = $" [{projectFile}]"; string line; - while ((line = p.StandardOutput.ReadLine()) != null) { - if (line.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) { + while ((line = p.StandardOutput.ReadLine()) != null) + { + if (line.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) + { line = line.Substring(0, line.Length - suffix.Length); } Match m = errorRegex.Match(line); - if (m.Success) { + if (m.Success) + { // Make path absolute so that it gets hyperlinked line = Path.GetDirectoryName(projectFile) + Path.DirectorySeparatorChar + line; } @@ -267,7 +293,7 @@ namespace ICSharpCode.Decompiler.Tests throw new CompilationFailedException($"Compilation of {Path.GetFileName(projectFile)} failed"); } } - + static void RunTest(string outputDir, string fileToTest) { var info = new ProcessStartInfo(nunit); @@ -277,9 +303,11 @@ namespace ICSharpCode.Decompiler.Tests info.UseShellExecute = false; info.RedirectStandardOutput = true; Console.WriteLine($"\"{info.FileName}\" {info.Arguments}"); - using (var p = Process.Start(info)) { + using (var p = Process.Start(info)) + { string line; - while ((line = p.StandardOutput.ReadLine()) != null) { + while ((line = p.StandardOutput.ReadLine()) != null) + { Console.WriteLine(line); } p.WaitForExit(); @@ -302,7 +330,7 @@ namespace ICSharpCode.Decompiler.Tests { } } - + class TestRunFailedException : Exception { public TestRunFailedException(string message) : base(message) diff --git a/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs b/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs index 9c7a43a4b..a6687124c 100644 --- a/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs +++ b/ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs @@ -20,21 +20,23 @@ using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Tests.TypeSystem; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Semantics { // assign short names to the fake reflection types - using Null = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Null; + using C = Conversion; using dynamic = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Dynamic; - using nuint = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.NUInt; using nint = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.NInt; - using C = Conversion; + using nuint = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.NUInt; + using Null = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Null; [TestFixture, Parallelizable(ParallelScope.All)] public unsafe class ConversionTest diff --git a/ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs b/ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs index 415ddcb05..f2bb2b440 100644 --- a/ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs +++ b/ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs @@ -19,17 +19,19 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Tests.TypeSystem; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Semantics { - using dynamic = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Dynamic; using C = Conversion; + using dynamic = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Dynamic; [TestFixture, Parallelizable(ParallelScope.All)] public class ExplicitConversionsTest @@ -40,8 +42,8 @@ namespace ICSharpCode.Decompiler.Tests.Semantics [OneTimeSetUp] public void SetUp() { - compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly, - TypeSystemLoaderTests.Mscorlib, + compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly, + TypeSystemLoaderTests.Mscorlib, TypeSystemLoaderTests.SystemCore); conversions = new CSharpConversions(compilation); } diff --git a/ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs b/ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs index c5143907b..46b297807 100644 --- a/ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs +++ b/ICSharpCode.Decompiler.Tests/Semantics/OverloadResolutionTests.cs @@ -20,11 +20,13 @@ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Tests.TypeSystem; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Semantics @@ -37,8 +39,8 @@ namespace ICSharpCode.Decompiler.Tests.Semantics [OneTimeSetUp] public void SetUp() { - compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly, - TypeSystemLoaderTests.Mscorlib, + compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly, + TypeSystemLoaderTests.Mscorlib, TypeSystemLoaderTests.SystemCore); } @@ -53,7 +55,8 @@ namespace ICSharpCode.Decompiler.Tests.Semantics var m = new FakeMethod(compilation, SymbolKind.Method); m.Name = "Method"; var parameters = new List(); - foreach (var typeOrDefaultValue in parameterTypesOrDefaultValues) { + foreach (var typeOrDefaultValue in parameterTypesOrDefaultValues) + { Type type = typeOrDefaultValue as Type; if (type != null) parameters.Add(new DefaultParameter(compilation.FindType(type), string.Empty, owner: m)); @@ -77,7 +80,7 @@ namespace ICSharpCode.Decompiler.Tests.Semantics m.Parameters = parameters; return m; } - + [Test] public void PreferIntOverUInt() { @@ -320,15 +323,16 @@ namespace ICSharpCode.Decompiler.Tests.Semantics var container = compilation.FindType(typeof(BetterFunctionMemberIsNotTransitiveTestCase)).GetDefinition(); var args = new ResolveResult[] { - new MockLambda(compilation.FindType(KnownTypeCode.String)) { parameters = { new DefaultParameter(SpecialType.UnknownType, "arg") } } + new MockLambda(compilation.FindType(KnownTypeCode.String)) { parameters = { new DefaultParameter(SpecialType.UnknownType, "arg") } } }; OverloadResolution r = new OverloadResolution(compilation, args); - foreach (var method in container.GetMethods(m => m.Name == "Method")) { + foreach (var method in container.GetMethods(m => m.Name == "Method")) + { Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(method)); } - Assert.AreEqual(container.GetMethods(m => m.Name == "Method").Last(), r.BestCandidate); + Assert.AreEqual(container.GetMethods(m => m.Name == "Method").Last(), r.BestCandidate); } class BetterFunctionMemberIsNotTransitiveTestCase diff --git a/ICSharpCode.Decompiler.Tests/TestAssemblyResolver.cs b/ICSharpCode.Decompiler.Tests/TestAssemblyResolver.cs index d97c6d526..49c650270 100644 --- a/ICSharpCode.Decompiler.Tests/TestAssemblyResolver.cs +++ b/ICSharpCode.Decompiler.Tests/TestAssemblyResolver.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.Tests @@ -15,7 +16,8 @@ namespace ICSharpCode.Decompiler.Tests : base(mainAssemblyFileName, false, targetFramework, PEStreamOptions.PrefetchMetadata, MetadataReaderOptions.ApplyWindowsRuntimeProjections) { var assemblyNames = new DirectoryInfo(baseDir).EnumerateFiles("*.dll").Select(f => Path.GetFileNameWithoutExtension(f.Name)); - foreach (var name in assemblyNames) { + foreach (var name in assemblyNames) + { localAssemblies.Add(name); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Async.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Async.cs index 842a90900..f48cabafe 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Async.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Async.cs @@ -44,9 +44,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness await AwaitMultipleCatchBlocks(Task.FromResult(1)); await AwaitMultipleCatchBlocks2(Task.FromResult(1)); Console.WriteLine(await AwaitInComplexFinally()); - try { + try + { await AwaitFinally(Task.FromResult(2)); - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex + " caught!"); } #endif @@ -75,7 +78,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness byte[] array = new byte[bufferSize]; int count; Console.WriteLine("BeforeLoop"); - while ((count = await destination.ReadAsync(array, 0, array.Length)) != 0) { + while ((count = await destination.ReadAsync(array, 0, array.Length)) != 0) + { Console.WriteLine("In Loop after condition!"); await destination.WriteAsync(array, 0, count); Console.WriteLine("In Loop after inner await"); @@ -89,7 +93,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness byte[] array = new byte[bufferSize]; int count; Console.WriteLine("Before Loop"); - while ((count = await destination.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0) { + while ((count = await destination.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0) + { Console.WriteLine("Before Inner Await"); await destination.WriteAsync(array, 0, count).ConfigureAwait(false); Console.WriteLine("After Inner Await"); @@ -101,7 +106,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { int num = 0; Console.WriteLine("Before Loop"); - foreach (Task current in elements) { + foreach (Task current in elements) + { Console.WriteLine("Before Inner Await"); num += await current; Console.WriteLine("After Inner Await"); @@ -112,11 +118,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public async Task TaskMethodWithoutAwaitButWithExceptionHandling() { - try { - using (new StringWriter()) { + try + { + using (new StringWriter()) + { Console.WriteLine("No Await"); } - } catch (Exception) { + } + catch (Exception) + { Console.WriteLine("Crash"); } } @@ -124,23 +134,31 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness #if CS60 public async Task AwaitCatch(Task task) { - try { + try + { Console.WriteLine("Before throw"); throw new Exception(); - } catch { + } + catch + { Console.WriteLine(await task); } } public async Task AwaitMultipleCatchBlocks(Task task) { - try { + try + { Console.WriteLine("Before throw"); throw new Exception(); - } catch (OutOfMemoryException ex) { + } + catch (OutOfMemoryException ex) + { Console.WriteLine(ex.ToString()); Console.WriteLine(await task); - } catch { + } + catch + { Console.WriteLine(await task); } } @@ -148,25 +166,35 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public async Task AwaitMultipleCatchBlocks2(Task task) { - try { + try + { Console.WriteLine("Before throw"); throw new Exception(); - } catch (OutOfMemoryException ex) { + } + catch (OutOfMemoryException ex) + { Console.WriteLine(ex.ToString()); Console.WriteLine(await task); - } catch (InternalBufferOverflowException ex) { + } + catch (InternalBufferOverflowException ex) + { Console.WriteLine(ex.ToString()); - } catch { + } + catch + { Console.WriteLine(await task); } } public async Task AwaitFinally(Task task) { - try { + try + { Console.WriteLine("Before throw"); throw new Exception(); - } finally { + } + finally + { Console.WriteLine(await task); } } @@ -184,9 +212,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public async Task AwaitWithStack2(Task task) { - if (await this.SimpleBoolTaskMethod()) { + if (await this.SimpleBoolTaskMethod()) + { Console.WriteLine("A", 1, await task); - } else { + } + else + { int num = 1; Console.WriteLine("A", 1, num); } @@ -195,11 +226,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness #if CS60 public async Task AwaitInCatch(Task task1, Task task2) { - try { + try + { Console.WriteLine("Start try"); await task1; Console.WriteLine("End try"); - } catch (Exception) { + } + catch (Exception) + { Console.WriteLine("Start catch"); await task2; Console.WriteLine("End catch"); @@ -209,11 +243,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public async Task AwaitInFinally(Task task1, Task task2) { - try { + try + { Console.WriteLine("Start try"); await task1; Console.WriteLine("End try"); - } finally { + } + finally + { Console.WriteLine("Start finally"); await task2; Console.WriteLine("End finally"); @@ -224,20 +261,29 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static async Task AwaitInComplexFinally() { Console.WriteLine("a"); - try { + try + { Console.WriteLine("b"); await Task.Delay(1); Console.WriteLine("c"); - } catch (Exception ex) { + } + catch (Exception ex) + { await Task.Delay(ex.HResult); - } finally { + } + finally + { Console.WriteLine("d"); int i = 0; - if (Console.CapsLock) { + if (Console.CapsLock) + { i++; await Task.Delay(i); - } else { - while (i < 5) { + } + else + { + while (i < 5) + { Console.WriteLine("i: " + i); i++; } @@ -250,15 +296,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public async Task AwaitInCatchAndFinally(Task task1, Task task2, Task task3) { - try { + try + { Console.WriteLine("Start try"); await task1; Console.WriteLine("End try"); - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine("Start catch"); await task2; Console.WriteLine("End catch"); - } finally { + } + finally + { Console.WriteLine("Start finally"); await task3; Console.WriteLine("End finally"); @@ -268,12 +319,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public async Task AwaitInFinallyInUsing(Task task1, Task task2, Task task3) { - using (await task1) { + using (await task1) + { Console.WriteLine("Start using"); - try { + try + { Console.WriteLine("Before return"); return await task2; - } finally { + } + finally + { Console.WriteLine("Start finally"); await task3; Console.WriteLine("End finally"); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Capturing.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Capturing.cs index 27f95114a..6ba1ed9c3 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Capturing.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Capturing.cs @@ -31,7 +31,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness List actions = new List(); int max = 5; string line; - while (ReadLine(out line, ref max)) { + while (ReadLine(out line, ref max)) + { actions.Add(() => Console.WriteLine(line)); } // line still declared @@ -47,7 +48,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness List actions = new List(); int max = 5; string line; - while (ReadLine(out line, ref max)) { + while (ReadLine(out line, ref max)) + { string capture = line; actions.Add(() => Console.WriteLine(capture)); } @@ -64,7 +66,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness List actions = new List(); int max = 5; string line, capture; - while (ReadLine(out line, ref max)) { + while (ReadLine(out line, ref max)) + { capture = line; actions.Add(() => Console.WriteLine(capture)); } @@ -96,16 +99,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("OutsideLoop"); var list = new List { 1, 2, 3 }; var functions = new List>(); - using (var e = list.GetEnumerator()) { + using (var e = list.GetEnumerator()) + { int val; // declared outside loop // The decompiler cannot convert this to a foreach-loop without // changing the lambda capture semantics. - while (e.MoveNext()) { + while (e.MoveNext()) + { val = e.Current; functions.Add(() => val); } } - foreach (var func in functions) { + foreach (var func in functions) + { Console.WriteLine(func()); } } @@ -115,13 +121,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("InsideLoop"); var list = new List { 1, 2, 3 }; var functions = new List>(); - using (var e = list.GetEnumerator()) { - while (e.MoveNext()) { + using (var e = list.GetEnumerator()) + { + while (e.MoveNext()) + { int val = e.Current; functions.Add(() => val); } } - foreach (var func in functions) { + foreach (var func in functions) + { Console.WriteLine(func()); } } @@ -134,11 +143,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness int val; // declared outside loop // The decompiler cannot convert this to a foreach-loop without // changing the lambda capture semantics. - for (int i = 0; i < array.Length; ++i) { + for (int i = 0; i < array.Length; ++i) + { val = array[i]; functions.Add(() => val); } - foreach (var func in functions) { + foreach (var func in functions) + { Console.WriteLine(func()); } } @@ -151,12 +162,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness int val; // declared outside loop // The decompiler can convert this to a foreach-loop, but the 'val' // variable must be declared outside. - for (int i = 0; i < array.Length; ++i) { + for (int i = 0; i < array.Length; ++i) + { int element = array[i]; val = element * 2; functions.Add(() => val); } - foreach (var func in functions) { + foreach (var func in functions) + { Console.WriteLine(func()); } } @@ -166,12 +179,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("InsideLoopOverArray2:"); var functions = new List>(); var array = new int[] { 1, 2, 3 }; - for (int i = 0; i < array.Length; ++i) { + for (int i = 0; i < array.Length; ++i) + { int element = array[i]; int val = element * 2; functions.Add(() => val); } - foreach (var func in functions) { + foreach (var func in functions) + { Console.WriteLine(func()); } } @@ -187,13 +202,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { Console.WriteLine("NotWhileDueToVariableInsideLoop:"); var functions = new List>(); - while (true) { + while (true) + { int v; if ((v = GetVal()) == 0) break; functions.Add(() => v); } - foreach (var f in functions) { + foreach (var f in functions) + { Console.WriteLine(f()); } } @@ -202,13 +219,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { Console.WriteLine("NotDoWhileDueToVariableInsideLoop:"); var functions = new List>(); - while (true) { + while (true) + { int v = GetVal(); functions.Add(() => v); if (v == 0) break; } - foreach (var f in functions) { + foreach (var f in functions) + { Console.WriteLine(f()); } } @@ -216,7 +235,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void Issue1936() { IEnumerable outerCapture = null; - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) + { int innerCapture = 0; Action a = (delegate { List list = new List(); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Comparisons.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Comparisons.cs index 276d75223..3bacfa9fa 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Comparisons.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Comparisons.cs @@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness TestFloatOp("!>", (a, b) => !(a > b)); TestFloatOp("!<=", (a, b) => !(a <= b)); TestFloatOp("!>=", (a, b) => !(a >= b)); - + TestUInt(0); TestUInt(uint.MaxValue); TestUShort(0); @@ -50,12 +50,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine(NullIsNot(new OverloadedOperators())); return 0; } - + static void TestFloatOp(string name, Func f) { float[] vals = { -1, 0, 3, float.PositiveInfinity, float.NaN }; - for (int i = 0; i < vals.Length; i++) { - for (int j = 0; j < vals.Length; j++) { + for (int i = 0; i < vals.Length; i++) + { + for (int j = 0; j < vals.Length; j++) + { Console.WriteLine("Float: {0} {1} {2:r} = {3}", vals[i].ToString("r", CultureInfo.InvariantCulture), name, @@ -64,12 +66,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness } } } - + static T Id(T arg) { return arg; } - + static void TestUShort(ushort i) { Console.WriteLine("ushort: {0} == ushort.MaxValue = {1}", i, i == ushort.MaxValue); @@ -77,7 +79,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("ushort: {0} == Id(-1) = {1}", i, i == Id(-1)); Console.WriteLine("ushort: {0} == 0x1ffff = {1}", i, i == 0x1ffff); } - + static void TestUInt(uint i) { Console.WriteLine("uint: {0} == uint.MaxValue = {1}", i, i == uint.MaxValue); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs index ee9bbb0af..6e4f2697d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs @@ -50,11 +50,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static int instanceCount; int instanceNumber = ++instanceCount; - + int instanceField; - public int InstanceProperty - { + public int InstanceProperty { get { Console.WriteLine("In {0}.get_InstanceProperty", instanceNumber); return instanceField; @@ -67,8 +66,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static int staticField; - public static int StaticProperty - { + public static int StaticProperty { get { Console.WriteLine("In get_StaticProperty"); return staticField; @@ -203,18 +201,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("Overflow:"); ByteProperty = 0; ByteProperty = (byte)checked(ByteProperty + 300); - try { + try + { ByteProperty = checked((byte)(ByteProperty + 300)); - } catch (OverflowException) { + } + catch (OverflowException) + { Console.WriteLine("Overflow OK"); } ByteProperty = 200; ByteProperty = (byte)checked(ByteProperty + 100); ByteProperty = 201; - try { + try + { ByteProperty = checked((byte)(ByteProperty + 100)); - } catch (OverflowException) { + } + catch (OverflowException) + { Console.WriteLine("Overflow OK"); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/ControlFlow.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/ControlFlow.cs index 3e4c55f9d..8a12ae0cd 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/ControlFlow.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/ControlFlow.cs @@ -47,7 +47,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void EmptyIf(string input, ref int result) { - if (input.Contains("test")) { + if (input.Contains("test")) + { } result = result + 1; Console.WriteLine("EmptyIf"); @@ -55,9 +56,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void NormalIf(string input, ref int result) { - if (input.Contains("test")) { + if (input.Contains("test")) + { Console.WriteLine("result"); - } else { + } + else + { Console.WriteLine("else"); } result = result + 1; @@ -66,7 +70,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void NormalIf2(string input, ref int result) { - if (input.Contains("test")) { + if (input.Contains("test")) + { Console.WriteLine("result"); } result = result + 1; @@ -75,9 +80,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void NormalIf3(string input, ref int result) { - if (input.Contains("test")) { + if (input.Contains("test")) + { Console.WriteLine("result"); - } else { + } + else + { Console.WriteLine("else"); } result = result + 1; @@ -85,13 +93,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void Test(string input, ref int result) { - foreach (char c in input) { + foreach (char c in input) + { Console.Write(c); result = result + 1; } - if (input.Contains("test")) { + if (input.Contains("test")) + { Console.WriteLine("result"); - } else { + } + else + { Console.WriteLine("else"); } } @@ -101,8 +113,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness var tens = new[] { 10, 20, 30 }; var ones = new[] { 1, 2, 3 }; - for (int i = 0; i < tens.Length; i++) { - for (int j = 0; j < ones.Length; j++) { + for (int i = 0; i < tens.Length; i++) + { + for (int j = 0; j < ones.Length; j++) + { if (tens[i] + ones[j] == arg) return i; } @@ -114,7 +128,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void ForeachWithAssignment(IEnumerable inputs) { Console.WriteLine("ForeachWithAssignment"); - foreach (int input in inputs) { + foreach (int input in inputs) + { int i = input; if (i < 10) i *= 2; @@ -125,11 +140,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void BreakUnlessContinue(bool b) { Console.WriteLine("BreakUnlessContinue({0})", b); - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) + { if ((i % 3) == 0) continue; Console.WriteLine(i); - if (b) { + if (b) + { Console.WriteLine("continuing"); continue; } @@ -154,11 +171,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static string Issue1946() { string obj = "1"; - try { + try + { obj = "2"; - } catch { + } + catch + { obj = "3"; - } finally { + } + finally + { obj = "4"; } return obj; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs index b8f4d0430..01b76929d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Conversions.cs @@ -19,6 +19,7 @@ // #include "../../../ICSharpCode.Decompiler/Util/CSharpPrimitiveCast.cs" using System; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -39,48 +40,48 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness TypeCode.Double, TypeCode.Decimal }; - + static object[] inputValues = { '\0', 'a', '\uFFFE', - + sbyte.MinValue, sbyte.MaxValue, (sbyte)-1, (sbyte)1, - + byte.MinValue, byte.MaxValue, (byte)1, - + short.MinValue, short.MaxValue, (short)-1, (short)1, - + ushort.MinValue, ushort.MaxValue, (ushort)1, - + int.MinValue, int.MaxValue, (int)-1, (int)1, - + uint.MinValue, uint.MaxValue, (uint)1, - + long.MinValue, long.MaxValue, (long)-1, (long)1, - + ulong.MinValue, ulong.MaxValue, (ulong)1, - + -1.1f, 1.1f, float.MinValue, @@ -88,7 +89,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness float.NegativeInfinity, float.PositiveInfinity, float.NaN, - + -1.1, 1.1, double.MinValue, @@ -96,64 +97,72 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness double.NegativeInfinity, double.PositiveInfinity, double.NaN, - + decimal.MinValue, decimal.MaxValue, decimal.MinusOne, decimal.One }; - + static void Main(string[] args) { RunTest(checkForOverflow: false); RunTest(checkForOverflow: true); - + Console.WriteLine(ReadZeroTerminatedString("Hello World!".Length)); C1.Test(); } - + static void RunTest(bool checkForOverflow) { string mode = checkForOverflow ? "checked" : "unchecked"; - foreach (object input in inputValues) { + foreach (object input in inputValues) + { string inputType = input.GetType().Name; - foreach (var targetType in targetTypes) { - try { + foreach (var targetType in targetTypes) + { + try + { object result = CSharpPrimitiveCast.Cast(targetType, input, checkForOverflow); Console.WriteLine("{0} ({1})({2}){3} = ({4}){5}", mode, targetType, inputType, input, - result.GetType().Name, result); - } catch (Exception ex) { + result.GetType().Name, result); + } + catch (Exception ex) + { Console.WriteLine("{0} ({1})({2}){3} = {4}", mode, targetType, inputType, input, - ex.GetType().Name); + ex.GetType().Name); } } } } - + static object MM(sbyte c) { - checked { + checked + { return (UInt64)c; } } - - static string ReadZeroTerminatedString (int length) + + static string ReadZeroTerminatedString(int length) { int read = 0; - var buffer = new char [length]; - var bytes = ReadBytes (length); - while (read < length) { - var current = bytes [read]; + var buffer = new char[length]; + var bytes = ReadBytes(length); + while (read < length) + { + var current = bytes[read]; if (current == 0) break; - buffer [read++] = (char) current; + buffer[read++] = (char)current; } - return new string (buffer, 0, read); + return new string(buffer, 0, read); } - - static byte[] ReadBytes(int length) { + + static byte[] ReadBytes(int length) + { return System.Text.Encoding.ASCII.GetBytes("Hello World!"); } } @@ -176,7 +185,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { Console.WriteLine(((Type)c).Name); } - + static Type ChainedImplicitConversions(C2 c) { return (C1)c; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/DecimalFields.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/DecimalFields.cs index 6a2d57816..f3873bc38 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/DecimalFields.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/DecimalFields.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public const decimal field2 = decimal.One; public const decimal field3 = decimal.MaxValue; public const decimal field4 = decimal.MinValue; - + public static int Main() { Console.WriteLine(field1); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/DeconstructionTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/DeconstructionTests.cs index f27372aca..ad8901f77 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/DeconstructionTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/DeconstructionTests.cs @@ -194,10 +194,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public void NullReferenceException_Field_Deconstruction(out int a) { - try { + try + { AssignmentTargets t0 = null; (t0.IntField, a) = GetSource(); - } catch (Exception ex) { + } + catch (Exception ex) + { a = 0; Console.WriteLine(ex.GetType().FullName); } @@ -205,11 +208,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public void NullReferenceException_RefLocalReferencesField_Deconstruction(out int a) { - try { + try + { AssignmentTargets t0 = null; ref int i = ref t0.IntField; (i, a) = GetSource(); - } catch (Exception ex) { + } + catch (Exception ex) + { a = 0; Console.WriteLine(ex.GetType().FullName); } @@ -217,10 +223,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public void NullReferenceException_RefLocalReferencesArrayElement_Deconstruction(out int a, int[] arr) { - try { + try + { ref int i = ref arr[0]; (i, a) = GetSource(); - } catch (Exception ex) { + } + catch (Exception ex) + { a = 0; Console.WriteLine(ex.GetType().FullName); } @@ -238,7 +247,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public void DeconstructTupleListForEachSameVar(List<(string, string)> tuples) { Console.WriteLine("DeconstructTupleListForEachSameVar:"); - foreach (var tuple in tuples) { + foreach (var tuple in tuples) + { string a; a = tuple.Item1; a = tuple.Item2; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/FloatingPointArithmetic.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/FloatingPointArithmetic.cs index e5a8fa9f3..0eeadc4e0 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/FloatingPointArithmetic.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/FloatingPointArithmetic.cs @@ -91,7 +91,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void CxAssert(bool v) { - if (!v) { + if (!v) + { throw new InvalidOperationException(); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Generics.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Generics.cs index df65be4f2..6535fa0bc 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Generics.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Generics.cs @@ -37,18 +37,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { return default(T); } - + public static void TestGenericParam() { Console.WriteLine(typeof(T)); } - + public static void TestGenericParam() { Console.WriteLine(typeof(T1) + " " + typeof(T2)); } } - + class GenericClass { public void M(out GenericClass self) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/InitializerTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/InitializerTests.cs index 9ab986685..5a73eab99 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/InitializerTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/InitializerTests.cs @@ -52,36 +52,30 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness private class Data { public List FieldList = new List(); - public InitializerTests.MyEnum a - { + public InitializerTests.MyEnum a { get; set; } - public InitializerTests.MyEnum b - { + public InitializerTests.MyEnum b { get; set; } - public List PropertyList - { + public List PropertyList { get; set; } - public InitializerTests.Data MoreData - { + public InitializerTests.Data MoreData { get; set; } - public InitializerTests.StructData NestedStruct - { + public InitializerTests.StructData NestedStruct { get; set; } - public InitializerTests.Data this[int i] - { + public InitializerTests.Data this[int i] { get { return null; } @@ -99,14 +93,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness private struct StructData { public int Field; - public int Property - { + public int Property { get; set; } - public InitializerTests.Data MoreData - { + public InitializerTests.Data MoreData { get; set; } @@ -191,8 +183,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void ObjectInitializer() { - InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data - { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data { a = InitializerTests.MyEnum.a }); } @@ -206,8 +197,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void ObjectInitializerAssignCollectionToField() { - InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data - { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data { a = InitializerTests.MyEnum.a, FieldList = new List { @@ -219,8 +209,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void ObjectInitializerAddToCollectionInField() { - InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data - { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data { a = InitializerTests.MyEnum.a, FieldList = { @@ -232,8 +221,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void ObjectInitializerAssignCollectionToProperty() { - InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data - { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data { a = InitializerTests.MyEnum.a, PropertyList = new List { @@ -245,8 +233,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void ObjectInitializerAddToCollectionInProperty() { - InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data - { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data { a = InitializerTests.MyEnum.a, PropertyList = { @@ -258,8 +245,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void ObjectInitializerWithInitializationOfNestedObjects() { - InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data - { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data { MoreData = { a = InitializerTests.MyEnum.a, @@ -342,8 +328,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void StructInitializer_DefaultConstructor() { - InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData - { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData { Field = 1, Property = 2 }); @@ -359,8 +344,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void StructInitializer_ExplicitConstructor() { - InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData(0) - { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData(0) { Field = 1, Property = 2 }); @@ -368,8 +352,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void StructInitializerWithInitializationOfNestedObjects() { - InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData - { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData { MoreData = { a = InitializerTests.MyEnum.a, @@ -384,10 +367,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void StructInitializerWithinObjectInitializer() { - InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data - { - NestedStruct = new InitializerTests.StructData(2) - { + InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data { + NestedStruct = new InitializerTests.StructData(2) { Field = 1, Property = 2 } @@ -435,7 +416,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness int num = 0; - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 2; i++) + { if (num < 10) items.SetItem(num, Item(string.Empty, new Data { Obj = null })); } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/LINQRaytracer.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/LINQRaytracer.cs index c18201788..84bf9ef6c 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/LINQRaytracer.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/LINQRaytracer.cs @@ -1,8 +1,8 @@ // This test case is taken from https://blogs.msdn.microsoft.com/lukeh/2007/10/01/taking-linq-to-objects-to-extremes-a-fully-linqified-raytracer/ -using System.Linq; using System; using System.Collections.Generic; +using System.Linq; namespace RayTracer { @@ -333,13 +333,17 @@ namespace RayTracer Vector eo = Vector.Minus(Center, ray.Start); double v = Vector.Dot(eo, ray.Dir); double dist; - if (v < 0) { + if (v < 0) + { dist = 0; - } else { + } + else + { double disc = Math.Pow(Radius, 2) - (Vector.Dot(eo, eo) - Math.Pow(v, 2)); dist = disc < 0 ? 0 : v - Math.Sqrt(disc); } - if (dist == 0) return null; + if (dist == 0) + return null; return new ISect() { Thing = this, Ray = ray, @@ -361,7 +365,8 @@ namespace RayTracer public override ISect Intersect(Ray ray) { double denom = Vector.Dot(Norm, ray.Dir); - if (denom > 0) return null; + if (denom > 0) + return null; return new ISect() { Thing = this, Ray = ray, diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs index e9468ccec..e1373d9a8 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Loops.cs @@ -41,7 +41,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public bool MoveNext() { - if (next) { + if (next) + { next = false; return true; } @@ -87,7 +88,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { int x, y; Console.WriteLine("before for"); - for (x = y = 0; x < 10; x++) { + for (x = y = 0; x < 10; x++) + { y++; Console.WriteLine("x = " + x + ", y = " + y); } @@ -97,11 +99,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void DoubleForEachWithSameVariable(IEnumerable enumerable) { Console.WriteLine("DoubleForEachWithSameVariable:"); - foreach (string current in enumerable) { + foreach (string current in enumerable) + { Console.WriteLine(current.ToLower()); } Console.WriteLine("after first loop"); - foreach (string current in enumerable) { + foreach (string current in enumerable) + { Console.WriteLine(current.ToUpper()); } Console.WriteLine("after second loop"); @@ -111,8 +115,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { Console.WriteLine("ForeachWithNameCollision:"); int current; - using (IEnumerator enumerator = inputs.GetEnumerator()) { - while (enumerator.MoveNext()) { + using (IEnumerator enumerator = inputs.GetEnumerator()) + { + while (enumerator.MoveNext()) + { current = enumerator.Current; Console.WriteLine(current); } @@ -125,8 +131,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { Console.WriteLine("ForeachExceptForContinuedUse"); int num = 0; - using (IEnumerator enumerator = inputs.GetEnumerator()) { - while (enumerator.MoveNext()) { + using (IEnumerator enumerator = inputs.GetEnumerator()) + { + while (enumerator.MoveNext()) + { num = enumerator.Current; Console.WriteLine(num); } @@ -138,15 +146,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { Console.WriteLine("NonGenericForeachWithReturnFallback:"); IEnumerator enumerator = e.GetEnumerator(); - try { + try + { Console.WriteLine("MoveNext"); - if (enumerator.MoveNext()) { + if (enumerator.MoveNext()) + { object current = enumerator.Current; Console.WriteLine("current: " + current); } - } finally { + } + finally + { IDisposable disposable = enumerator as IDisposable; - if (disposable != null) { + if (disposable != null) + { disposable.Dispose(); } } @@ -156,7 +169,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static object NonGenericForeachWithReturn(IEnumerable enumerable) { Console.WriteLine("NonGenericForeachWithReturn:"); - foreach (var obj in enumerable) { + foreach (var obj in enumerable) + { Console.WriteLine("return: " + obj); return obj; } @@ -168,7 +182,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static int? ForeachWithReturn(IEnumerable enumerable) { Console.WriteLine("ForeachWithReturn:"); - foreach (var obj in enumerable) { + foreach (var obj in enumerable) + { Console.WriteLine("return: " + obj); return obj; } @@ -180,7 +195,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void ForeachWithRefUsage(List items) { Console.WriteLine("ForeachWithRefUsage:"); - foreach (var item in items) { + foreach (var item in items) + { var itemToChange = item; Console.WriteLine("item: " + item); Operation(ref itemToChange); @@ -191,7 +207,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static T FirstOrDefault(IEnumerable items) { T result = default(T); - foreach (T item in items) { + foreach (T item in items) + { result = item; break; } @@ -202,8 +219,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { Console.WriteLine("NoForeachDueToMultipleCurrentAccess:"); T result = default(T); - using (IEnumerator enumerator = items.GetEnumerator()) { - while (enumerator.MoveNext()) { + using (IEnumerator enumerator = items.GetEnumerator()) + { + while (enumerator.MoveNext()) + { result = enumerator.Current; Console.WriteLine("result: " + result); } @@ -214,14 +233,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static T NoForeachCallWithSideEffect(CustomClassEnumeratorWithIDisposable items) { Console.WriteLine("NoForeachCallWithSideEffect:"); - using (CustomClassEnumeratorWithIDisposable enumerator = items.GetEnumerator()) { - while (enumerator.MoveNext()) { + using (CustomClassEnumeratorWithIDisposable enumerator = items.GetEnumerator()) + { + while (enumerator.MoveNext()) + { T result = enumerator.Current; } return CallWithSideEffect(); } } - + static bool GetBool(string text) { return false; @@ -231,31 +252,39 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void LoopWithGotoRepeat() { Console.WriteLine("LoopWithGotoRepeat:"); - try { + try + { REPEAT: Console.WriteLine("after repeat label"); - while (GetBool("Loop condition")) { - if (GetBool("if1")) { - if (GetBool("if3")) { + while (GetBool("Loop condition")) + { + if (GetBool("if1")) + { + if (GetBool("if3")) + { goto REPEAT; } break; } } Console.WriteLine("after loop"); - } finally { + } + finally + { Console.WriteLine("finally"); } Console.WriteLine("after finally"); } - + private static int LoopFollowedByIf() { int num = 0; - while (num == 0) { + while (num == 0) + { num++; } - if (num == 0) { + if (num == 0) + { return -1; } return num; @@ -263,9 +292,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void Issue1392ForWithNestedSwitchPlusGoto() { - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 100; i++) + { again: - switch (i) { + switch (i) + { case 10: Console.WriteLine("10"); break; @@ -281,13 +312,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness private static void NoForeachDueToVariableAssignment() { - try { + try + { int[] array = new int[] { 1, 2, 3 }; - for (int i = 0; i < array.Length; i++) { + for (int i = 0; i < array.Length; i++) + { Console.WriteLine(array[i]); array = null; } - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.GetType() + ": " + ex.Message); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/MemberLookup.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/MemberLookup.cs index d41b30775..5a8b3be7b 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/MemberLookup.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/MemberLookup.cs @@ -23,7 +23,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public class MemberLookup { static readonly Action delegateConstruction = (new Child1() as Base1).TestAction; - + public static int Main() { Console.WriteLine((new Child1() as Base1).Field); @@ -32,49 +32,49 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness new Child2b().CallTestMethod(); return 0; } - + class Base1 { public int Field = 1; - + protected virtual void TestMethod() { Property = 5; Console.WriteLine("Base1.TestMethod()"); Console.WriteLine(Property); } - + public void TestAction() { Console.WriteLine("Base1.TestAction()"); } - + public int Property { get; set; } - + public virtual int VirtProp { get { return 3; } } } - + class Child1 : Base1 { Child1 child; new public int Field = 2; - + public static void Test() { var o = new Child1(); o.child = new Child1(); o.TestMethod(); - + Console.WriteLine(((Base1)o).Property); Console.WriteLine(o.Property); Console.WriteLine(((Base1)o).VirtProp); Console.WriteLine(o.VirtProp); } - + protected override void TestMethod() { Property = 10; @@ -86,14 +86,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("Field = " + Field); Console.WriteLine("base.Field = " + base.Field); } - + new public void TestAction() { Console.WriteLine("Child1.TestAction()"); } - + new public int Property { get; set; } - + public override int VirtProp { get { return base.VirtProp * 2; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/MiniJSON.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/MiniJSON.cs index 5feddd8a1..be81da823 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/MiniJSON.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/MiniJSON.cs @@ -9,30 +9,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness // taken from https://github.com/Jackyjjc/MiniJSON.cs // Copyright (c) 2013 Calvin Rien. // Licensed under the MIT LICENSE. - public class MiniJSONTest { - public static void Main(string[] args) { - var jsonString = "{ \"array\": [1.44,2,3], " + - "\"object\": {\"key1\":\"value1\", \"key2\":256}, " + - "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " + - "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " + - "\"int\": 65536, " + - "\"float\": 3.1415926, " + - "\"bool\": true, " + - "\"null\": null }"; - - var dict = Json.Deserialize(jsonString) as Dictionary; - - Console.WriteLine("deserialized: " + dict.GetType()); - Console.WriteLine("dict['array'][0]: " + ((List) dict["array"])[0]); - Console.WriteLine("dict['string']: " + (string) dict["string"]); - Console.WriteLine("dict['float']: " + (double) dict["float"]); // floats come out as doubles - Console.WriteLine("dict['int']: " + (long) dict["int"]); // ints come out as longs - Console.WriteLine("dict['unicode']: " + (string) dict["unicode"]); - - var str = Json.Serialize(dict); - - Console.WriteLine("serialized: " + str); - } + public class MiniJSONTest + { + public static void Main(string[] args) + { + var jsonString = "{ \"array\": [1.44,2,3], " + + "\"object\": {\"key1\":\"value1\", \"key2\":256}, " + + "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " + + "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " + + "\"int\": 65536, " + + "\"float\": 3.1415926, " + + "\"bool\": true, " + + "\"null\": null }"; + + var dict = Json.Deserialize(jsonString) as Dictionary; + + Console.WriteLine("deserialized: " + dict.GetType()); + Console.WriteLine("dict['array'][0]: " + ((List)dict["array"])[0]); + Console.WriteLine("dict['string']: " + (string)dict["string"]); + Console.WriteLine("dict['float']: " + (double)dict["float"]); // floats come out as doubles + Console.WriteLine("dict['int']: " + (long)dict["int"]); // ints come out as longs + Console.WriteLine("dict['unicode']: " + (string)dict["unicode"]); + + var str = Json.Serialize(dict); + + Console.WriteLine("serialized: " + str); + } } public static class Json @@ -45,7 +47,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static object Deserialize(string json) { // save the string for debug information - if (json == null) { + if (json == null) + { return null; } @@ -93,7 +96,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static object Parse(string jsonString) { - using (var instance = new Parser(jsonString)) { + using (var instance = new Parser(jsonString)) + { return instance.ParseValue(); } } @@ -112,8 +116,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness json.Read(); // { - while (true) { - switch (NextToken) { + while (true) + { + switch (NextToken) + { case TOKEN.NONE: return null; case TOKEN.COMMA: @@ -123,12 +129,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness case TOKEN.STRING: // name string name = ParseString(); - if (name == null) { + if (name == null) + { return null; } // : - if (NextToken != TOKEN.COLON) { + if (NextToken != TOKEN.COLON) + { return null; } // ditch the colon @@ -156,10 +164,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness // [ var parsing = true; - while (parsing) { + while (parsing) + { TOKEN nextToken = NextToken; - switch (nextToken) { + switch (nextToken) + { case TOKEN.NONE: return null; case TOKEN.COMMA: @@ -187,7 +197,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness object ParseByToken(TOKEN token) { - switch (token) { + switch (token) + { case TOKEN.STRING: return ParseString(); case TOKEN.NUMBER: @@ -216,26 +227,31 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness json.Read(); bool parsing = true; - while (parsing) { + while (parsing) + { - if (json.Peek() == -1) { + if (json.Peek() == -1) + { parsing = false; break; } c = NextChar; - switch (c) { + switch (c) + { case '"': parsing = false; break; case '\\': - if (json.Peek() == -1) { + if (json.Peek() == -1) + { parsing = false; break; } c = NextChar; - switch (c) { + switch (c) + { case '"': case '\\': case '/': @@ -259,7 +275,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness case 'u': var hex = new char[4]; - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) + { hex[i] = NextChar; if (!IsHexDigit(hex[i])) return null; @@ -282,7 +299,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { string number = NextWord; - if (number.IndexOf('.') == -1 && number.IndexOf('E') == -1 && number.IndexOf('e') == -1) { + if (number.IndexOf('.') == -1 && number.IndexOf('E') == -1 && number.IndexOf('e') == -1) + { long parsedInt; Int64.TryParse(number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedInt); return parsedInt; @@ -295,10 +313,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness void EatWhitespace() { - while (Char.IsWhiteSpace(PeekChar)) { + while (Char.IsWhiteSpace(PeekChar)) + { json.Read(); - if (json.Peek() == -1) { + if (json.Peek() == -1) + { break; } } @@ -320,10 +340,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness get { StringBuilder word = new StringBuilder(); - while (!IsWordBreak(PeekChar)) { + while (!IsWordBreak(PeekChar)) + { word.Append(NextChar); - if (json.Peek() == -1) { + if (json.Peek() == -1) + { break; } } @@ -336,11 +358,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness get { EatWhitespace(); - if (json.Peek() == -1) { + if (json.Peek() == -1) + { return TOKEN.NONE; } - switch (PeekChar) { + switch (PeekChar) + { case '{': return TOKEN.CURLY_OPEN; case '}': @@ -372,7 +396,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness return TOKEN.NUMBER; } - switch (NextWord) { + switch (NextWord) + { case "false": return TOKEN.FALSE; case "true": @@ -420,19 +445,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness IDictionary asDict; string asStr; - if (value == null) { + if (value == null) + { builder.Append("null"); - } else if ((asStr = value as string) != null) { + } + else if ((asStr = value as string) != null) + { SerializeString(asStr); - } else if (value is bool) { + } + else if (value is bool) + { builder.Append((bool)value ? "true" : "false"); - } else if ((asList = value as IList) != null) { + } + else if ((asList = value as IList) != null) + { SerializeArray(asList); - } else if ((asDict = value as IDictionary) != null) { + } + else if ((asDict = value as IDictionary) != null) + { SerializeObject(asDict); - } else if (value is char) { + } + else if (value is char) + { SerializeString(new string((char)value, 1)); - } else { + } + else + { SerializeOther(value); } } @@ -443,8 +481,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness builder.Append('{'); - foreach (object e in obj.Keys) { - if (!first) { + foreach (object e in obj.Keys) + { + if (!first) + { builder.Append(','); } @@ -465,9 +505,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness bool first = true; - for (int i = 0; i < anArray.Count; i++) { + for (int i = 0; i < anArray.Count; i++) + { object obj = anArray[i]; - if (!first) { + if (!first) + { builder.Append(','); } @@ -484,9 +526,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness builder.Append('\"'); char[] charArray = str.ToCharArray(); - for (int i = 0; i < charArray.Length; i++) { + for (int i = 0; i < charArray.Length; i++) + { char c = charArray[i]; - switch (c) { + switch (c) + { case '"': builder.Append("\\\""); break; @@ -510,9 +554,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness break; default: int codepoint = Convert.ToInt32(c); - if ((codepoint >= 32) && (codepoint <= 126)) { + if ((codepoint >= 32) && (codepoint <= 126)) + { builder.Append(c); - } else { + } + else + { builder.Append("\\u"); builder.Append(codepoint.ToString("x4")); } @@ -528,21 +575,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness // NOTE: decimals lose precision during serialization. // They always have, I'm just letting you know. // Previously floats and doubles lost precision too. - if (value is float) { + if (value is float) + { builder.Append(((float)value).ToString("R", System.Globalization.CultureInfo.InvariantCulture)); - } else if (value is int - || value is uint - || value is long - || value is sbyte - || value is byte - || value is short - || value is ushort - || value is ulong) { + } + else if (value is int + || value is uint + || value is long + || value is sbyte + || value is byte + || value is short + || value is ushort + || value is ulong) + { builder.Append(value); - } else if (value is double - || value is decimal) { + } + else if (value is double + || value is decimal) + { builder.Append(Convert.ToDouble(value).ToString("R", System.Globalization.CultureInfo.InvariantCulture)); - } else { + } + else + { SerializeString(value.ToString()); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullPropagation.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullPropagation.cs index 62e7875ab..f4d76320c 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullPropagation.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullPropagation.cs @@ -13,7 +13,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { public string Text; } - + void TestNotCoalescing() { Console.WriteLine("TestNotCoalescing:"); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullableTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullableTests.cs index 9200488bf..43204dd88 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullableTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/NullableTests.cs @@ -103,18 +103,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void FieldAccessOrderOfEvaluation(NullableTests c) { Console.WriteLine("GetInt, then NRE:"); - try { + try + { c.intField = GetValue(); - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.Message); } Console.WriteLine("NRE before GetInt:"); - try { + try + { #if CS60 ref int i = ref c.intField; i = GetValue(); #endif - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.Message); } } @@ -124,18 +130,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void FieldAccessOrderOfEvaluationWithStruct(NullableTests c) { Console.WriteLine("GetInt, then NRE (with struct):"); - try { + try + { c.structField.IntField = GetValue(); - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.Message); } Console.WriteLine("NRE before GetInt (with struct):"); - try { + try + { #if CS60 ref SomeStruct s = ref c.structField; s.IntField = GetValue(); #endif - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.Message); } } @@ -155,27 +167,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void ArrayAccessOrderOfEvaluation() { Console.WriteLine("GetArray direct:"); - try { + try + { GetArray()[GetIndex()] = GetValue(); - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.Message); } Console.WriteLine("GetArray with ref:"); - try { + try + { #if CS60 ref int elem = ref GetArray()[GetIndex()]; elem = GetValue(); #endif - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.Message); } Console.WriteLine("GetArray direct with value-type:"); - try { + try + { // This line is mis-compiled by legacy csc: // with the legacy compiler the NRE is thrown before the GetValue call; // with Roslyn the NRE is thrown after the GetValue call. GetArray()[GetIndex()] = GetValue(); - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.Message); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs index 4ec7a432e..d70bcc17d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/OverloadResolution.cs @@ -100,7 +100,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void TestCallIssue1281(params object[] args) { Console.Write("TestCallIssue1281: count = " + args.Length + ": "); - foreach (var arg in args) { + foreach (var arg in args) + { Console.Write(arg); Console.Write(", "); } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/PropertiesAndEvents.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/PropertiesAndEvents.cs index dab3bac6d..de36a7307 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/PropertiesAndEvents.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/PropertiesAndEvents.cs @@ -21,16 +21,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { int thisValue; - public int this[int i] - { + public int this[int i] { get { Console.WriteLine("get_this({0})", i); return i * i; } - set { Console.WriteLine("set_this({0}, {1})", i, value); thisValue = value; } + set { Console.WriteLine("set_this({0}, {1})", i, value); thisValue = value; } } public string AutoProp { get; set; } - public double PISquare - { + public double PISquare { get { Console.WriteLine("get_PISquare"); return Math.Pow(Math.PI, 2); } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Switch.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Switch.cs index bb63a2096..ca4c4ff04 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Switch.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Switch.cs @@ -41,7 +41,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void TestCase(Func target, params T[] args) { - foreach (var arg in args) { + foreach (var arg in args) + { Console.WriteLine(target(arg)); } } @@ -49,26 +50,40 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static string SparseIntegerSwitch(int i) { Console.WriteLine("SparseIntegerSwitch: " + i); - switch (i) { - case -10000000: return "-10 mln"; - case -100: return "-hundred"; - case -1: return "-1"; - case 0: return "0"; - case 1: return "1"; - case 2: return "2"; - case 4: return "4"; - case 100: return "hundred"; - case 10000: return "ten thousand"; - case 10001: return "ten thousand and one"; - case int.MaxValue: return "int.MaxValue"; - default: return "something else"; + switch (i) + { + case -10000000: + return "-10 mln"; + case -100: + return "-hundred"; + case -1: + return "-1"; + case 0: + return "0"; + case 1: + return "1"; + case 2: + return "2"; + case 4: + return "4"; + case 100: + return "hundred"; + case 10000: + return "ten thousand"; + case 10001: + return "ten thousand and one"; + case int.MaxValue: + return "int.MaxValue"; + default: + return "something else"; } } public static string ShortSwitchOverString(string text) { Console.WriteLine("ShortSwitchOverString: " + text); - switch (text) { + switch (text) + { case "First case": return "Text"; default: @@ -79,7 +94,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static string ShortSwitchOverString2(string text) { Console.WriteLine("ShortSwitchOverString2: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -94,7 +110,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static string ShortSwitchOverStringNoExplicitDefault(string text) { Console.WriteLine("ShortSwitchOverStringNoExplicitDefault: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -108,7 +125,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static string SwitchOverString1(string text) { Console.WriteLine("SwitchOverString1: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -132,7 +150,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static string SwitchOverString2() { Console.WriteLine("SwitchOverString2:"); - switch (Environment.UserName) { + switch (Environment.UserName) + { case "First case": return "Text1"; case "Second case": @@ -163,7 +182,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static string SwitchOverBool(bool b) { Console.WriteLine("SwitchOverBool: " + b); - switch (b) { + switch (b) + { case true: return bool.TrueString; case false: @@ -178,8 +198,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void SwitchInLoop(int i) { Console.WriteLine("SwitchInLoop: " + i); - while (true) { - switch (i) { + while (true) + { + switch (i) + { case 1: Console.WriteLine("one"); break; @@ -204,7 +226,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void SwitchWithGoto(int i) { Console.WriteLine("SwitchWithGoto: " + i); - switch (i) { + switch (i) + { case 1: Console.WriteLine("one"); goto default; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs index 151b8ac95..ffbbef707 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs @@ -59,13 +59,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("TruncatedComp1(-1):"); TruncatedComp1(-1); - + Console.WriteLine("TruncatedComp1(0x100000001):"); TruncatedComp1(0x100000001); Console.WriteLine("TruncatedComp1(long.MinValue):"); TruncatedComp1(long.MinValue); - + Console.WriteLine("TruncatedComp2(1):"); TruncatedComp2(1, 1); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/UndocumentedExpressions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/UndocumentedExpressions.cs index 6d98e6330..7d14b19de 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/UndocumentedExpressions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/UndocumentedExpressions.cs @@ -38,12 +38,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness ArgIterator argIterator = new ArgIterator(__arglist); Console.WriteLine("Called with {0} arguments", argIterator.GetRemainingCount()); int pos = 0; - while (argIterator.GetRemainingCount() > 0) { + while (argIterator.GetRemainingCount() > 0) + { TypedReference tr = argIterator.GetNextArg(); object val; - try { + try + { val = __refvalue(tr, object); - } catch (Exception ex) { + } + catch (Exception ex) + { val = ex.GetType().Name; } Console.WriteLine("{0} : {1} = {2}", pos++, __reftype(tr).Name, val); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/UnsafeCode.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/UnsafeCode.cs index 49d398c2e..d7d6f5ccc 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/UnsafeCode.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/UnsafeCode.cs @@ -36,7 +36,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public unsafe int MultipleExitsOutOfFixedBlock(int[] arr) { - fixed (int* ptr = &arr[0]) { + fixed (int* ptr = &arr[0]) + { if (*ptr < 0) return *ptr; if (*ptr == 21) @@ -49,10 +50,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("outside"); return 2; } - + public unsafe void FixMultipleStrings(string text) { - fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text) { + fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text) + { *ptr = 'c'; *userName = 'd'; *ptr2 = 'e'; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Using.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Using.cs index 9b673da66..a75f4a6a6 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Using.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Using.cs @@ -57,7 +57,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("before using"); // Mono has a compiler bug and introduces an assembly reference to [gmcs] here... #if !MCS - using (null) { + using (null) + { Console.WriteLine("using (null)"); } #endif @@ -67,9 +68,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void NoUsingDueToAssignment() { PrintOnDispose printOnDispose = new PrintOnDispose("Wrong"); - try { + try + { printOnDispose = new PrintOnDispose("Correct"); - } finally { + } + finally + { printOnDispose.Dispose(); } } @@ -77,11 +81,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void NoUsingDueToAssignment2() { PrintOnDispose printOnDispose = new PrintOnDispose("NoUsing(): Wrong"); - try { + try + { printOnDispose = new PrintOnDispose("NoUsing(): Correct"); - } finally { + } + finally + { IDisposable disposable = (object)printOnDispose as IDisposable; - if (disposable != null) { + if (disposable != null) + { disposable.Dispose(); } } @@ -95,12 +103,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void NoUsingDueToByRefCall() { PrintOnDispose printOnDispose = new PrintOnDispose("NoUsingDueToByRefCall(): Wrong"); - try { + try + { Console.WriteLine("NoUsingDueToByRefCall"); Clear(ref printOnDispose); - } finally { + } + finally + { IDisposable disposable = (object)printOnDispose as IDisposable; - if (disposable != null) { + if (disposable != null) + { disposable.Dispose(); } } @@ -110,11 +122,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { var obj = new System.IO.StringWriter(); IDisposable disposable; - try { + try + { obj.WriteLine("NoUsingDueToContinuedDisposableUse"); - } finally { + } + finally + { disposable = (object)obj as IDisposable; - if (disposable != null) { + if (disposable != null) + { disposable.Dispose(); } } @@ -124,11 +140,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void ContinuedObjectUse() { var obj = new System.IO.StringWriter(); - try { + try + { obj.WriteLine("ContinuedObjectUse"); - } finally { + } + finally + { IDisposable disposable = (object)obj as IDisposable; - if (disposable != null) { + if (disposable != null) + { disposable.Dispose(); } } @@ -141,11 +161,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness obj.Write("VariableAlreadyUsedBefore - 1"); Console.WriteLine(obj); obj = new System.IO.StringWriter(); - try { + try + { obj.WriteLine("VariableAlreadyUsedBefore - 2"); - } finally { + } + finally + { IDisposable disposable = (object)obj as IDisposable; - if (disposable != null) { + if (disposable != null) + { disposable.Dispose(); } } @@ -154,11 +178,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static void UsingObject() { object obj = new object(); - try { + try + { Console.WriteLine("UsingObject: {0}", obj); - } finally { + } + finally + { IDisposable disposable = obj as IDisposable; - if (disposable != null) { + if (disposable != null) + { disposable.Dispose(); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/ValueTypeCall.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/ValueTypeCall.cs index 0a8250c92..e399012f9 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/ValueTypeCall.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/ValueTypeCall.cs @@ -6,7 +6,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public struct MutValueType : IDisposable { public int val; - + public void Increment() { Console.WriteLine("Inc() called on {0}", val); @@ -23,35 +23,35 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness return "MutValueType.ToString() " + (++val); } } - + public struct GenericValueType { T data; int num; - + public GenericValueType(T data) { this.data = data; this.num = 1; } - + public void Call(ref GenericValueType v) { num++; Console.WriteLine("Call #{0}: {1} with v=#{2}", num, data, v.num); } } - + public struct ValueTypeWithReadOnlyMember { public readonly int Member; - + public ValueTypeWithReadOnlyMember(int member) { this.Member = member; } } - + public class ValueTypeCall { public static void Main() @@ -68,22 +68,22 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness new ValueTypeCall().InstanceFieldTests(); ForEach(); } - + static void RefParameter(ref MutValueType m) { m.Increment(); m.Increment(); } - + static void ValueParameter(MutValueType m) { m.Increment(); m.Increment(); } - + static readonly MutValueType ReadonlyField = new MutValueType { val = 100 }; static MutValueType MutableField = new MutValueType { val = 200 }; - + static void Field() { ReadonlyField.Increment(); @@ -99,7 +99,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness MutValueType localCopy = ReadonlyField; RefParameter(ref localCopy); } - + static void Box() { Console.WriteLine("Box"); @@ -126,7 +126,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness MutValueType instanceField; ValueTypeWithReadOnlyMember mutableInstanceFieldWithReadOnlyMember; - + void InstanceFieldTests() { this.instanceField.val = 42; @@ -145,7 +145,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void Using1() { Console.WriteLine("Using:"); - using (var x = new MutValueType()) { + using (var x = new MutValueType()) + { x.Increment(); } } @@ -154,9 +155,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { Console.WriteLine("Not using:"); var y = new MutValueType(); - try { + try + { y.Increment(); - } finally { + } + finally + { MutValueType x = y; x.Dispose(); } @@ -166,7 +170,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { Console.WriteLine("Using with variable declared outside:"); MutValueType z; - using (z = new MutValueType()) { + using (z = new MutValueType()) + { z.Increment(); } } @@ -190,7 +195,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void ForEach1(List list) { Console.WriteLine("ForEach1:"); - foreach (var val in list) { + foreach (var val in list) + { val.Increment(); val.Increment(); } @@ -200,7 +206,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness static void ForEachArray1(MutValueType[] list) { Console.WriteLine("ForEachArray1:"); - foreach (var val in list) { + foreach (var val in list) + { val.Increment(); val.Increment(); } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/YieldReturn.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/YieldReturn.cs index 6398f740b..cb8f7b6ed 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/YieldReturn.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/YieldReturn.cs @@ -47,9 +47,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Print("YieldBreakInTryCatchInTryFinally", YieldBreakInTryCatchInTryFinally().GetEnumerator()); Print("YieldBreakInTryFinallyInTryFinally(false)", YieldBreakInTryFinallyInTryFinally(false).GetEnumerator()); Print("YieldBreakInTryFinallyInTryFinally(true)", YieldBreakInTryFinallyInTryFinally(true).GetEnumerator()); - try { + try + { Print("UnconditionalThrowInTryFinally()", UnconditionalThrowInTryFinally().GetEnumerator()); - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.Message); } Print("NestedTryFinallyStartingOnSamePosition", NestedTryFinallyStartingOnSamePosition().GetEnumerator()); @@ -69,7 +72,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness internal static void Print(string name, IEnumerator enumerator) { Console.WriteLine(name + ": Test start"); - while (enumerator.MoveNext()) { + while (enumerator.MoveNext()) + { Console.WriteLine(name + ": " + enumerator.Current); } } @@ -112,7 +116,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable YieldReturnInLoop() { - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 100; i++) + { yield return i; } } @@ -120,9 +125,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable YieldReturnWithTryFinally() { yield return 0; - try { + try + { yield return 1; - } finally { + } + finally + { Console.WriteLine("Finally!"); } yield return 2; @@ -130,14 +138,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable YieldReturnInLock1(object o) { - lock (o) { + lock (o) + { yield return 1; } } public static IEnumerable YieldReturnInLock2(object o) { - lock (o) { + lock (o) + { yield return 1; o = null; yield return 2; @@ -149,28 +159,35 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("Start of method - 1"); yield return "Start of method"; Console.WriteLine("Start of method - 2"); - try { + try + { Console.WriteLine("Within outer try - 1"); yield return "Within outer try"; Console.WriteLine("Within outer try - 2"); - try { + try + { Console.WriteLine("Within inner try - 1"); yield return "Within inner try"; Console.WriteLine("Within inner try - 2"); - if (breakInMiddle) { + if (breakInMiddle) + { Console.WriteLine("Breaking..."); yield break; } Console.WriteLine("End of inner try - 1"); yield return "End of inner try"; Console.WriteLine("End of inner try - 2"); - } finally { + } + finally + { Console.WriteLine("Inner Finally"); } Console.WriteLine("End of outer try - 1"); yield return "End of outer try"; Console.WriteLine("End of outer try - 2"); - } finally { + } + finally + { Console.WriteLine("Outer Finally"); } Console.WriteLine("End of method - 1"); @@ -181,11 +198,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable YieldReturnWithTwoNonNestedFinallyBlocks(IEnumerable input) { // outer try-finally block - foreach (string line in input) { + foreach (string line in input) + { // nested try-finally block - try { + try + { yield return line; - } finally { + } + finally + { Console.WriteLine("Processed " + line); } } @@ -196,21 +217,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness yield return "E"; yield return "F"; // outer try-finally block - foreach (string line in input) { + foreach (string line in input) + { yield return line.ToUpper(); } } public static IEnumerable> YieldReturnWithAnonymousMethods1(IEnumerable input) { - foreach (string line in input) { + foreach (string line in input) + { yield return () => line; } } public static IEnumerable> YieldReturnWithAnonymousMethods2(IEnumerable input) { - foreach (string line in input) { + foreach (string line in input) + { string copy = line; yield return () => copy; } @@ -218,8 +242,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable GetEvenNumbers(int n) { - for (int i = 0; i < n; i++) { - if (i % 2 == 0) { + for (int i = 0; i < n; i++) + { + if (i % 2 == 0) + { yield return i; } } @@ -229,20 +255,29 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable ExceptionHandling() { yield return 'a'; - try { + try + { Console.WriteLine("1 - try"); - } catch (Exception) { + } + catch (Exception) + { Console.WriteLine("1 - catch"); } yield return 'b'; - try { - try { + try + { + try + { Console.WriteLine("2 - try"); - } finally { + } + finally + { Console.WriteLine("2 - finally"); } yield return 'c'; - } finally { + } + finally + { Console.WriteLine("outer finally"); } } @@ -250,22 +285,29 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable YieldBreakInCatch() { yield return 0; - try { + try + { Console.WriteLine("In Try"); - } catch { + } + catch + { // yield return is not allowed in catch, but yield break is yield break; } yield return 1; } - + public static IEnumerable YieldBreakInCatchInTryFinally() { - try { + try + { yield return 0; - try { + try + { Console.WriteLine("In Try"); - } catch { + } + catch + { // yield return is not allowed in catch, but yield break is // Note that pre-roslyn, this code triggers a compiler bug: // If the finally block throws an exception, it ends up getting @@ -273,43 +315,58 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness yield break; } yield return 1; - } finally { + } + finally + { Console.WriteLine("Finally"); } } public static IEnumerable YieldBreakInTryCatchInTryFinally() { - try { + try + { yield return 0; - try { + try + { Console.WriteLine("In Try"); // same compiler bug as in YieldBreakInCatchInTryFinally yield break; - } catch { + } + catch + { Console.WriteLine("Catch"); } yield return 1; - } finally { + } + finally + { Console.WriteLine("Finally"); } } public static IEnumerable YieldBreakInTryFinallyInTryFinally(bool b) { - try { + try + { yield return 0; - try { + try + { Console.WriteLine("In Try"); - if (b) { + if (b) + { // same compiler bug as in YieldBreakInCatchInTryFinally yield break; } - } finally { + } + finally + { Console.WriteLine("Inner Finally"); } yield return 1; - } finally { + } + finally + { Console.WriteLine("Finally"); } } @@ -318,15 +375,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness { yield break; } - + public static IEnumerable UnconditionalThrowInTryFinally() { // Here, MoveNext() doesn't call the finally methods at all // (only indirectly via Dispose()) - try { + try + { yield return 0; throw new NotImplementedException(); - } finally { + } + finally + { Console.WriteLine("Finally"); } } @@ -334,13 +394,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable NestedTryFinallyStartingOnSamePosition() { // The first user IL instruction is already in 2 nested try blocks. - try { - try { + try + { + try + { yield return 0; - } finally { + } + finally + { Console.WriteLine("Inner Finally"); } - } finally { + } + finally + { Console.WriteLine("Outer Finally"); } } @@ -349,15 +415,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable TryFinallyWithTwoExitPoints(bool b) { // Uses goto for multiple non-exceptional exits out of try-finally. - try { - if (b) { + try + { + if (b) + { yield return 1; goto exit1; - } else { + } + else + { yield return 2; goto exit2; } - } finally { + } + finally + { Console.WriteLine("Finally"); } exit1: @@ -370,15 +442,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness #if !LEGACY_CSC public static IEnumerable YieldBreakInNestedTryFinally() { - try { + try + { yield return 1; - try { + try + { // Compiler bug: pre-Roslyn, the finally blocks will execute in the wrong order yield break; - } finally { + } + finally + { Console.WriteLine("Inner Finally"); } - } finally { + } + finally + { Console.WriteLine("Outer Finally"); } } @@ -388,17 +466,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness // that exception gets caught by the catch block. public static IEnumerable TryFinallyWithTwoExitPointsInNestedTry(bool b) { - try { + try + { yield return 1; - try { + try + { if (b) goto exit1; else goto exit2; - } catch { + } + catch + { Console.WriteLine("Catch"); } - } finally { + } + finally + { Console.WriteLine("Finally"); } exit1: @@ -410,17 +494,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable TryFinallyWithTwoExitPointsInNestedCatch(bool b) { - try { + try + { yield return 1; - try { + try + { Console.WriteLine("Nested Try"); - } catch { + } + catch + { if (b) goto exit1; else goto exit2; } - } finally { + } + finally + { Console.WriteLine("Finally"); } exit1: @@ -434,9 +524,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable LocalInFinally(T a) where T : IDisposable { yield return 1; - try { + try + { yield return 2; - } finally { + } + finally + { T val = a; val.Dispose(); val.Dispose(); @@ -447,7 +540,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness public static IEnumerable GenericYield() where T : new() { T val = new T(); - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) + { yield return val; } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Debug.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Debug.cs index 419acf191..04d879a8d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Debug.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Debug.cs @@ -55,7 +55,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SparseIntegerSwitch(int i) { Console.WriteLine("SparseIntegerSwitch: " + i); - switch (i) { + switch (i) + { case -10000000: return "-10 mln"; case -100: @@ -85,7 +86,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchOverInt(int i) { - switch (i) { + switch (i) + { case 0: Console.WriteLine("zero"); break; @@ -113,7 +115,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string ShortSwitchOverString(string text) { Console.WriteLine("ShortSwitchOverString: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -128,7 +131,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string ShortSwitchOverStringWithNullCase(string text) { Console.WriteLine("ShortSwitchOverStringWithNullCase: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -143,7 +147,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverString1(string text) { Console.WriteLine("SwitchOverString1: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -167,7 +172,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverString2() { Console.WriteLine("SwitchOverString2:"); - switch (Environment.UserName) { + switch (Environment.UserName) + { case "First case": return "Text1"; case "Second case": @@ -197,9 +203,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string TwoDifferentSwitchBlocksInTryFinally() { - try { + try + { Console.WriteLine("TwoDifferentSwitchBlocks:"); - switch (Environment.UserName) { + switch (Environment.UserName) + { case "First case": return "Text1"; case "Second case": @@ -225,9 +233,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty default: return "Default"; } - } finally { + } + finally + { Console.WriteLine("Second switch:"); - switch (Console.ReadLine()) { + switch (Console.ReadLine()) + { case "12": Console.WriteLine("Te43234xt1"); break; @@ -271,7 +282,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverBool(bool b) { Console.WriteLine("SwitchOverBool: " + b); - switch (b) { + switch (b) + { case true: return bool.TrueString; case false: @@ -284,8 +296,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchInLoop(int i) { Console.WriteLine("SwitchInLoop: " + i); - while (true) { - switch (i) { + while (true) + { + switch (i) + { case 1: Console.WriteLine("one"); break; @@ -310,7 +324,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithGoto(int i) { Console.WriteLine("SwitchWithGoto: " + i); - switch (i) { + switch (i) + { case 1: Console.WriteLine("one"); goto default; @@ -340,10 +355,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty ArrayList arrayList = new ArrayList(); ArrayList arrayList2 = new ArrayList(); SetProperty[] properties = GetProperties(); - for (int i = 0; i < properties.Length; i++) { + for (int i = 0; i < properties.Length; i++) + { Console.WriteLine("In for-loop"); SetProperty setProperty = properties[i]; - switch (setProperty.Property.Name) { + switch (setProperty.Property.Name) + { case "Name1": setProperty.Set = 1; arrayList.Add(setProperty); @@ -373,7 +390,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithComplexCondition(string[] args) { - switch ((args.Length == 0) ? "dummy" : args[0]) { + switch ((args.Length == 0) ? "dummy" : args[0]) + { case "a": Console.WriteLine("a"); break; @@ -392,7 +410,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithArray(string[] args) { - switch (args[0]) { + switch (args[0]) + { case "a": Console.WriteLine("a"); break; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Release.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Release.cs index 419acf191..0a39a49f8 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Release.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/CS1xSwitch_Release.cs @@ -55,7 +55,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SparseIntegerSwitch(int i) { Console.WriteLine("SparseIntegerSwitch: " + i); - switch (i) { + switch (i) + { case -10000000: return "-10 mln"; case -100: @@ -85,7 +86,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchOverInt(int i) { - switch (i) { + switch (i) + { case 0: Console.WriteLine("zero"); break; @@ -113,7 +115,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string ShortSwitchOverString(string text) { Console.WriteLine("ShortSwitchOverString: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -128,7 +131,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string ShortSwitchOverStringWithNullCase(string text) { Console.WriteLine("ShortSwitchOverStringWithNullCase: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -143,7 +147,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverString1(string text) { Console.WriteLine("SwitchOverString1: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -167,7 +172,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverString2() { Console.WriteLine("SwitchOverString2:"); - switch (Environment.UserName) { + switch (Environment.UserName) + { case "First case": return "Text1"; case "Second case": @@ -197,9 +203,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string TwoDifferentSwitchBlocksInTryFinally() { - try { + try + { Console.WriteLine("TwoDifferentSwitchBlocks:"); - switch (Environment.UserName) { + switch (Environment.UserName) + { case "First case": return "Text1"; case "Second case": @@ -225,9 +233,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty default: return "Default"; } - } finally { + } + finally + { Console.WriteLine("Second switch:"); - switch (Console.ReadLine()) { + switch (Console.ReadLine()) + { case "12": Console.WriteLine("Te43234xt1"); break; @@ -271,7 +282,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverBool(bool b) { Console.WriteLine("SwitchOverBool: " + b); - switch (b) { + switch (b) + { case true: return bool.TrueString; case false: @@ -284,8 +296,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchInLoop(int i) { Console.WriteLine("SwitchInLoop: " + i); - while (true) { - switch (i) { + while (true) + { + switch (i) + { case 1: Console.WriteLine("one"); break; @@ -310,7 +324,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithGoto(int i) { Console.WriteLine("SwitchWithGoto: " + i); - switch (i) { + switch (i) + { case 1: Console.WriteLine("one"); goto default; @@ -340,10 +355,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty ArrayList arrayList = new ArrayList(); ArrayList arrayList2 = new ArrayList(); SetProperty[] properties = GetProperties(); - for (int i = 0; i < properties.Length; i++) { + for (int i = 0; i < properties.Length; i++) + { Console.WriteLine("In for-loop"); SetProperty setProperty = properties[i]; - switch (setProperty.Property.Name) { + switch (setProperty.Property.Name) + { case "Name1": setProperty.Set = 1; arrayList.Add(setProperty); @@ -373,7 +390,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithComplexCondition(string[] args) { - switch ((args.Length == 0) ? "dummy" : args[0]) { + switch ((args.Length == 0) ? "dummy" : args[0]) + { case "a": Console.WriteLine("a"); break; @@ -392,7 +410,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithArray(string[] args) { - switch (args[0]) { + switch (args[0]) + { case "a": Console.WriteLine("a"); break; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs index 62620a8b9..67d808472 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs @@ -65,7 +65,8 @@ public static class Program public override int GenerateNext(ref IEnumerable next) { - switch (pc) { + switch (pc) + { default: pc = 1; current = 1; @@ -87,7 +88,8 @@ public static class Program public override bool get_CheckClose() { - switch (pc) { + switch (pc) + { default: return false; case 0: @@ -137,23 +139,28 @@ public static class Program public static int main(string[] argv) { IDisposable disposable; - using (Program.disposable()) { + using (Program.disposable()) + { Console.WriteLine("Hello 1"); disposable = Program.disposable(); } - using (disposable) { + using (disposable) + { IEnumerable seq = getSeq(); - foreach (int item in seq) { + foreach (int item in seq) + { Console.WriteLine(item); } FSharpList fSharpList = getList(); - for (FSharpList tailOrNull = fSharpList.TailOrNull; tailOrNull != null; tailOrNull = fSharpList.TailOrNull) { + for (FSharpList tailOrNull = fSharpList.TailOrNull; tailOrNull != null; tailOrNull = fSharpList.TailOrNull) + { int headOrDefault = fSharpList.HeadOrDefault; Console.WriteLine(headOrDefault); fSharpList = tailOrNull; } int[] array = getArray(); - foreach (int value in array) { + foreach (int value in array) + { Console.WriteLine(value); } return 0; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs index b465dafc3..537df0d43 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs @@ -66,7 +66,8 @@ public static class Program public override int GenerateNext(ref IEnumerable next) { - switch (pc) { + switch (pc) + { default: pc = 1; current = 1; @@ -88,7 +89,8 @@ public static class Program public override bool get_CheckClose() { - switch (pc) { + switch (pc) + { default: return false; case 0: @@ -138,17 +140,21 @@ public static class Program public static int main(string[] argv) { IDisposable disposable; - using (Program.disposable()) { + using (Program.disposable()) + { Console.WriteLine("Hello 1"); disposable = Program.disposable(); } - using (disposable) { + using (disposable) + { IEnumerable seq = getSeq(); - foreach (int item in seq) { + foreach (int item in seq) + { Console.WriteLine(item); } FSharpList fSharpList = FSharpList.Cons(1, FSharpList.Empty); - for (FSharpList tailOrNull = fSharpList.TailOrNull; tailOrNull != null; tailOrNull = fSharpList.TailOrNull) { + for (FSharpList tailOrNull = fSharpList.TailOrNull; tailOrNull != null; tailOrNull = fSharpList.TailOrNull) + { int headOrDefault = fSharpList.HeadOrDefault; Console.WriteLine(headOrDefault); fSharpList = tailOrNull; @@ -156,7 +162,8 @@ public static class Program int[] array = new int[1] { 1 }; - for (int headOrDefault = 0; headOrDefault < array.Length; headOrDefault++) { + for (int headOrDefault = 0; headOrDefault < array.Length; headOrDefault++) + { Console.WriteLine(array[headOrDefault]); } return 0; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Debug.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Debug.cs index b4ab3c3d3..ea6f59c90 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Debug.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Debug.cs @@ -5,7 +5,8 @@ public static class FSharpUsingPatterns { public static void sample1() { - using (FileStream fileStream = File.Create("x.txt")) { + using (FileStream fileStream = File.Create("x.txt")) + { fileStream.WriteByte((byte)1); } } @@ -13,7 +14,8 @@ public static class FSharpUsingPatterns public static void sample2() { Console.WriteLine("some text"); - using (FileStream fileStream = File.Create("x.txt")) { + using (FileStream fileStream = File.Create("x.txt")) + { fileStream.WriteByte((byte)2); Console.WriteLine("some text"); } @@ -22,7 +24,8 @@ public static class FSharpUsingPatterns public static void sample3() { Console.WriteLine("some text"); - using (FileStream fileStream = File.Create("x.txt")) { + using (FileStream fileStream = File.Create("x.txt")) + { fileStream.WriteByte((byte)3); } Console.WriteLine("some text"); @@ -32,7 +35,8 @@ public static class FSharpUsingPatterns { Console.WriteLine("some text"); int num; - using (FileStream fileStream = File.OpenRead("x.txt")) { + using (FileStream fileStream = File.OpenRead("x.txt")) + { num = fileStream.ReadByte(); } int num2 = num; @@ -43,12 +47,14 @@ public static class FSharpUsingPatterns { Console.WriteLine("some text"); int num; - using (FileStream fileStream = File.OpenRead("x.txt")) { + using (FileStream fileStream = File.OpenRead("x.txt")) + { num = fileStream.ReadByte(); } int num2 = num; int num3; - using (FileStream fileStream = File.OpenRead("x.txt")) { + using (FileStream fileStream = File.OpenRead("x.txt")) + { fileStream.ReadByte(); num3 = fileStream.ReadByte(); } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Release.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Release.cs index 355a18d58..b8d8a71a9 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Release.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Release.cs @@ -5,7 +5,8 @@ public static class FSharpUsingPatterns { public static void sample1() { - using (FileStream fileStream = File.Create("x.txt")) { + using (FileStream fileStream = File.Create("x.txt")) + { fileStream.WriteByte(1); } } @@ -13,7 +14,8 @@ public static class FSharpUsingPatterns public static void sample2() { Console.WriteLine("some text"); - using (FileStream fileStream = File.Create("x.txt")) { + using (FileStream fileStream = File.Create("x.txt")) + { fileStream.WriteByte(2); Console.WriteLine("some text"); } @@ -22,7 +24,8 @@ public static class FSharpUsingPatterns public static void sample3() { Console.WriteLine("some text"); - using (FileStream fileStream = File.Create("x.txt")) { + using (FileStream fileStream = File.Create("x.txt")) + { fileStream.WriteByte(3); } Console.WriteLine("some text"); @@ -32,7 +35,8 @@ public static class FSharpUsingPatterns { Console.WriteLine("some text"); int num; - using (FileStream fileStream = File.OpenRead("x.txt")) { + using (FileStream fileStream = File.OpenRead("x.txt")) + { num = fileStream.ReadByte(); } int num2 = num; @@ -43,12 +47,14 @@ public static class FSharpUsingPatterns { Console.WriteLine("some text"); int num; - using (FileStream fileStream = File.OpenRead("x.txt")) { + using (FileStream fileStream = File.OpenRead("x.txt")) + { num = fileStream.ReadByte(); } int num2 = num; int num3; - using (FileStream fileStream = File.OpenRead("x.txt")) { + using (FileStream fileStream = File.OpenRead("x.txt")) + { fileStream.ReadByte(); num3 = fileStream.ReadByte(); } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1047.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1047.cs index 93f375a02..2ab71efcc 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1047.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1047.cs @@ -6,7 +6,8 @@ private void ProblemMethod() { - while (!dummy) { + while (!dummy) + { } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1454.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1454.cs index a496e48d2..b7aea6421 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1454.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1454.cs @@ -10,7 +10,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty bitArray.CopyTo(array, 0); int num = 0; array[array.Length - 1] &= ~(-1 << bitArray.Count % 32); - for (int i = 0; i < array.Length; i++) { + for (int i = 0; i < array.Length; i++) + { int num2 = array[i]; num2 -= ((num2 >> 1) & 0x55555555); num2 = (num2 & 0x33333333) + ((num2 >> 2) & 0x33333333); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1681.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1681.cs index 31ea4c132..447948fe8 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1681.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1681.cs @@ -4,7 +4,7 @@ { public int importsClausePosition; } - + internal class Issue1681 : BaseClass { public void Test() diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1918.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1918.cs index 42787d642..969057eec 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1918.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1918.cs @@ -8,17 +8,22 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty public unsafe void ProblemFunction(Guid[] A_0, int A_1) { - fixed (Guid* ptr = A_0) { + fixed (Guid* ptr = A_0) + { void* ptr2 = ptr; UIntPtr* ptr3 = (UIntPtr*)((byte*)ptr2 - sizeof(UIntPtr)); UIntPtr uIntPtr = *ptr3; - try { + try + { *ptr3 = (UIntPtr)(ulong)A_1; - } finally { + } + finally + { *ptr3 = uIntPtr; } } - fixed (Guid[] ptr = NullVal) { + fixed (Guid[] ptr = NullVal) + { } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue646.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue646.cs index b8e2f59f2..2480b5d13 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue646.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue646.cs @@ -12,7 +12,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty public static void Main() { List list = new List(); - foreach (string item in list) { + foreach (string item in list) + { Debug.WriteLine(item); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue684.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue684.cs index 5ec516778..e10af2db7 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue684.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue684.cs @@ -9,25 +9,34 @@ public static class Issue684 // Point of this test was to ensure the stack slot here uses an appropriate type, // (bool instead of int). Unfortunately our type fixup runs too late to affect variable names. bool num2 = num >= 1000; - if (!num2) { + if (!num2) + { num2 = (num < 2); } - if (num2) { + if (num2) + { Console.WriteLine(-1); - } else { + } + else + { int i = 2; - for (int num3 = 2; num3 <= num; num3 = i) { + for (int num3 = 2; num3 <= num; num3 = i) + { Console.WriteLine(num3); - for (; i <= num; i += num3) { + for (; i <= num; i += num3) + { int num4 = array[i] = 1; } i = num3; - while (true) { + while (true) + { bool num5 = i <= num; - if (num5) { + if (num5) + { num5 = (array[i] != 0); } - if (!num5) { + if (!num5) + { break; } i++; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue959.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue959.cs index cee558bc4..e5463de16 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue959.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue959.cs @@ -4,7 +4,8 @@ { public void Test(bool arg) { - if (!arg && arg) { + if (!arg && arg) + { } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/SequenceOfNestedIfs.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/SequenceOfNestedIfs.cs index 4b404b118..3f14f4638 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/SequenceOfNestedIfs.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/SequenceOfNestedIfs.cs @@ -18,25 +18,32 @@ public class SequenceOfNestedIfs } public override void CreateMaterials() { - if (!_clear) { - if (!CheckShader()) { + if (!_clear) + { + if (!CheckShader()) + { return; } _material = new Material(); } - if (!_material) { - if (!CheckShader()) { + if (!_material) + { + if (!CheckShader()) + { return; } _material = new Material(); } - if (!_material) { - if (!CheckShader()) { + if (!_material) + { + if (!CheckShader()) + { return; } _material = new Material(); } - if (!_material && CheckShader()) { + if (!_material && CheckShader()) + { _material = new Material(); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs index fd288864c..cd1081484 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Unsafe.cs @@ -17,7 +17,8 @@ internal sealed class ExtraUnsafeTests { public unsafe static void PinWithTypeMismatch(ref uint managedPtr) { - fixed (ushort* ptr = &Unsafe.As(ref managedPtr)) { + fixed (ushort* ptr = &Unsafe.As(ref managedPtr)) + { } } @@ -29,7 +30,8 @@ internal sealed class ExtraUnsafeTests public static ref ulong RefAssignTypeMismatch(ref uint a, ref uint b) { ref ushort reference = ref Unsafe.As(ref a); - if (a != 0) { + if (a != 0) + { reference = ref Unsafe.As(ref b); } Console.WriteLine(reference); @@ -40,11 +42,15 @@ internal sealed class ExtraUnsafeTests { //The blocks IL_0019 are reachable both inside and outside the pinned region starting at IL_0013. ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement. byte[] array; - if ((array = arr) != null && array.Length != 0) { - fixed (byte* ptr = &array[0]) { + if ((array = arr) != null && array.Length != 0) + { + fixed (byte* ptr = &array[0]) + { *(int*)ptr = val; } - } else { + } + else + { /*pinned*/ref byte reference = ref *(byte*)null; *(int*)Unsafe.AsPointer(ref reference) = val; } @@ -55,14 +61,17 @@ internal sealed class ExtraUnsafeTests { //The blocks IL_0016 are reachable both inside and outside the pinned region starting at IL_0007. ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement. ref int reference; - fixed (int* ptr = &a[0]) { - if (*ptr <= 0) { + fixed (int* ptr = &a[0]) + { + if (*ptr <= 0) + { ptr[4 * 0] = 1; return; } reference = ref *ptr; } - fixed (int* ptr = &b[reference]) { + fixed (int* ptr = &b[reference]) + { ptr[4 * 0] = 1; } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs index 49577f6f0..1b3060df0 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs @@ -95,7 +95,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public async void TwoAwaitsWithDifferentAwaiterTypes() { Console.WriteLine("Before"); - if (await SimpleBoolTaskMethod()) { + if (await SimpleBoolTaskMethod()) + { await Task.Delay(TimeSpan.FromSeconds(1.0)); } Console.WriteLine("After"); @@ -103,7 +104,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public async void AwaitInLoopCondition() { - while (await SimpleBoolTaskMethod()) { + while (await SimpleBoolTaskMethod()) + { Console.WriteLine("Body"); } } @@ -111,14 +113,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty #if CS60 public async Task AwaitInCatch(bool b, Task task1, Task task2) { - try { + try + { Console.WriteLine("Start try"); await task1; Console.WriteLine("End try"); - } catch (Exception) { - if (!b) { + } + catch (Exception) + { + if (!b) + { await task2; - } else { + } + else + { Console.WriteLine("No await"); } } @@ -126,14 +134,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public async Task AwaitInFinally(bool b, Task task1, Task task2) { - try { + try + { Console.WriteLine("Start try"); await task1; Console.WriteLine("End try"); - } finally { - if (!b) { + } + finally + { + if (!b) + { await task2; - } else { + } + else + { Console.WriteLine("No await"); } } @@ -144,7 +158,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { await Task.Delay(100); int num = 0; - foreach (int item in items) { + foreach (int item in items) + { num += item; } return num; @@ -174,13 +189,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static async Task InfiniteLoop() { - while (true) { + while (true) + { } } public static async Task InfiniteLoopWithAwait() { - while (true) { + while (true) + { await Task.Delay(10); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncForeach.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncForeach.cs index 2dc7a2a42..2beb02547 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncForeach.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncForeach.cs @@ -27,8 +27,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public async Task SumIntegers(IAsyncEnumerable items, CancellationToken token) { int sum = 0; - await foreach (int item in items.WithCancellation(token)) { - if (token.IsCancellationRequested) { + await foreach (int item in items.WithCancellation(token)) + { + if (token.IsCancellationRequested) + { break; } sum += item; @@ -39,8 +41,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public async Task MaxInteger(IAsyncEnumerable items) { int max = int.MinValue; - await foreach (int item in items) { - if (item > max) { + await foreach (int item in items) + { + if (item > max) + { max = item; } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs index dcce5f293..76b2d8a5c 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncStreams.cs @@ -10,7 +10,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { public static async IAsyncEnumerable CountTo(int until) { - for (int i = 0; i < until; i++) { + for (int i = 0; i < until; i++) + { yield return i; await Task.Delay(10); } @@ -24,14 +25,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static async IAsyncEnumerator InfiniteLoop() { - while (true) { + while (true) + { } yield break; } public static async IAsyncEnumerable InfiniteLoopWithAwait() { - while (true) { + while (true) + { await Task.Delay(10); } yield break; @@ -39,11 +42,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public async IAsyncEnumerable AwaitInFinally() { - try { + try + { Console.WriteLine("try"); yield return 1; Console.WriteLine("end try"); - } finally { + } + finally + { Console.WriteLine("finally"); await Task.Yield(); Console.WriteLine("end finally"); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncUsing.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncUsing.cs index 98b3ce07b..7049333aa 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncUsing.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncUsing.cs @@ -25,28 +25,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static async void TestAsyncUsing(IAsyncDisposable disposable) { - await using (disposable) { + await using (disposable) + { Console.WriteLine("Hello"); } } public static async void TestAsyncUsingClass() { - await using (AsyncDisposableClass test = new AsyncDisposableClass()) { + await using (AsyncDisposableClass test = new AsyncDisposableClass()) + { Use(test); } } public static async void TestAsyncUsingStruct() { - await using (AsyncDisposableStruct asyncDisposableStruct = default(AsyncDisposableStruct)) { + await using (AsyncDisposableStruct asyncDisposableStruct = default(AsyncDisposableStruct)) + { Use(asyncDisposableStruct); } } public static async void TestAsyncUsingNullableStruct() { - await using (AsyncDisposableStruct? asyncDisposableStruct = new AsyncDisposableStruct?(default(AsyncDisposableStruct))) { + await using (AsyncDisposableStruct? asyncDisposableStruct = new AsyncDisposableStruct?(default(AsyncDisposableStruct))) + { Use(asyncDisposableStruct); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs index 80b6a7c83..d71c17281 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CheckedUnchecked.cs @@ -52,8 +52,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForWithCheckedIteratorAndUncheckedBody(int n) { - checked { - for (int i = n + 1; i < n + 1; i++) { + checked + { + for (int i = n + 1; i < n + 1; i++) + { n = unchecked(i * i); } } @@ -62,7 +64,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForWithCheckedInitializerAndUncheckedIterator(int n) { int num = n; - for (num = checked(num - 10); num < n; num++) { + for (num = checked(num - 10); num < n; num++) + { n--; } } @@ -111,13 +114,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public short Unbox(TypeCode c, object b) { - checked { - switch (c) { + checked + { + switch (c) + { case TypeCode.Int32: return (short)((Box)b).Value; case TypeCode.UInt32: return (short)((Box)b).Value; - case TypeCode.Double: { + case TypeCode.Double: + { float num = (float)((Box)b).Value; Console.WriteLine(num); return (short)num; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs index a441c3a55..7e81a8282 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs @@ -45,12 +45,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public bool HasIndex; public int Field; } - + public class MutableClass { public int Field; public short ShortField; - + public int Property { get; set; @@ -65,7 +65,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty get; set; } - + public uint this[string name] { get { return 0u; @@ -500,27 +500,27 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return new MutableClass(); } - + private int[,] Array() { return null; } - + private unsafe int* GetPointer() { return null; } - + public int GetIndex() { return new Random().Next(0, 100); } - + public int[] GetArray() { throw new NotImplementedException(); } - + public int GetValue(int value) { return value; @@ -530,7 +530,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return a == 'A'; } - + public void Int32_Local_Add(int i) { i++; @@ -539,7 +539,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty i += 5; Console.WriteLine(i += 5); } - + public void Int32_Local_Sub(int i) { i--; @@ -548,61 +548,61 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty i -= 5; Console.WriteLine(i -= 5); } - + public void Int32_Local_Mul(int i) { i *= 5; Console.WriteLine(i *= 5); } - + public void Int32_Local_Div(int i) { i /= 5; Console.WriteLine(i /= 5); } - + public void Int32_Local_Rem(int i) { i %= 5; Console.WriteLine(i %= 5); } - + public void Int32_Local_BitAnd(int i) { i &= 5; Console.WriteLine(i &= 5); } - + public void Int32_Local_BitOr(int i) { i |= 5; Console.WriteLine(i |= 5); } - + public void Int32_Local_BitXor(int i) { i ^= 5; Console.WriteLine(i ^= 5); } - + public void Int32_Local_ShiftLeft(int i) { i <<= 5; Console.WriteLine(i <<= 5); } - + public void Int32_Local_ShiftRight(int i) { i >>= 5; Console.WriteLine(i >>= 5); } - + public void IntegerWithInline(int i) { Console.WriteLine(i += 5); Console.WriteLine(i); } - + public void IntegerField(int i) { Console.WriteLine(test1 += i); @@ -610,27 +610,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(test1 -= i); Console.WriteLine(test1); } - + public void Array(int i) { Console.WriteLine(array1[i] += i); Console.WriteLine(array1[i * 2] += i * 2); } - + public int ArrayUsageWithMethods() { return GetArray()[GetIndex()]++; } - + public void NestedField() { - if (field1.HasIndex) { + if (field1.HasIndex) + { Console.WriteLine(field1.Field *= 2); field1.Field++; Console.WriteLine(field1.Field++); } } - + public void Enum() { enumField |= MyEnum.Two; @@ -651,7 +652,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return i + ++j; } - + public int PreIncrementArrayElement(int[] array, int pos) { return --array[pos]; @@ -706,7 +707,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return ++M().Field; } - + public int PostIncrementInstanceField() { return M().Field++; @@ -731,7 +732,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return ++m.Field; } - + public int PostIncrementInstanceField2(MutableClass m) { return m.Field++; @@ -4587,9 +4588,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // The 'chars[i]' result is stored in a temporary, and both branches use the // same temporary. In order to inline the generated value-type temporary, we // need to split it, even though it has the address taken for the ToString() call. - if (flag) { + if (flag) + { strings[1] += chars[i]; - } else { + } + else + { strings[0] += chars[i]; } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributeConflicts.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributeConflicts.cs index 3d293496d..93072782e 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributeConflicts.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomAttributeConflicts.cs @@ -1,8 +1,9 @@ -using CustomAttributeConflicts.NS1; +using System; + +using CustomAttributeConflicts.NS1; using CustomAttributeConflicts.NS2; using CustomAttributeConflicts.NSWithConflictingTypes; using CustomAttributeConflicts.NSWithConflictingTypes2; -using System; namespace CustomAttributeConflicts { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomShortCircuitOperators.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomShortCircuitOperators.cs index cd91f5c37..84a033f06 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomShortCircuitOperators.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomShortCircuitOperators.cs @@ -82,13 +82,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.CustomShortCircuitOperat private static void Test2() { - if (GetC(1) && GetC(2)) { + if (GetC(1) && GetC(2)) + { Console.WriteLine(GetC(3)); } - if (GetC(1) || GetC(2)) { + if (GetC(1) || GetC(2)) + { Console.WriteLine(GetC(3)); } - if (!(GetC(1) && GetC(2))) { + if (!(GetC(1) && GetC(2))) + { Console.WriteLine(GetC(3)); } } @@ -96,10 +99,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.CustomShortCircuitOperat private static void Test3() { C c = new C(); - if (c) { + if (c) + { Console.WriteLine(c.ToString()); } - if (!c) { + if (!c) + { Console.WriteLine(c.ToString()); } } @@ -108,10 +113,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.CustomShortCircuitOperat { Console.WriteLine(GetC(1) && d.P); Console.WriteLine(GetC(2) || d.P); - if (GetC(3) && d.P) { + if (GetC(3) && d.P) + { Console.WriteLine(GetC(4)); } - if (GetC(5) || d.P) { + if (GetC(5) || d.P) + { Console.WriteLine(GetC(6)); } } @@ -169,14 +176,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.CustomShortCircuitOperat public void InConditionDetection() { Console.WriteLine("a"); - if (Get(1) && Get(2)) { + if (Get(1) && Get(2)) + { Console.WriteLine("b"); - } else { + } + else + { Console.WriteLine("c"); } - if (Get(1) || Get(2)) { + if (Get(1) || Get(2)) + { Console.WriteLine("d"); - } else { + } + else + { Console.WriteLine("e"); } } @@ -185,10 +198,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.CustomShortCircuitOperat { Console.WriteLine(Get(1) && d.P); Console.WriteLine(Get(2) || d.P); - if (Get(3) && d.P) { + if (Get(3) && d.P) + { Console.WriteLine(Get(4)); } - if (Get(5) || d.P) { + if (Get(5) || d.P) + { Console.WriteLine(Get(6)); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomTaskType.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomTaskType.cs index 01b70b6c5..77b6ff1ea 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomTaskType.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomTaskType.cs @@ -44,7 +44,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public async void TwoAwaitsWithDifferentAwaiterTypes() { Console.WriteLine("Before"); - if (await SimpleBoolTaskMethod()) { + if (await SimpleBoolTaskMethod()) + { await Task.Delay(TimeSpan.FromSeconds(1.0)); } Console.WriteLine("After"); @@ -52,21 +53,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public async void AwaitInLoopCondition() { - while (await SimpleBoolTaskMethod()) { + while (await SimpleBoolTaskMethod()) + { Console.WriteLine("Body"); } } public async ValueTask AwaitInCatch(bool b, ValueTask task1, ValueTask task2) { - try { + try + { Console.WriteLine("Start try"); await task1; Console.WriteLine("End try"); - } catch (Exception) { - if (!b) { + } + catch (Exception) + { + if (!b) + { await task2; - } else { + } + else + { Console.WriteLine("No await"); } } @@ -74,14 +82,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public async ValueTask AwaitInFinally(bool b, ValueTask task1, ValueTask task2) { - try { + try + { Console.WriteLine("Start try"); await task1; Console.WriteLine("End try"); - } finally { - if (!b) { + } + finally + { + if (!b) + { await task2; - } else { + } + else + { Console.WriteLine("No await"); } } @@ -91,7 +105,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { await Task.Delay(100); int num = 0; - foreach (int item in items) { + foreach (int item in items) + { num += item; } return num; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DeconstructionTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DeconstructionTests.cs index 566a56c3e..625266dbc 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DeconstructionTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DeconstructionTests.cs @@ -581,14 +581,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void DeconstructDictionaryForEach(Dictionary dictionary) { - foreach (var (str, num2) in dictionary) { + foreach (var (str, num2) in dictionary) + { Console.WriteLine(str + ": " + num2); } } public void DeconstructTupleListForEach(List<(string, int)> tuples) { - foreach (var (str, num) in tuples) { + foreach (var (str, num) in tuples) + { Console.WriteLine(str + ": " + num); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs index 8d5f6fdab..32f24b93e 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs @@ -48,8 +48,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public Action CaptureOfThisAndParameterInForEach(int a) { - foreach (int item in Enumerable.Empty()) { - if (item > 0) { + foreach (int item in Enumerable.Empty()) + { + if (item > 0) + { return delegate { CaptureOfThisAndParameter(item + a); }; @@ -60,9 +62,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a) { - foreach (int item in Enumerable.Empty()) { + foreach (int item in Enumerable.Empty()) + { int copyOfItem = item; - if (item > 0) { + if (item > 0) + { return delegate { CaptureOfThisAndParameter(item + a + copyOfItem); }; @@ -73,7 +77,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void LambdaInForLoop() { - for (int i = 0; i < 100000; i++) { + for (int i = 0; i < 100000; i++) + { Bar(() => Foo()); } } @@ -96,7 +101,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void Bug951(int amount) { DoAction(delegate { - if (amount < 0) { + if (amount < 0) + { amount = 0; } DoAction(delegate { @@ -109,7 +115,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { int amount = Foo(); DoAction(delegate { - if (amount < 0) { + if (amount < 0) + { amount = 0; } DoAction(delegate { @@ -225,7 +232,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public Func GetFunc(Func f) { TCaptured captured = f(); - return delegate(TNonCaptured a, TNonCapturedMP d) { + return delegate (TNonCaptured a, TNonCapturedMP d) { Console.WriteLine(a.GetHashCode()); Console.WriteLine(captured.GetType().FullName); return captured; @@ -248,10 +255,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static Predicate And(this Predicate filter1, Predicate filter2) { - if (filter1 == null) { + if (filter1 == null) + { return filter2; } - if (filter2 == null) { + if (filter2 == null) + { return filter1; } return (T m) => filter1(m) && filter2(m); @@ -295,9 +304,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static List> AnonymousMethodStoreWithinLoop() { List> list = new List>(); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) + { int counter; - list.Add(delegate(int x) { + list.Add(delegate (int x) { counter = x; }); } @@ -308,8 +318,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { List> list = new List>(); int counter; - for (int i = 0; i < 10; i++) { - list.Add(delegate(int x) { + for (int i = 0; i < 10; i++) + { + list.Add(delegate (int x) { counter = x; }); } @@ -331,11 +342,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // k is local in main method // Ensure that the decompiler doesn't introduce name conflicts List> list = new List>(); - for (int k = 0; k < 10; k++) { + for (int k = 0; k < 10; k++) + { int i; - for (i = 0; i < 10; i++) { - list.Add(delegate(int j) { - for (int l = 0; l < i; l += j) { + for (i = 0; i < 10; i++) + { + list.Add(delegate (int j) { + for (int l = 0; l < i; l += j) + { Console.WriteLine(); } }); @@ -346,8 +360,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void NameConflict2(int j) { List> list = new List>(); - for (int k = 0; k < 10; k++) { - list.Add(delegate(int i) { + for (int k = 0; k < 10; k++) + { + list.Add(delegate (int i) { Console.WriteLine(i); }); } @@ -355,8 +370,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static Action NameConflict3(int i) { - return delegate(int j) { - for (int k = 0; k < j; k++) { + return delegate (int j) { + for (int k = 0; k < j; k++) + { Console.WriteLine(k); } }; @@ -450,10 +466,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { Issue1867 m1; Issue1867 m2; - if (x.value > value) { + if (x.value > value) + { m1 = this; m2 = x; - } else { + } + else + { m1 = x; m2 = this; } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs index 3f6ab5112..4ee345c28 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DynamicTests.cs @@ -126,9 +126,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private static void DynamicThrow() { - try { + try + { throw (Exception)field; - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.ToString()); throw; } @@ -247,7 +250,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private static void CheckedArithmeticBinaryOperators(dynamic a, dynamic b) { - checked { + checked + { DynamicTests.MemberAccess(a + b); DynamicTests.MemberAccess(a + 1); DynamicTests.MemberAccess(a + null); @@ -268,7 +272,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private static void UncheckedArithmeticBinaryOperators(dynamic a, dynamic b) { - checked { + checked + { DynamicTests.MemberAccess(a + b); DynamicTests.MemberAccess(a + 1); DynamicTests.MemberAccess(a + null); @@ -375,37 +380,44 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private static void Loops(dynamic list) { - foreach (dynamic item in list) { + foreach (dynamic item in list) + { DynamicTests.UnaryOperators(item); } } private static void If(dynamic a, dynamic b) { - if (a == b) { + if (a == b) + { Console.WriteLine("Equal"); } } private static void If2(dynamic a, dynamic b) { - if (a == null || b == null) { + if (a == null || b == null) + { Console.WriteLine("One is null"); } } private static void If3(dynamic a, dynamic b) { - if (a == null && b == null) { + if (a == null && b == null) + { Console.WriteLine("Both are null"); } } private static void If4(dynamic a, dynamic b) { - if ((a == null || b == null) && GetDynamic(1) && !(GetDynamic(2) && GetDynamic(3))) { + if ((a == null || b == null) && GetDynamic(1) && !(GetDynamic(2) && GetDynamic(3))) + { Console.WriteLine("then"); - } else { + } + else + { Console.WriteLine("else"); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.cs index 1472eda8f..8cfdfa74f 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.cs @@ -33,21 +33,28 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public bool ConditionalReturnInThrow() { - try { - if (B(0)) { + try + { + if (B(0)) + { return B(1); } - } catch { + } + catch + { } return false; } public bool SimpleTryCatchException() { - try { + try + { Console.WriteLine("Try"); return B(new Random().Next()); - } catch (Exception) { + } + catch (Exception) + { Console.WriteLine("CatchException"); } return false; @@ -55,10 +62,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public bool SimpleTryCatchExceptionWithName() { - try { + try + { Console.WriteLine("Try"); return B(new Random().Next()); - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine("CatchException ex: " + ex.ToString()); } return false; @@ -67,10 +77,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty #if CS60 public bool SimpleTryCatchExceptionWithNameAndCondition() { - try { + try + { Console.WriteLine("Try"); return B(new Random().Next()); - } catch (Exception ex) when (ex.Message.Contains("test")) { + } + catch (Exception ex) when (ex.Message.Contains("test")) + { Console.WriteLine("CatchException ex: " + ex.ToString()); } return false; @@ -78,10 +91,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public bool SimpleTryCatchExceptionWithNameAndConditionWithOr() { - try { + try + { Console.WriteLine("Try"); return B(new Random().Next()); - } catch (Exception ex) when (ex is ArgumentException || ex is IOException) { + } + catch (Exception ex) when (ex is ArgumentException || ex is IOException) + { Console.WriteLine("CatchException ex: " + ex.ToString()); } return false; @@ -89,10 +105,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public async Task SimpleAsyncTryCatchExceptionWithNameAndConditionWithOr() { - try { + try + { Console.WriteLine("Try"); return await T(); - } catch (Exception ex) when (ex is ArgumentException || ex is IOException) { + } + catch (Exception ex) when (ex is ArgumentException || ex is IOException) + { Console.WriteLine("CatchException ex: " + ex.ToString()); } return false; @@ -101,9 +120,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void CatchWhenWithConditionWithoutExceptionVar() { int num = 0; - try { + try + { throw new Exception(); - } catch (Exception) when (num == 0) { + } + catch (Exception) when (num == 0) + { Console.WriteLine("jo"); } } @@ -112,9 +134,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public bool SimpleTryFinally() { - try { + try + { Console.WriteLine("Try"); - } finally { + } + finally + { Console.WriteLine("Finally"); } return false; @@ -122,42 +147,60 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void MethodEndingWithEndFinally() { - try { + try + { throw null; - } finally { + } + finally + { Console.WriteLine(); } } public void MethodEndingWithRethrow() { - try { + try + { throw null; - } catch { + } + catch + { throw; } } public void TryCatchFinally() { - try { + try + { Console.WriteLine("Try"); - } catch (Exception ex) { + } + catch (Exception ex) + { Console.WriteLine(ex.Message); - } finally { + } + finally + { Console.WriteLine("Finally"); } } public void TryCatchMultipleHandlers() { - try { + try + { Console.WriteLine("Try"); - } catch (InvalidOperationException ex) { + } + catch (InvalidOperationException ex) + { Console.WriteLine(ex.Message); - } catch (SystemException ex2) { + } + catch (SystemException ex2) + { Console.WriteLine(ex2.Message); - } catch { + } + catch + { Console.WriteLine("other"); } } @@ -179,10 +222,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void NoUsingStatementBecauseTheVariableIsAssignedTo() { CancellationTokenSource cancellationTokenSource = null; - try { + try + { cancellationTokenSource = new CancellationTokenSource(); - } finally { - if (cancellationTokenSource != null) { + } + finally + { + if (cancellationTokenSource != null) + { cancellationTokenSource.Dispose(); } } @@ -190,8 +237,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ThrowInFinally() { - try { - } finally { + try + { + } + finally + { throw new Exception(); } } @@ -214,14 +264,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty //} public bool EarlyExitInLoopTry() { - while (true) { - try { - if (!B(0)) { + while (true) + { + try + { + if (!B(0)) + { return false; } Console.WriteLine(); - } catch { + } + catch + { } } } @@ -229,14 +284,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public bool ComplexConditionalReturnInThrow() { - try { - if (B(0)) { - if (B(1)) { + try + { + if (B(0)) + { + if (B(1)) + { Console.WriteLine("0 && 1"); return B(2); } - if (B(3)) { + if (B(3)) + { Console.WriteLine("0 && 3"); return !B(2); } @@ -246,22 +305,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine("End Try"); - } catch { - try { - try { - if (((B(0) || B(1)) && B(2)) || B(3)) { + } + catch + { + try + { + try + { + if (((B(0) || B(1)) && B(2)) || B(3)) + { return B(4) && !B(5); } - if (B(6) || B(7)) { + if (B(6) || B(7)) + { return B(8) || B(9); } - } catch { + } + catch + { Console.WriteLine("Catch2"); } return B(10) && B(11); - } catch { + } + catch + { Console.WriteLine("Catch"); - } finally { + } + finally + { Console.WriteLine("Finally"); } } @@ -271,12 +342,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void AppropriateLockExit() { int num = 0; - lock (this) { - if (num <= 256) { + lock (this) + { + if (num <= 256) + { Console.WriteLine(0); - } else if (num <= 1024) { + } + else if (num <= 1024) + { Console.WriteLine(1); - } else if (num <= 16384) { + } + else if (num <= 16384) + { Console.WriteLine(2); } } @@ -284,10 +361,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ReassignExceptionVar() { - try { + try + { Console.WriteLine("ReassignExceptionVar"); - } catch (Exception innerException) { - if (innerException.InnerException != null) { + } + catch (Exception innerException) + { + if (innerException.InnerException != null) + { innerException = innerException.InnerException; } Console.WriteLine(innerException); @@ -297,9 +378,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public int UseExceptionVarOutsideCatch() { Exception ex2; - try { + try + { return 1; - } catch (Exception ex) { + } + catch (Exception ex) + { ex2 = ex; } Console.WriteLine(ex2 != null); @@ -308,9 +392,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void GenericException(int input) where TException : Exception { - try { + try + { Console.WriteLine(input); - } catch (TException val) { + } + catch (TException val) + { Console.WriteLine(val.Message); throw; } @@ -318,14 +405,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void GenericException2() where T : Exception { - try { + try + { Console.WriteLine("CatchT"); #if ROSLYN - } catch (T val) { + } + catch (T val) + { Console.WriteLine("{0} {1}", val, val.ToString()); } #else - } catch (T arg) { + } + catch (T arg) + { Console.WriteLine("{0} {1}", arg, arg.ToString()); } #endif @@ -334,9 +426,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty #if CS60 public void GenericExceptionWithCondition(int input) where TException : Exception { - try { + try + { Console.WriteLine(input); - } catch (TException val) when (val.Message.Contains("Test")) { + } + catch (TException val) when (val.Message.Contains("Test")) + { Console.WriteLine(val.Message); throw; } @@ -344,9 +439,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void GenericException2WithCondition(int input) where TException : Exception { - try { + try + { Console.WriteLine(input); - } catch (TException val) when (val.Message.Contains("Test")) { + } + catch (TException val) when (val.Message.Contains("Test")) + { Console.WriteLine("{0} {1}", val, val.ToString()); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs index 4bcc19f1a..b140ed306 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs @@ -332,7 +332,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private void Issue1249(int ID) { - if (ID == 0) { + if (ID == 0) + { ViewBag.data = "''"; return; } @@ -960,15 +961,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Test>((int a) => a.ToString(), (int a) => a.ToString()); Test>((string a) => a.ToArray(), (string a) => a.ToArray()); Test>(() => 'a'.CompareTo('b') < 0, () => 'a'.CompareTo('b') < 0); - Test>(delegate(object lockObj, bool lockTaken) { + Test>(delegate (object lockObj, bool lockTaken) { Monitor.Enter(lockObj, ref lockTaken); }, (object lockObj, bool lockTaken) => Monitor.Enter(lockObj, ref lockTaken)); Test>((string str, int num) => int.TryParse(str, out num), (string str, int num) => int.TryParse(str, out num)); Test>((string str, SimpleType t) => int.TryParse(str, out t.Field), (string str, SimpleType t) => int.TryParse(str, out t.Field)); - Test>(delegate(object o) { + Test>(delegate (object o) { TestCall(o); }, (object o) => TestCall(o)); - Test>(delegate(object o) { + Test>(delegate (object o) { TestCall(ref o); }, (object o) => TestCall(ref o)); } @@ -1038,10 +1039,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { await Task.Delay(100); #if CS70 - if (string.IsNullOrEmpty(str) && int.TryParse(str, out int id)) { + if (string.IsNullOrEmpty(str) && int.TryParse(str, out int id)) + { #else int id; - if (string.IsNullOrEmpty(str) && int.TryParse(str, out id)) { + if (string.IsNullOrEmpty(str) && int.TryParse(str, out id)) + { #endif (from a in new List().AsQueryable() where a == id diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs index 6b48c4f9b..58cc8cbd0 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs @@ -96,10 +96,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty protected internal override void Test(string test) { - action = delegate(string a) { + action = delegate (string a) { base.Test(a); }; - if (test.Equals(1)) { + if (test.Equals(1)) + { throw new Exception("roslyn optimizes is inlining the assignment which lets the test fail"); } action(test); @@ -118,7 +119,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty { public Action M(object state) { - return delegate(object x) { + return delegate (object x) { base.BaseCall(x, state, (Func)(() => null)); }; } @@ -138,7 +139,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty Action action = delegate { base.Test(a); }; - if (a.Equals(1)) { + if (a.Equals(1)) + { throw new Exception("roslyn optimize is inlining the assignment which lets the test fail"); } action(); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs index 6dfb19368..2ae08c5ca 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Generics.cs @@ -73,7 +73,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void Grow(int capacity) { - if (capacity >= arr.Length) { + if (capacity >= arr.Length) + { Size(capacity); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs index 0aa2ecae5..abc96c66c 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InitializerTests.cs @@ -1233,9 +1233,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests } }; } -#endregion + #endregion -#region Object initializers + #region Object initializers public C Test1() { C c = new C(); @@ -1537,7 +1537,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests private Data Issue1279(int p) { - if (p == 1) { + if (p == 1) + { Data data = new Data(); data.a = MyEnum.a; data.TestEvent += Data_TestEvent; @@ -1546,9 +1547,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests return null; } -#endregion + #endregion -#region Collection initializer + #region Collection initializer public static void ExtensionMethodInCollectionInitializer() { @@ -1733,6 +1734,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.InitializerTests } #endif -#endregion - } + #endregion + } } \ No newline at end of file diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs index 8ca021f08..595dc2b82 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs @@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(GetFormat(), value = new InlineAssignmentTest()); Console.WriteLine(value); } - + public void SimpleInlineWithFields() { Console.WriteLine(field1 = 5); @@ -71,7 +71,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty UseShort(field4 = UseShort(0)); Console.WriteLine(field4); } - + public short UseShort(short s) { Console.WriteLine(s); @@ -81,7 +81,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ReadLoop1(TextReader r) { string value; - while ((value = r.ReadLine()) != null) { + while ((value = r.ReadLine()) != null) + { Console.WriteLine(value); } } @@ -92,32 +93,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(num = a[0]); Console.WriteLine(a[num] = num); } - + public int Return(ref int a) { return a = 3; } - + public int Array(int[] a, int i) { return a[i] = i; } - + public int Array2(int i) { return field3[i] = 1; } - + public int GetIndex() { return new Random().Next(0, 100); } - + public int[] GetArray() { throw new NotImplementedException(); } - + public string GetFormat() { return "{0}"; @@ -127,7 +128,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return value; } - + public int ArrayUsageWithMethods() { return GetArray()[GetIndex()] = GetValue(GetIndex()); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue1080.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue1080.cs index 45d437c94..340625bc2 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue1080.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue1080.cs @@ -13,7 +13,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080 private static void Test(object obj) { ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080.SpaceA.Type2 type = obj as ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080.SpaceA.Type2; - if (type != null) { + if (type != null) + { ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue1080.SpaceC.Extensions.Extension(type); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.cs index 0052e99db..56f9c2729 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LiftedOperators.cs @@ -30,54 +30,67 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void BoolBasic(bool? a, bool? b) { - if (a == b) { + if (a == b) + { Console.WriteLine(); } - if (a != b) { + if (a != b) + { Console.WriteLine(); } } public static void BoolComplex(bool? a, Func x) { - if (a == x()) { + if (a == x()) + { Console.WriteLine(); } - if (a != x()) { + if (a != x()) + { Console.WriteLine(); } - if (x() == a) { + if (x() == a) + { Console.WriteLine(); } - if (x() != a) { + if (x() != a) + { Console.WriteLine(); } - if (a ?? x()) { + if (a ?? x()) + { Console.WriteLine(); } } public static void BoolConst(bool? a) { - if (a == true) { + if (a == true) + { Console.WriteLine(); } - if (a != true) { + if (a != true) + { Console.WriteLine(); } - if (a == false) { + if (a == false) + { Console.WriteLine(); } - if (a != false) { + if (a != false) + { Console.WriteLine(); } - if (a ?? true) { + if (a ?? true) + { Console.WriteLine(); } #if !ROSLYN // Roslyn 3 (VS2019) started optimizing this to "a.GetValueOrDefault()" - if (a ?? false) { + if (a ?? false) + { Console.WriteLine(); } #endif @@ -87,7 +100,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { Console.WriteLine(a == b); Console.WriteLine(a != b); - + Console.WriteLine(a & b); Console.WriteLine(a | b); Console.WriteLine(a ^ b); @@ -105,7 +118,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(x() == a); Console.WriteLine(x() != a); - + //Console.WriteLine(a & x()); // we currently can't tell the order //Console.WriteLine(a | x()); // of the operands in bool [&|] bool? Console.WriteLine(a ^ x()); @@ -136,82 +149,104 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void IntBasic(int? a, int? b) { - if (a == b) { + if (a == b) + { Console.WriteLine(); } - if (a != b) { + if (a != b) + { Console.WriteLine(); } - if (a > b) { + if (a > b) + { Console.WriteLine(); } - if (a < b) { + if (a < b) + { Console.WriteLine(); } - if (a >= b) { + if (a >= b) + { Console.WriteLine(); } - if (a <= b) { + if (a <= b) + { Console.WriteLine(); } - - if (!(a > b)) { + + if (!(a > b)) + { Console.WriteLine(); } - if (!(a <= b)) { + if (!(a <= b)) + { Console.WriteLine(); } } public static void IntComplex(int? a, Func x) { - if (a == x()) { + if (a == x()) + { Console.WriteLine(); } - if (a != x()) { + if (a != x()) + { Console.WriteLine(); } - if (a > x()) { + if (a > x()) + { Console.WriteLine(); } - if (x() == a) { + if (x() == a) + { Console.WriteLine(); } - if (x() != a) { + if (x() != a) + { Console.WriteLine(); } - if (x() > a) { + if (x() > a) + { Console.WriteLine(); } - if (!(a > x())) { + if (!(a > x())) + { Console.WriteLine(); } - if (!(a <= x())) { + if (!(a <= x())) + { Console.WriteLine(); } } public static void IntConst(int? a) { - if (a == 2) { + if (a == 2) + { Console.WriteLine(); } - if (a != 2) { + if (a != 2) + { Console.WriteLine(); } - if (a > 2) { + if (a > 2) + { Console.WriteLine(); } - if (2 == a) { + if (2 == a) + { Console.WriteLine(); } - if (2 != a) { + if (2 != a) + { Console.WriteLine(); } - if (2 > a) { + if (2 > a) + { Console.WriteLine(); } } @@ -221,7 +256,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(a == b); Console.WriteLine(a != b); Console.WriteLine(a > b); - + Console.WriteLine(!(a > b)); Console.WriteLine(!(a >= b)); @@ -328,36 +363,45 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void NumberBasic(decimal? a, decimal? b) { - if (a == b) { + if (a == b) + { Console.WriteLine(); } #if ROSLYN // Roslyn 2.9 started invoking op_Equality even if the source code says 'a != b' - if (!(a == b)) { + if (!(a == b)) + { Console.WriteLine(); } #else - if (a != b) { + if (a != b) + { Console.WriteLine(); } #endif - if (a > b) { + if (a > b) + { Console.WriteLine(); } - if (a < b) { + if (a < b) + { Console.WriteLine(); } - if (a >= b) { + if (a >= b) + { Console.WriteLine(); } - if (a <= b) { + if (a <= b) + { Console.WriteLine(); } - if (!(a > b)) { + if (!(a > b)) + { Console.WriteLine(); } - if (!(a < b)) { + if (!(a < b)) + { Console.WriteLine(); } } @@ -502,10 +546,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void CompareWithImplictCast(int? a, long? b) { - if (a < b) { + if (a < b) + { Console.WriteLine(); } - if (a == b) { + if (a == b) + { Console.WriteLine(); } // TODO: unnecessary cast @@ -519,7 +565,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void CompareWithSignChange(int? a, int? b) { - if ((uint?)a < (uint?)b) { + if ((uint?)a < (uint?)b) + { Console.WriteLine(); } // TODO: unnecessary cast @@ -530,32 +577,41 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void StructBasic(TS? a, TS? b) { - if (a == b) { + if (a == b) + { Console.WriteLine(); } - if (a != b) { + if (a != b) + { Console.WriteLine(); } - if (a > b) { + if (a > b) + { Console.WriteLine(); } - if (a < b) { + if (a < b) + { Console.WriteLine(); } - if (a >= b) { + if (a >= b) + { Console.WriteLine(); } - if (a <= b) { + if (a <= b) + { Console.WriteLine(); } - if (!(a == b)) { + if (!(a == b)) + { Console.WriteLine(); } - if (!(a != b)) { + if (!(a != b)) + { Console.WriteLine(); } - if (!(a > b)) { + if (!(a > b)) + { Console.WriteLine(); } } @@ -785,7 +841,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void CheckedCasts(int? i4, long? i8, float? f) { - checked { + checked + { Print((byte?)i4); Print((short?)i4); Print((uint?)i4); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs index ff0ee4f62..292688f7d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs @@ -36,7 +36,8 @@ namespace LocalFunctions #pragma warning disable CS0219 T2 t2 = default(T2); object z = this; - for (int j = 0; j < 10; j++) { + for (int j = 0; j < 10; j++) + { int i = 0; i += NonStaticMethod6(0); #if CS90 @@ -115,7 +116,8 @@ namespace LocalFunctions { T2 t2 = default(T2); object z = this; - for (int j = 0; j < 10; j++) { + for (int j = 0; j < 10; j++) + { int i = 0; i += StaticInvokeAsFunc(NonStaticMethod6); int NonStaticMethod6() @@ -366,7 +368,8 @@ namespace LocalFunctions public static void StaticContextNoCapture(int length) { - for (int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) + { LocalWrite("Hello " + i); } @@ -382,7 +385,8 @@ namespace LocalFunctions public static void StaticContextSimpleCapture(int length) { - for (int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) + { LocalWrite(); } @@ -395,7 +399,8 @@ namespace LocalFunctions public static void StaticContextCaptureForLoopVariable(int length) { int i; - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++) + { LocalWrite(); } void LocalWrite() @@ -406,7 +411,8 @@ namespace LocalFunctions public void ContextNoCapture() { - for (int i = 0; i < field; i++) { + for (int i = 0; i < field; i++) + { LocalWrite("Hello " + i); } @@ -422,7 +428,8 @@ namespace LocalFunctions public void ContextSimpleCapture() { - for (int i = 0; i < field; i++) { + for (int i = 0; i < field; i++) + { LocalWrite(); } @@ -435,7 +442,8 @@ namespace LocalFunctions public void ContextCaptureForLoopVariable() { int i; - for (i = 0; i < field; i++) { + for (i = 0; i < field; i++) + { LocalWrite(); } void LocalWrite() @@ -447,7 +455,8 @@ namespace LocalFunctions public void CapturedOutsideLoop() { int i = 0; - while (i < field) { + while (i < field) + { i = GetInt("asdf"); LocalWrite(); } @@ -460,7 +469,8 @@ namespace LocalFunctions public void CapturedInForeachLoop(IEnumerable args) { - foreach (string arg2 in args) { + foreach (string arg2 in args) + { string arg = arg2; LocalWrite(); void LocalWrite() @@ -563,7 +573,8 @@ namespace LocalFunctions int FibHelper(int n) #endif { - if (n <= 0) { + if (n <= 0) + { return 0; } @@ -580,7 +591,8 @@ namespace LocalFunctions int A(int i) #endif { - if (i > 0) { + if (i > 0) + { return A(i - 1) + 2 * B(i - 1) + 3 * C(i - 1); } return 1; @@ -592,7 +604,8 @@ namespace LocalFunctions int B(int i) #endif { - if (i > 0) { + if (i > 0) + { return 3 * A(i - 1) + B(i - 1); } return 1; @@ -604,7 +617,8 @@ namespace LocalFunctions int C(int i) #endif { - if (i > 0) { + if (i > 0) + { return 2 * A(i - 1) + C(i - 1); } return 1; @@ -629,7 +643,7 @@ namespace LocalFunctions public static int LocalFunctionInLambda(IEnumerable xs) { - return xs.First(delegate(int x) { + return xs.First(delegate (int x) { return Do(); bool Do() @@ -645,7 +659,8 @@ namespace LocalFunctions IEnumerable GetNumbers() { - for (int i = 0; i < n; i++) { + for (int i = 0; i < n; i++) + { yield return i; } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Lock.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Lock.cs index dd475ceb6..4704c2767 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Lock.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Lock.cs @@ -24,14 +24,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { public void LockThis() { - lock (this) { + lock (this) + { Console.WriteLine(); } } public void LockOnType() { - lock (typeof(Lock)) { + lock (typeof(Lock)) + { Console.WriteLine(); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs index 220bd873d..a5405103f 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs @@ -290,14 +290,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForEachOnField() { - foreach (string alternative in alternatives) { + foreach (string alternative in alternatives) + { alternative.ToLower(); } } public void ForEach(IEnumerable alternatives) { - foreach (string alternative in alternatives) { + foreach (string alternative in alternatives) + { alternative.ToLower(); } } @@ -305,35 +307,40 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForEachOverList(List list) { // List has a struct as enumerator, so produces quite different IL than foreach over the IEnumerable interface - foreach (string item in list) { + foreach (string item in list) + { item.ToLower(); } } public void ForEachOverNonGenericEnumerable(IEnumerable enumerable) { - foreach (object item in enumerable) { + foreach (object item in enumerable) + { item.ToString(); } } public void ForEachOverNonGenericEnumerableWithAutomaticCastValueType(IEnumerable enumerable) { - foreach (int item in enumerable) { + foreach (int item in enumerable) + { item.ToString(); } } public void ForEachOverNonGenericEnumerableWithAutomaticCastRefType(IEnumerable enumerable) { - foreach (string item in enumerable) { + foreach (string item in enumerable) + { Console.WriteLine(item); } } public void ForEachOnCustomClassEnumerator(CustomClassEnumerator e) { - foreach (object item in e) { + foreach (object item in e) + { Console.WriteLine(item); } } @@ -350,7 +357,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForEachOnGenericCustomClassEnumerator(CustomClassEnumerator e) { - foreach (T item in e) { + foreach (T item in e) + { Console.WriteLine(item); } } @@ -367,28 +375,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForEachOnCustomClassEnumeratorWithIDisposable(CustomClassEnumeratorWithIDisposable e) { - foreach (object item in e) { + foreach (object item in e) + { Console.WriteLine(item); } } public void ForEachOnCustomStructEnumeratorWithIDisposable(CustomStructEnumeratorWithIDisposable e) { - foreach (object item in e) { + foreach (object item in e) + { Console.WriteLine(item); } } public void ForEachOnGenericCustomClassEnumeratorWithIDisposable(CustomClassEnumeratorWithIDisposable e) { - foreach (T item in e) { + foreach (T item in e) + { Console.WriteLine(item); } } public void ForEachOnGenericCustomStructEnumeratorWithIDisposable(CustomStructEnumeratorWithIDisposable e) { - foreach (T item in e) { + foreach (T item in e) + { Console.WriteLine(item); } } @@ -397,16 +409,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { Console.WriteLine("NonGenericForeachWithReturnFallback:"); IEnumerator enumerator = e.GetEnumerator(); - try { + try + { Console.WriteLine("MoveNext"); - if (enumerator.MoveNext()) { + if (enumerator.MoveNext()) + { object current = enumerator.Current; Console.WriteLine("please don't inline 'current'"); Console.WriteLine(current); } - } finally { + } + finally + { IDisposable disposable = enumerator as IDisposable; - if (disposable != null) { + if (disposable != null) + { disposable.Dispose(); } } @@ -415,7 +432,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void ForeachWithRefUsage(List items) { - foreach (int item in items) { + foreach (int item in items) + { #if ROSLYN && OPT // The variable name differs based on whether roslyn optimizes out the 'item' variable int i = item; @@ -429,7 +447,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void ForeachWithCapturedVariable(List items) { - foreach (int item in items) { + foreach (int item in items) + { int c = item; Operation(() => c == 5); } @@ -438,7 +457,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static T LastOrDefault(IEnumerable items) { T result = default(T); - foreach (T item in items) { + foreach (T item in items) + { result = item; } return result; @@ -446,14 +466,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForEachOverArray(string[] array) { - foreach (string text in array) { + foreach (string text in array) + { Console.WriteLine(text.ToLower() + text.ToUpper()); } } public unsafe void ForEachOverArrayOfPointers(int*[] array) { - foreach (int* value in array) { + foreach (int* value in array) + { Console.WriteLine(new IntPtr(value)); Console.WriteLine(new IntPtr(value)); } @@ -462,15 +484,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForEachBreakWhenFound(string name, ref StringComparison output) { #if MCS - foreach (int value in Enum.GetValues(typeof(StringComparison))) { - if (((StringComparison)value).ToString() == name) { + foreach (int value in Enum.GetValues(typeof(StringComparison))) + { + if (((StringComparison)value).ToString() == name) + { output = (StringComparison)value; break; } } #else - foreach (StringComparison value in Enum.GetValues(typeof(StringComparison))) { - if (value.ToString() == name) { + foreach (StringComparison value in Enum.GetValues(typeof(StringComparison))) + { + if (value.ToString() == name) + { output = value; break; } @@ -480,7 +506,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForEachOverListOfStruct(List items, int value) { - foreach (DataItem item in items) { + foreach (DataItem item in items) + { #if ROSLYN && OPT // The variable name differs based on whether roslyn optimizes out the 'item' variable DataItem current = item; @@ -494,7 +521,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForEachOverListOfStruct2(List items, int value) { - foreach (DataItem item in items) { + foreach (DataItem item in items) + { #if ROSLYN && OPT // The variable name differs based on whether roslyn optimizes out the 'item' variable DataItem current = item; @@ -510,7 +538,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForEachOverListOfStruct3(List items, int value) { - foreach (DataItem item in items) { + foreach (DataItem item in items) + { item.TestCall(); } } @@ -518,7 +547,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty #if !MCS public void ForEachOverMultiDimArray(int[,] items) { - foreach (int value in items) { + foreach (int value in items) + { Console.WriteLine(value); Console.WriteLine(value); } @@ -526,7 +556,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForEachOverMultiDimArray2(int[,,] items) { - foreach (int value in items) { + foreach (int value in items) + { Console.WriteLine(value); Console.WriteLine(value); } @@ -535,12 +566,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public unsafe void ForEachOverMultiDimArray3(int*[,] items) { #if ROSLYN && OPT - foreach (int* intPtr in items) { + foreach (int* intPtr in items) + { Console.WriteLine(*intPtr); Console.WriteLine(*intPtr); } #else - foreach (int* ptr in items) { + foreach (int* ptr in items) + { Console.WriteLine(*ptr); Console.WriteLine(*ptr); } @@ -548,20 +581,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } #endif -#endregion + #endregion public void ForOverArray(string[] array) { - for (int i = 0; i < array.Length; i++) { + for (int i = 0; i < array.Length; i++) + { array[i].ToLower(); } } public void NoForeachOverArray(string[] array) { - for (int i = 0; i < array.Length; i++) { + for (int i = 0; i < array.Length; i++) + { string value = array[i]; - if (i % 5 == 0) { + if (i % 5 == 0) + { Console.WriteLine(value); } } @@ -569,12 +605,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void NestedLoops() { - for (int i = 0; i < 10; i++) { - if (i % 2 == 0) { - for (int j = 0; j < 5; j++) { + for (int i = 0; i < 10; i++) + { + if (i % 2 == 0) + { + for (int j = 0; j < 5; j++) + { Console.WriteLine("Y"); } - } else { + } + else + { Console.WriteLine("X"); } } @@ -583,17 +624,22 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public int MultipleExits() { int num = 0; - while (true) { - if (num % 4 == 0) { + while (true) + { + if (num % 4 == 0) + { return 4; } - if (num % 7 == 0) { + if (num % 7 == 0) + { break; } - if (num % 9 == 0) { + if (num % 9 == 0) + { return 5; } - if (num % 11 == 0) { + if (num % 11 == 0) + { break; } num++; @@ -630,18 +676,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public int InterestingLoop() { int num = 0; - if (num % 11 == 0) { - while (true) { - if (num % 4 == 0) { - if (num % 7 != 0) { + if (num % 11 == 0) + { + while (true) + { + if (num % 4 == 0) + { + if (num % 7 != 0) + { Console.WriteLine("!7"); break; } - if (num % 11 != 0) { + if (num % 11 != 0) + { Console.WriteLine("7"); break; } - } else { + } + else + { num++; } } @@ -659,14 +712,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void WhileLoop() { Console.WriteLine("Initial"); - if (Condition("if")) { - while (Condition("while")) { + if (Condition("if")) + { + while (Condition("while")) + { Console.WriteLine("Loop Body"); - if (Condition("test")) { - if (Condition("continue")) { + if (Condition("test")) + { + if (Condition("continue")) + { continue; } - if (!Condition("break")) { + if (!Condition("break")) + { break; } } @@ -676,20 +734,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } Console.WriteLine("End of method"); } - + //other configurations work fine, just with different labels #if OPT && !MCS public void WhileWithGoto() { - while (Condition("Main Loop")) { - if (Condition("Condition")) { + while (Condition("Main Loop")) + { + if (Condition("Condition")) + { goto IL_000f; } // TODO reorder branches with successive block? goto IL_0026; IL_000f: Console.WriteLine("Block1"); - if (Condition("Condition2")) { + if (Condition("Condition2")) + { continue; } // TODO remove redundant goto? @@ -704,14 +765,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void DoWhileLoop() { Console.WriteLine("Initial"); - if (Condition("if")) { - do { + if (Condition("if")) + { + do + { Console.WriteLine("Loop Body"); - if (Condition("test")) { - if (Condition("continue")) { + if (Condition("test")) + { + if (Condition("continue")) + { continue; } - if (!Condition("break")) { + if (!Condition("break")) + { break; } } @@ -725,30 +791,38 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void Issue1395(int count) { Environment.GetCommandLineArgs(); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { Environment.GetCommandLineArgs(); - do { + do + { #if OPT || MCS IL_0013: #else IL_0016: #endif Environment.GetCommandLineArgs(); - if (Condition("part1")) { + if (Condition("part1")) + { Environment.GetEnvironmentVariables(); - if (Condition("restart")) { + if (Condition("restart")) + { #if OPT || MCS goto IL_0013; #else goto IL_0016; #endif } - } else { + } + else + { Environment.GetLogicalDrives(); } Environment.GetCommandLineArgs(); - while (count > 0) { - switch (count) { + while (count > 0) + { + switch (count) + { case 0: case 1: case 2: @@ -774,14 +848,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForLoop() { Console.WriteLine("Initial"); - if (Condition("if")) { - for (int i = 0; Condition("for"); i++) { + if (Condition("if")) + { + for (int i = 0; Condition("for"); i++) + { Console.WriteLine("Loop Body"); - if (Condition("test")) { - if (Condition("continue")) { + if (Condition("test")) + { + if (Condition("continue")) + { continue; } - if (!Condition("not-break")) { + if (!Condition("not-break")) + { break; } } @@ -794,15 +873,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ReturnFromDoWhileInTryFinally() { - try { - do { - if (Condition("return")) { + try + { + do + { + if (Condition("return")) + { return; } } while (Condition("repeat")); Environment.GetCommandLineArgs(); - } finally { + } + finally + { Environment.GetCommandLineArgs(); } @@ -811,10 +895,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForLoopWithEarlyReturn(int[] ids) { - for (int i = 0; i < ids.Length; i++) { + for (int i = 0; i < ids.Length; i++) + { Item item = null; TryGetItem(ids[i], out item); - if (item == null) { + if (item == null) + { break; } } @@ -822,8 +908,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ForeachLoopWithEarlyReturn(List items) { - foreach (object item in items) { - if ((someObject = item) == null) { + foreach (object item in items) + { + if ((someObject = item) == null) + { break; } } @@ -831,16 +919,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void NestedForeach(List items1, List items2) { - foreach (object item in items1) { + foreach (object item in items1) + { bool flag = false; - foreach (object item2 in items2) { - if (item2 == item) { + foreach (object item2 in items2) + { + if (item2 == item) + { flag = true; break; } } - if (!flag) { + if (!flag) + { Console.WriteLine(item); } } @@ -849,23 +941,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void MergeAroundContinue() { - for (int i = 0; i < 20; i++) { - if (i % 3 == 0) { - if (i != 6) { + for (int i = 0; i < 20; i++) + { + if (i % 3 == 0) + { + if (i != 6) + { continue; } - } else if (i % 5 == 0) { - if (i != 5) { + } + else if (i % 5 == 0) + { + if (i != 5) + { continue; } - } else if (i % 7 == 0) { - if (i != 7) { + } + else if (i % 7 == 0) + { + if (i != 7) + { continue; } - } else if (i % 11 == 0) { + } + else if (i % 11 == 0) + { continue; } - + Console.WriteLine(i); } Console.WriteLine("end"); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs index 7574f4757..69d11baa0 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs @@ -143,15 +143,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void CompoundAssign() { GetInstance(0).i += i32; - checked { + checked + { GetInstance(1).i += i32; } GetInstance(2).u *= 2u; - checked { + checked + { GetInstance(3).u *= 2u; } GetInstance(4).intptr += (nint)i32; - checked { + checked + { // Note: the cast is necessary here, without it we'd call IntPtr.op_Addition // but that is always unchecked. GetInstance(5).intptr += (nint)i32; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs index 6e927db63..fe20aa4c7 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullPropagation.cs @@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { } } - + private class Container { public GenericStruct Other; @@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return "(" + Field1?.ToString() + ", " + Field2?.ToString() + ")"; } - + public int? GetTextLength() { return Field1?.ToString().Length + Field2?.ToString().Length + 4; @@ -250,10 +250,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private void NotNullPropagation(MyClass c) { // don't decompile this to "(c?.IntVal ?? 0) != 0" - if (c != null && c.IntVal != 0) { + if (c != null && c.IntVal != 0) + { Console.WriteLine("non-zero"); } - if (c == null || c.IntVal == 0) { + if (c == null || c.IntVal == 0) + { Console.WriteLine("null or zero"); } Console.WriteLine("end of method"); @@ -261,11 +263,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private void Setter(MyClass c) { - if (c != null) { + if (c != null) + { c.IntVal = 1; } Console.WriteLine(); - if (c != null) { + if (c != null) + { c.Property = null; } } @@ -310,7 +314,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(setsOfNumbers?[0]?[1].ToString() == "2"); Console.WriteLine(setsOfNumbers?[1]?[1].ToString() == null); } - + private static dynamic DynamicNullProp(dynamic a) { return a?.b.c(1)?.d[10]; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs index 5a6916b8e..a1bdf6971 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/OutVariables.cs @@ -25,7 +25,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { public static void OutVarInShortCircuit(Dictionary d) { - if (d.Count > 2 && d.TryGetValue(42, out string value)) { + if (d.Count > 2 && d.TryGetValue(42, out string value)) + { Console.WriteLine(value); } } @@ -34,7 +35,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { // Note: needs reasoning about "definitely assigned if true" // to ensure that the value is initialized when the delegate is declared. - if (d.Count > 2 && d.TryGetValue(42, out string value)) { + if (d.Count > 2 && d.TryGetValue(42, out string value)) + { return delegate { Console.WriteLine(value); }; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs index e0274c353..7ec581a14 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/PInvoke.cs @@ -88,7 +88,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } [DllImport("ws2_32.dll", SetLastError = true)] - internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In] [Out] ref int argp); + internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In][Out] ref int argp); public void CallMethodWithInOutParameter() { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs index 35c042533..fc7fa41ba 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs @@ -264,7 +264,8 @@ namespace ICSharpCode.Decompiler.Tests.Pretty private void LocalConflictsWithTypeName() { - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) + { QualifierTests.i.Test(); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.cs index 4c9048bbf..f1c957790 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.cs @@ -165,11 +165,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty let pname = pi.Name let pvalue = pi.GetValue(customers, null) select new HbmParam { - Name = pname, - Text = new string[1] { + Name = pname, + Text = new string[1] { (pvalue == null) ? "null" : pvalue.ToString() } - }).ToArray(); + }).ToArray(); } public object Join() diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs index 8d9b4c841..f08a49b8a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ReduceNesting.cs @@ -9,12 +9,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void IfIf() { - if (B(0)) { + if (B(0)) + { Console.WriteLine(0); return; } - if (B(1)) { + if (B(1)) + { Console.WriteLine(1); } @@ -23,13 +25,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void IfSwitch() { - if (B(0)) { + if (B(0)) + { Console.WriteLine(0); return; } Console.WriteLine("switch"); - switch (I(0)) { + switch (I(0)) + { case 0: Console.WriteLine("case 0"); break; @@ -44,13 +48,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void IfSwitchSwitch() { - if (B(0)) { + if (B(0)) + { Console.WriteLine(0); return; } Console.WriteLine("switch 0"); - switch (I(1)) { + switch (I(1)) + { case 0: Console.WriteLine("case 0"); return; @@ -60,7 +66,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } Console.WriteLine("switch 1"); - switch (I(1)) { + switch (I(1)) + { case 0: Console.WriteLine("case 0"); break; @@ -75,12 +82,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void IfLoop() { - if (B(0)) { + if (B(0)) + { Console.WriteLine(0); return; } - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); } @@ -89,14 +98,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void LoopContinue() { - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); - if (B(0)) { + if (B(0)) + { Console.WriteLine(0); continue; } - - if (B(1)) { + + if (B(1)) + { Console.WriteLine(1); } Console.WriteLine("loop-tail"); @@ -105,19 +117,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void LoopBreak() { - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); - if (B(0)) { + if (B(0)) + { Console.WriteLine(0); continue; } - - if (B(1)) { + + if (B(1)) + { Console.WriteLine(1); break; } - if (B(2)) { + if (B(2)) + { Console.WriteLine(2); } @@ -129,16 +145,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void LoopBreakElseIf() { - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); - if (B(0)) { + if (B(0)) + { Console.WriteLine(0); continue; } - - if (B(1)) { + + if (B(1)) + { Console.WriteLine(1); - } else if (B(2)) { + } + else if (B(2)) + { Console.WriteLine(2); } break; @@ -148,7 +169,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void SwitchIf() { - switch (I(0)) { + switch (I(0)) + { case 0: Console.WriteLine("case 0"); return; @@ -156,8 +178,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine("case 1"); return; } - - if (B(0)) { + + if (B(0)) + { Console.WriteLine(0); } Console.WriteLine("end"); @@ -165,8 +188,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void NestedSwitchIf() { - if (B(0)) { - switch (I(0)) { + if (B(0)) + { + switch (I(0)) + { case 0: Console.WriteLine("case 0"); return; @@ -175,10 +200,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return; } - if (B(1)) { + if (B(1)) + { Console.WriteLine(1); } - } else { + } + else + { Console.WriteLine("else"); } } @@ -186,66 +214,84 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // nesting should not be reduced as maximum nesting level is 1 public void EarlyExit1() { - if (!B(0)) { - for (int i = 0; i < 10; i++) { + if (!B(0)) + { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); } Console.WriteLine("end"); } } - + // nesting should be reduced as maximum nesting level is 2 public void EarlyExit2() { - if (B(0)) { + if (B(0)) + { return; } - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); - if (i % 2 == 0) { + if (i % 2 == 0) + { Console.WriteLine("even"); } } Console.WriteLine("end"); } - + // nesting should not be reduced as maximum nesting level is 1 and the else block has no more instructions than any other block public void BalancedIf() { - if (B(0)) { + if (B(0)) + { Console.WriteLine("true"); - if (B(1)) { + if (B(1)) + { Console.WriteLine(1); } - } else { - if (B(2)) { + } + else + { + if (B(2)) + { Console.WriteLine(2); } Console.WriteLine("false"); } } - + public string ComplexCase1(string s) { - if (B(0)) { + if (B(0)) + { return s; } - for (int i = 0; i < s.Length; i++) { - if (B(1)) { + for (int i = 0; i < s.Length; i++) + { + if (B(1)) + { Console.WriteLine(1); - } else if (B(2)) { - switch (i) { + } + else if (B(2)) + { + switch (i) + { case 1: - if (B(3)) { + if (B(3)) + { Console.WriteLine(3); break; } - + Console.WriteLine("case1"); - if (B(4)) { + if (B(4)) + { Console.WriteLine(4); } break; @@ -255,10 +301,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty break; } Console.WriteLine(2); - } else if (B(5)) { + } + else if (B(5)) + { Console.WriteLine(5); - } else { - if (B(6)) { + } + else + { + if (B(6)) + { Console.WriteLine(6); } Console.WriteLine("else"); @@ -269,48 +320,64 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void EarlyExitBeforeTry() { - if (B(0)) { + if (B(0)) + { return; } - try { - if (B(1)) { + try + { + if (B(1)) + { Console.WriteLine(); } - } catch { + } + catch + { } } public void EarlyExitInTry() { - try { - if (B(0)) { + try + { + if (B(0)) + { return; } Console.WriteLine(); - if (B(1)) { - for (int i = 0; i < 10; i++) { + if (B(1)) + { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); } } - } catch { + } + catch + { } } public void ContinueLockInLoop() { - while (B(0)) { - lock (Console.Out) { - if (B(1)) { + while (B(0)) + { + lock (Console.Out) + { + if (B(1)) + { continue; } Console.WriteLine(); - if (B(2)) { - for (int i = 0; i < 10; i++) { + if (B(2)) + { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); } } @@ -320,18 +387,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void BreakLockInLoop() { - while (B(0)) { - lock (Console.Out) { + while (B(0)) + { + lock (Console.Out) + { // Before ReduceNestingTransform, the rest of the lock body is nested in if(!B(1)) with a continue; // the B(1) case falls through to a break outside the lock - if (B(1)) { + if (B(1)) + { break; } Console.WriteLine(); - if (B(2)) { - for (int i = 0; i < 10; i++) { + if (B(2)) + { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); } } @@ -347,16 +419,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public unsafe void BreakPinnedInLoop(int[] arr) { - while (B(0)) { - fixed (int* ptr = arr) { - if (B(1)) { + while (B(0)) + { + fixed (int* ptr = arr) + { + if (B(1)) + { break; } Console.WriteLine(); - if (B(2)) { - for (int i = 0; i < 10; i++) { + if (B(2)) + { + for (int i = 0; i < 10; i++) + { Console.WriteLine(ptr[i]); } } @@ -370,29 +447,39 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void CannotEarlyExitInTry() { - try { - if (B(0)) { + try + { + if (B(0)) + { Console.WriteLine(); - if (B(1)) { - for (int i = 0; i < 10; i++) { + if (B(1)) + { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); } } } - } catch { + } + catch + { } Console.WriteLine(); } public void EndpointUnreachableDueToEarlyExit() { - using (Console.Out) { - if (B(0)) { + using (Console.Out) + { + if (B(0)) + { return; } - do { - if (B(1)) { + do + { + if (B(1)) + { return; } } while (B(2)); @@ -402,8 +489,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void SwitchInTry() { - try { - switch (I(0)) { + try + { + switch (I(0)) + { case 1: Console.WriteLine(1); return; @@ -412,19 +501,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return; } Console.WriteLine(3); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) + { Console.WriteLine(i); } - } catch { + } + catch + { throw; } } public void SwitchInTryInLoopReturn() { - for (int i = 0; i < 10; i++) { - try { - switch (I(0)) { + for (int i = 0; i < 10; i++) + { + try + { + switch (I(0)) + { case 1: Console.WriteLine(1); return; @@ -433,10 +528,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return; } Console.WriteLine(3); - for (int j = 0; j < 10; j++) { + for (int j = 0; j < 10; j++) + { Console.WriteLine(j); } - } catch { + } + catch + { throw; } } @@ -444,9 +542,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void SwitchInTryInLoopContinue() { - for (int i = 0; i < 10; i++) { - try { - switch (I(0)) { + for (int i = 0; i < 10; i++) + { + try + { + switch (I(0)) + { case 1: Console.WriteLine(1); continue; @@ -455,10 +556,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty continue; } Console.WriteLine(3); - for (int j = 0; j < 10; j++) { + for (int j = 0; j < 10; j++) + { Console.WriteLine(j); } - } catch { + } + catch + { throw; } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs index 895efc1f1..1addf018b 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs @@ -36,7 +36,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { Issue1630[] array = new Issue1630[1]; int num = 0; - while (num >= 0) { + while (num >= 0) + { ref Issue1630 reference = ref array[num]; Console.WriteLine(reference.data); num = reference.next; @@ -225,8 +226,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static ref int FindNumber(int target) { - for (int i = 0; i < numbers.Length; i++) { - if (numbers[i] >= target) { + for (int i = 0; i < numbers.Length; i++) + { + if (numbers[i] >= target) + { return ref numbers[i]; } } @@ -240,7 +243,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static ref int ElementAtOrDefault(int index) { - if (index >= 0 && index < numbers.Length) { + if (index >= 0 && index < numbers.Length) + { return ref numbers[index]; } return ref DefaultInt; @@ -248,7 +252,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static ref int LastOrDefault() { - if (numbers.Length != 0) { + if (numbers.Length != 0) + { return ref numbers[numbers.Length - 1]; } return ref DefaultInt; @@ -263,7 +268,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static ref string GetOrSetString(int index) { - if (index < 0 || index >= strings.Length) { + if (index < 0 || index >= strings.Length) + { return ref NullString; } @@ -285,7 +291,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { ref NormalStruct @ref = ref GetRef(); RefReassignment(ref @ref); - if (s.GetHashCode() == 0) { + if (s.GetHashCode() == 0) + { @ref = ref GetRef(); } RefReassignment(ref @ref.GetHashCode() == 4 ? ref @ref : ref s); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.cs index aadbe6a87..f753d91c3 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.cs @@ -31,37 +31,37 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public abstract void M1(); public abstract void M2(); public abstract void E(); - + public void ExprAnd() { B(F(0) && F(1)); } - + public void ExprOr() { B(F(0) || F(1)); } - + public void ExprCond() { B(F(0) ? F(1) : F(2)); } - + public void ExprCondAnd() { B((F(0) && F(1)) ? F(2) : F(3)); } - + public void ExprMix4A() { B(((F(0) || F(1)) && F(2)) || F(3)); } - + public void ExprMix4B() { B((F(0) || F(1)) && (F(2) || F(3))); } - + public void ExprMix4C() { B((F(0) && F(1)) || (F(2) && F(3))); @@ -69,9 +69,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void StmtAnd2() { - if (F(0) && F(1)) { + if (F(0) && F(1)) + { M1(); - } else { + } + else + { M2(); } E(); @@ -79,16 +82,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void StmtOr2A() { - if (F(0) || F(1)) { + if (F(0) || F(1)) + { M1(); } } - + public void StmtOr2B() { - if (F(0) || F(1)) { + if (F(0) || F(1)) + { M1(); - } else { + } + else + { M2(); } E(); @@ -96,9 +103,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void StmtAnd3() { - if (F(0) && F(1) && F(2)) { + if (F(0) && F(1) && F(2)) + { M1(); - } else { + } + else + { M2(); } E(); @@ -106,9 +116,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void StmtOr3() { - if (F(0) || F(1) || F(2)) { + if (F(0) || F(1) || F(2)) + { M1(); - } else { + } + else + { M2(); } E(); @@ -116,9 +129,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void StmtOr4() { - if (GetInt(0) != 0 || GetInt(1) != 0) { + if (GetInt(0) != 0 || GetInt(1) != 0) + { M1(); - } else { + } + else + { M2(); } E(); @@ -126,73 +142,92 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void StmtMix3A() { - if ((F(0) || F(1)) && F(2)) { + if ((F(0) || F(1)) && F(2)) + { M1(); } } public void StmtMix3B() { - if ((F(0) || F(1)) && F(2)) { + if ((F(0) || F(1)) && F(2)) + { M1(); - } else { + } + else + { M2(); } } public void StmtMix4V1A() { - if (((F(0) || F(1)) && F(2)) || F(3)) { + if (((F(0) || F(1)) && F(2)) || F(3)) + { M1(); } } public void StmtMix4V1B() { - if (((F(0) || F(1)) && F(2)) || F(3)) { + if (((F(0) || F(1)) && F(2)) || F(3)) + { M1(); - } else { + } + else + { M2(); } } public void StmtMix4V2A() { - if ((F(0) || F(1)) && (F(2) || F(3))) { + if ((F(0) || F(1)) && (F(2) || F(3))) + { M1(); } } public void StmtMix4V2B() { - if ((F(0) || F(1)) && (F(2) || F(3))) { + if ((F(0) || F(1)) && (F(2) || F(3))) + { M1(); - } else { + } + else + { M2(); } } public void StmtMix4V3A() { - if ((F(0) && F(1)) || (F(2) && F(3))) { + if ((F(0) && F(1)) || (F(2) && F(3))) + { M1(); } } public void StmtMix4V3B() { - if ((F(0) && F(1)) || (F(2) && F(3))) { + if ((F(0) && F(1)) || (F(2) && F(3))) + { M1(); - } else { + } + else + { M2(); } } public void StmtComplex() { - if (F(0) && F(1) && !F(2) && (F(3) || F(4))) { + if (F(0) && F(1) && !F(2) && (F(3) || F(4))) + { M1(); - } else { + } + else + { M2(); } E(); @@ -200,9 +235,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void StmtComplex2(int i) { - if (i > 1000 || (i >= 1 && i <= 8) || i == 42) { + if (i > 1000 || (i >= 1 && i <= 8) || i == 42) + { M1(); - } else { + } + else + { M2(); } E(); @@ -210,9 +248,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void StmtComplex3(int i) { - if (i > 1000 || (i >= 1 && i <= 8) || (i >= 100 && i <= 200) || i == 42) { + if (i > 1000 || (i >= 1 && i <= 8) || (i >= 100 && i <= 200) || i == 42) + { M1(); - } else { + } + else + { M2(); } E(); @@ -220,9 +261,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void StmtComplex4(int i) { - if (i > 1000 || (i >= 1 && i <= 8) || i == 42 || i == 23) { + if (i > 1000 || (i >= 1 && i <= 8) || i == 42 || i == 23) + { M1(); - } else { + } + else + { M2(); } E(); @@ -230,11 +274,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void StmtComplex5() { - if (F(0)) { - if (!F(1) && !F(2)) { + if (F(0)) + { + if (!F(1) && !F(2)) + { return; } - } else if (!F(3) || !F(4)) { + } + else if (!F(3) || !F(4)) + { M2(); return; } @@ -243,9 +291,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public int StmtComplex6() { - if (F(0)) { + if (F(0)) + { M1(); - if (F(1) || F(2)) { + if (F(1) || F(2)) + { return 1; } } @@ -254,7 +304,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public int InferCorrectOrder() { - if (F(1) || F(2)) { + if (F(1) || F(2)) + { return 1; } return 2; @@ -263,15 +314,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty #if !OPT public void EmptyIf() { - if (F(0)) { + if (F(0)) + { } - if (!F(1)) { + if (!F(1)) + { } - if (F(2) && F(3)) { + if (F(2) && F(3)) + { } - if (F(4) || F(5)) { + if (F(4) || F(5)) + { } - if (F(0) && F(1) && !F(2) && (F(3) || F(4))) { + if (F(0) && F(1) && !F(2) && (F(3) || F(4))) + { } E(); } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs index 4c412db43..da277b141 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs @@ -52,7 +52,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty #if !ROSLYN public static State SwitchOverNullableBool(bool? value) { - switch (value) { + switch (value) + { case false: return State.False; case true: @@ -67,7 +68,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static bool? SwitchOverNullableEnum(State? state) { - switch (state) { + switch (state) + { case State.False: return false; case State.True: @@ -82,7 +84,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SparseIntegerSwitch(int i) { Console.WriteLine("SparseIntegerSwitch: " + i); - switch (i) { + switch (i) + { case -10000000: return "-10 mln"; case -100: @@ -112,7 +115,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SparseIntegerSwitch2(int i) { - switch (i) { + switch (i) + { case 4: case 10: case 11: @@ -130,7 +134,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static bool SparseIntegerSwitch3(int i) { - switch (i) { + switch (i) + { case 0: case 10: case 11: @@ -146,7 +151,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverNullableInt(int? i) { - switch (i) { + switch (i) + { case null: return "null"; case 0: @@ -162,7 +168,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverNullableIntNullCaseCombined(int? i) { - switch (i) { + switch (i) + { case null: case 0: return "zero"; @@ -177,7 +184,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverNullableIntShifted(int? i) { - switch (i + 5) { + switch (i + 5) + { case null: return "null"; case 0: @@ -193,7 +201,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverNullableIntShiftedNullCaseCombined(int? i) { - switch (i + 5) { + switch (i + 5) + { case null: case 0: return "zero"; @@ -208,7 +217,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverNullableIntNoNullCase(int? i) { - switch (i) { + switch (i) + { case 0: return "zero"; case 5: @@ -222,7 +232,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverNullableIntNoNullCaseShifted(int? i) { - switch (i + 5) { + switch (i + 5) + { case 0: return "zero"; case 5: @@ -236,7 +247,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchOverInt(int i) { - switch (i) { + switch (i) + { case 0: Console.WriteLine("zero"); break; @@ -264,7 +276,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // SwitchDetection.UseCSharpSwitch requires more complex heuristic to identify this when compiled with Roslyn public static void CompactSwitchOverInt(int i) { - switch (i) { + switch (i) + { case 0: case 1: case 2: @@ -283,7 +296,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string ShortSwitchOverString(string text) { Console.WriteLine("ShortSwitchOverString: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -298,7 +312,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string ShortSwitchOverStringWithNullCase(string text) { Console.WriteLine("ShortSwitchOverStringWithNullCase: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -313,7 +328,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverString1(string text) { Console.WriteLine("SwitchOverString1: " + text); - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": @@ -337,7 +353,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverString2() { Console.WriteLine("SwitchOverString2:"); - switch (Environment.UserName) { + switch (Environment.UserName) + { case "First case": return "Text1"; case "Second case": @@ -369,7 +386,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverBool(bool b) { Console.WriteLine("SwitchOverBool: " + b); - switch (b) { + switch (b) + { case true: return bool.TrueString; case false: @@ -383,8 +401,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchInLoop(int i) { Console.WriteLine("SwitchInLoop: " + i); - while (true) { - switch (i) { + while (true) + { + switch (i) + { case 1: Console.WriteLine("one"); break; @@ -409,7 +429,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithGoto(int i) { Console.WriteLine("SwitchWithGoto: " + i); - switch (i) { + switch (i) + { case 1: Console.WriteLine("one"); goto default; @@ -433,7 +454,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithGotoString(string s) { Console.WriteLine("SwitchWithGotoString: " + s); - switch (s) { + switch (s) + { case "1": Console.WriteLine("one"); goto default; @@ -471,7 +493,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithGotoComplex(string s) { Console.WriteLine("SwitchWithGotoComplex: " + s); - switch (s) { + switch (s) + { case "1": Console.WriteLine("one"); goto case "8"; @@ -480,7 +503,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty goto case "3"; case "3": Console.WriteLine("three"); - if (s.Length != 2) { + if (s.Length != 2) + { break; } goto case "5"; @@ -518,10 +542,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty List list = new List(); List list2 = new List(); SetProperty[] properties = GetProperties(); - for (int i = 0; i < properties.Length; i++) { + for (int i = 0; i < properties.Length; i++) + { Console.WriteLine("In for-loop"); SetProperty setProperty = properties[i]; - switch (setProperty.Property.Name) { + switch (setProperty.Property.Name) + { case "Name1": setProperty.Set = 1; list.Add(setProperty); @@ -551,8 +577,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchInTryBlock(string value) { - try { - switch (value.Substring(5)) { + try + { + switch (value.Substring(5)) + { case "Name1": Console.WriteLine("1"); break; @@ -573,14 +601,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine("default"); break; } - } catch (Exception) { + } + catch (Exception) + { Console.WriteLine("catch block"); } } public static void SwitchWithComplexCondition(string[] args) { - switch ((args.Length == 0) ? "dummy" : args[0]) { + switch ((args.Length == 0) ? "dummy" : args[0]) + { case "a": Console.WriteLine("a"); break; @@ -599,7 +630,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithArray(string[] args) { - switch (args[0]) { + switch (args[0]) + { case "a": Console.WriteLine("a"); break; @@ -618,19 +650,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithContinue1(int i, bool b) { - while (true) { - switch (i) { + while (true) + { + switch (i) + { #if OPT case 1: continue; #endif case 0: - if (b) { + if (b) + { continue; } break; case 2: - if (!b) { + if (!b) + { continue; } break; @@ -646,10 +682,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // while condition, return and break cases public static void SwitchWithContinue2(int i, bool b) { - while (i < 10) { - switch (i) { + while (i < 10) + { + switch (i) + { case 0: - if (b) { + if (b) + { Console.WriteLine("0b"); continue; } @@ -657,14 +696,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty break; case 2: #if OPT - if (b) { + if (b) + { Console.WriteLine("2b"); return; } Console.WriteLine("2!b"); continue; #else - if (!b) { + if (!b) + { Console.WriteLine("2!b"); continue; } @@ -687,10 +728,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // for loop version public static void SwitchWithContinue3(bool b) { - for (int i = 0; i < 10; i++) { - switch (i) { + for (int i = 0; i < 10; i++) + { + switch (i) + { case 0: - if (b) { + if (b) + { Console.WriteLine("0b"); continue; } @@ -698,14 +742,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty break; case 2: #if OPT - if (b) { + if (b) + { Console.WriteLine("2b"); return; } Console.WriteLine("2!b"); continue; #else - if (!b) { + if (!b) + { Console.WriteLine("2!b"); continue; } @@ -727,16 +773,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // foreach version public static void SwitchWithContinue4(bool b) { - foreach (int item in Enumerable.Range(0, 10)) { + foreach (int item in Enumerable.Range(0, 10)) + { Console.WriteLine("loop: " + item); - switch (item) { + switch (item) + { case 1: - if (b) { + if (b) + { continue; } break; case 3: - if (!b) { + if (!b) + { continue; } return; @@ -747,20 +797,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(5); goto default; case 6: - if (b) { + if (b) + { continue; } goto case 3; case 7: - if (item % 2 == 0) { + if (item % 2 == 0) + { goto case 3; } - if (!b) { + if (!b) + { continue; } goto case 8; case 8: - if (b) { + if (b) + { continue; } goto case 5; @@ -776,11 +830,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // internal if statement, loop increment block not dominated by the switch head public static void SwitchWithContinue5(bool b) { - for (int i = 0; i < 10; i++) { - if (i < 5) { - switch (i) { + for (int i = 0; i < 10; i++) + { + if (i < 5) + { + switch (i) + { case 0: - if (b) { + if (b) + { Console.WriteLine("0b"); continue; } @@ -788,14 +846,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty break; case 2: #if OPT - if (b) { + if (b) + { Console.WriteLine("2b"); return; } Console.WriteLine("2!b"); continue; #else - if (!b) { + if (!b) + { Console.WriteLine("2!b"); continue; } @@ -819,10 +879,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // do-while loop version public static void SwitchWithContinue6(int i, bool b) { - do { - switch (i) { + do + { + switch (i) + { case 0: - if (!b) { + if (!b) + { Console.WriteLine("0!b"); break; } @@ -830,7 +893,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // ConditionDetection doesn't recognise Do-While continues yet continue; case 2: - if (b) { + if (b) + { Console.WriteLine("2b"); return; } @@ -851,9 +915,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // double break from switch to loop exit requires additional pattern matching in HighLevelLoopTransform public static void SwitchWithContinue7() { - for (int num = 0; num >= 0; num--) { + for (int num = 0; num >= 0; num--) + { Console.WriteLine("loop-head"); - switch (num) { + switch (num) + { default: Console.WriteLine("default"); break; @@ -870,9 +936,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithContinueInDoubleLoop() { bool value = false; - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 10; j++) { - switch (i + j) { + for (int i = 0; i < 10; i++) + { + for (int j = 0; j < 10; j++) + { + switch (i + j) + { case 1: case 3: case 5: @@ -893,8 +962,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchLoopNesting() { - for (int i = 0; i < 10; i++) { - switch (i) { + for (int i = 0; i < 10; i++) + { + switch (i) + { case 0: Console.WriteLine(0); break; @@ -902,8 +973,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(1); break; default: - if (i % 2 == 0) { - while (i % 3 != 0) { + if (i % 2 == 0) + { + while (i % 3 != 0) + { Console.WriteLine(i++); } } @@ -911,9 +984,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty break; } - if (i > 4) { + if (i > 4) + { Console.WriteLine("high"); - } else { + } + else + { Console.WriteLine("low"); } } @@ -925,7 +1001,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty #if ROSLYN || OPT public static void SingleIf1(int i, bool a) { - if (i == 1 || (i == 2 && a)) { + if (i == 1 || (i == 2 && a)) + { Console.WriteLine(1); } Console.WriteLine(2); @@ -934,7 +1011,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SingleIf2(int i, bool a, bool b) { - if (i == 1 || (i == 2 && a) || (i == 3 && b)) { + if (i == 1 || (i == 2 && a) || (i == 3 && b)) + { Console.WriteLine(1); } Console.WriteLine(2); @@ -942,7 +1020,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SingleIf3(int i, bool a, bool b) { - if (a || i == 1 || (i == 2 && b)) { + if (a || i == 1 || (i == 2 && b)) + { Console.WriteLine(1); } Console.WriteLine(2); @@ -950,7 +1029,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SingleIf4(int i, bool a) { - if (i == 1 || i == 2 || (i != 3 && a) || i != 4) { + if (i == 1 || i == 2 || (i != 3 && a) || i != 4) + { Console.WriteLine(1); } Console.WriteLine(2); @@ -958,8 +1038,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void NestedIf(int i) { - if (i != 1) { - if (i == 2) { + if (i != 1) + { + if (i == 2) + { Console.WriteLine(2); } Console.WriteLine("default"); @@ -969,19 +1051,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void IfChainWithCondition(int i) { - if (i == 0) { + if (i == 0) + { Console.WriteLine(0); - } else if (i == 1) { + } + else if (i == 1) + { Console.WriteLine(1); - } else if (i == 2) { + } + else if (i == 2) + { Console.WriteLine(2); - } else if (i == 3) { + } + else if (i == 3) + { Console.WriteLine(3); - } else if (i == 4) { + } + else if (i == 4) + { Console.WriteLine(4); - } else if (i == 5 && Console.CapsLock) { + } + else if (i == 5 && Console.CapsLock) + { Console.WriteLine("5A"); - } else { + } + else + { Console.WriteLine("default"); } @@ -990,37 +1085,48 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static bool SwitchlikeIf(int i, int j) { - if (i != 0 && j != 0) { - if (i == -1 && j == -1) { + if (i != 0 && j != 0) + { + if (i == -1 && j == -1) + { Console.WriteLine("-1, -1"); } - if (i == -1 && j == 1) { + if (i == -1 && j == 1) + { Console.WriteLine("-1, 1"); } - if (i == 1 && j == -1) { + if (i == 1 && j == -1) + { Console.WriteLine("1, -1"); } - if (i == 1 && j == 1) { + if (i == 1 && j == 1) + { Console.WriteLine("1, 1"); } return false; } - if (i != 0) { - if (i == -1) { + if (i != 0) + { + if (i == -1) + { Console.WriteLine("-1, 0"); } - if (i == 1) { + if (i == 1) + { Console.WriteLine("1, 0"); } return false; } - if (j != 0) { - if (j == -1) { + if (j != 0) + { + if (j == -1) + { Console.WriteLine("0, -1"); } - if (j == 1) { + if (j == 1) + { Console.WriteLine("0, 1"); } return false; @@ -1031,15 +1137,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static bool SwitchlikeIf2(int i) { - if (i != 0) { + if (i != 0) + { // note that using else-if in this chain creates a nice-looking switch here (as expected) - if (i == 1) { + if (i == 1) + { Console.WriteLine(1); } - if (i == 2) { + if (i == 2) + { Console.WriteLine(2); } - if (i == 3) { + if (i == 3) + { Console.WriteLine(3); } return false; @@ -1049,7 +1159,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SingleIntervalIf(char c) { - if (c >= 'A' && c <= 'Z') { + if (c >= 'A' && c <= 'Z') + { Console.WriteLine("alphabet"); } Console.WriteLine("end"); @@ -1057,8 +1168,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static bool Loop8(char c, bool b, Func getChar) { - if (b) { - while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + if (b) + { + while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) + { c = getChar(); } } @@ -1069,7 +1182,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void Loop9(Func getChar) { char c; - do { + do + { c = getChar(); } while (c != -1 && c != '\n' && c != '\u2028' && c != '\u2029'); } @@ -1078,8 +1192,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // Ensure correctness of SwitchDetection.UseCSharpSwitch control flow heuristics public static void SwitchWithBreakCase(int i, bool b) { - if (b) { - switch (i) { + if (b) + { + switch (i) + { case 1: Console.WriteLine(1); break; @@ -1096,14 +1212,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithReturnAndBreak(int i, bool b) { - switch (i) { + switch (i) + { case 0: - if (b) { + if (b) + { return; } break; case 1: - if (!b) { + if (!b) + { return; } break; @@ -1113,13 +1232,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static int SwitchWithReturnAndBreak2(int i, bool b) { - switch (i) { + switch (i) + { case 4: case 33: Console.WriteLine(); return 1; case 334: - if (b) { + if (b) + { return 2; } break; @@ -1135,7 +1256,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchWithReturnAndBreak3(int i) { - switch (i) { + switch (i) + { default: return; case 0: @@ -1150,10 +1272,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string Issue1621(int x) { - if (x == 5) { + if (x == 5) + { return "5"; } - switch (x) { + switch (x) + { case 1: return "1"; case 2: @@ -1173,7 +1297,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static int Issue1602(string x) { - switch (x) { + switch (x) + { case null: return 0; case "": @@ -1197,7 +1322,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void Issue1745(string aaa) { - switch (aaa) { + switch (aaa) + { case "a": case "b": case "c": @@ -1218,7 +1344,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static bool DoNotRemoveAssignmentBeforeSwitch(string x, out ConsoleKey key) { key = (ConsoleKey)0; - switch (x) { + switch (x) + { case "A": key = ConsoleKey.A; break; @@ -1234,7 +1361,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void Issue1767(string s) { - switch (s) { + switch (s) + { case "a": ch1767 = s[0]; break; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs index 37b086cbc..0535fb7c3 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/SwitchExpressions.cs @@ -31,7 +31,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static bool? SwitchOverNullableEnum(State? state) { - return state switch { + return state switch + { State.False => false, State.True => true, State.Null => null, @@ -42,7 +43,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SparseIntegerSwitch(int i) { Console.WriteLine("SparseIntegerSwitch: " + i); - return i switch { + return i switch + { -10000000 => "-10 mln", -100 => "-hundred", -1 => "-1", @@ -61,7 +63,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static bool SparseIntegerSwitch3(int i) { // not using a switch expression because we'd have to duplicate the 'true' branch - switch (i) { + switch (i) + { case 0: case 10: case 11: @@ -77,7 +80,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverNullableInt(int? i, int? j) { - return (i + j) switch { + return (i + j) switch + { null => "null", 0 => "zero", 5 => "five", @@ -88,7 +92,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void SwitchOverInt(int i) { - Console.WriteLine(i switch { + Console.WriteLine(i switch + { 0 => "zero", 5 => "five", 10 => "ten", @@ -103,7 +108,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverString1(string text) { Console.WriteLine("SwitchOverString1: " + text); - return text switch { + return text switch + { "First case" => "Text1", "Second case" => "Text2", "Third case" => "Text3", @@ -119,7 +125,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { Console.WriteLine("SwitchOverString1: " + text); // Cannot use switch expression, because "return Text2;" would need to be duplicated - switch (text) { + switch (text) + { case "First case": return "Text1"; case "Second case": diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs index df8e1f41c..ca248165e 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ThrowExpressions.cs @@ -32,7 +32,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private static int? GetIntOrNull(string v) { - if (int.TryParse(v, out int result)) { + if (int.TryParse(v, out int result)) + { return result; } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.cs index 697bcfd06..a5581f48a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TupleTests.cs @@ -129,7 +129,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void UseDict() { - if (TupleDict.Count > 10) { + if (TupleDict.Count > 10) + { TupleDict.Clear(); } // TODO: it would be nice if we could infer the name 'c' for the local @@ -153,21 +154,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void Foreach(IEnumerable<(int, string)> input) { - foreach (var item in input) { + foreach (var item in input) + { Console.WriteLine($"{item.Item1}: {item.Item2}"); } } public void ForeachNamedElements(IEnumerable<(int Index, string Data)> input) { - foreach (var item in input) { + foreach (var item in input) + { Console.WriteLine($"{item.Index}: {item.Data}"); } } public void NonGenericForeach(IEnumerable input) { - foreach ((string, int) item in input) { + foreach ((string, int) item in input) + { Console.WriteLine($"{item.Item1}: {item.Item2}"); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs index 2993b179a..7c47e5aea 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs @@ -118,7 +118,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void TernaryOp(Random a, Random b, bool c) { - if ((c ? a : b) == null) { + if ((c ? a : b) == null) + { Console.WriteLine(); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeMemberTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeMemberTests.cs index 66103b036..e4fdd1397 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeMemberTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeMemberTests.cs @@ -201,7 +201,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } public interface T15_IMyInterface_PropertyInterfaceImplementation - { + { int MyProperty { get; set; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs index ee703d20b..e432bbf6a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs @@ -170,7 +170,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public unsafe void PassRefParameterAsPointer(ref int p) { - fixed (int* ptr = &p) { + fixed (int* ptr = &p) + { UsePointer(ptr); } } @@ -187,16 +188,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public unsafe void AddressInMultiDimensionalArray(double[,] matrix) { - fixed (double* d = &matrix[1, 2]) { + fixed (double* d = &matrix[1, 2]) + { PointerReferenceExpression(d); PointerReferenceExpression(d); } } - + public unsafe void FixedStringAccess(string text) { - fixed (char* ptr = text) { - for (char* ptr2 = ptr; *ptr2 == 'a'; ptr2++) { + fixed (char* ptr = text) + { + for (char* ptr2 = ptr; *ptr2 == 'a'; ptr2++) + { *ptr2 = 'A'; } } @@ -204,7 +208,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public unsafe void FixedStringNoPointerUse(string text) { - fixed (char* ptr = text) { + fixed (char* ptr = text) + { } } @@ -213,21 +218,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // leaving no pinned region we could detect. public unsafe void FixedArrayNoPointerUse(int[] arr) { - fixed (int* ptr = arr) { + fixed (int* ptr = arr) + { } } #endif public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val) { - fixed (long* ptr = array) { + fixed (long* ptr = array) + { *(double*)(ptr + index) = val; } } public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val) { - fixed (long* ptr = &array[index]) { + fixed (long* ptr = &array[index]) + { *(double*)ptr = val; } } @@ -355,7 +363,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public unsafe void PinFixedMember(ref StructWithFixedSizeMembers m) { - fixed (int* ptr = m.Integers) { + fixed (int* ptr = m.Integers) + { UsePointer(ptr); } } @@ -376,7 +385,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public unsafe void FixedMultiDimArray(int[,] arr) { - fixed (int* ptr = arr) { + fixed (int* ptr = arr) + { UsePointer(ptr); } } @@ -384,7 +394,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty #if CS73 public unsafe void FixedSpan(Span span) { - fixed (int* ptr = span) { + fixed (int* ptr = span) + { UsePointer(ptr); } } @@ -401,7 +412,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { char* ptr = stackalloc char[count]; char* ptr2 = stackalloc char[100]; - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { ptr[i] = (char)i; ptr2[i] = '\0'; } @@ -417,7 +429,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty #endif ptr->X = count; ptr[1].X = ptr->X; - for (int i = 2; i < 10; i++) { + for (int i = 2; i < 10; i++) + { ptr[i].X = count; } return UsePointer(&ptr->Y); @@ -450,13 +463,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private unsafe static ResultStruct NestedFixedBlocks(byte[] array) { - try { - fixed (byte* ptr = array) { - fixed (byte* ptr2 = Get()) { + try + { + fixed (byte* ptr = array) + { + fixed (byte* ptr2 = Get()) + { return new ResultStruct(ptr, ptr2); } } - } finally { + } + finally + { Console.WriteLine("Finally"); } } @@ -468,17 +486,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private unsafe static object Issue1386(int arraySize, bool createFirstBuffer) { - if (createFirstBuffer) { + if (createFirstBuffer) + { byte[] array = new byte[arraySize]; Console.WriteLine("first fixed"); - fixed (byte* ptr = array) { + fixed (byte* ptr = array) + { return CreateBuffer(array.Length, ptr); } } byte[] array2 = new byte[arraySize]; Console.WriteLine("second fixed"); - fixed (byte* ptr2 = array2) { + fixed (byte* ptr2 = array2) + { return CreateBuffer(array2.Length, ptr2); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs index fbac6758c..9674b8cf7 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Using.cs @@ -62,7 +62,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // roslyn optimizes out the try-finally; mcs has a compiler bug on using(null-literal) public void SimpleUsingNullStatement() { - using (null) { + using (null) + { Console.WriteLine("using (null)"); } } @@ -70,14 +71,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void SimpleUsingExpressionStatement() { - using (new MemoryStream()) { + using (new MemoryStream()) + { Console.WriteLine("using-body"); } } public void SimpleUsingExpressionStatementWithDeclaration() { - using (MemoryStream memoryStream = new MemoryStream()) { + using (MemoryStream memoryStream = new MemoryStream()) + { memoryStream.WriteByte(42); Console.WriteLine("using-body: " + memoryStream.Position); } @@ -86,7 +89,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void UsingStatementThatChangesTheVariable() { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); - using (cancellationTokenSource) { + using (cancellationTokenSource) + { cancellationTokenSource = new CancellationTokenSource(); } cancellationTokenSource.Cancel(); @@ -94,49 +98,56 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void UsingStatementOnStruct() { - using (new UsingStruct(1)) { + using (new UsingStruct(1)) + { Console.WriteLine("using-body"); } } public void UsingStatementOnStructWithVariable() { - using (UsingStruct usingStruct = new UsingStruct(2)) { + using (UsingStruct usingStruct = new UsingStruct(2)) + { Console.WriteLine("using-body: " + usingStruct); } } private void UsingStatementOnNullableStruct(UsingStruct? us) { - using (us) { + using (us) + { Console.WriteLine("using-body: " + us.ToString()); } } public void GenericUsing(T t) where T : IDisposable { - using (t) { + using (t) + { Console.WriteLine(t); } } public void GenericStructUsing(T t) where T : struct, IDisposable { - using (t) { + using (t) + { Console.WriteLine(t); } } public void GenericClassUsing(T t) where T : class, IDisposable { - using (t) { + using (t) + { Console.WriteLine(t); } } public void GenericNullableUsing(T? t) where T : struct, IDisposable { - using (t) { + using (t) + { Console.WriteLine(t); } } @@ -144,7 +155,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty #if CS80 public void UsingRefStruct1(UsingRefStruct s) { - using (s) { + using (s) + { Console.WriteLine(s.i); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UsingVariables.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UsingVariables.cs index fcdd372f8..0d08ce885 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UsingVariables.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UsingVariables.cs @@ -54,7 +54,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void NotAUsingVar() { Console.WriteLine("before using"); - using (IDisposable disposable = GetDisposable()) { + using (IDisposable disposable = GetDisposable()) + { Console.WriteLine("inside using"); Use(disposable); } @@ -63,7 +64,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void UsingVarInNestedBlocks(bool condition) { - if (condition) { + if (condition) + { using IDisposable disposable = GetDisposable(); Console.WriteLine("inside using"); Use(disposable); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ValueTypes.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ValueTypes.cs index 3ee360f1e..a33954feb 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ValueTypes.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ValueTypes.cs @@ -154,7 +154,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return new S(10); } - + public static S Copy1(S p) { return p; @@ -228,21 +228,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void UseRefBoolInCondition(ref bool x) { - if (x) { + if (x) + { Console.WriteLine("true"); } } public static void CompareNotEqual0IsReallyNotEqual(IComparable a) { - if (a.CompareTo(0) != 0) { + if (a.CompareTo(0) != 0) + { Console.WriteLine("true"); } } public static void CompareEqual0IsReallyEqual(IComparable a) { - if (a.CompareTo(0) == 0) { + if (a.CompareTo(0) == 0) + { Console.WriteLine("true"); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs index 880428737..d97228ff7 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/YieldReturn.cs @@ -47,7 +47,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty internal static void Print(string name, IEnumerator enumerator) { Console.WriteLine(name + ": Test start"); - while (enumerator.MoveNext()) { + while (enumerator.MoveNext()) + { Console.WriteLine(name + ": " + enumerator.Current); } } @@ -80,7 +81,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static IEnumerable YieldReturnInLoop() { - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 100; i++) + { yield return i; } } @@ -88,9 +90,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static IEnumerable YieldReturnWithTryFinally() { yield return 0; - try { + try + { yield return 1; - } finally { + } + finally + { Console.WriteLine("Finally!"); } yield return 2; @@ -120,28 +125,35 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine("Start of method - 1"); yield return "Start of method"; Console.WriteLine("Start of method - 2"); - try { + try + { Console.WriteLine("Within outer try - 1"); yield return "Within outer try"; Console.WriteLine("Within outer try - 2"); - try { + try + { Console.WriteLine("Within inner try - 1"); yield return "Within inner try"; Console.WriteLine("Within inner try - 2"); - if (breakInMiddle) { + if (breakInMiddle) + { Console.WriteLine("Breaking..."); yield break; } Console.WriteLine("End of inner try - 1"); yield return "End of inner try"; Console.WriteLine("End of inner try - 2"); - } finally { + } + finally + { Console.WriteLine("Inner Finally"); } Console.WriteLine("End of outer try - 1"); yield return "End of outer try"; Console.WriteLine("End of outer try - 2"); - } finally { + } + finally + { Console.WriteLine("Outer Finally"); } Console.WriteLine("End of method - 1"); @@ -152,11 +164,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static IEnumerable YieldReturnWithTwoNonNestedFinallyBlocks(IEnumerable input) { // outer try-finally block - foreach (string line in input) { + foreach (string line in input) + { // nested try-finally block - try { + try + { yield return line; - } finally { + } + finally + { Console.WriteLine("Processed " + line); } } @@ -167,21 +183,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty yield return "E"; yield return "F"; // outer try-finally block - foreach (string item in input) { + foreach (string item in input) + { yield return item.ToUpper(); } } public static IEnumerable> YieldReturnWithAnonymousMethods1(IEnumerable input) { - foreach (string line in input) { + foreach (string line in input) + { yield return () => line; } } public static IEnumerable> YieldReturnWithAnonymousMethods2(IEnumerable input) { - foreach (string item in input) { + foreach (string item in input) + { string copy = item; yield return () => copy; } @@ -189,8 +208,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static IEnumerable GetEvenNumbers(int n) { - for (int i = 0; i < n; i++) { - if (i % 2 == 0) { + for (int i = 0; i < n; i++) + { + if (i % 2 == 0) + { yield return i; } } @@ -199,20 +220,29 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static IEnumerable ExceptionHandling() { yield return 'a'; - try { + try + { Console.WriteLine("1 - try"); - } catch (Exception) { + } + catch (Exception) + { Console.WriteLine("1 - catch"); } yield return 'b'; - try { - try { + try + { + try + { Console.WriteLine("2 - try"); - } finally { + } + finally + { Console.WriteLine("2 - finally"); } yield return 'c'; - } finally { + } + finally + { Console.WriteLine("outer finally"); } } @@ -220,22 +250,29 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static IEnumerable YieldBreakInCatch() { yield return 0; - try { + try + { Console.WriteLine("In Try"); - } catch { + } + catch + { // yield return is not allowed in catch, but yield break is yield break; } yield return 1; } - + public static IEnumerable YieldBreakInCatchInTryFinally() { - try { + try + { yield return 0; - try { + try + { Console.WriteLine("In Try"); - } catch { + } + catch + { // yield return is not allowed in catch, but yield break is // Note that pre-roslyn, this code triggers a compiler bug: // If the finally block throws an exception, it ends up getting @@ -243,43 +280,58 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty yield break; } yield return 1; - } finally { + } + finally + { Console.WriteLine("Finally"); } } public static IEnumerable YieldBreakInTryCatchInTryFinally() { - try { + try + { yield return 0; - try { + try + { Console.WriteLine("In Try"); // same compiler bug as in YieldBreakInCatchInTryFinally yield break; - } catch { + } + catch + { Console.WriteLine("Catch"); } yield return 1; - } finally { + } + finally + { Console.WriteLine("Finally"); } } public static IEnumerable YieldBreakInTryFinallyInTryFinally(bool b) { - try { + try + { yield return 0; - try { + try + { Console.WriteLine("In Try"); - if (b) { + if (b) + { // same compiler bug as in YieldBreakInCatchInTryFinally yield break; } - } finally { + } + finally + { Console.WriteLine("Inner Finally"); } yield return 1; - } finally { + } + finally + { Console.WriteLine("Finally"); } } @@ -288,15 +340,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { yield break; } - + public static IEnumerable UnconditionalThrowInTryFinally() { // Here, MoveNext() doesn't call the finally methods at all // (only indirectly via Dispose()) - try { + try + { yield return 0; throw new NotImplementedException(); - } finally { + } + finally + { Console.WriteLine("Finally"); } } @@ -304,23 +359,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static IEnumerable NestedTryFinallyStartingOnSamePosition() { // The first user IL instruction is already in 2 nested try blocks. - try { - try { + try + { + try + { yield return 0; - } finally { + } + finally + { Console.WriteLine("Inner Finally"); } - } finally { + } + finally + { Console.WriteLine("Outer Finally"); } } - + public static IEnumerable LocalInFinally(T a) where T : IDisposable { yield return 1; - try { + try + { yield return 2; - } finally { + } + finally + { T val = a; val.Dispose(); val.Dispose(); @@ -331,27 +395,34 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static IEnumerable GenericYield() where T : new() { T val = new T(); - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) + { yield return val; } } public static IEnumerable MultipleYieldBreakInTryFinally(int i) { - try { - if (i == 2) { + try + { + if (i == 2) + { yield break; } - while (i < 40) { - if (i % 2 == 0) { + while (i < 40) + { + if (i % 2 == 0) + { yield break; } i++; yield return i; } - } finally { + } + finally + { Console.WriteLine("finally"); } Console.WriteLine("normal exit"); @@ -362,8 +433,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // This loop needs to pick the implicit "yield break;" as exit point // in order to produce pretty code; not the "throw" which would // be a less-pretty option. - for (int i = 0; i < end; i++) { - if (i == evil) { + for (int i = 0; i < end; i++) + { + if (i == evil) + { throw new InvalidOperationException("Found evil number"); } yield return i; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.Expected.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.Expected.cs index fb7860794..cfa266a46 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.Expected.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.Expected.cs @@ -58,9 +58,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly int field1 = 4711; string field2 = "ILSpy"; DisplayClass field3; - if (displayClass.field1 > 100) { + if (displayClass.field1 > 100) + { field3 = displayClass; - } else { + } + else + { field3 = null; } Console.WriteLine("{0} {1}", displayClass, field3); @@ -76,9 +79,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly int field1 = 4711; string field2 = "ILSpy"; DisplayClass field3; - if (displayClass.field1 > 100) { + if (displayClass.field1 > 100) + { field3 = displayClass; - } else { + } + else + { field3 = null; } Console.WriteLine("{0} {1}", field2 + field1, field3); @@ -93,8 +99,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly int field1 = default(int); string field2 = default(string); DisplayClass field3 = default(DisplayClass); - while (true) { - switch (Rand()) { + while (true) + { + switch (Rand()) + { case 1: field1 = Rand(); continue; @@ -115,7 +123,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly { int field1 = i; string field2 = "Hello World!"; - if (i < 0) { + if (i < 0) + { i = -i; } Console.WriteLine("{0} {1}", field1, field2); @@ -126,7 +135,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly int num = i; int field1 = num; string field2 = "Hello World!"; - if (num < 0) { + if (num < 0) + { num = -num; } Console.WriteLine("{0} {1}", field1, field2); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.cs index 0fb451750..89301ee39 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/AggressiveScalarReplacementOfAggregates.cs @@ -15,14 +15,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly public int field1; public string field2; } - + public class Program { public int Rand() { throw new NotImplementedException(); } - + public void Test1() { DisplayClass displayClass = new DisplayClass { @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly }; Console.WriteLine("{0} {1}", displayClass.field1, displayClass.field2); } - + public void Test2() { DisplayClass displayClass = new DisplayClass { @@ -40,7 +40,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly }; Console.WriteLine("{0} {1}", displayClass.field1, displayClass.GetHashCode()); } - + public void Test3() { DisplayClass displayClass = new DisplayClass { @@ -61,9 +61,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly field1 = 4711, field2 = "ILSpy" }; - if (displayClass.field1 > 100) { + if (displayClass.field1 > 100) + { nested.field3 = displayClass; - } else { + } + else + { nested.field3 = null; } Console.WriteLine("{0} {1}", displayClass, nested.field3); @@ -80,14 +83,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly field1 = 4711, field2 = "ILSpy" }; - if (displayClass.field1 > 100) { + if (displayClass.field1 > 100) + { nested.field3 = displayClass; - } else { + } + else + { nested.field3 = null; } Console.WriteLine("{0} {1}", nested.field2 + nested.field1, nested.field3); } - + public void Issue1898(int i) { DisplayClass displayClass = new DisplayClass { @@ -95,8 +101,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly field1 = i }; NestedDisplayClass nested = new NestedDisplayClass(); - while (true) { - switch (Rand()) { + while (true) + { + switch (Rand()) + { case 1: nested.field1 = Rand(); break; @@ -121,12 +129,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly field1 = i, field2 = "Hello World!" }; - if (i < 0) { + if (i < 0) + { i = -i; } Console.WriteLine("{0} {1}", displayClass.field1, displayClass.field2); } - + public void Test6b(int i) { int num = i; @@ -134,7 +143,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly field1 = num, field2 = "Hello World!" }; - if (num < 0) { + if (num < 0) + { num = -num; } Console.WriteLine("{0} {1}", displayClass.field1, displayClass.field2); @@ -170,15 +180,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly Console.WriteLine("{0} {1}", displayClass.field1, displayClass.field2); } -// public void Test9() -// { -// DisplayClass displayClass = new DisplayClass { -// thisField = this, -// field1 = 1, -// field2 = "Hello World!" -// }; -// displayClass.thisField = new Program(); -// Console.WriteLine("{0} {1}", this, displayClass.thisField); -// } + // public void Test9() + // { + // DisplayClass displayClass = new DisplayClass { + // thisField = this, + // field1 = 1, + // field2 = "Hello World!" + // }; + // displayClass.thisField = new Program(); + // Console.WriteLine("{0} {1}", this, displayClass.thisField); + // } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.Expected.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.Expected.cs index 50c053240..ee9b27686 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.Expected.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.Expected.cs @@ -7,7 +7,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly { [DecimalConstant(1, 0, 0u, 0u, 10u)] private static readonly decimal constant = 1.0m; - private void MethodWithOptionalParameter([Optional] [DecimalConstant(1, 0, 0u, 0u, 10u)] decimal parameter) + private void MethodWithOptionalParameter([Optional][DecimalConstant(1, 0, 0u, 0u, 10u)] decimal parameter) { } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoForEachStatement.Expected.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoForEachStatement.Expected.cs index 05c27d59c..83a13b41d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoForEachStatement.Expected.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoForEachStatement.Expected.cs @@ -9,8 +9,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly public static void SimpleNonGenericForeach(IEnumerable enumerable) { IEnumerator enumerator = enumerable.GetEnumerator(); - try { - while (enumerator.MoveNext()) { + try + { + while (enumerator.MoveNext()) + { #if ROSLYN && OPT Console.WriteLine(enumerator.Current); #else @@ -18,9 +20,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly Console.WriteLine(current); #endif } - } finally { + } + finally + { IDisposable disposable = enumerator as IDisposable; - if (disposable != null) { + if (disposable != null) + { disposable.Dispose(); } } @@ -28,8 +33,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly public static void SimpleForeachOverInts(IEnumerable enumerable) { - using (IEnumerator enumerator = enumerable.GetEnumerator()) { - while (enumerator.MoveNext()) { + using (IEnumerator enumerator = enumerable.GetEnumerator()) + { + while (enumerator.MoveNext()) + { #if ROSLYN && OPT Console.WriteLine(enumerator.Current); #else diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoForEachStatement.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoForEachStatement.cs index 6cced27e6..f0d3ebd77 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoForEachStatement.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoForEachStatement.cs @@ -8,14 +8,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly { public static void SimpleNonGenericForeach(IEnumerable enumerable) { - foreach (object item in enumerable) { + foreach (object item in enumerable) + { Console.WriteLine(item); } } public static void SimpleForeachOverInts(IEnumerable enumerable) { - foreach (int item in enumerable) { + foreach (int item in enumerable) + { Console.WriteLine(item); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Async.cs b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Async.cs index be22cc581..43b6ab950 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Async.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Async.cs @@ -1,6 +1,6 @@ using System; -using System.Threading.Tasks; using System.IO; +using System.Threading.Tasks; namespace EquivalentCSharpConsoleApp { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Select.cs b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Select.cs index 1b9e9ede6..0adcc593d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Select.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/Select.cs @@ -1,12 +1,14 @@ -using Microsoft.VisualBasic.CompilerServices; -using System; +using System; + +using Microsoft.VisualBasic.CompilerServices; [StandardModule] internal sealed class Program { public static void SelectOnString() { - switch (Environment.CommandLine) { + switch (Environment.CommandLine) + { case "123": Console.WriteLine("a"); break; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBCompoundAssign.cs b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBCompoundAssign.cs index 8b8807ec4..35ecd84f9 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBCompoundAssign.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBCompoundAssign.cs @@ -8,8 +8,10 @@ internal sealed class VBCompoundAssign { double[] array = new double[4]; int num = Information.UBound(v); - checked { - for (int i = 0; i <= num; i += 3) { + checked + { + for (int i = 0; i <= num; i += 3) + { array[0] += v[i]; array[1] += v[i + 1]; array[2] += v[i + 2]; diff --git a/ICSharpCode.Decompiler.Tests/TestTraceListener.cs b/ICSharpCode.Decompiler.Tests/TestTraceListener.cs index e57c0ca90..849b82477 100644 --- a/ICSharpCode.Decompiler.Tests/TestTraceListener.cs +++ b/ICSharpCode.Decompiler.Tests/TestTraceListener.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Diagnostics; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests @@ -29,13 +30,13 @@ namespace ICSharpCode.Decompiler.Tests { Debug.Listeners.Insert(0, this); } - + [OneTimeTearDown] public void RunAfterAnyTests() { Debug.Listeners.Remove(this); } - + public override void Fail(string message, string detailMessage) { Assert.Fail(message + " " + detailMessage); diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs index 273cf2b38..a0e9fc773 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs @@ -25,9 +25,11 @@ using System.Reflection.Metadata; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -499,7 +501,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.IsFalse(valueField.IsConst); Assert.IsFalse(valueField.IsStatic); - foreach (IField f in fields) { + foreach (IField f in fields) + { Assert.IsTrue(f.IsStatic); Assert.IsTrue(f.IsConst); Assert.AreEqual(Accessibility.Public, f.Accessibility); @@ -1020,7 +1023,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.AreEqual(5, arr.Length); return arr[index]; } - + [Test] public void ParamsAttribute_Integer() { @@ -1166,7 +1169,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public void PropertyAccessorsHaveBody() { ITypeDefinition type = GetTypeDefinition(typeof(ClassWithStaticAndNonStaticMembers)); - foreach (var prop in type.Properties) { + foreach (var prop in type.Properties) + { Assert.IsTrue(prop.Getter.HasBody, prop.Getter.Name); Assert.IsTrue(prop.Setter.HasBody, prop.Setter.Name); } @@ -1189,7 +1193,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public void EventAccessorHaveBody() { ITypeDefinition type = GetTypeDefinition(typeof(ClassWithStaticAndNonStaticMembers)); - foreach (var ev in type.Events) { + foreach (var ev in type.Events) + { Assert.IsTrue(ev.AddAccessor.HasBody, ev.AddAccessor.Name); Assert.IsTrue(ev.RemoveAccessor.HasBody, ev.RemoveAccessor.Name); } @@ -1353,7 +1358,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem { IType type = compilation.FindType(typeof(ExplicitGenericInterfaceImplementationWithUnifiableMethods)); Assert.AreEqual(2, type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count()); - foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) { + foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) + { Assert.AreEqual(1, method.ExplicitlyImplementedInterfaceMembers.Count(), method.ToString()); Assert.AreEqual("System.Int32", method.Parameters.Single().Type.ReflectionName); IMethod interfaceMethod = (IMethod)method.ExplicitlyImplementedInterfaceMembers.Single(); @@ -1365,7 +1371,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.AreEqual(genericParamType.ReflectionName, interfaceGenericParamType.ReflectionName); } } - + [Test] public void ExplicitGenericInterfaceImplementation() { @@ -1592,40 +1598,40 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem [Test] public void ExplicitImplementation() { - var type = GetTypeDefinition(typeof(ExplicitImplementationTests)); - var itype = GetTypeDefinition(typeof(IExplicitImplementationTests)); - - var methods = type.GetMethods(m => m.Name == "M" || m.Name.EndsWith(".M")).ToList(); - var imethod = itype.GetMethods(m => m.Name == "M").Single(); - Assert.That(methods.Select(m => m.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(methods.SelectMany(m => m.ExplicitlyImplementedInterfaceMembers).Single(), imethod); - - var properties = type.GetProperties(p => p.Name == "P" || p.Name.EndsWith(".P")).ToList(); - var iproperty = itype.GetProperties(m => m.Name == "P").Single(); - Assert.That(properties.Select(p => p.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(properties.SelectMany(p => p.ExplicitlyImplementedInterfaceMembers).Single(), iproperty); - Assert.That(properties.Select(p => p.Getter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(properties.SelectMany(p => p.Getter.ExplicitlyImplementedInterfaceMembers).Single(), iproperty.Getter); - Assert.That(properties.Select(p => p.Setter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(properties.SelectMany(p => p.Setter.ExplicitlyImplementedInterfaceMembers).Single(), iproperty.Setter); - - var indexers = type.GetProperties(p => p.Name == "Item" || p.Name.EndsWith(".Item")).ToList(); - var iindexer = itype.GetProperties(m => m.Name == "Item").Single(); - Assert.That(indexers.Select(p => p.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(indexers.SelectMany(p => p.ExplicitlyImplementedInterfaceMembers).Single(), iindexer); - Assert.That(indexers.Select(p => p.Getter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(indexers.SelectMany(p => p.Getter.ExplicitlyImplementedInterfaceMembers).Single(), iindexer.Getter); - Assert.That(indexers.Select(p => p.Setter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(indexers.SelectMany(p => p.Setter.ExplicitlyImplementedInterfaceMembers).Single(), iindexer.Setter); - - var events = type.GetEvents(e => e.Name == "E" || e.Name.EndsWith(".E")).ToList(); - var ievent = itype.GetEvents(m => m.Name == "E").Single(); - Assert.That(events.Select(e => e.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(events.SelectMany(e => e.ExplicitlyImplementedInterfaceMembers).Single(), ievent); - Assert.That(events.Select(e => e.AddAccessor.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(events.SelectMany(e => e.AddAccessor.ExplicitlyImplementedInterfaceMembers).Single(), ievent.AddAccessor); - Assert.That(events.Select(e => e.RemoveAccessor.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); - Assert.AreEqual(events.SelectMany(e => e.RemoveAccessor.ExplicitlyImplementedInterfaceMembers).Single(), ievent.RemoveAccessor); + var type = GetTypeDefinition(typeof(ExplicitImplementationTests)); + var itype = GetTypeDefinition(typeof(IExplicitImplementationTests)); + + var methods = type.GetMethods(m => m.Name == "M" || m.Name.EndsWith(".M")).ToList(); + var imethod = itype.GetMethods(m => m.Name == "M").Single(); + Assert.That(methods.Select(m => m.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); + Assert.AreEqual(methods.SelectMany(m => m.ExplicitlyImplementedInterfaceMembers).Single(), imethod); + + var properties = type.GetProperties(p => p.Name == "P" || p.Name.EndsWith(".P")).ToList(); + var iproperty = itype.GetProperties(m => m.Name == "P").Single(); + Assert.That(properties.Select(p => p.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); + Assert.AreEqual(properties.SelectMany(p => p.ExplicitlyImplementedInterfaceMembers).Single(), iproperty); + Assert.That(properties.Select(p => p.Getter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); + Assert.AreEqual(properties.SelectMany(p => p.Getter.ExplicitlyImplementedInterfaceMembers).Single(), iproperty.Getter); + Assert.That(properties.Select(p => p.Setter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); + Assert.AreEqual(properties.SelectMany(p => p.Setter.ExplicitlyImplementedInterfaceMembers).Single(), iproperty.Setter); + + var indexers = type.GetProperties(p => p.Name == "Item" || p.Name.EndsWith(".Item")).ToList(); + var iindexer = itype.GetProperties(m => m.Name == "Item").Single(); + Assert.That(indexers.Select(p => p.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); + Assert.AreEqual(indexers.SelectMany(p => p.ExplicitlyImplementedInterfaceMembers).Single(), iindexer); + Assert.That(indexers.Select(p => p.Getter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); + Assert.AreEqual(indexers.SelectMany(p => p.Getter.ExplicitlyImplementedInterfaceMembers).Single(), iindexer.Getter); + Assert.That(indexers.Select(p => p.Setter.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); + Assert.AreEqual(indexers.SelectMany(p => p.Setter.ExplicitlyImplementedInterfaceMembers).Single(), iindexer.Setter); + + var events = type.GetEvents(e => e.Name == "E" || e.Name.EndsWith(".E")).ToList(); + var ievent = itype.GetEvents(m => m.Name == "E").Single(); + Assert.That(events.Select(e => e.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); + Assert.AreEqual(events.SelectMany(e => e.ExplicitlyImplementedInterfaceMembers).Single(), ievent); + Assert.That(events.Select(e => e.AddAccessor.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); + Assert.AreEqual(events.SelectMany(e => e.AddAccessor.ExplicitlyImplementedInterfaceMembers).Single(), ievent.AddAccessor); + Assert.That(events.Select(e => e.RemoveAccessor.ExplicitlyImplementedInterfaceMembers.Count()).ToList(), Is.EquivalentTo(new[] { 0, 1 })); + Assert.AreEqual(events.SelectMany(e => e.RemoveAccessor.ExplicitlyImplementedInterfaceMembers).Single(), ievent.RemoveAccessor); } [Test] diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs index 079057bd4..d6f54d953 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs @@ -18,8 +18,8 @@ using System; using System.Collections.Generic; -using System.Runtime.InteropServices; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; [assembly: ICSharpCode.Decompiler.Tests.TypeSystem.TypeTestAttribute( 42, typeof(System.Action<>), typeof(IDictionary>))] @@ -537,30 +537,30 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public interface IMarshalAsTests { [DispId(48)] - void AliasComponent([MarshalAs(UnmanagedType.BStr)] [In] string bstrSrcApplicationIDOrName, [MarshalAs(UnmanagedType.BStr)] [In] string bstrCLSIDOrProgID, [MarshalAs(UnmanagedType.BStr)] [In] string bstrDestApplicationIDOrName, [MarshalAs(UnmanagedType.BStr)] [In] string bstrNewProgId, [MarshalAs(UnmanagedType.BStr)] [In] string bstrNewClsid); + void AliasComponent([MarshalAs(UnmanagedType.BStr)][In] string bstrSrcApplicationIDOrName, [MarshalAs(UnmanagedType.BStr)][In] string bstrCLSIDOrProgID, [MarshalAs(UnmanagedType.BStr)][In] string bstrDestApplicationIDOrName, [MarshalAs(UnmanagedType.BStr)][In] string bstrNewProgId, [MarshalAs(UnmanagedType.BStr)][In] string bstrNewClsid); [DispId(33)] [return: MarshalAs(UnmanagedType.VariantBool)] - bool AreApplicationInstancesPaused([MarshalAs(UnmanagedType.LPStruct)] [In] object pVarApplicationInstanceID); + bool AreApplicationInstancesPaused([MarshalAs(UnmanagedType.LPStruct)][In] object pVarApplicationInstanceID); [DispId(19)] - void BackupREGDB([MarshalAs(UnmanagedType.BStr)] [In] string bstrBackupFilePath); + void BackupREGDB([MarshalAs(UnmanagedType.BStr)][In] string bstrBackupFilePath); [DispId(2)] [return: MarshalAs(UnmanagedType.Interface)] - object Connect([MarshalAs(UnmanagedType.BStr)] [In] string connectStr); + object Connect([MarshalAs(UnmanagedType.BStr)][In] string connectStr); [DispId(45)] - void CopyApplications([MarshalAs(UnmanagedType.BStr)] [In] string bstrSourcePartitionIDOrName, [MarshalAs(UnmanagedType.LPStruct)] [In] object pVarApplicationID, [MarshalAs(UnmanagedType.BStr)] [In] string bstrDestinationPartitionIDOrName); + void CopyApplications([MarshalAs(UnmanagedType.BStr)][In] string bstrSourcePartitionIDOrName, [MarshalAs(UnmanagedType.LPStruct)][In] object pVarApplicationID, [MarshalAs(UnmanagedType.BStr)][In] string bstrDestinationPartitionIDOrName); [DispId(46)] - void CopyComponents([MarshalAs(UnmanagedType.BStr)] [In] string bstrSourceApplicationIDOrName, [MarshalAs(UnmanagedType.LPStruct)] [In] object pVarCLSIDOrProgID, [MarshalAs(UnmanagedType.BStr)] [In] string bstrDestinationApplicationIDOrName); + void CopyComponents([MarshalAs(UnmanagedType.BStr)][In] string bstrSourceApplicationIDOrName, [MarshalAs(UnmanagedType.LPStruct)][In] object pVarCLSIDOrProgID, [MarshalAs(UnmanagedType.BStr)][In] string bstrDestinationApplicationIDOrName); [DispId(36)] - void CreateServiceForApplication([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationIDOrName, [MarshalAs(UnmanagedType.BStr)] [In] string bstrServiceName, [MarshalAs(UnmanagedType.BStr)] [In] string bstrStartType, [MarshalAs(UnmanagedType.BStr)] [In] string bstrErrorControl, [MarshalAs(UnmanagedType.BStr)] [In] string bstrDependencies, [MarshalAs(UnmanagedType.BStr)] [In] string bstrRunAs, [MarshalAs(UnmanagedType.BStr)] [In] string bstrPassword, [MarshalAs(UnmanagedType.VariantBool)] [In] bool bDesktopOk); + void CreateServiceForApplication([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationIDOrName, [MarshalAs(UnmanagedType.BStr)][In] string bstrServiceName, [MarshalAs(UnmanagedType.BStr)][In] string bstrStartType, [MarshalAs(UnmanagedType.BStr)][In] string bstrErrorControl, [MarshalAs(UnmanagedType.BStr)][In] string bstrDependencies, [MarshalAs(UnmanagedType.BStr)][In] string bstrRunAs, [MarshalAs(UnmanagedType.BStr)][In] string bstrPassword, [MarshalAs(UnmanagedType.VariantBool)][In] bool bDesktopOk); [DispId(40)] - void CurrentPartition([MarshalAs(UnmanagedType.BStr)] [In] string bstrPartitionIDOrName); + void CurrentPartition([MarshalAs(UnmanagedType.BStr)][In] string bstrPartitionIDOrName); [DispId(41)] [return: MarshalAs(UnmanagedType.BStr)] @@ -571,85 +571,85 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem string CurrentPartitionName(); [DispId(37)] - void DeleteServiceForApplication([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationIDOrName); + void DeleteServiceForApplication([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationIDOrName); [DispId(34)] [return: MarshalAs(UnmanagedType.BStr)] - string DumpApplicationInstance([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationInstanceID, [MarshalAs(UnmanagedType.BStr)] [In] string bstrDirectory, [MarshalAs(UnmanagedType.I4)] [In] int lMaxImages); + string DumpApplicationInstance([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationInstanceID, [MarshalAs(UnmanagedType.BStr)][In] string bstrDirectory, [MarshalAs(UnmanagedType.I4)][In] int lMaxImages); [DispId(9)] - void ExportApplication([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationFile, [In] int lOptions); + void ExportApplication([MarshalAs(UnmanagedType.BStr)][In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationFile, [In] int lOptions); [DispId(54)] - void ExportPartition([MarshalAs(UnmanagedType.BStr)] [In] string bstrPartitionIDOrName, [MarshalAs(UnmanagedType.BStr)] [In] string bstrPartitionFileName, [MarshalAs(UnmanagedType.I4)] [In] int lOptions); + void ExportPartition([MarshalAs(UnmanagedType.BStr)][In] string bstrPartitionIDOrName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPartitionFileName, [MarshalAs(UnmanagedType.I4)][In] int lOptions); [DispId(44)] void FlushPartitionCache(); [DispId(28)] [return: MarshalAs(UnmanagedType.BStr)] - string GetApplicationInstanceIDFromProcessID([MarshalAs(UnmanagedType.I4)] [In] int lProcessID); + string GetApplicationInstanceIDFromProcessID([MarshalAs(UnmanagedType.I4)][In] int lProcessID); [DispId(1)] [return: MarshalAs(UnmanagedType.Interface)] - object GetCollection([MarshalAs(UnmanagedType.BStr)] [In] string bstrCollName); + object GetCollection([MarshalAs(UnmanagedType.BStr)][In] string bstrCollName); [DispId(5)] [return: MarshalAs(UnmanagedType.Interface)] - object GetCollectionByQuery([MarshalAs(UnmanagedType.BStr)] [In] string collName, [MarshalAs(UnmanagedType.SafeArray)] [In] ref object[] aQuery); + object GetCollectionByQuery([MarshalAs(UnmanagedType.BStr)][In] string collName, [MarshalAs(UnmanagedType.SafeArray)][In] ref object[] aQuery); [DispId(27)] [return: MarshalAs(UnmanagedType.Interface)] - object GetCollectionByQuery2([MarshalAs(UnmanagedType.BStr)] [In] string bstrCollectionName, [MarshalAs(UnmanagedType.LPStruct)] [In] object pVarQueryStrings); + object GetCollectionByQuery2([MarshalAs(UnmanagedType.BStr)][In] string bstrCollectionName, [MarshalAs(UnmanagedType.LPStruct)][In] object pVarQueryStrings); [DispId(57)] [return: MarshalAs(UnmanagedType.I4)] - int GetComponentVersionCount([MarshalAs(UnmanagedType.BStr)] [In] string bstrCLSIDOrProgID); + int GetComponentVersionCount([MarshalAs(UnmanagedType.BStr)][In] string bstrCLSIDOrProgID); [DispId(26)] - void GetEventClassesForIID([In] string bstrIID, [MarshalAs(UnmanagedType.SafeArray)] [In] [Out] ref object[] varCLSIDS, [MarshalAs(UnmanagedType.SafeArray)] [In] [Out] ref object[] varProgIDs, [MarshalAs(UnmanagedType.SafeArray)] [In] [Out] ref object[] varDescriptions); + void GetEventClassesForIID([In] string bstrIID, [MarshalAs(UnmanagedType.SafeArray)][In][Out] ref object[] varCLSIDS, [MarshalAs(UnmanagedType.SafeArray)][In][Out] ref object[] varProgIDs, [MarshalAs(UnmanagedType.SafeArray)][In][Out] ref object[] varDescriptions); [DispId(17)] - void GetMultipleComponentsInfo([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplIdOrName, [In] object varFileNames, [MarshalAs(UnmanagedType.SafeArray)] out object[] varCLSIDS, [MarshalAs(UnmanagedType.SafeArray)] out object[] varClassNames, [MarshalAs(UnmanagedType.SafeArray)] out object[] varFileFlags, [MarshalAs(UnmanagedType.SafeArray)] out object[] varComponentFlags); + void GetMultipleComponentsInfo([MarshalAs(UnmanagedType.BStr)][In] string bstrApplIdOrName, [In] object varFileNames, [MarshalAs(UnmanagedType.SafeArray)] out object[] varCLSIDS, [MarshalAs(UnmanagedType.SafeArray)] out object[] varClassNames, [MarshalAs(UnmanagedType.SafeArray)] out object[] varFileFlags, [MarshalAs(UnmanagedType.SafeArray)] out object[] varComponentFlags); [DispId(38)] [return: MarshalAs(UnmanagedType.BStr)] - string GetPartitionID([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationIDOrName); + string GetPartitionID([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationIDOrName); [DispId(39)] [return: MarshalAs(UnmanagedType.BStr)] - string GetPartitionName([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationIDOrName); + string GetPartitionName([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationIDOrName); [DispId(43)] [return: MarshalAs(UnmanagedType.BStr)] string GlobalPartitionID(); [DispId(6)] - void ImportComponent([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.BStr)] [In] string bstrCLSIDOrProgId); + void ImportComponent([MarshalAs(UnmanagedType.BStr)][In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.BStr)][In] string bstrCLSIDOrProgId); [DispId(52)] - void ImportComponents([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationIDOrName, [MarshalAs(UnmanagedType.LPStruct)] [In] object pVarCLSIDOrProgID, [MarshalAs(UnmanagedType.LPStruct)] [In] object pVarComponentType); + void ImportComponents([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationIDOrName, [MarshalAs(UnmanagedType.LPStruct)][In] object pVarCLSIDOrProgID, [MarshalAs(UnmanagedType.LPStruct)][In] object pVarComponentType); [DispId(50)] - void ImportUnconfiguredComponents([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationIDOrName, [MarshalAs(UnmanagedType.LPStruct)] [In] object pVarCLSIDOrProgID, [MarshalAs(UnmanagedType.LPStruct)] [In] object pVarComponentType); + void ImportUnconfiguredComponents([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationIDOrName, [MarshalAs(UnmanagedType.LPStruct)][In] object pVarCLSIDOrProgID, [MarshalAs(UnmanagedType.LPStruct)][In] object pVarComponentType); [DispId(10)] - void InstallApplication([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationFile, [MarshalAs(UnmanagedType.BStr)] [In] string bstrDestinationDirectory, [In] int lOptions, [MarshalAs(UnmanagedType.BStr)] [In] string bstrUserId, [MarshalAs(UnmanagedType.BStr)] [In] string bstrPassword, [MarshalAs(UnmanagedType.BStr)] [In] string bstrRSN); + void InstallApplication([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationFile, [MarshalAs(UnmanagedType.BStr)][In] string bstrDestinationDirectory, [In] int lOptions, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserId, [MarshalAs(UnmanagedType.BStr)][In] string bstrPassword, [MarshalAs(UnmanagedType.BStr)][In] string bstrRSN); [DispId(7)] - void InstallComponent([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.BStr)] [In] string bstrDLL, [MarshalAs(UnmanagedType.BStr)] [In] string bstrTLB, [MarshalAs(UnmanagedType.BStr)] [In] string bstrPSDLL); + void InstallComponent([MarshalAs(UnmanagedType.BStr)][In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.BStr)][In] string bstrDLL, [MarshalAs(UnmanagedType.BStr)][In] string bstrTLB, [MarshalAs(UnmanagedType.BStr)][In] string bstrPSDLL); [DispId(25)] - void InstallEventClass([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.BStr)] [In] string bstrDLL, [MarshalAs(UnmanagedType.BStr)] [In] string bstrTLB, [MarshalAs(UnmanagedType.BStr)] [In] string bstrPSDLL); + void InstallEventClass([MarshalAs(UnmanagedType.BStr)][In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.BStr)][In] string bstrDLL, [MarshalAs(UnmanagedType.BStr)][In] string bstrTLB, [MarshalAs(UnmanagedType.BStr)][In] string bstrPSDLL); [DispId(16)] - void InstallMultipleComponents([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] [In] ref object[] fileNames, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] [In] ref object[] CLSIDS); + void InstallMultipleComponents([MarshalAs(UnmanagedType.BStr)][In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)][In] ref object[] fileNames, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)][In] ref object[] CLSIDS); [DispId(24)] - void InstallMultipleEventClasses([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] [In] ref object[] fileNames, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] [In] ref object[] CLSIDS); + void InstallMultipleEventClasses([MarshalAs(UnmanagedType.BStr)][In] string bstrApplIdOrName, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)][In] ref object[] fileNames, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)][In] ref object[] CLSIDS); [DispId(55)] - void InstallPartition([MarshalAs(UnmanagedType.BStr)] [In] string bstrFileName, [MarshalAs(UnmanagedType.BStr)] [In] string bstrDestDirectory, [MarshalAs(UnmanagedType.I4)] [In] int lOptions, [MarshalAs(UnmanagedType.BStr)] [In] string bstrUserID, [MarshalAs(UnmanagedType.BStr)] [In] string bstrPassword, [MarshalAs(UnmanagedType.BStr)] [In] string bstrRSN); + void InstallPartition([MarshalAs(UnmanagedType.BStr)][In] string bstrFileName, [MarshalAs(UnmanagedType.BStr)][In] string bstrDestDirectory, [MarshalAs(UnmanagedType.I4)][In] int lOptions, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserID, [MarshalAs(UnmanagedType.BStr)][In] string bstrPassword, [MarshalAs(UnmanagedType.BStr)][In] string bstrRSN); [DispId(53)] [return: MarshalAs(UnmanagedType.VariantBool)] @@ -661,7 +661,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem [DispId(49)] [return: MarshalAs(UnmanagedType.Interface)] - object IsSafeToDelete([MarshalAs(UnmanagedType.BStr)] [In] string bstrDllName); + object IsSafeToDelete([MarshalAs(UnmanagedType.BStr)][In] string bstrDllName); [DispId(3)] int MajorVersion(); @@ -670,23 +670,23 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem int MinorVersion(); [DispId(47)] - void MoveComponents([MarshalAs(UnmanagedType.BStr)] [In] string bstrSourceApplicationIDOrName, [MarshalAs(UnmanagedType.LPStruct)] [In] object pVarCLSIDOrProgID, [MarshalAs(UnmanagedType.BStr)] [In] string bstrDestinationApplicationIDOrName); + void MoveComponents([MarshalAs(UnmanagedType.BStr)][In] string bstrSourceApplicationIDOrName, [MarshalAs(UnmanagedType.LPStruct)][In] object pVarCLSIDOrProgID, [MarshalAs(UnmanagedType.BStr)][In] string bstrDestinationApplicationIDOrName); [DispId(30)] - void PauseApplicationInstances([MarshalAs(UnmanagedType.LPStruct)] [In] object pVarApplicationInstanceID); + void PauseApplicationInstances([MarshalAs(UnmanagedType.LPStruct)][In] object pVarApplicationInstanceID); [DispId(51)] - void PromoteUnconfiguredComponents([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationIDOrName, [MarshalAs(UnmanagedType.LPStruct)] [In] object pVarCLSIDOrProgID, [MarshalAs(UnmanagedType.LPStruct)] [In] object pVarComponentType); + void PromoteUnconfiguredComponents([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationIDOrName, [MarshalAs(UnmanagedType.LPStruct)][In] object pVarCLSIDOrProgID, [MarshalAs(UnmanagedType.LPStruct)][In] object pVarComponentType); [DispId(21)] - void QueryApplicationFile([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationFile, [MarshalAs(UnmanagedType.BStr)] out string bstrApplicationName, [MarshalAs(UnmanagedType.BStr)] out string bstrApplicationDescription, [MarshalAs(UnmanagedType.VariantBool)] out bool bHasUsers, [MarshalAs(UnmanagedType.VariantBool)] out bool bIsProxy, [MarshalAs(UnmanagedType.SafeArray)] out object[] varFileNames); + void QueryApplicationFile([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationFile, [MarshalAs(UnmanagedType.BStr)] out string bstrApplicationName, [MarshalAs(UnmanagedType.BStr)] out string bstrApplicationDescription, [MarshalAs(UnmanagedType.VariantBool)] out bool bHasUsers, [MarshalAs(UnmanagedType.VariantBool)] out bool bIsProxy, [MarshalAs(UnmanagedType.SafeArray)] out object[] varFileNames); [DispId(56)] [return: MarshalAs(UnmanagedType.IDispatch)] - object QueryApplicationFile2([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplicationFile); + object QueryApplicationFile2([MarshalAs(UnmanagedType.BStr)][In] string bstrApplicationFile); [DispId(32)] - void RecycleApplicationInstances([MarshalAs(UnmanagedType.LPStruct)] [In] object pVarApplicationInstanceID, [MarshalAs(UnmanagedType.I4)] [In] int lReasonCode); + void RecycleApplicationInstances([MarshalAs(UnmanagedType.LPStruct)][In] object pVarApplicationInstanceID, [MarshalAs(UnmanagedType.I4)][In] int lReasonCode); [DispId(18)] void RefreshComponents(); @@ -701,22 +701,22 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem void Reserved2(); [DispId(20)] - void RestoreREGDB([MarshalAs(UnmanagedType.BStr)] [In] string bstrBackupFilePath); + void RestoreREGDB([MarshalAs(UnmanagedType.BStr)][In] string bstrBackupFilePath); [DispId(31)] - void ResumeApplicationInstances([MarshalAs(UnmanagedType.LPStruct)] [In] object pVarApplicationInstanceID); + void ResumeApplicationInstances([MarshalAs(UnmanagedType.LPStruct)][In] object pVarApplicationInstanceID); [DispId(23)] int ServiceCheck([In] int lService); [DispId(8)] - void ShutdownApplication([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplIdOrName); + void ShutdownApplication([MarshalAs(UnmanagedType.BStr)][In] string bstrApplIdOrName); [DispId(29)] - void ShutdownApplicationInstances([MarshalAs(UnmanagedType.LPStruct)] [In] object pVarApplicationInstanceID); + void ShutdownApplicationInstances([MarshalAs(UnmanagedType.LPStruct)][In] object pVarApplicationInstanceID); [DispId(22)] - void StartApplication([MarshalAs(UnmanagedType.BStr)] [In] string bstrApplIdOrName); + void StartApplication([MarshalAs(UnmanagedType.BStr)][In] string bstrApplIdOrName); [DispId(13)] void StartRouter(); diff --git a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs index 8a8ce9559..71542efce 100644 --- a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs @@ -21,7 +21,9 @@ using System.CodeDom.Compiler; using System.IO; using System.Linq; using System.Runtime.CompilerServices; + using ICSharpCode.Decompiler.Tests.Helpers; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests @@ -38,9 +40,11 @@ namespace ICSharpCode.Decompiler.Tests .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any()) .Select(m => m.Name) .ToArray(); - foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) { + foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) + { if (file.Extension.Equals(".il", StringComparison.OrdinalIgnoreCase) - || file.Extension.Equals(".cs", StringComparison.OrdinalIgnoreCase)) { + || file.Extension.Equals(".cs", StringComparison.OrdinalIgnoreCase)) + { var testName = file.Name.Split('.')[0]; Assert.Contains(testName, testNames); } @@ -125,13 +129,17 @@ namespace ICSharpCode.Decompiler.Tests var csFile = Path.Combine(TestCasePath, testName + ".cs"); var expectedFile = Path.Combine(TestCasePath, testName + ".Expected.cs"); - if (!File.Exists(ilFile)) { + if (!File.Exists(ilFile)) + { // re-create .il file if necessary CompilerResults output = null; - try { + try + { output = Tester.CompileCSharp(csFile, cscOptions); Tester.Disassemble(output.PathToAssembly, ilFile, asmOptions); - } finally { + } + finally + { if (output != null) output.TempFiles.Delete(); } @@ -139,7 +147,7 @@ namespace ICSharpCode.Decompiler.Tests var executable = Tester.AssembleIL(ilFile, asmOptions); var decompiled = Tester.DecompileCSharp(executable, decompilerSettings); - + CodeAssert.FilesAreEqual(expectedFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray()); } } diff --git a/ICSharpCode.Decompiler.Tests/Util/BitSetTests.cs b/ICSharpCode.Decompiler.Tests/Util/BitSetTests.cs index 66cf10636..8f22676bb 100644 --- a/ICSharpCode.Decompiler.Tests/Util/BitSetTests.cs +++ b/ICSharpCode.Decompiler.Tests/Util/BitSetTests.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using ICSharpCode.Decompiler.Util; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Util @@ -31,7 +32,8 @@ namespace ICSharpCode.Decompiler.Tests.Util bitset.Set(2, 300); Assert.IsFalse(bitset[0]); Assert.IsFalse(bitset[1]); - for (int i = 2; i < 300; ++i) { + for (int i = 2; i < 300; ++i) + { Assert.IsTrue(bitset[i]); } Assert.IsFalse(bitset[301]); @@ -44,7 +46,8 @@ namespace ICSharpCode.Decompiler.Tests.Util bitset.Set(0, 300); bitset.Clear(1, 299); Assert.IsTrue(bitset[0]); - for (int i = 1; i < 299; ++i) { + for (int i = 1; i < 299; ++i) + { Assert.IsFalse(bitset[i]); } Assert.IsTrue(bitset[299]); diff --git a/ICSharpCode.Decompiler.Tests/Util/IntervalTests.cs b/ICSharpCode.Decompiler.Tests/Util/IntervalTests.cs index b6fe013e9..6fcf322af 100644 --- a/ICSharpCode.Decompiler.Tests/Util/IntervalTests.cs +++ b/ICSharpCode.Decompiler.Tests/Util/IntervalTests.cs @@ -16,9 +16,10 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using NUnit.Framework; using ICSharpCode.Decompiler.Util; +using NUnit.Framework; + namespace ICSharpCode.Decompiler.Tests.Util { public class IntervalTests @@ -41,7 +42,7 @@ namespace ICSharpCode.Decompiler.Tests.Util Assert.IsFalse(default(Interval).Contains(1)); Assert.IsFalse(default(Interval).Contains(2)); } - + [Test] public void OneToThree() { @@ -52,7 +53,7 @@ namespace ICSharpCode.Decompiler.Tests.Util Assert.IsTrue(i.Contains(2)); Assert.IsFalse(i.Contains(3)); } - + [Test] public void FullInterval() { @@ -62,7 +63,7 @@ namespace ICSharpCode.Decompiler.Tests.Util Assert.IsTrue(full.Contains(0)); Assert.IsTrue(full.Contains(int.MaxValue)); } - + [Test] public void NonNegativeIntegers() { @@ -75,7 +76,7 @@ namespace ICSharpCode.Decompiler.Tests.Util Assert.IsFalse(i.Contains(-1000)); Assert.IsFalse(i.Contains(int.MinValue)); } - + [Test] public void Intersection() { diff --git a/ICSharpCode.Decompiler.Tests/Util/LongSetTests.cs b/ICSharpCode.Decompiler.Tests/Util/LongSetTests.cs index 72e9add70..1718a394b 100644 --- a/ICSharpCode.Decompiler.Tests/Util/LongSetTests.cs +++ b/ICSharpCode.Decompiler.Tests/Util/LongSetTests.cs @@ -18,7 +18,9 @@ using System.Collections.Immutable; using System.Linq; + using ICSharpCode.Decompiler.Util; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Util diff --git a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs index 6c1df2b1e..57018170a 100644 --- a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs @@ -20,7 +20,9 @@ using System; using System.IO; using System.Linq; using System.Runtime.CompilerServices; + using ICSharpCode.Decompiler.Tests.Helpers; + using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests @@ -37,8 +39,10 @@ namespace ICSharpCode.Decompiler.Tests .Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any()) .Select(m => m.Name) .ToArray(); - foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) { - if (file.Extension.Equals(".vb", StringComparison.OrdinalIgnoreCase)) { + foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) + { + if (file.Extension.Equals(".vb", StringComparison.OrdinalIgnoreCase)) + { var testName = file.Name.Split('.')[0]; Assert.Contains(testName, testNames); Assert.IsTrue(File.Exists(Path.Combine(TestCasePath, testName + ".cs"))); @@ -89,7 +93,8 @@ namespace ICSharpCode.Decompiler.Tests var vbFile = Path.Combine(TestCasePath, testName + ".vb"); var csFile = Path.Combine(TestCasePath, testName + ".cs"); var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(options) + ".exe"; - if (options.HasFlag(CompilerOptions.Library)) { + if (options.HasFlag(CompilerOptions.Library)) + { exeFile = Path.ChangeExtension(exeFile, ".dll"); } diff --git a/ICSharpCode.Decompiler/CSharp/Annotations.cs b/ICSharpCode.Decompiler/CSharp/Annotations.cs index 631a6e29d..5f5a2e8ba 100644 --- a/ICSharpCode.Decompiler/CSharp/Annotations.cs +++ b/ICSharpCode.Decompiler/CSharp/Annotations.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; @@ -30,28 +31,33 @@ namespace ICSharpCode.Decompiler.CSharp // Annotations: // * AstNodes should be annotated with the corresponding ILInstruction // * AstNodes referring to other entities should be annotated with the IEntity - // * Expression type information is currently only available in the ExpressionBuilder, but we might change 'WithTypeInfo()' - // to use an annotation in the future - // * IntroduceUnsafeModifier.PointerArithmeticAnnotation is placed on arithmetic operators that operate on pointers. + // * Expression type information is currently only available in the ExpressionBuilder, but we might + // change 'WithTypeInfo()' to use an annotation in the future + // * IntroduceUnsafeModifier.PointerArithmeticAnnotation is placed on arithmetic operators that operate + // on pointers. // TODO: actually, we could use the type info instead? - // * AddCheckedBlocks.CheckedAnnotation / AddCheckedBlocks.UnCheckedAnnotation is used on checked/unchecked integer arithmetic + // * AddCheckedBlocks.CheckedAnnotation / AddCheckedBlocks.UnCheckedAnnotation is used on + // checked/unchecked integer arithmetic // TODO: here the info is also redundant, we could peek at the BinaryNumericInstruction instead // but on the other hand, some unchecked casts are not backed by any BinaryNumericInstruction /// - /// Currently unused; we'll probably use the LdToken ILInstruction as annotation instead when LdToken support gets reimplemented. + /// Currently unused; we'll probably use the LdToken ILInstruction as annotation instead when LdToken + /// support gets reimplemented. /// public class LdTokenAnnotation { } public static class AnnotationExtensions { - internal static ExpressionWithILInstruction WithILInstruction(this Expression expression, ILInstruction instruction) + internal static ExpressionWithILInstruction WithILInstruction(this Expression expression, + ILInstruction instruction) { expression.AddAnnotation(instruction); return new ExpressionWithILInstruction(expression); } - internal static ExpressionWithILInstruction WithILInstruction(this Expression expression, IEnumerable instructions) + internal static ExpressionWithILInstruction WithILInstruction(this Expression expression, + IEnumerable instructions) { foreach (var inst in instructions) expression.AddAnnotation(inst); @@ -63,13 +69,15 @@ namespace ICSharpCode.Decompiler.CSharp return new ExpressionWithILInstruction(expression); } - internal static TranslatedStatement WithILInstruction(this Statement statement, ILInstruction instruction) + internal static TranslatedStatement WithILInstruction(this Statement statement, + ILInstruction instruction) { statement.AddAnnotation(instruction); return new TranslatedStatement(statement); } - internal static TranslatedStatement WithILInstruction(this Statement statement, IEnumerable instructions) + internal static TranslatedStatement WithILInstruction(this Statement statement, + IEnumerable instructions) { foreach (var inst in instructions) statement.AddAnnotation(inst); @@ -81,20 +89,23 @@ namespace ICSharpCode.Decompiler.CSharp return new TranslatedStatement(statement); } - internal static TranslatedExpression WithILInstruction(this ExpressionWithResolveResult expression, ILInstruction instruction) + internal static TranslatedExpression WithILInstruction(this ExpressionWithResolveResult expression, + ILInstruction instruction) { expression.Expression.AddAnnotation(instruction); return new TranslatedExpression(expression.Expression, expression.ResolveResult); } - internal static TranslatedExpression WithILInstruction(this ExpressionWithResolveResult expression, IEnumerable instructions) + internal static TranslatedExpression WithILInstruction(this ExpressionWithResolveResult expression, + IEnumerable instructions) { foreach (var inst in instructions) expression.Expression.AddAnnotation(inst); return new TranslatedExpression(expression.Expression, expression.ResolveResult); } - internal static TranslatedExpression WithILInstruction(this TranslatedExpression expression, ILInstruction instruction) + internal static TranslatedExpression WithILInstruction(this TranslatedExpression expression, + ILInstruction instruction) { expression.Expression.AddAnnotation(instruction); return expression; @@ -105,37 +116,46 @@ namespace ICSharpCode.Decompiler.CSharp return new TranslatedExpression(expression.Expression, expression.ResolveResult); } - internal static ExpressionWithResolveResult WithRR(this Expression expression, ResolveResult resolveResult) + internal static ExpressionWithResolveResult WithRR(this Expression expression, + ResolveResult resolveResult) { expression.AddAnnotation(resolveResult); return new ExpressionWithResolveResult(expression, resolveResult); } - internal static TranslatedExpression WithRR(this ExpressionWithILInstruction expression, ResolveResult resolveResult) + internal static TranslatedExpression WithRR(this ExpressionWithILInstruction expression, + ResolveResult resolveResult) { expression.Expression.AddAnnotation(resolveResult); return new TranslatedExpression(expression, resolveResult); } /// - /// Retrieves the associated with this AstNode, or null if no symbol is associated with the node. + /// Retrieves the associated with this AstNode, or null if no symbol + /// is associated with the node. /// public static ISymbol GetSymbol(this AstNode node) { var rr = node.Annotation(); - if (rr is MethodGroupResolveResult) { + if (rr is MethodGroupResolveResult) + { // delegate construction? var newObj = node.Annotation(); - if (newObj != null) { + if (newObj != null) + { var funcptr = newObj.Arguments.ElementAtOrDefault(1); - if (funcptr is LdFtn ldftn) { + if (funcptr is LdFtn ldftn) + { return ldftn.Method; - } else if (funcptr is LdVirtFtn ldVirtFtn) { + } + else if (funcptr is LdVirtFtn ldVirtFtn) + { return ldVirtFtn.Method; } } var ldVirtDelegate = node.Annotation(); - if (ldVirtDelegate != null) { + if (ldVirtDelegate != null) + { return ldVirtDelegate.Method; } } @@ -143,7 +163,8 @@ namespace ICSharpCode.Decompiler.CSharp } /// - /// Retrieves the associated with this , or if no resolve result is associated with the node. + /// Retrieves the associated with this , + /// or if no resolve result is associated with the node. /// public static ResolveResult GetResolveResult(this AstNode node) { @@ -151,7 +172,8 @@ namespace ICSharpCode.Decompiler.CSharp } /// - /// Retrieves the associated with this , or null if no variable is associated with this identifier. + /// Retrieves the associated with this , + /// or null if no variable is associated with this identifier. /// public static ILVariable GetILVariable(this IdentifierExpression expr) { @@ -162,7 +184,8 @@ namespace ICSharpCode.Decompiler.CSharp } /// - /// Retrieves the associated with this , or null if no variable is associated with this initializer. + /// Retrieves the associated with this , + /// or null if no variable is associated with this initializer. /// public static ILVariable GetILVariable(this VariableInitializer vi) { @@ -173,7 +196,8 @@ namespace ICSharpCode.Decompiler.CSharp } /// - /// Retrieves the associated with this , or null if no variable is associated with this foreach statement. + /// Retrieves the associated with this , + /// or null if no variable is associated with this foreach statement. /// public static ILVariable GetILVariable(this ForeachStatement loop) { @@ -206,18 +230,21 @@ namespace ICSharpCode.Decompiler.CSharp /// public static T CopyAnnotationsFrom(this T node, AstNode other) where T : AstNode { - foreach (object annotation in other.Annotations) { + foreach (object annotation in other.Annotations) + { node.AddAnnotation(annotation); } return node; } /// - /// Copies all annotations from to . + /// Copies all annotations from + /// to . /// public static T CopyInstructionsFrom(this T node, AstNode other) where T : AstNode { - foreach (object annotation in other.Annotations.OfType()) { + foreach (object annotation in other.Annotations.OfType()) + { node.AddAnnotation(annotation); } return node; @@ -243,7 +270,8 @@ namespace ICSharpCode.Decompiler.CSharp } /// - /// Annotates a with the instructions for the GetEnumerator, MoveNext and get_Current calls. + /// Annotates a with the instructions for the GetEnumerator, MoveNext + /// and get_Current calls. /// public class ForeachAnnotation { @@ -251,7 +279,8 @@ namespace ICSharpCode.Decompiler.CSharp public readonly ILInstruction MoveNextCall; public readonly ILInstruction GetCurrentCall; - public ForeachAnnotation(ILInstruction getEnumeratorCall, ILInstruction moveNextCall, ILInstruction getCurrentCall) + public ForeachAnnotation(ILInstruction getEnumeratorCall, ILInstruction moveNextCall, + ILInstruction getCurrentCall) { GetEnumeratorCall = getEnumeratorCall; MoveNextCall = moveNextCall; diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index c09132e42..3a2af8620 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -18,31 +18,33 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; +using System.IO; using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Reflection.PortableExecutable; +using System.Runtime.InteropServices; using System.Threading; + using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax; +using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.CSharp.Transforms; +using ICSharpCode.Decompiler.DebugInfo; +using ICSharpCode.Decompiler.Disassembler; +using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.ControlFlow; using ICSharpCode.Decompiler.IL.Transforms; -using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Semantics; +using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; -using System.IO; -using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; -using System.Collections.Immutable; -using System.Runtime.InteropServices; -using System.Reflection.Metadata; + using SRM = System.Reflection.Metadata; -using ICSharpCode.Decompiler.Metadata; -using System.Reflection.PortableExecutable; -using ICSharpCode.Decompiler.Documentation; -using ICSharpCode.Decompiler.DebugInfo; -using ICSharpCode.Decompiler.Disassembler; -using System.Reflection.Metadata.Ecma335; namespace ICSharpCode.Decompiler.CSharp { @@ -276,7 +278,8 @@ namespace ICSharpCode.Decompiler.CSharp return false; var metadata = module.Metadata; string name; - switch (member.Kind) { + switch (member.Kind) + { case HandleKind.MethodDefinition: var methodHandle = (MethodDefinitionHandle)member; var method = metadata.GetMethodDefinition(methodHandle); @@ -294,7 +297,8 @@ namespace ICSharpCode.Decompiler.CSharp var typeHandle = (TypeDefinitionHandle)member; var type = metadata.GetTypeDefinition(typeHandle); name = metadata.GetString(type.Name); - if (!type.GetDeclaringType().IsNil) { + if (!type.GetDeclaringType().IsNil) + { if (LocalFunctionDecompiler.IsLocalFunctionDisplayClass(module, typeHandle)) return settings.LocalFunctions; if (settings.AnonymousMethods && IsClosureType(type, metadata)) @@ -307,7 +311,9 @@ namespace ICSharpCode.Decompiler.CSharp return true; if (settings.FixedBuffers && name.StartsWith("<", StringComparison.Ordinal) && name.Contains("__FixedBuffer")) return true; - } else if (type.IsCompilerGenerated(metadata)) { + } + else if (type.IsCompilerGenerated(metadata)) + { if (settings.ArrayInitializers && name.StartsWith("", StringComparison.Ordinal)) return true; if (settings.AnonymousTypes && type.IsAnonymousType(metadata)) @@ -322,7 +328,8 @@ namespace ICSharpCode.Decompiler.CSharp var fieldHandle = (FieldDefinitionHandle)member; var field = metadata.GetFieldDefinition(fieldHandle); name = metadata.GetString(field.Name); - if (field.IsCompilerGenerated(metadata)) { + if (field.IsCompilerGenerated(metadata)) + { if (settings.AnonymousMethods && IsAnonymousMethodCacheField(field, metadata)) return true; if (settings.AutomaticProperties && IsAutomaticPropertyBackingField(field, metadata)) @@ -333,7 +340,8 @@ namespace ICSharpCode.Decompiler.CSharp // event-fields are not [CompilerGenerated] if (settings.AutomaticEvents && metadata.GetTypeDefinition(field.GetDeclaringType()).GetEvents().Any(ev => metadata.GetEventDefinition(ev).Name == field.Name)) return true; - if (settings.ArrayInitializers && metadata.GetString(metadata.GetTypeDefinition(field.GetDeclaringType()).Name).StartsWith("", StringComparison.Ordinal)) { + if (settings.ArrayInitializers && metadata.GetString(metadata.GetTypeDefinition(field.GetDeclaringType()).Name).StartsWith("", StringComparison.Ordinal)) + { // only hide fields starting with '__StaticArrayInit' if (name.StartsWith("__StaticArrayInit", StringComparison.Ordinal)) return true; @@ -412,9 +420,12 @@ namespace ICSharpCode.Decompiler.CSharp IDocumentationProvider CreateDefaultDocumentationProvider() { - try { + try + { return XmlDocLoader.LoadDocumentation(module.PEFile); - } catch (System.Xml.XmlException) { + } + catch (System.Xml.XmlException) + { return null; } } @@ -423,7 +434,8 @@ namespace ICSharpCode.Decompiler.CSharp { var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings); var context = new TransformContext(typeSystem, decompileRun, decompilationContext, typeSystemAstBuilder); - foreach (var transform in astTransforms) { + foreach (var transform in astTransforms) + { CancellationToken.ThrowIfCancellationRequested(); transform.Run(rootNode, context); } @@ -467,20 +479,25 @@ namespace ICSharpCode.Decompiler.CSharp void DoDecompileModuleAndAssemblyAttributes(DecompileRun decompileRun, ITypeResolveContext decompilationContext, SyntaxTree syntaxTree) { - try { - foreach (var a in typeSystem.MainModule.GetAssemblyAttributes()) { + try + { + foreach (var a in typeSystem.MainModule.GetAssemblyAttributes()) + { var astBuilder = CreateAstBuilder(decompileRun.Settings); var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a)); attrSection.AttributeTarget = "assembly"; syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole); } - foreach (var a in typeSystem.MainModule.GetModuleAttributes()) { + foreach (var a in typeSystem.MainModule.GetModuleAttributes()) + { var astBuilder = CreateAstBuilder(decompileRun.Settings); var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a)); attrSection.AttributeTarget = "module"; syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole); } - } catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) { + } + catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) + { throw new DecompilerException(module, null, innerException, "Error decompiling module and assembly attributes of " + module.AssemblyName); } } @@ -489,16 +506,21 @@ namespace ICSharpCode.Decompiler.CSharp { string currentNamespace = null; AstNode groupNode = null; - foreach (var typeDefHandle in types) { + foreach (var typeDefHandle in types) + { var typeDef = module.GetDefinition(typeDefHandle); if (typeDef.Name == "" && typeDef.Members.Count == 0) continue; if (MemberIsHidden(module.PEFile, typeDefHandle, settings)) continue; - if(string.IsNullOrEmpty(typeDef.Namespace)) { + if (string.IsNullOrEmpty(typeDef.Namespace)) + { groupNode = syntaxTree; - } else { - if (currentNamespace != typeDef.Namespace) { + } + else + { + if (currentNamespace != typeDef.Namespace) + { groupNode = new NamespaceDeclaration(typeDef.Namespace); syntaxTree.AddChild(groupNode, SyntaxTree.MemberRole); } @@ -533,7 +555,8 @@ namespace ICSharpCode.Decompiler.CSharp RequiredNamespaceCollector.CollectNamespaces(module, decompileRun.Namespaces); DoDecompileModuleAndAssemblyAttributes(decompileRun, decompilationContext, syntaxTree); var typeDefs = metadata.GetTopLevelTypeDefinitions(); - if (sortTypes) { + if (sortTypes) + { typeDefs = typeDefs.OrderBy(td => { var typeDef = module.metadata.GetTypeDefinition(td); return (module.metadata.GetString(typeDef.Namespace), module.metadata.GetString(typeDef.Name)); @@ -567,7 +590,8 @@ namespace ICSharpCode.Decompiler.CSharp { var declaringType = member.GetDeclaringType(module.Metadata); - if (declaringType.IsNil && member.Kind == HandleKind.TypeDefinition) { + if (declaringType.IsNil && member.Kind == HandleKind.TypeDefinition) + { declaringType = (TypeDefinitionHandle)member; } @@ -575,7 +599,8 @@ namespace ICSharpCode.Decompiler.CSharp var td = module.Metadata.GetTypeDefinition(declaringType); - foreach (var method in td.GetMethods()) { + foreach (var method in td.GetMethods()) + { var parent = method; var part = method; @@ -584,13 +609,17 @@ namespace ICSharpCode.Decompiler.CSharp var processedNestedTypes = new HashSet(); connectedMethods.Enqueue(part); - while (connectedMethods.Count > 0) { + while (connectedMethods.Count > 0) + { part = connectedMethods.Dequeue(); if (!processedMethods.Add(part)) continue; - try { + try + { ReadCodeMappingInfo(module, info, parent, part, connectedMethods, processedNestedTypes); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { // ignore invalid IL } } @@ -603,7 +632,8 @@ namespace ICSharpCode.Decompiler.CSharp { var md = module.Metadata.GetMethodDefinition(part); - if (!md.HasBody()) { + if (!md.HasBody()) + { info.AddMapping(parent, part); return; } @@ -611,9 +641,11 @@ namespace ICSharpCode.Decompiler.CSharp var declaringType = md.GetDeclaringType(); var blob = module.Reader.GetMethodBody(md.RelativeVirtualAddress).GetILReader(); - while (blob.RemainingBytes > 0) { + while (blob.RemainingBytes > 0) + { var code = blob.DecodeOpCode(); - switch (code) { + switch (code) + { case ILOpCode.Newobj: case ILOpCode.Stfld: // async and yield fsms: @@ -621,7 +653,8 @@ namespace ICSharpCode.Decompiler.CSharp if (token.IsNil) continue; TypeDefinitionHandle fsmTypeDef; - switch (token.Kind) { + switch (token.Kind) + { case HandleKind.MethodDefinition: var fsmMethod = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)token); fsmTypeDef = fsmMethod.GetDeclaringType(); @@ -637,20 +670,24 @@ namespace ICSharpCode.Decompiler.CSharp default: continue; } - if (!fsmTypeDef.IsNil) { + if (!fsmTypeDef.IsNil) + { var fsmType = module.Metadata.GetTypeDefinition(fsmTypeDef); // Must be a nested type of the containing type. if (fsmType.GetDeclaringType() != declaringType) break; if (YieldReturnDecompiler.IsCompilerGeneratorEnumerator(fsmTypeDef, module.Metadata) - || AsyncAwaitDecompiler.IsCompilerGeneratedStateMachine(fsmTypeDef, module.Metadata)) { + || AsyncAwaitDecompiler.IsCompilerGeneratedStateMachine(fsmTypeDef, module.Metadata)) + { if (!processedNestedTypes.Add(fsmTypeDef)) break; - foreach (var h in fsmType.GetMethods()) { + foreach (var h in fsmType.GetMethods()) + { if (module.MethodSemanticsLookup.GetSemantics(h).Item2 != 0) continue; var otherMethod = module.Metadata.GetMethodDefinition(h); - if (!otherMethod.GetCustomAttributes().HasKnownAttribute(module.Metadata, KnownAttribute.DebuggerHidden)) { + if (!otherMethod.GetCustomAttributes().HasKnownAttribute(module.Metadata, KnownAttribute.DebuggerHidden)) + { connectedMethods.Enqueue(h); } } @@ -663,9 +700,11 @@ namespace ICSharpCode.Decompiler.CSharp if (token.IsNil) continue; TypeDefinitionHandle closureTypeHandle; - switch (token.Kind) { + switch (token.Kind) + { case HandleKind.MethodDefinition: - if (((MethodDefinitionHandle)token).IsCompilerGeneratedOrIsInCompilerGeneratedClass(module.Metadata)) { + if (((MethodDefinitionHandle)token).IsCompilerGeneratedOrIsInCompilerGeneratedClass(module.Metadata)) + { connectedMethods.Enqueue((MethodDefinitionHandle)token); } continue; @@ -674,20 +713,26 @@ namespace ICSharpCode.Decompiler.CSharp if (memberRef.GetKind() != MemberReferenceKind.Method) continue; closureTypeHandle = ExtractDeclaringType(memberRef); - if (!closureTypeHandle.IsNil) { + if (!closureTypeHandle.IsNil) + { var closureType = module.Metadata.GetTypeDefinition(closureTypeHandle); - if (closureTypeHandle != declaringType) { + if (closureTypeHandle != declaringType) + { // Must be a nested type of the containing type. if (closureType.GetDeclaringType() != declaringType) break; if (!processedNestedTypes.Add(closureTypeHandle)) break; - foreach (var m in closureType.GetMethods()) { + foreach (var m in closureType.GetMethods()) + { connectedMethods.Enqueue(m); } - } else { + } + else + { // Delegate body is declared in the same type - foreach (var m in closureType.GetMethods()) { + foreach (var m in closureType.GetMethods()) + { var methodDef = module.Metadata.GetMethodDefinition(m); if (methodDef.Name == memberRef.Name) connectedMethods.Enqueue(m); @@ -706,7 +751,8 @@ namespace ICSharpCode.Decompiler.CSharp token = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); if (token.IsNil) continue; - switch (token.Kind) { + switch (token.Kind) + { case HandleKind.MethodDefinition: break; case HandleKind.MethodSpecification: @@ -718,7 +764,8 @@ namespace ICSharpCode.Decompiler.CSharp default: continue; } - if (LocalFunctionDecompiler.IsLocalFunctionMethod(module, (MethodDefinitionHandle)token)) { + if (LocalFunctionDecompiler.IsLocalFunctionMethod(module, (MethodDefinitionHandle)token)) + { connectedMethods.Enqueue((MethodDefinitionHandle)token); } break; @@ -732,7 +779,8 @@ namespace ICSharpCode.Decompiler.CSharp TypeDefinitionHandle ExtractDeclaringType(MemberReference memberRef) { - switch (memberRef.Parent.Kind) { + switch (memberRef.Parent.Kind) + { case HandleKind.TypeReference: // This should never happen in normal code, because we are looking at nested types // If it's not a nested type, it can't be a reference to the state machine or lambda anyway, and @@ -790,7 +838,8 @@ namespace ICSharpCode.Decompiler.CSharp }; syntaxTree = new SyntaxTree(); - foreach (var type in types) { + foreach (var type in types) + { CancellationToken.ThrowIfCancellationRequested(); if (type.IsNil) throw new ArgumentException("types contains null element"); @@ -870,7 +919,8 @@ namespace ICSharpCode.Decompiler.CSharp DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(), CancellationToken = CancellationToken }; - foreach (var entity in definitions) { + foreach (var entity in definitions) + { if (entity.IsNil) throw new ArgumentException("definitions contains null element"); RequiredNamespaceCollector.CollectNamespaces(entity, module, decompileRun.Namespaces); @@ -879,23 +929,31 @@ namespace ICSharpCode.Decompiler.CSharp bool first = true; ITypeDefinition parentTypeDef = null; - foreach (var entity in definitions) { - switch (entity.Kind) { + foreach (var entity in definitions) + { + switch (entity.Kind) + { case HandleKind.TypeDefinition: ITypeDefinition typeDef = module.GetDefinition((TypeDefinitionHandle)entity); syntaxTree.Members.Add(DoDecompile(typeDef, decompileRun, new SimpleTypeResolveContext(typeDef))); - if (first) { + if (first) + { parentTypeDef = typeDef.DeclaringTypeDefinition; - } else if (parentTypeDef != null) { + } + else if (parentTypeDef != null) + { parentTypeDef = FindCommonDeclaringTypeDefinition(parentTypeDef, typeDef.DeclaringTypeDefinition); } break; case HandleKind.MethodDefinition: IMethod method = module.GetDefinition((MethodDefinitionHandle)entity); syntaxTree.Members.Add(DoDecompile(method, decompileRun, new SimpleTypeResolveContext(method))); - if (first) { + if (first) + { parentTypeDef = method.DeclaringTypeDefinition; - } else if (parentTypeDef != null) { + } + else if (parentTypeDef != null) + { parentTypeDef = FindCommonDeclaringTypeDefinition(parentTypeDef, method.DeclaringTypeDefinition); } break; @@ -907,18 +965,24 @@ namespace ICSharpCode.Decompiler.CSharp case HandleKind.PropertyDefinition: IProperty property = module.GetDefinition((PropertyDefinitionHandle)entity); syntaxTree.Members.Add(DoDecompile(property, decompileRun, new SimpleTypeResolveContext(property))); - if (first) { + if (first) + { parentTypeDef = property.DeclaringTypeDefinition; - } else if (parentTypeDef != null) { + } + else if (parentTypeDef != null) + { parentTypeDef = FindCommonDeclaringTypeDefinition(parentTypeDef, property.DeclaringTypeDefinition); } break; case HandleKind.EventDefinition: IEvent ev = module.GetDefinition((EventDefinitionHandle)entity); syntaxTree.Members.Add(DoDecompile(ev, decompileRun, new SimpleTypeResolveContext(ev))); - if (first) { + if (first) + { parentTypeDef = ev.DeclaringTypeDefinition; - } else if (parentTypeDef != null) { + } + else if (parentTypeDef != null) + { parentTypeDef = FindCommonDeclaringTypeDefinition(parentTypeDef, ev.DeclaringTypeDefinition); } break; @@ -960,12 +1024,14 @@ namespace ICSharpCode.Decompiler.CSharp EntityDeclaration memberDecl, IMethod method, TypeSystemAstBuilder astBuilder) { - if (!memberDecl.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole).IsNull) { + if (!memberDecl.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole).IsNull) + { yield break; // cannot create forwarder for existing explicit interface impl } var genericContext = new Decompiler.TypeSystem.GenericContext(method); var methodHandle = (MethodDefinitionHandle)method.MetadataToken; - foreach (var h in methodHandle.GetMethodImplementations(metadata)) { + foreach (var h in methodHandle.GetMethodImplementations(metadata)) + { var mi = metadata.GetMethodImplementation(h); IMethod m = module.ResolveMethod(mi.MethodDeclaration, genericContext); if (m == null || m.DeclaringType.Kind != TypeKind.Interface) @@ -975,22 +1041,25 @@ namespace ICSharpCode.Decompiler.CSharp methodDecl.PrivateImplementationType = astBuilder.ConvertType(m.DeclaringType); methodDecl.Name = m.Name; methodDecl.TypeParameters.AddRange(memberDecl.GetChildrenByRole(Roles.TypeParameter) - .Select(n => (TypeParameterDeclaration)n.Clone())); + .Select(n => (TypeParameterDeclaration)n.Clone())); methodDecl.Parameters.AddRange(memberDecl.GetChildrenByRole(Roles.Parameter).Select(n => n.Clone())); methodDecl.Constraints.AddRange(memberDecl.GetChildrenByRole(Roles.Constraint) - .Select(n => (Constraint)n.Clone())); + .Select(n => (Constraint)n.Clone())); methodDecl.Body = new BlockStatement(); methodDecl.Body.AddChild(new Comment( "ILSpy generated this explicit interface implementation from .override directive in " + memberDecl.Name), - Roles.Comment); + Roles.Comment); var forwardingCall = new InvocationExpression(new MemberReferenceExpression(new ThisReferenceExpression(), memberDecl.Name, methodDecl.TypeParameters.Select(tp => new SimpleType(tp.Name))), methodDecl.Parameters.Select(p => ForwardParameter(p)) ); - if (m.ReturnType.IsKnownType(KnownTypeCode.Void)) { + if (m.ReturnType.IsKnownType(KnownTypeCode.Void)) + { methodDecl.Body.Add(new ExpressionStatement(forwardingCall)); - } else { + } + else + { methodDecl.Body.Add(new ReturnStatement(forwardingCall)); } yield return methodDecl; @@ -999,7 +1068,8 @@ namespace ICSharpCode.Decompiler.CSharp Expression ForwardParameter(ParameterDeclaration p) { - switch (p.ParameterModifier) { + switch (p.ParameterModifier) + { case ParameterModifier.Ref: return new DirectionExpression(FieldDirection.Ref, new IdentifierExpression(p.Name)); case ParameterModifier.Out: @@ -1035,21 +1105,28 @@ namespace ICSharpCode.Decompiler.CSharp { var parameterListComparer = ParameterListComparer.WithOptions(includeModifiers: true); - foreach (IType baseType in baseTypes) { - if (!hideBasedOnSignature) { + foreach (IType baseType in baseTypes) + { + if (!hideBasedOnSignature) + { if (baseType.GetNestedTypes(t => t.Name == entity.Name && lookup.IsAccessible(t, true), options).Any()) return true; if (baseType.GetMembers(m => m.Name == entity.Name && m.SymbolKind != SymbolKind.Indexer && lookup.IsAccessible(m, true), options).Any()) return true; - } else { - if (entity.SymbolKind == SymbolKind.Indexer) { + } + else + { + if (entity.SymbolKind == SymbolKind.Indexer) + { // An indexer introduced in a class or struct hides all base class indexers with the same signature (parameter count and types). if (baseType.GetProperties(p => p.SymbolKind == SymbolKind.Indexer && lookup.IsAccessible(p, true)) .Any(p => parameterListComparer.Equals(((IProperty)entity).Parameters, p.Parameters))) { return true; } - } else if (entity.SymbolKind == SymbolKind.Method) { + } + else if (entity.SymbolKind == SymbolKind.Method) + { // A method introduced in a class or struct hides all non-method base class members with the same name, and all // base class methods with the same signature (method name and parameter count, modifiers, and types). if (baseType.GetMembers(m => m.SymbolKind != SymbolKind.Indexer && m.Name == entity.Name && lookup.IsAccessible(m, true)) @@ -1069,8 +1146,10 @@ namespace ICSharpCode.Decompiler.CSharp void FixParameterNames(EntityDeclaration entity) { int i = 0; - foreach (var parameter in entity.GetChildrenByRole(Roles.Parameter)) { - if (string.IsNullOrEmpty(parameter.Name) && !parameter.Type.IsArgList()) { + foreach (var parameter in entity.GetChildrenByRole(Roles.Parameter)) + { + if (string.IsNullOrEmpty(parameter.Name) && !parameter.Type.IsArgList()) + { // needs to be consistent with logic in ILReader.CreateILVarable(ParameterDefinition) parameter.Name = "P_" + i; } @@ -1081,55 +1160,71 @@ namespace ICSharpCode.Decompiler.CSharp EntityDeclaration DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun, ITypeResolveContext decompilationContext) { Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef); - try { + try + { var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings); var entityDecl = typeSystemAstBuilder.ConvertEntity(typeDef); var typeDecl = entityDecl as TypeDeclaration; - if (typeDecl == null) { + if (typeDecl == null) + { // e.g. DelegateDeclaration return entityDecl; } - foreach (var type in typeDef.NestedTypes) { - if (!type.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, type.MetadataToken, settings)) { + foreach (var type in typeDef.NestedTypes) + { + if (!type.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, type.MetadataToken, settings)) + { var nestedType = DoDecompile(type, decompileRun, decompilationContext.WithCurrentTypeDefinition(type)); SetNewModifier(nestedType); typeDecl.Members.Add(nestedType); } } - foreach (var field in typeDef.Fields) { - if (!field.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, field.MetadataToken, settings)) { + foreach (var field in typeDef.Fields) + { + if (!field.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, field.MetadataToken, settings)) + { if (typeDef.Kind == TypeKind.Enum && !field.IsConst) continue; var memberDecl = DoDecompile(field, decompileRun, decompilationContext.WithCurrentMember(field)); typeDecl.Members.Add(memberDecl); } } - foreach (var property in typeDef.Properties) { - if (!property.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, property.MetadataToken, settings)) { + foreach (var property in typeDef.Properties) + { + if (!property.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, property.MetadataToken, settings)) + { var propDecl = DoDecompile(property, decompileRun, decompilationContext.WithCurrentMember(property)); typeDecl.Members.Add(propDecl); } } - foreach (var @event in typeDef.Events) { - if (!@event.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, @event.MetadataToken, settings)) { + foreach (var @event in typeDef.Events) + { + if (!@event.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, @event.MetadataToken, settings)) + { var eventDecl = DoDecompile(@event, decompileRun, decompilationContext.WithCurrentMember(@event)); typeDecl.Members.Add(eventDecl); } } - foreach (var method in typeDef.Methods) { - if (!method.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, method.MetadataToken, settings)) { + foreach (var method in typeDef.Methods) + { + if (!method.MetadataToken.IsNil && !MemberIsHidden(module.PEFile, method.MetadataToken, settings)) + { var memberDecl = DoDecompile(method, decompileRun, decompilationContext.WithCurrentMember(method)); typeDecl.Members.Add(memberDecl); typeDecl.Members.AddRange(AddInterfaceImplHelpers(memberDecl, method, typeSystemAstBuilder)); } } - if (typeDecl.Members.OfType().Any(idx => idx.PrivateImplementationType.IsNull)) { + if (typeDecl.Members.OfType().Any(idx => idx.PrivateImplementationType.IsNull)) + { // Remove the [DefaultMember] attribute if the class contains indexers RemoveAttribute(typeDecl, KnownAttribute.DefaultMember); } - if (settings.IntroduceRefModifiersOnStructs) { - if (FindAttribute(typeDecl, KnownAttribute.Obsolete, out var attr)) { - if (obsoleteAttributePattern.IsMatch(attr)) { + if (settings.IntroduceRefModifiersOnStructs) + { + if (FindAttribute(typeDecl, KnownAttribute.Obsolete, out var attr)) + { + if (obsoleteAttributePattern.IsMatch(attr)) + { if (attr.Parent is AttributeSection section && section.Attributes.Count == 1) section.Remove(); else @@ -1137,17 +1232,22 @@ namespace ICSharpCode.Decompiler.CSharp } } } - if (typeDecl.ClassType == ClassType.Enum) { - switch (DetectBestEnumValueDisplayMode(typeDef, module.PEFile)) { + if (typeDecl.ClassType == ClassType.Enum) + { + switch (DetectBestEnumValueDisplayMode(typeDef, module.PEFile)) + { case EnumValueDisplayMode.FirstOnly: - foreach (var enumMember in typeDecl.Members.OfType().Skip(1)) { + foreach (var enumMember in typeDecl.Members.OfType().Skip(1)) + { enumMember.Initializer = null; } break; case EnumValueDisplayMode.None: - foreach (var enumMember in typeDecl.Members.OfType()) { + foreach (var enumMember in typeDecl.Members.OfType()) + { enumMember.Initializer = null; - if (enumMember.GetSymbol() is IField f && f.GetConstantValue() == null) { + if (enumMember.GetSymbol() is IField f && f.GetConstantValue() == null) + { typeDecl.InsertChildBefore(enumMember, new Comment(" error: enumerator has no value"), Roles.Comment); } } @@ -1160,7 +1260,9 @@ namespace ICSharpCode.Decompiler.CSharp } } return typeDecl; - } catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) { + } + catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) + { throw new DecompilerException(module, typeDef, innerException); } } @@ -1180,17 +1282,21 @@ namespace ICSharpCode.Decompiler.CSharp return EnumValueDisplayMode.All; bool first = true; long firstValue = 0, previousValue = 0; - foreach (var field in typeDef.Fields) { + foreach (var field in typeDef.Fields) + { if (MemberIsHidden(module, field.MetadataToken, settings)) continue; object constantValue = field.GetConstantValue(); if (constantValue == null) continue; long currentValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false); - if (first) { + if (first) + { firstValue = currentValue; first = false; - } else if (previousValue + 1 != currentValue) { + } + else if (previousValue + 1 != currentValue) + { return EnumValueDisplayMode.All; } previousValue = currentValue; @@ -1207,7 +1313,7 @@ namespace ICSharpCode.Decompiler.CSharp }; MethodDeclaration GenerateConvHelper(string name, KnownTypeCode source, KnownTypeCode target, TypeSystemAstBuilder typeSystemAstBuilder, - Expression intermediate32, Expression intermediate64) + Expression intermediate32, Expression intermediate64) { MethodDeclaration method = new MethodDeclaration(); method.Name = name; @@ -1248,12 +1354,14 @@ namespace ICSharpCode.Decompiler.CSharp var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings); var methodDecl = typeSystemAstBuilder.ConvertEntity(method); int lastDot = method.Name.LastIndexOf('.'); - if (method.IsExplicitInterfaceImplementation && lastDot >= 0) { + if (method.IsExplicitInterfaceImplementation && lastDot >= 0) + { methodDecl.Name = method.Name.Substring(lastDot + 1); } FixParameterNames(methodDecl); var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); - if (!settings.LocalFunctions && LocalFunctionDecompiler.LocalFunctionNeedsAccessibilityChange(method.ParentModule.PEFile, (MethodDefinitionHandle)method.MetadataToken)) { + if (!settings.LocalFunctions && LocalFunctionDecompiler.LocalFunctionNeedsAccessibilityChange(method.ParentModule.PEFile, (MethodDefinitionHandle)method.MetadataToken)) + { // if local functions are not active and we're dealing with a local function, // reduce the visibility of the method to private, // otherwise this leads to compile errors because the display classes have lesser accessibility. @@ -1261,12 +1369,16 @@ namespace ICSharpCode.Decompiler.CSharp methodDecl.Modifiers &= ~(Modifiers.Internal | Modifiers.Static); methodDecl.Modifiers |= Modifiers.Private | (method.IsStatic ? Modifiers.Static : 0); } - if (methodDefinition.HasBody()) { + if (methodDefinition.HasBody()) + { DecompileBody(method, methodDecl, decompileRun, decompilationContext); - } else if (!method.IsAbstract && method.DeclaringType.Kind != TypeKind.Interface) { + } + else if (!method.IsAbstract && method.DeclaringType.Kind != TypeKind.Interface) + { methodDecl.Modifiers |= Modifiers.Extern; } - if (method.SymbolKind == SymbolKind.Method && !method.IsExplicitInterfaceImplementation && methodDefinition.HasFlag(System.Reflection.MethodAttributes.Virtual) == methodDefinition.HasFlag(System.Reflection.MethodAttributes.NewSlot)) { + if (method.SymbolKind == SymbolKind.Method && !method.IsExplicitInterfaceImplementation && methodDefinition.HasFlag(System.Reflection.MethodAttributes.Virtual) == methodDefinition.HasFlag(System.Reflection.MethodAttributes.NewSlot)) + { SetNewModifier(methodDecl); } return methodDecl; @@ -1279,7 +1391,8 @@ namespace ICSharpCode.Decompiler.CSharp void DecompileBody(IMethod method, EntityDeclaration entityDecl, DecompileRun decompileRun, ITypeResolveContext decompilationContext) { - try { + try + { var ilReader = new ILReader(typeSystem.MainModule) { UseDebugSymbols = settings.UseDebugSymbols, DebugInfo = DebugInfoProvider @@ -1287,9 +1400,12 @@ namespace ICSharpCode.Decompiler.CSharp var methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); var body = BlockStatement.Null; MethodBodyBlock methodBody; - try { + try + { methodBody = module.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); - } catch (BadImageFormatException ex) { + } + catch (BadImageFormatException ex) + { body = new BlockStatement(); body.AddChild(new Comment("Invalid MethodBodyBlock: " + ex.Message), Roles.Comment); entityDecl.AddChild(body, Roles.Body); @@ -1298,10 +1414,12 @@ namespace ICSharpCode.Decompiler.CSharp var function = ilReader.ReadIL((MethodDefinitionHandle)method.MetadataToken, methodBody, cancellationToken: CancellationToken); function.CheckInvariant(ILPhase.Normal); - if (entityDecl != null) { + if (entityDecl != null) + { int i = 0; var parameters = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index); - foreach (var parameter in entityDecl.GetChildrenByRole(Roles.Parameter)) { + foreach (var parameter in entityDecl.GetChildrenByRole(Roles.Parameter)) + { if (parameters.TryGetValue(i, out var v)) parameter.AddAnnotation(new ILVariableResolveResult(v, method.Parameters[i].Type)); i++; @@ -1310,7 +1428,8 @@ namespace ICSharpCode.Decompiler.CSharp } var localSettings = settings.Clone(); - if (IsWindowsFormsInitializeComponentMethod(method)) { + if (IsWindowsFormsInitializeComponentMethod(method)) + { localSettings.UseImplicitMethodGroupConversion = false; localSettings.UsingDeclarations = false; localSettings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls = true; @@ -1321,7 +1440,8 @@ namespace ICSharpCode.Decompiler.CSharp CancellationToken = CancellationToken, DecompileRun = decompileRun }; - foreach (var transform in ilTransforms) { + foreach (var transform in ilTransforms) + { CancellationToken.ThrowIfCancellationRequested(); transform.Run(function, context); function.CheckInvariant(ILPhase.Normal); @@ -1333,13 +1453,15 @@ namespace ICSharpCode.Decompiler.CSharp } // Generate C# AST only if bodies should be displayed. - if (localSettings.DecompileMemberBodies) { + if (localSettings.DecompileMemberBodies) + { AddDefinesForConditionalAttributes(function, decompileRun); var statementBuilder = new StatementBuilder(typeSystem, decompilationContext, function, localSettings, CancellationToken); body = statementBuilder.ConvertAsBlock(function.Body); Comment prev = null; - foreach (string warning in function.Warnings) { + foreach (string warning in function.Warnings) + { body.InsertChildAfter(prev, prev = new Comment(warning), Roles.Comment); } @@ -1348,27 +1470,36 @@ namespace ICSharpCode.Decompiler.CSharp entityDecl.AddAnnotation(function); CleanUpMethodDeclaration(entityDecl, body, function, localSettings.DecompileMemberBodies); - } catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) { + } + catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) + { throw new DecompilerException(module, method, innerException); } } internal static void CleanUpMethodDeclaration(EntityDeclaration entityDecl, BlockStatement body, ILFunction function, bool decompileBody = true) { - if (function.IsIterator) { - if (decompileBody && !body.Descendants.Any(d => d is YieldReturnStatement || d is YieldBreakStatement)) { + if (function.IsIterator) + { + if (decompileBody && !body.Descendants.Any(d => d is YieldReturnStatement || d is YieldBreakStatement)) + { body.Add(new YieldBreakStatement()); } - if (function.IsAsync) { + if (function.IsAsync) + { RemoveAttribute(entityDecl, KnownAttribute.AsyncIteratorStateMachine); - } else { + } + else + { RemoveAttribute(entityDecl, KnownAttribute.IteratorStateMachine); } - if (function.StateMachineCompiledWithMono) { + if (function.StateMachineCompiledWithMono) + { RemoveAttribute(entityDecl, KnownAttribute.DebuggerHidden); } } - if (function.IsAsync) { + if (function.IsAsync) + { entityDecl.Modifiers |= Modifiers.Async; RemoveAttribute(entityDecl, KnownAttribute.AsyncStateMachine); RemoveAttribute(entityDecl, KnownAttribute.DebuggerStepThrough); @@ -1378,15 +1509,19 @@ namespace ICSharpCode.Decompiler.CSharp internal static bool RemoveAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType) { bool found = false; - foreach (var section in entityDecl.Attributes) { - foreach (var attr in section.Attributes) { + foreach (var section in entityDecl.Attributes) + { + foreach (var attr in section.Attributes) + { var symbol = attr.Type.GetSymbol(); - if (symbol is ITypeDefinition td && td.FullTypeName == attributeType.GetTypeName()) { + if (symbol is ITypeDefinition td && td.FullTypeName == attributeType.GetTypeName()) + { attr.Remove(); found = true; } } - if (section.Attributes.Count == 0) { + if (section.Attributes.Count == 0) + { section.Remove(); } } @@ -1396,10 +1531,13 @@ namespace ICSharpCode.Decompiler.CSharp bool FindAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType, out Syntax.Attribute attribute) { attribute = null; - foreach (var section in entityDecl.Attributes) { - foreach (var attr in section.Attributes) { + foreach (var section in entityDecl.Attributes) + { + foreach (var attr in section.Attributes) + { var symbol = attr.Type.GetSymbol(); - if (symbol is ITypeDefinition td && td.FullTypeName == attributeType.GetTypeName()) { + if (symbol is ITypeDefinition td && td.FullTypeName == attributeType.GetTypeName()) + { attribute = attr; return true; } @@ -1410,7 +1548,8 @@ namespace ICSharpCode.Decompiler.CSharp void AddDefinesForConditionalAttributes(ILFunction function, DecompileRun decompileRun) { - foreach (var call in function.Descendants.OfType()) { + foreach (var call in function.Descendants.OfType()) + { var attr = call.Method.GetAttribute(KnownAttribute.Conditional, inherit: true); var symbolName = attr?.FixedArguments.FirstOrDefault().Value as string; if (symbolName == null || !decompileRun.DefinedSymbols.Add(symbolName)) @@ -1422,17 +1561,21 @@ namespace ICSharpCode.Decompiler.CSharp EntityDeclaration DoDecompile(IField field, DecompileRun decompileRun, ITypeResolveContext decompilationContext) { Debug.Assert(decompilationContext.CurrentMember == field); - try { + try + { var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings); - if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum && field.IsConst) { + if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum && field.IsConst) + { var enumDec = new EnumMemberDeclaration { Name = field.Name }; object constantValue = field.GetConstantValue(); - if (constantValue != null) { + if (constantValue != null) + { long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false); enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, constantValue); if (enumDec.Initializer is PrimitiveExpression primitive && initValue >= 0 && (decompilationContext.CurrentTypeDefinition.HasAttribute(KnownAttribute.Flags) - || (initValue > 9 && (unchecked(initValue & (initValue - 1)) == 0 || unchecked(initValue & (initValue + 1)) == 0)))) { + || (initValue > 9 && (unchecked(initValue & (initValue - 1)) == 0 || unchecked(initValue & (initValue + 1)) == 0)))) + { primitive.Format = LiteralFormat.HexadecimalNumber; } } @@ -1444,7 +1587,8 @@ namespace ICSharpCode.Decompiler.CSharp typeSystemAstBuilder.UseSpecialConstants = !(field.DeclaringType.Equals(field.ReturnType) || isMathPIOrE); var fieldDecl = typeSystemAstBuilder.ConvertEntity(field); SetNewModifier(fieldDecl); - if (settings.FixedBuffers && IsFixedField(field, out var elementType, out var elementCount)) { + if (settings.FixedBuffers && IsFixedField(field, out var elementType, out var elementCount)) + { var fixedFieldDecl = new FixedFieldDeclaration(); fieldDecl.Attributes.MoveTo(fixedFieldDecl.Attributes); fixedFieldDecl.Modifiers = fieldDecl.Modifiers; @@ -1456,21 +1600,27 @@ namespace ICSharpCode.Decompiler.CSharp return fixedFieldDecl; } var fieldDefinition = metadata.GetFieldDefinition((FieldDefinitionHandle)field.MetadataToken); - if (fieldDefinition.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) { + if (fieldDefinition.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) + { // Field data as specified in II.16.3.1 of ECMA-335 6th edition: // .data I_X = int32(123) // .field public static int32 _x at I_X string message; - try { + try + { var initVal = fieldDefinition.GetInitialValue(module.PEFile.Reader, TypeSystem); message = string.Format(" Not supported: data({0}) ", BitConverter.ToString(initVal.ReadBytes(initVal.RemainingBytes)).Replace('-', ' ')); - } catch (BadImageFormatException ex) { + } + catch (BadImageFormatException ex) + { message = ex.Message; } ((FieldDeclaration)fieldDecl).Variables.Single().AddChild(new Comment(message, CommentType.MultiLine), Roles.Comment); } return fieldDecl; - } catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) { + } + catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) + { throw new DecompilerException(module, field, innerException); } } @@ -1480,8 +1630,10 @@ namespace ICSharpCode.Decompiler.CSharp type = null; elementCount = 0; IAttribute attr = field.GetAttribute(KnownAttribute.FixedBuffer, inherit: false); - if (attr != null && attr.FixedArguments.Length == 2) { - if (attr.FixedArguments[0].Value is IType trr && attr.FixedArguments[1].Value is int length) { + if (attr != null && attr.FixedArguments.Length == 2) + { + if (attr.FixedArguments[0].Value is IType trr && attr.FixedArguments[1].Value is int length) + { type = trr; elementCount = length; return true; @@ -1493,26 +1645,33 @@ namespace ICSharpCode.Decompiler.CSharp EntityDeclaration DoDecompile(IProperty property, DecompileRun decompileRun, ITypeResolveContext decompilationContext) { Debug.Assert(decompilationContext.CurrentMember == property); - try { + try + { var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings); EntityDeclaration propertyDecl = typeSystemAstBuilder.ConvertEntity(property); - if (property.IsExplicitInterfaceImplementation && !property.IsIndexer) { + if (property.IsExplicitInterfaceImplementation && !property.IsIndexer) + { int lastDot = property.Name.LastIndexOf('.'); propertyDecl.Name = property.Name.Substring(lastDot + 1); } FixParameterNames(propertyDecl); Accessor getter, setter; - if (propertyDecl is PropertyDeclaration) { + if (propertyDecl is PropertyDeclaration) + { getter = ((PropertyDeclaration)propertyDecl).Getter; setter = ((PropertyDeclaration)propertyDecl).Setter; - } else { + } + else + { getter = ((IndexerDeclaration)propertyDecl).Getter; setter = ((IndexerDeclaration)propertyDecl).Setter; } - if (property.CanGet && property.Getter.HasBody) { + if (property.CanGet && property.Getter.HasBody) + { DecompileBody(property.Getter, getter, decompileRun, decompilationContext); } - if (property.CanSet && property.Setter.HasBody) { + if (property.CanSet && property.Setter.HasBody) + { DecompileBody(property.Setter, setter, decompileRun, decompilationContext); } var accessorHandle = (MethodDefinitionHandle)(property.Getter ?? property.Setter).MetadataToken; @@ -1520,7 +1679,9 @@ namespace ICSharpCode.Decompiler.CSharp if (!accessorHandle.GetMethodImplementations(metadata).Any() && accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot)) SetNewModifier(propertyDecl); return propertyDecl; - } catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) { + } + catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) + { throw new DecompilerException(module, property, innerException); } } @@ -1528,26 +1689,33 @@ namespace ICSharpCode.Decompiler.CSharp EntityDeclaration DoDecompile(IEvent ev, DecompileRun decompileRun, ITypeResolveContext decompilationContext) { Debug.Assert(decompilationContext.CurrentMember == ev); - try { + try + { var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings); typeSystemAstBuilder.UseCustomEvents = ev.DeclaringTypeDefinition.Kind != TypeKind.Interface; var eventDecl = typeSystemAstBuilder.ConvertEntity(ev); int lastDot = ev.Name.LastIndexOf('.'); - if (ev.IsExplicitInterfaceImplementation) { + if (ev.IsExplicitInterfaceImplementation) + { eventDecl.Name = ev.Name.Substring(lastDot + 1); } - if (ev.CanAdd && ev.AddAccessor.HasBody) { + if (ev.CanAdd && ev.AddAccessor.HasBody) + { DecompileBody(ev.AddAccessor, ((CustomEventDeclaration)eventDecl).AddAccessor, decompileRun, decompilationContext); } - if (ev.CanRemove && ev.RemoveAccessor.HasBody) { + if (ev.CanRemove && ev.RemoveAccessor.HasBody) + { DecompileBody(ev.RemoveAccessor, ((CustomEventDeclaration)eventDecl).RemoveAccessor, decompileRun, decompilationContext); } var accessor = metadata.GetMethodDefinition((MethodDefinitionHandle)(ev.AddAccessor ?? ev.RemoveAccessor).MetadataToken); - if (accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot)) { + if (accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot)) + { SetNewModifier(eventDecl); } return eventDecl; - } catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) { + } + catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) + { throw new DecompilerException(module, ev, innerException); } } @@ -1563,7 +1731,7 @@ namespace ICSharpCode.Decompiler.CSharp SequencePointBuilder spb = new SequencePointBuilder(); syntaxTree.AcceptVisitor(spb); return spb.GetSequencePoints(); - } + } #endregion } } diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index 4254dcac8..a1d95ee4e 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -22,6 +22,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; @@ -72,20 +73,26 @@ namespace ICSharpCode.Decompiler.CSharp && !ParameterNames.Any(p => string.IsNullOrEmpty(p))) { Debug.Assert(skipCount == 0); - if (ArgumentNames == null) { + if (ArgumentNames == null) + { ArgumentNames = new string[Arguments.Length]; } - for (int i = 0; i < Arguments.Length; i++) { - if (IsPrimitiveValue[i] && ArgumentNames[i] == null) { + for (int i = 0; i < Arguments.Length; i++) + { + if (IsPrimitiveValue[i] && ArgumentNames[i] == null) + { ArgumentNames[i] = ParameterNames[i]; } } } int argumentCount = GetActualArgumentCount(); - if (ArgumentNames == null) { + if (ArgumentNames == null) + { return Arguments.Skip(skipCount).Take(argumentCount).Select(arg => arg.Expression); - } else { + } + else + { Debug.Assert(skipCount == 0); return Arguments.Take(argumentCount).Zip(ArgumentNames.Take(argumentCount), (arg, name) => { @@ -99,9 +106,11 @@ namespace ICSharpCode.Decompiler.CSharp public bool CanInferAnonymousTypePropertyNamesFromArguments() { - for (int i = 0; i < Arguments.Length; i++) { + for (int i = 0; i < Arguments.Length; i++) + { string inferredName; - switch (Arguments[i].Expression) { + switch (Arguments[i].Expression) + { case IdentifierExpression identifier: inferredName = identifier.Identifier; break; @@ -113,7 +122,8 @@ namespace ICSharpCode.Decompiler.CSharp break; } - if (inferredName != ExpectedParameters[i].Name) { + if (inferredName != ExpectedParameters[i].Name) + { return false; } } @@ -142,16 +152,19 @@ namespace ICSharpCode.Decompiler.CSharp public TranslatedExpression Build(CallInstruction inst) { - if (inst is NewObj newobj && IL.Transforms.DelegateConstruction.IsDelegateConstruction(newobj)) { + if (inst is NewObj newobj && IL.Transforms.DelegateConstruction.IsDelegateConstruction(newobj)) + { return HandleDelegateConstruction(newobj); } - if (settings.TupleTypes && TupleTransform.MatchTupleConstruction(inst as NewObj, out var tupleElements) && tupleElements.Length >= 2) { + if (settings.TupleTypes && TupleTransform.MatchTupleConstruction(inst as NewObj, out var tupleElements) && tupleElements.Length >= 2) + { var elementTypes = TupleType.GetTupleElementTypes(inst.Method.DeclaringType); Debug.Assert(!elementTypes.IsDefault, "MatchTupleConstruction should not success unless we got a valid tuple type."); Debug.Assert(elementTypes.Length == tupleElements.Length); var tuple = new TupleExpression(); var elementRRs = new List(); - foreach (var (element, elementType) in tupleElements.Zip(elementTypes)) { + foreach (var (element, elementType) in tupleElements.Zip(elementTypes)) + { var translatedElement = expressionBuilder.Translate(element, elementType) .ConvertTo(elementType, expressionBuilder, allowImplicitConversion: true); tuple.Elements.Add(translatedElement.Expression); @@ -172,12 +185,14 @@ namespace ICSharpCode.Decompiler.CSharp IReadOnlyList argumentToParameterMap = null, IType constrainedTo = null) { - if (method.IsExplicitInterfaceImplementation && callOpCode == OpCode.Call) { + if (method.IsExplicitInterfaceImplementation && callOpCode == OpCode.Call) + { // Direct non-virtual call to explicit interface implementation. // This can't really be represented in C#, but at least in the case where // the class is sealed, we can equivalently call the interface member instead: var interfaceMembers = method.ExplicitlyImplementedInterfaceMembers.ToList(); - if (method.DeclaringTypeDefinition?.Kind == TypeKind.Class && method.DeclaringTypeDefinition.IsSealed && interfaceMembers.Count == 1) { + if (method.DeclaringTypeDefinition?.Kind == TypeKind.Class && method.DeclaringTypeDefinition.IsSealed && interfaceMembers.Count == 1) + { method = (IMethod)interfaceMembers.Single(); callOpCode = OpCode.CallVirt; } @@ -187,22 +202,29 @@ namespace ICSharpCode.Decompiler.CSharp CallOpCode = callOpCode }; ILFunction localFunction = null; - if (method.IsLocalFunction) { + if (method.IsLocalFunction) + { localFunction = expressionBuilder.ResolveLocalFunction(method); Debug.Assert(localFunction != null); } TranslatedExpression target; - if (callOpCode == OpCode.NewObj) { + if (callOpCode == OpCode.NewObj) + { target = default(TranslatedExpression); // no target - } else if (localFunction != null) { + } + else if (localFunction != null) + { var ide = new IdentifierExpression(localFunction.Name); - if (method.TypeArguments.Count > 0) { + if (method.TypeArguments.Count > 0) + { ide.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); } ide.AddAnnotation(localFunction); target = ide.WithoutILInstruction() .WithRR(ToMethodGroup(method, localFunction)); - } else { + } + else + { target = expressionBuilder.TranslateTarget( callArguments.FirstOrDefault(), nonVirtualInvocation: callOpCode == OpCode.Call || method.IsConstructor, @@ -229,13 +251,15 @@ namespace ICSharpCode.Decompiler.CSharp var argumentList = BuildArgumentList(expectedTargetDetails, target.ResolveResult, method, firstParamIndex, callArguments, argumentToParameterMap); - if (localFunction != null) { + if (localFunction != null) + { return new InvocationExpression(target, argumentList.GetArgumentExpressions()) .WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method, argumentList.GetArgumentResolveResults().ToList(), isExpandedForm: argumentList.IsExpandedForm)); } - - if (method is VarArgInstanceMethod) { + + if (method is VarArgInstanceMethod) + { argumentList.FirstOptionalArgumentIndex = -1; argumentList.AddNamesToPrimitiveValues = false; int regularParameterCount = ((VarArgInstanceMethod)method).RegularParameterCount; @@ -252,17 +276,21 @@ namespace ICSharpCode.Decompiler.CSharp argumentList.ExpectedParameters = method.Parameters.ToArray(); } - if (settings.Ranges) { - if (HandleRangeConstruction(out var result, callOpCode, method, target, argumentList)) { + if (settings.Ranges) + { + if (HandleRangeConstruction(out var result, callOpCode, method, target, argumentList)) + { return result; } } - if (callOpCode == OpCode.NewObj) { + if (callOpCode == OpCode.NewObj) + { return HandleConstructorCall(expectedTargetDetails, target.ResolveResult, method, argumentList); } - if (method.Name == "Invoke" && method.DeclaringType.Kind == TypeKind.Delegate && !IsNullConditional(target)) { + if (method.Name == "Invoke" && method.DeclaringType.Kind == TypeKind.Delegate && !IsNullConditional(target)) + { return new InvocationExpression(target, argumentList.GetArgumentExpressions()) .WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method, argumentList.GetArgumentResolveResults().ToList(), isExpandedForm: argumentList.IsExpandedForm, isDelegateInvocation: true)); @@ -280,17 +308,21 @@ namespace ICSharpCode.Decompiler.CSharp void UnpackSingleElementArray(ref TranslatedExpression argument) { - if (!unpackSingleElementArray) return; + if (!unpackSingleElementArray) + return; var arrayCreation = (ArrayCreateExpression)argumentList.Arguments[1].Expression; var arrayCreationRR = (ArrayCreateResolveResult)argumentList.Arguments[1].ResolveResult; var element = arrayCreation.Initializer.Elements.First().Detach(); argument = new TranslatedExpression(element, arrayCreationRR.InitializerElements.First()); } - if (tokens.Count > 0) { - foreach (var (kind, index, text) in tokens) { + if (tokens.Count > 0) + { + foreach (var (kind, index, text) in tokens) + { TranslatedExpression argument; - switch (kind) { + switch (kind) + { case TokenKind.String: content.Add(new InterpolatedStringText(text)); break; @@ -320,19 +352,22 @@ namespace ICSharpCode.Decompiler.CSharp } int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0); - if (method.IsAccessor && (method.AccessorOwner.SymbolKind == SymbolKind.Indexer || argumentList.ExpectedParameters.Length == allowedParamCount)) { + if (method.IsAccessor && (method.AccessorOwner.SymbolKind == SymbolKind.Indexer || argumentList.ExpectedParameters.Length == allowedParamCount)) + { argumentList.CheckNoNamedOrOptionalArguments(); - return HandleAccessorCall(expectedTargetDetails, method, target, argumentList.Arguments.ToList(), argumentList.ArgumentNames); + return HandleAccessorCall(expectedTargetDetails, method, target, argumentList.Arguments.ToList(), argumentList.ArgumentNames); } - - if (IsDelegateEqualityComparison(method, argumentList.Arguments)) { + + if (IsDelegateEqualityComparison(method, argumentList.Arguments)) + { argumentList.CheckNoNamedOrOptionalArguments(); return HandleDelegateEqualityComparison(method, argumentList.Arguments) .WithRR(new CSharpInvocationResolveResult(target.ResolveResult, method, argumentList.GetArgumentResolveResults().ToList(), isExpandedForm: argumentList.IsExpandedForm)); } - - if (method.IsOperator && method.Name == "op_Implicit" && argumentList.Length == 1) { + + if (method.IsOperator && method.Name == "op_Implicit" && argumentList.Length == 1) + { argumentList.CheckNoNamedOrOptionalArguments(); return HandleImplicitConversion(method, argumentList.Arguments[0]); } @@ -344,8 +379,10 @@ namespace ICSharpCode.Decompiler.CSharp // but as far as allowed by IsAppropriateCallTarget(). // Need to update list of parameter names, because foundMethod is different and thus might use different names. - if (!method.Equals(foundMethod) && argumentList.ParameterNames.Length >= foundMethod.Parameters.Count) { - for (int i = 0; i < foundMethod.Parameters.Count; i++) { + if (!method.Equals(foundMethod) && argumentList.ParameterNames.Length >= foundMethod.Parameters.Count) + { + for (int i = 0; i < foundMethod.Parameters.Count; i++) + { argumentList.ParameterNames[i] = foundMethod.Parameters[i].Name; } } @@ -353,27 +390,32 @@ namespace ICSharpCode.Decompiler.CSharp Expression targetExpr; string methodName = method.Name; AstNodeCollection typeArgumentList; - if ((transform & CallTransformation.NoOptionalArgumentAllowed) != 0) { + if ((transform & CallTransformation.NoOptionalArgumentAllowed) != 0) + { argumentList.FirstOptionalArgumentIndex = -1; } - if ((transform & CallTransformation.RequireTarget) != 0) { + if ((transform & CallTransformation.RequireTarget) != 0) + { targetExpr = new MemberReferenceExpression(target.Expression, methodName); typeArgumentList = ((MemberReferenceExpression)targetExpr).TypeArguments; // HACK : convert this.Dispose() to ((IDisposable)this).Dispose(), if Dispose is an explicitly implemented interface method. // settings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls == true is used in Windows Forms' InitializeComponent methods. - if (method.IsExplicitInterfaceImplementation && (target.Expression is ThisReferenceExpression || settings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls)) { + if (method.IsExplicitInterfaceImplementation && (target.Expression is ThisReferenceExpression || settings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls)) + { var interfaceMember = method.ExplicitlyImplementedInterfaceMembers.First(); var castExpression = new CastExpression(expressionBuilder.ConvertType(interfaceMember.DeclaringType), target.Expression.Detach()); methodName = interfaceMember.Name; targetExpr = new MemberReferenceExpression(castExpression, methodName); typeArgumentList = ((MemberReferenceExpression)targetExpr).TypeArguments; } - } else { + } + else + { targetExpr = new IdentifierExpression(methodName); typeArgumentList = ((IdentifierExpression)targetExpr).TypeArguments; } - + if ((transform & CallTransformation.RequireTypeArguments) != 0 && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType()))) typeArgumentList.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); return new InvocationExpression(targetExpr, argumentList.GetArgumentExpressions()) @@ -423,11 +465,14 @@ namespace ICSharpCode.Decompiler.CSharp // Any special cases are handled by the caller (i.e., ExpressionBuilder.TranslateObjectAndCollectionInitializer) // Note: we intentionally ignore the firstOptionalArgumentIndex in this case. int skipCount; - if (method.IsExtensionMethod) { + if (method.IsExtensionMethod) + { if (argumentList.Arguments.Length == 2) return argumentList.Arguments[1]; skipCount = 1; - } else { + } + else + { if (argumentList.Arguments.Length == 1) return argumentList.Arguments[0]; skipCount = 0; @@ -457,7 +502,7 @@ namespace ICSharpCode.Decompiler.CSharp var assignment = HandleAccessorCall(expectedTargetDetails, method, unused, argumentList.Arguments.ToList(), argumentList.ArgumentNames); - if (((AssignmentExpression)assignment).Left is IndexerExpression indexer && !indexer.Target.IsNull) + if (((AssignmentExpression)assignment).Left is IndexerExpression indexer && !indexer.Target.IsNull) indexer.Target.ReplaceWith(n => null); if (value != null) @@ -495,9 +540,11 @@ namespace ICSharpCode.Decompiler.CSharp tokens = new List<(TokenKind, int, string)>(); int i = 0; format = (string)crr.ConstantValue; - foreach (var (kind, data) in TokenizeFormatString(format)) { + foreach (var (kind, data) in TokenizeFormatString(format)) + { int index; - switch (kind) { + switch (kind) + { case TokenKind.Error: return false; case TokenKind.String: @@ -555,15 +602,21 @@ namespace ICSharpCode.Decompiler.CSharp TokenKind kind = TokenKind.String; StringBuilder sb = new StringBuilder(); - while ((next = Next()) > -1) { - switch ((char)next) { + while ((next = Next()) > -1) + { + switch ((char)next) + { case '{': - if (Peek() == '{') { + if (Peek() == '{') + { kind = TokenKind.String; sb.Append("{{"); Next(); - } else { - if (sb.Length > 0) { + } + else + { + if (sb.Length > 0) + { yield return (kind, sb.ToString()); } kind = TokenKind.Argument; @@ -571,16 +624,20 @@ namespace ICSharpCode.Decompiler.CSharp } break; case '}': - if (kind != TokenKind.String) { + if (kind != TokenKind.String) + { yield return (kind, sb.ToString()); sb.Clear(); kind = TokenKind.String; - } else { + } + else + { sb.Append((char)next); } break; case ':': - if (kind == TokenKind.Argument) { + if (kind == TokenKind.Argument) + { kind = TokenKind.ArgumentWithFormat; } sb.Append(':'); @@ -590,7 +647,8 @@ namespace ICSharpCode.Decompiler.CSharp break; } } - if (sb.Length > 0) { + if (sb.Length > 0) + { if (kind == TokenKind.String) yield return (kind, sb.ToString()); else @@ -618,37 +676,49 @@ namespace ICSharpCode.Decompiler.CSharp // >= 0 - the index of the first argument that can be removed, because it is optional // and is the default value of the parameter. int firstOptionalArgumentIndex = expressionBuilder.settings.OptionalArguments ? -2 : -1; - for (int i = firstParamIndex; i < callArguments.Count; i++) { + for (int i = firstParamIndex; i < callArguments.Count; i++) + { IParameter parameter; - if (argumentToParameterMap != null) { - if (argumentNames == null && argumentToParameterMap[i] != i - firstParamIndex) { + if (argumentToParameterMap != null) + { + if (argumentNames == null && argumentToParameterMap[i] != i - firstParamIndex) + { // Starting at the first argument that is out-of-place, // assign names to that argument and all following arguments: argumentNames = new string[method.Parameters.Count]; } parameter = method.Parameters[argumentToParameterMap[i]]; - if (argumentNames != null) { + if (argumentNames != null) + { argumentNames[arguments.Count] = parameter.Name; } - } else { + } + else + { parameter = method.Parameters[i - firstParamIndex]; } var arg = expressionBuilder.Translate(callArguments[i], parameter.Type); - if (IsPrimitiveValueThatShouldBeNamedArgument(arg, method, parameter)) { + if (IsPrimitiveValueThatShouldBeNamedArgument(arg, method, parameter)) + { isPrimitiveValue.Set(arguments.Count); } - if (IsOptionalArgument(parameter, arg)) { + if (IsOptionalArgument(parameter, arg)) + { if (firstOptionalArgumentIndex == -2) firstOptionalArgumentIndex = i - firstParamIndex; - } else { + } + else + { firstOptionalArgumentIndex = -2; } - if (parameter.IsParams && i + 1 == callArguments.Count && argumentToParameterMap == null) { + if (parameter.IsParams && i + 1 == callArguments.Count && argumentToParameterMap == null) + { // Parameter is marked params // If the argument is an array creation, inline all elements into the call and add missing default values. // Otherwise handle it normally. if (TransformParamsArgument(expectedTargetDetails, target, method, parameter, - arg, ref expectedParameters, ref arguments)) { + arg, ref expectedParameters, ref arguments)) + { Debug.Assert(argumentNames == null); firstOptionalArgumentIndex = -1; isExpandedForm = true; @@ -657,15 +727,19 @@ namespace ICSharpCode.Decompiler.CSharp } IType parameterType; - if (parameter.Type.Kind == TypeKind.Dynamic) { + if (parameter.Type.Kind == TypeKind.Dynamic) + { parameterType = expressionBuilder.compilation.FindType(KnownTypeCode.Object); - } else { + } + else + { parameterType = parameter.Type; } arg = arg.ConvertTo(parameterType, expressionBuilder, allowImplicitConversion: arg.Type.Kind != TypeKind.Dynamic); - if (parameter.ReferenceKind != ReferenceKind.None) { + if (parameter.ReferenceKind != ReferenceKind.None) + { arg = ExpressionBuilder.ChangeDirectionExpressionTo(arg, parameter.ReferenceKind); } @@ -696,12 +770,15 @@ namespace ICSharpCode.Decompiler.CSharp IMethod method, IParameter parameter, TranslatedExpression arg, ref List expectedParameters, ref List arguments) { - if (CheckArgument(out int length, out IType elementType)) { + if (CheckArgument(out int length, out IType elementType)) + { var expandedParameters = new List(expectedParameters); var expandedArguments = new List(arguments); - if (length > 0) { + if (length > 0) + { var arrayElements = ((ArrayCreateExpression)arg.Expression).Initializer.Elements.ToArray(); - for (int j = 0; j < length; j++) { + for (int j = 0; j < length; j++) + { expandedParameters.Add(new DefaultParameter(elementType, parameter.Name + j)); if (j < arrayElements.Length) expandedArguments.Add(new TranslatedExpression(arrayElements[j])); @@ -724,8 +801,8 @@ namespace ICSharpCode.Decompiler.CSharp { len = 0; t = null; - if (arg.ResolveResult is CSharpInvocationResolveResult csirr && - csirr.Arguments.Count == 0 && csirr.Member is IMethod emptyMethod && + if (arg.ResolveResult is CSharpInvocationResolveResult csirr && + csirr.Arguments.Count == 0 && csirr.Member is IMethod emptyMethod && emptyMethod.IsStatic && "System.Array.Empty" == emptyMethod.FullName && emptyMethod.TypeArguments.Count == 1) @@ -776,10 +853,14 @@ namespace ICSharpCode.Decompiler.CSharp // initialize requireTarget flag bool requireTarget; ResolveResult targetResolveResult; - if ((allowedTransforms & CallTransformation.RequireTarget) != 0) { - if (settings.AlwaysQualifyMemberReferences || expressionBuilder.HidesVariableWithName(method.Name)) { + if ((allowedTransforms & CallTransformation.RequireTarget) != 0) + { + if (settings.AlwaysQualifyMemberReferences || expressionBuilder.HidesVariableWithName(method.Name)) + { requireTarget = true; - } else { + } + else + { if (method.IsLocalFunction) requireTarget = false; else if (method.IsStatic) @@ -792,7 +873,9 @@ namespace ICSharpCode.Decompiler.CSharp requireTarget = !(target.Expression is ThisReferenceExpression); } targetResolveResult = requireTarget ? target.ResolveResult : null; - } else { + } + else + { // HACK: this is a special case for collection initializer calls, they do not allow a target to be // emitted, but we still need it for overload resolution. requireTarget = true; @@ -804,22 +887,28 @@ namespace ICSharpCode.Decompiler.CSharp IType[] typeArguments; bool appliedRequireTypeArgumentsShortcut = false; if (method.TypeParameters.Count > 0 && (allowedTransforms & CallTransformation.RequireTypeArguments) != 0 - && !IsPossibleExtensionMethodCallOnNull(method, argumentList.Arguments)) { + && !IsPossibleExtensionMethodCallOnNull(method, argumentList.Arguments)) + { // The ambiguity resolution below only adds type arguments as last resort measure, however there are // methods, such as Enumerable.OfType(IEnumerable input) that always require type arguments, // as those cannot be inferred from the parameters, which leads to bloated expressions full of extra casts // that are no longer required once we add the type arguments. // We lend overload resolution a hand by detecting such cases beforehand and requiring type arguments, // if necessary. - if (!CanInferTypeArgumentsFromArguments(method, argumentList, expressionBuilder.typeInference)) { + if (!CanInferTypeArgumentsFromArguments(method, argumentList, expressionBuilder.typeInference)) + { requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); appliedRequireTypeArgumentsShortcut = true; - } else { + } + else + { requireTypeArguments = false; typeArguments = Empty.Array; } - } else { + } + else + { requireTypeArguments = false; typeArguments = Empty.Array; } @@ -831,48 +920,64 @@ namespace ICSharpCode.Decompiler.CSharp argumentList.Arguments, argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out foundMethod, out var bestCandidateIsExpandedForm)) != OverloadResolutionErrors.None || bestCandidateIsExpandedForm != argumentList.IsExpandedForm) { - switch (errors) { + switch (errors) + { case OverloadResolutionErrors.TypeInferenceFailed: - if ((allowedTransforms & CallTransformation.RequireTypeArguments) != 0) { + if ((allowedTransforms & CallTransformation.RequireTypeArguments) != 0) + { goto case OverloadResolutionErrors.WrongNumberOfTypeArguments; } goto default; case OverloadResolutionErrors.WrongNumberOfTypeArguments: Debug.Assert((allowedTransforms & CallTransformation.RequireTypeArguments) != 0); - if (requireTypeArguments) goto default; + if (requireTypeArguments) + goto default; requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); continue; case OverloadResolutionErrors.MissingArgumentForRequiredParameter: - if (argumentList.FirstOptionalArgumentIndex == -1) goto default; + if (argumentList.FirstOptionalArgumentIndex == -1) + goto default; argumentList.FirstOptionalArgumentIndex = -1; continue; default: // TODO : implement some more intelligent algorithm that decides which of these fixes (cast args, add target, cast target, add type args) // is best in this case. Additionally we should not cast all arguments at once, but step-by-step try to add only a minimal number of casts. - if (argumentList.FirstOptionalArgumentIndex >= 0) { + if (argumentList.FirstOptionalArgumentIndex >= 0) + { argumentList.FirstOptionalArgumentIndex = -1; - } else if (!argumentsCasted) { + } + else if (!argumentsCasted) + { // If we added type arguments beforehand, but that didn't make the code any better, // undo that decision and add casts first. - if (appliedRequireTypeArgumentsShortcut) { + if (appliedRequireTypeArgumentsShortcut) + { requireTypeArguments = false; typeArguments = Empty.Array; appliedRequireTypeArgumentsShortcut = false; } argumentsCasted = true; CastArguments(argumentList.Arguments, argumentList.ExpectedParameters); - } else if ((allowedTransforms & CallTransformation.RequireTarget) != 0 && !requireTarget) { + } + else if ((allowedTransforms & CallTransformation.RequireTarget) != 0 && !requireTarget) + { requireTarget = true; targetResolveResult = target.ResolveResult; - } else if ((allowedTransforms & CallTransformation.RequireTarget) != 0 && !targetCasted) { + } + else if ((allowedTransforms & CallTransformation.RequireTarget) != 0 && !targetCasted) + { targetCasted = true; target = target.ConvertTo(method.DeclaringType, expressionBuilder); targetResolveResult = target.ResolveResult; - } else if ((allowedTransforms & CallTransformation.RequireTypeArguments) != 0 && !requireTypeArguments) { + } + else if ((allowedTransforms & CallTransformation.RequireTypeArguments) != 0 && !requireTypeArguments) + { requireTypeArguments = true; typeArguments = method.TypeArguments.ToArray(); - } else { + } + else + { break; } continue; @@ -909,16 +1014,24 @@ namespace ICSharpCode.Decompiler.CSharp private void CastArguments(IList arguments, IList expectedParameters) { - for (int i = 0; i < arguments.Count; i++) { - if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) { - if (arguments[i].Expression is LambdaExpression lambda) { + for (int i = 0; i < arguments.Count; i++) + { + if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) + { + if (arguments[i].Expression is LambdaExpression lambda) + { ModifyReturnTypeOfLambda(lambda); } - } else { + } + else + { IType parameterType; - if (expectedParameters[i].Type.Kind == TypeKind.Dynamic) { + if (expectedParameters[i].Type.Kind == TypeKind.Dynamic) + { parameterType = expressionBuilder.compilation.FindType(KnownTypeCode.Object); - } else { + } + else + { parameterType = expectedParameters[i].Type; } @@ -944,10 +1057,12 @@ namespace ICSharpCode.Decompiler.CSharp private void ModifyReturnStatementInsideLambda(IType returnType, AstNode parent) { - foreach (var child in parent.Children) { + foreach (var child in parent.Children) + { if (child is LambdaExpression || child is AnonymousMethodExpression) continue; - if (child is ReturnStatement ret) { + if (child is ReturnStatement ret) + { ret.Expression = new TranslatedExpression(ret.Expression.Detach()).ConvertTo(returnType, expressionBuilder); continue; } @@ -982,7 +1097,8 @@ namespace ICSharpCode.Decompiler.CSharp var conversions = CSharpConversions.Get(expressionBuilder.compilation); IType targetType = method.ReturnType; var conv = conversions.ImplicitConversion(argument.Type, targetType); - if (!(conv.IsUserDefined && conv.Method.Equals(method))) { + if (!(conv.IsUserDefined && conv.Method.Equals(method))) + { // implicit conversion to targetType isn't directly possible, so first insert a cast to the argument type argument = argument.ConvertTo(method.Parameters[0].Type, expressionBuilder); conv = conversions.ImplicitConversion(argument.Type, targetType); @@ -1008,36 +1124,51 @@ namespace ICSharpCode.Decompiler.CSharp argumentNames: firstOptionalArgumentIndex < 0 || argumentNames == null ? argumentNames : argumentNames.Take(firstOptionalArgumentIndex).ToArray(), typeArguments: typeArguments, conversions: expressionBuilder.resolver.conversions); - if (expectedTargetDetails.CallOpCode == OpCode.NewObj) { - foreach (IMethod ctor in method.DeclaringType.GetConstructors()) { - if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == method.DeclaringTypeDefinition)) { + if (expectedTargetDetails.CallOpCode == OpCode.NewObj) + { + foreach (IMethod ctor in method.DeclaringType.GetConstructors()) + { + if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == method.DeclaringTypeDefinition)) + { or.AddCandidate(ctor); } } - } else if (method.IsOperator) { + } + else if (method.IsOperator) + { IEnumerable operatorCandidates; - if (arguments.Count == 1) { + if (arguments.Count == 1) + { IType argType = NullableType.GetUnderlyingType(arguments[0].Type); operatorCandidates = resolver.GetUserDefinedOperatorCandidates(argType, method.Name); - } else if (arguments.Count == 2) { + } + else if (arguments.Count == 2) + { IType lhsType = NullableType.GetUnderlyingType(arguments[0].Type); IType rhsType = NullableType.GetUnderlyingType(arguments[1].Type); var hashSet = new HashSet(); hashSet.UnionWith(resolver.GetUserDefinedOperatorCandidates(lhsType, method.Name)); hashSet.UnionWith(resolver.GetUserDefinedOperatorCandidates(rhsType, method.Name)); operatorCandidates = hashSet; - } else { + } + else + { operatorCandidates = EmptyList.Instance; } - foreach (var m in operatorCandidates) { + foreach (var m in operatorCandidates) + { or.AddCandidate(m); } - } else if (target == null) { + } + else if (target == null) + { var result = resolver.ResolveSimpleName(method.Name, typeArguments, isInvocationTarget: true) as MethodGroupResolveResult; if (result == null) return OverloadResolutionErrors.AmbiguousMatch; or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray()); - } else { + } + else + { var result = lookup.Lookup(target, method.Name, typeArguments, isInvocation: true) as MethodGroupResolveResult; if (result == null) return OverloadResolutionErrors.AmbiguousMatch; @@ -1061,16 +1192,20 @@ namespace ICSharpCode.Decompiler.CSharp Log.WriteCollection(" Arguments: ", arguments.Select(a => a.ResolveResult)); foundMember = null; - if (target == null) { + if (target == null) + { var result = resolver.ResolveSimpleName(method.AccessorOwner.Name, EmptyList.Instance, isInvocationTarget: false) as MemberResolveResult; if (result == null || result.IsError) return false; foundMember = result.Member; - } else { + } + else + { var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentModule); - if (method.AccessorOwner.SymbolKind == SymbolKind.Indexer) { + if (method.AccessorOwner.SymbolKind == SymbolKind.Indexer) + { var or = new OverloadResolution(resolver.Compilation, arguments.SelectArray(a => a.ResolveResult), argumentNames: argumentNames, @@ -1082,7 +1217,9 @@ namespace ICSharpCode.Decompiler.CSharp if (or.IsAmbiguous) return false; foundMember = or.GetBestCandidateWithSubstitutedTypeArguments(); - } else { + } + else + { var result = lookup.Lookup(target, method.AccessorOwner.Name, EmptyList.Instance, @@ -1111,63 +1248,88 @@ namespace ICSharpCode.Decompiler.CSharp var targetResolveResult = requireTarget ? target.ResolveResult : null; TranslatedExpression value = default(TranslatedExpression); - if (isSetter) { + if (isSetter) + { value = arguments.Last(); arguments.Remove(value); } IMember foundMember; - while (!IsUnambiguousAccess(expectedTargetDetails, targetResolveResult, method, arguments, argumentNames, out foundMember)) { - if (!argumentsCasted) { + while (!IsUnambiguousAccess(expectedTargetDetails, targetResolveResult, method, arguments, argumentNames, out foundMember)) + { + if (!argumentsCasted) + { argumentsCasted = true; CastArguments(arguments, method.Parameters.ToList()); - } else if(!requireTarget) { + } + else if (!requireTarget) + { requireTarget = true; targetResolveResult = target.ResolveResult; - } else if (!targetCasted) { + } + else if (!targetCasted) + { targetCasted = true; target = target.ConvertTo(method.AccessorOwner.DeclaringType, expressionBuilder); targetResolveResult = target.ResolveResult; - } else { + } + else + { foundMember = method.AccessorOwner; break; } } - + var rr = new MemberResolveResult(target.ResolveResult, foundMember); - if (isSetter) { + if (isSetter) + { TranslatedExpression expr; - if (arguments.Count != 0) { + if (arguments.Count != 0) + { expr = new IndexerExpression(target.ResolveResult is InitializedObjectResolveResult ? null : target.Expression, arguments.Select(a => a.Expression)) .WithoutILInstruction().WithRR(rr); - } else if (requireTarget) { + } + else if (requireTarget) + { expr = new MemberReferenceExpression(target.Expression, method.AccessorOwner.Name) .WithoutILInstruction().WithRR(rr); - } else { + } + else + { expr = new IdentifierExpression(method.AccessorOwner.Name) .WithoutILInstruction().WithRR(rr); } var op = AssignmentOperatorType.Assign; - if (method.AccessorOwner is IEvent parentEvent) { - if (method.Equals(parentEvent.AddAccessor)) { + if (method.AccessorOwner is IEvent parentEvent) + { + if (method.Equals(parentEvent.AddAccessor)) + { op = AssignmentOperatorType.Add; } - if (method.Equals(parentEvent.RemoveAccessor)) { + if (method.Equals(parentEvent.RemoveAccessor)) + { op = AssignmentOperatorType.Subtract; } } return new AssignmentExpression(expr, op, value.Expression).WithRR(new TypeResolveResult(method.AccessorOwner.ReturnType)); - } else { - if (arguments.Count != 0) { + } + else + { + if (arguments.Count != 0) + { return new IndexerExpression(target.Expression, arguments.Select(a => a.Expression)) .WithoutILInstruction().WithRR(rr); - } else if (requireTarget) { + } + else if (requireTarget) + { return new MemberReferenceExpression(target.Expression, method.AccessorOwner.Name) .WithoutILInstruction().WithRR(rr); - } else { + } + else + { return new IdentifierExpression(method.AccessorOwner.Name) .WithoutILInstruction().WithRR(rr); } @@ -1179,10 +1341,12 @@ namespace ICSharpCode.Decompiler.CSharp if (expectedTarget.Equals(actualTarget, NormalizeTypeVisitor.TypeErasure)) return true; - if (expectedTargetDetails.CallOpCode == OpCode.CallVirt && actualTarget.IsOverride) { + if (expectedTargetDetails.CallOpCode == OpCode.CallVirt && actualTarget.IsOverride) + { if (expectedTargetDetails.NeedsBoxingConversion && actualTarget.DeclaringType.IsReferenceType != true) return false; - foreach (var possibleTarget in InheritanceHelper.GetBaseMembers(actualTarget, false)) { + foreach (var possibleTarget in InheritanceHelper.GetBaseMembers(actualTarget, false)) + { if (expectedTarget.Equals(possibleTarget, NormalizeTypeVisitor.TypeErasure)) return true; if (!possibleTarget.IsOverride) @@ -1194,13 +1358,18 @@ namespace ICSharpCode.Decompiler.CSharp ExpressionWithResolveResult HandleConstructorCall(ExpectedTargetDetails expectedTargetDetails, ResolveResult target, IMethod method, ArgumentList argumentList) { - if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType()) { + if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType()) + { Debug.Assert(argumentList.ArgumentToParameterMap == null && argumentList.ArgumentNames == null && argumentList.FirstOptionalArgumentIndex < 0); var atce = new AnonymousTypeCreateExpression(); - if (argumentList.CanInferAnonymousTypePropertyNamesFromArguments()) { + if (argumentList.CanInferAnonymousTypePropertyNamesFromArguments()) + { atce.Initializers.AddRange(argumentList.GetArgumentExpressions()); - } else { - for (int i = 0; i < argumentList.Length; i++) { + } + else + { + for (int i = 0; i < argumentList.Length; i++) + { atce.Initializers.Add( new NamedExpression { Name = argumentList.ExpectedParameters[i].Name, @@ -1212,12 +1381,15 @@ namespace ICSharpCode.Decompiler.CSharp target, method, argumentList.GetArgumentResolveResults().ToList(), isExpandedForm: argumentList.IsExpandedForm, argumentToParameterMap: argumentList.ArgumentToParameterMap )); - } else { + } + else + { while (IsUnambiguousCall(expectedTargetDetails, method, null, Empty.Array, argumentList.Arguments, argumentList.ArgumentNames, argumentList.FirstOptionalArgumentIndex, out _, out var bestCandidateIsExpandedForm) != OverloadResolutionErrors.None || bestCandidateIsExpandedForm != argumentList.IsExpandedForm) { - if (argumentList.FirstOptionalArgumentIndex >= 0) { + if (argumentList.FirstOptionalArgumentIndex >= 0) + { argumentList.FirstOptionalArgumentIndex = -1; continue; } @@ -1240,7 +1412,8 @@ namespace ICSharpCode.Decompiler.CSharp ILInstruction func = inst.Arguments[1]; IMethod method; ExpectedTargetDetails expectedTargetDetails = default; - switch (func.OpCode) { + switch (func.OpCode) + { case OpCode.LdFtn: method = ((LdFtn)func).Method; expectedTargetDetails.CallOpCode = OpCode.Call; @@ -1252,9 +1425,12 @@ namespace ICSharpCode.Decompiler.CSharp default: throw new ArgumentException($"Unknown instruction type: {func.OpCode}"); } - if (CanUseDelegateConstruction(method, thisArg, inst.Method.DeclaringType.GetDelegateInvokeMethod())) { + if (CanUseDelegateConstruction(method, thisArg, inst.Method.DeclaringType.GetDelegateInvokeMethod())) + { return HandleDelegateConstruction(inst.Method.DeclaringType, method, expectedTargetDetails, thisArg, inst); - } else { + } + else + { var argumentList = BuildArgumentList(expectedTargetDetails, null, inst.Method, 0, inst.Arguments, null); return HandleConstructorCall(new ExpectedTargetDetails { CallOpCode = OpCode.NewObj }, null, inst.Method, argumentList).WithILInstruction(inst); @@ -1267,22 +1443,33 @@ namespace ICSharpCode.Decompiler.CSharp // see https://github.com/icsharpcode/ILSpy/issues/1741#issuecomment-540179101 if (targetMethod.IsAccessor) return false; - if (targetMethod.IsStatic) { + if (targetMethod.IsStatic) + { // If the invoke method is known, we can compare the parameter counts to figure out whether the // delegate is static or binds the first argument - if (invokeMethod != null) { - if (invokeMethod.Parameters.Count == targetMethod.Parameters.Count) { + if (invokeMethod != null) + { + if (invokeMethod.Parameters.Count == targetMethod.Parameters.Count) + { return thisArg.MatchLdNull(); - } else if (targetMethod.IsExtensionMethod && invokeMethod.Parameters.Count == targetMethod.Parameters.Count - 1) { + } + else if (targetMethod.IsExtensionMethod && invokeMethod.Parameters.Count == targetMethod.Parameters.Count - 1) + { return true; - } else { + } + else + { return false; } - } else { + } + else + { // delegate type unknown: return thisArg.MatchLdNull() || targetMethod.IsExtensionMethod; } - } else { + } + else + { // targetMethod is instance method if (invokeMethod != null && invokeMethod.Parameters.Count != targetMethod.Parameters.Count) return false; @@ -1315,21 +1502,26 @@ namespace ICSharpCode.Decompiler.CSharp // 3. cast target (represented as bit 2) int step; ILFunction localFunction = null; - if (method.IsLocalFunction) { + if (method.IsLocalFunction) + { localFunction = expressionBuilder.ResolveLocalFunction(method); Debug.Assert(localFunction != null); } - if (localFunction != null) { + if (localFunction != null) + { step = 2; requireTarget = false; result = ToMethodGroup(method, localFunction); target = default; targetType = default; methodName = localFunction.Name; - } else if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) { + } + else if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) + { step = 5; targetType = method.Parameters[0].Type; - if (targetType.Kind == TypeKind.ByReference && thisArg is Box thisArgBox) { + if (targetType.Kind == TypeKind.ByReference && thisArg is Box thisArgBox) + { targetType = ((ByReferenceType)targetType).ElementType; thisArg = thisArgBox.Argument; } @@ -1347,14 +1539,20 @@ namespace ICSharpCode.Decompiler.CSharp }, method.TypeArguments ); - } else { + } + else + { targetType = method.DeclaringType; - if (targetType.IsReferenceType == false && thisArg is Box thisArgBox) { + if (targetType.IsReferenceType == false && thisArg is Box thisArgBox) + { // Normal struct instance method calls (which TranslateTarget is meant for) expect a 'ref T', // but delegate construction uses a 'box T'. - if (thisArgBox.Argument is LdObj ldobj) { + if (thisArgBox.Argument is LdObj ldobj) + { thisArg = ldobj.Target; - } else { + } + else + { thisArg = new AddressOf(thisArgBox.Argument, thisArgBox.Type); } } @@ -1366,22 +1564,30 @@ namespace ICSharpCode.Decompiler.CSharp || (method.IsStatic ? !expressionBuilder.IsCurrentOrContainingType(method.DeclaringTypeDefinition) : !(target.Expression is ThisReferenceExpression)); step = requireTarget ? 1 : 0; var savedTarget = target; - for (; step < 7; step++) { + for (; step < 7; step++) + { ResolveResult targetResolveResult; //TODO: why there is an check for IsLocalFunction here, it should be unreachable in old code - if (localFunction == null && (step & 1) != 0) { + if (localFunction == null && (step & 1) != 0) + { targetResolveResult = savedTarget.ResolveResult; target = savedTarget; - } else { + } + else + { targetResolveResult = null; } IReadOnlyList typeArguments; - if ((step & 2) != 0) { + if ((step & 2) != 0) + { typeArguments = method.TypeArguments; - } else { + } + else + { typeArguments = EmptyList.Instance; } - if (targetResolveResult != null && targetType != null && (step & 4) != 0) { + if (targetResolveResult != null && targetType != null && (step & 4) != 0) + { target = target.ConvertTo(targetType, expressionBuilder); targetResolveResult = target.ResolveResult; } @@ -1395,15 +1601,19 @@ namespace ICSharpCode.Decompiler.CSharp requireTarget = localFunction == null && (step & 1) != 0; ExpressionWithResolveResult targetExpression; Debug.Assert(result != null); - if (requireTarget) { + if (requireTarget) + { Debug.Assert(target.Expression != null); var mre = new MemberReferenceExpression(target, methodName); if ((step & 2) != 0) mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); targetExpression = mre.WithRR(result); - } else { + } + else + { var ide = new IdentifierExpression(methodName); - if ((step & 2) != 0) { + if ((step & 2) != 0) + { ide.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); } targetExpression = ide.WithRR(result); @@ -1435,12 +1645,15 @@ namespace ICSharpCode.Decompiler.CSharp typeArguments.ToArray(), conversions: expressionBuilder.resolver.conversions ); - if (target == null) { + if (target == null) + { result = resolver.ResolveSimpleName(method.Name, typeArguments, isInvocationTarget: false); if (!(result is MethodGroupResolveResult mgrr)) return false; or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray()); - } else { + } + else + { result = lookup.Lookup(target, method.Name, typeArguments, isInvocation: false); if (!(result is MethodGroupResolveResult mgrr)) return false; @@ -1476,15 +1689,18 @@ namespace ICSharpCode.Decompiler.CSharp int firstParamIndex = call.IsInstanceCall ? 1 : 0; // Arguments from temporary variables (VariableKind.NamedArgument): int pos = 0; - foreach (StLoc stloc in block.Instructions) { + foreach (StLoc stloc in block.Instructions) + { Debug.Assert(stloc.Variable.LoadInstructions.Single().Parent == call); arguments[pos] = stloc.Value; argumentToParameterMap[pos] = stloc.Variable.LoadInstructions.Single().ChildIndex - firstParamIndex; pos++; } // Remaining argument: - foreach (var arg in call.Arguments) { - if (arg.MatchLdLoc(out var v) && v.Kind == VariableKind.NamedArgument) { + foreach (var arg in call.Arguments) + { + if (arg.MatchLdLoc(out var v) && v.Kind == VariableKind.NamedArgument) + { continue; // already handled in loop above } arguments[pos] = arg; @@ -1499,28 +1715,39 @@ namespace ICSharpCode.Decompiler.CSharp private bool HandleRangeConstruction(out ExpressionWithResolveResult result, OpCode callOpCode, IMethod method, TranslatedExpression target, ArgumentList argumentList) { result = default; - if (argumentList.ArgumentNames != null) { + if (argumentList.ArgumentNames != null) + { return false; // range syntax doesn't support named arguments } - if (method.DeclaringType.IsKnownType(KnownTypeCode.Range)) { - if (callOpCode == OpCode.NewObj && argumentList.Length == 2) { + if (method.DeclaringType.IsKnownType(KnownTypeCode.Range)) + { + if (callOpCode == OpCode.NewObj && argumentList.Length == 2) + { result = new BinaryOperatorExpression(argumentList.Arguments[0], BinaryOperatorType.Range, argumentList.Arguments[1]) .WithRR(new MemberResolveResult(null, method)); return true; - } else if (callOpCode == OpCode.Call && method.Name == "get_All" && argumentList.Length == 0) { + } + else if (callOpCode == OpCode.Call && method.Name == "get_All" && argumentList.Length == 0) + { result = new BinaryOperatorExpression(Expression.Null, BinaryOperatorType.Range, Expression.Null) .WithRR(new MemberResolveResult(null, method.AccessorOwner ?? method)); return true; - } else if (callOpCode == OpCode.Call && method.Name == "StartAt" && argumentList.Length == 1) { + } + else if (callOpCode == OpCode.Call && method.Name == "StartAt" && argumentList.Length == 1) + { result = new BinaryOperatorExpression(argumentList.Arguments[0], BinaryOperatorType.Range, Expression.Null) .WithRR(new MemberResolveResult(null, method)); return true; - } else if (callOpCode == OpCode.Call && method.Name == "EndAt" && argumentList.Length == 1) { + } + else if (callOpCode == OpCode.Call && method.Name == "EndAt" && argumentList.Length == 1) + { result = new BinaryOperatorExpression(Expression.Null, BinaryOperatorType.Range, argumentList.Arguments[0]) .WithRR(new MemberResolveResult(null, method)); return true; } - } else if (callOpCode == OpCode.NewObj && method.DeclaringType.IsKnownType(KnownTypeCode.Index)) { + } + else if (callOpCode == OpCode.NewObj && method.DeclaringType.IsKnownType(KnownTypeCode.Index)) + { if (argumentList.Length != 2) return false; if (!(argumentList.Arguments[1].Expression is PrimitiveExpression pe && pe.Value is true)) @@ -1528,7 +1755,9 @@ namespace ICSharpCode.Decompiler.CSharp result = new UnaryOperatorExpression(UnaryOperatorType.IndexFromEnd, argumentList.Arguments[0]) .WithRR(new MemberResolveResult(null, method)); return true; - } else if (method is SyntheticRangeIndexAccessor rangeIndexAccessor && rangeIndexAccessor.IsSlicing) { + } + else if (method is SyntheticRangeIndexAccessor rangeIndexAccessor && rangeIndexAccessor.IsSlicing) + { // For slicing the method is called Slice()/Substring(), but we still need to output indexer notation. // So special-case range-based slicing here. result = new IndexerExpression(target, argumentList.Arguments.Select(a => a.Expression)) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 8b84b8322..002993cbf 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -20,6 +20,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Threading; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Transforms; @@ -29,9 +31,9 @@ using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; + using ExpressionType = System.Linq.Expressions.ExpressionType; using PrimitiveType = ICSharpCode.Decompiler.CSharp.Syntax.PrimitiveType; -using System.Threading; namespace ICSharpCode.Decompiler.CSharp { @@ -77,7 +79,7 @@ namespace ICSharpCode.Decompiler.CSharp internal readonly TypeInference typeInference; internal readonly DecompilerSettings settings; readonly CancellationToken cancellationToken; - + public ExpressionBuilder(StatementBuilder statementBuilder, IDecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext, ILFunction currentFunction, DecompilerSettings settings, CancellationToken cancellationToken) { Debug.Assert(decompilationContext != null); @@ -103,27 +105,34 @@ namespace ICSharpCode.Decompiler.CSharp Debug.Assert(astType.Annotation() != null); return astType; } - + public ExpressionWithResolveResult ConvertConstantValue(ResolveResult rr, bool allowImplicitConversion = false) { var expr = astBuilder.ConvertConstantValue(rr); - if (!allowImplicitConversion) { - if (expr is NullReferenceExpression && rr.Type.Kind != TypeKind.Null) { + if (!allowImplicitConversion) + { + if (expr is NullReferenceExpression && rr.Type.Kind != TypeKind.Null) + { expr = new CastExpression(ConvertType(rr.Type), expr); - } else if (rr.Type.IsCSharpSmallIntegerType()) { + } + else if (rr.Type.IsCSharpSmallIntegerType()) + { expr = new CastExpression(new PrimitiveType(KnownTypeReference.GetCSharpNameByTypeCode(rr.Type.GetDefinition().KnownTypeCode)), expr); - } else if (rr.Type.IsCSharpNativeIntegerType()) { + } + else if (rr.Type.IsCSharpNativeIntegerType()) + { expr = new CastExpression(new PrimitiveType(rr.Type.Name), expr); } } var exprRR = expr.Annotation(); - if (exprRR == null) { + if (exprRR == null) + { exprRR = rr; expr.AddAnnotation(rr); } return new ExpressionWithResolveResult(expr, exprRR); } - + public TranslatedExpression Translate(ILInstruction inst, IType typeHint = null) { Debug.Assert(inst != null); @@ -132,37 +141,48 @@ namespace ICSharpCode.Decompiler.CSharp TypeHint = typeHint ?? SpecialType.UnknownType }; var cexpr = inst.AcceptVisitor(this, context); - #if DEBUG - if (inst.ResultType != StackType.Void && cexpr.Type.Kind != TypeKind.Unknown && inst.ResultType != StackType.Unknown && cexpr.Type.Kind != TypeKind.None) { +#if DEBUG + if (inst.ResultType != StackType.Void && cexpr.Type.Kind != TypeKind.Unknown && inst.ResultType != StackType.Unknown && cexpr.Type.Kind != TypeKind.None) + { // Validate the Translate post-condition (documented at beginning of this file): - if (inst.ResultType.IsIntegerType()) { + if (inst.ResultType.IsIntegerType()) + { Debug.Assert(cexpr.Type.GetStackType().IsIntegerType(), "IL instructions of integer type must convert into C# expressions of integer type"); Debug.Assert(cexpr.Type.GetSign() != Sign.None, "Must have a sign specified for zero/sign-extension"); - } else if (inst is ILiftableInstruction liftable && liftable.IsLifted) { + } + else if (inst is ILiftableInstruction liftable && liftable.IsLifted) + { Debug.Assert(NullableType.IsNullable(cexpr.Type)); IType underlying = NullableType.GetUnderlyingType(cexpr.Type); - if (liftable.UnderlyingResultType.IsIntegerType()) { + if (liftable.UnderlyingResultType.IsIntegerType()) + { Debug.Assert(underlying.GetStackType().IsIntegerType(), "IL instructions of integer type must convert into C# expressions of integer type"); Debug.Assert(underlying.GetSign() != Sign.None, "Must have a sign specified for zero/sign-extension"); - } else { + } + else + { Debug.Assert(underlying.GetStackType() == liftable.UnderlyingResultType); } - } else if (inst.ResultType == StackType.Ref) { + } + else if (inst.ResultType == StackType.Ref) + { Debug.Assert(cexpr.Type.GetStackType() == StackType.Ref || cexpr.Type.GetStackType().IsIntegerType()); - } else { + } + else + { Debug.Assert(cexpr.Type.GetStackType() == inst.ResultType); } } - #endif +#endif return cexpr; } - + public TranslatedExpression TranslateCondition(ILInstruction condition, bool negate = false) { var expr = Translate(condition, compilation.FindType(KnownTypeCode.Boolean)); return expr.ConvertToBoolean(this, negate); } - + internal ExpressionWithResolveResult ConvertVariable(ILVariable variable) { Expression expr; @@ -170,18 +190,21 @@ namespace ICSharpCode.Decompiler.CSharp expr = new ThisReferenceExpression(); else expr = new IdentifierExpression(variable.Name); - if (variable.Type.Kind == TypeKind.ByReference) { + if (variable.Type.Kind == TypeKind.ByReference) + { // When loading a by-ref parameter, use 'ref paramName'. // We'll strip away the 'ref' when dereferencing. - + // Ensure that the IdentifierExpression itself also gets a resolve result, as that might // get used after the 'ref' is stripped away: var elementType = ((ByReferenceType)variable.Type).ElementType; expr.WithRR(new ILVariableResolveResult(variable, elementType)); - + expr = new DirectionExpression(FieldDirection.Ref, expr); return expr.WithRR(new ByReferenceResolveResult(elementType, ReferenceKind.Ref)); - } else { + } + else + { return expr.WithRR(new ILVariableResolveResult(variable, variable.Type)); } } @@ -197,12 +220,14 @@ namespace ICSharpCode.Decompiler.CSharp bool HidesVariableOrNestedFunction(ILFunction function) { - foreach (var v in function.Variables) { + foreach (var v in function.Variables) + { if (v.Name == name) return true; } - foreach (var f in function.LocalFunctions) { + foreach (var f in function.LocalFunctions) + { if (f.Name == name) return true; } @@ -215,9 +240,11 @@ namespace ICSharpCode.Decompiler.CSharp { Debug.Assert(method.IsLocalFunction); method = (IMethod)((IMethod)method.MemberDefinition).ReducedFrom.MemberDefinition; - foreach (var parent in currentFunction.Ancestors.OfType()) { + foreach (var parent in currentFunction.Ancestors.OfType()) + { var definition = parent.LocalFunctions.FirstOrDefault(f => f.Method.MemberDefinition.Equals(method)); - if (definition != null) { + if (definition != null) + { return definition; } } @@ -249,7 +276,9 @@ namespace ICSharpCode.Decompiler.CSharp && decompilationContext.CurrentMember != property) { requireTarget = RequiresQualifier(property, target); - } else { + } + else + { requireTarget = RequiresQualifier(field, target); } bool targetCasted = false; @@ -257,9 +286,12 @@ namespace ICSharpCode.Decompiler.CSharp bool IsAmbiguousAccess(out MemberResolveResult result) { - if (targetResolveResult == null) { + if (targetResolveResult == null) + { result = resolver.ResolveSimpleName(field.Name, EmptyList.Instance, isInvocationTarget: false) as MemberResolveResult; - } else { + } + else + { var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentModule); result = lookup.Lookup(target.ResolveResult, field.Name, EmptyList.Instance, isInvocation: false) as MemberResolveResult; } @@ -267,32 +299,42 @@ namespace ICSharpCode.Decompiler.CSharp } MemberResolveResult mrr; - while (IsAmbiguousAccess(out mrr)) { - if (!requireTarget) { + while (IsAmbiguousAccess(out mrr)) + { + if (!requireTarget) + { requireTarget = true; targetResolveResult = target.ResolveResult; - } else if (!targetCasted) { + } + else if (!targetCasted) + { targetCasted = true; target = target.ConvertTo(field.DeclaringType, this); targetResolveResult = target.ResolveResult; - } else { + } + else + { break; } } - if (mrr == null) { + if (mrr == null) + { mrr = new MemberResolveResult(target.ResolveResult, field); } - if (requireTarget) { + if (requireTarget) + { return new MemberReferenceExpression(target, field.Name) .WithRR(mrr); - } else { + } + else + { return new IdentifierExpression(field.Name) .WithRR(mrr); } } - + TranslatedExpression IsType(IsInst inst) { var arg = Translate(inst.Argument); @@ -301,18 +343,20 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(new TypeIsResolveResult(arg.ResolveResult, inst.Type, compilation.FindType(TypeCode.Boolean))); } - + protected internal override TranslatedExpression VisitIsInst(IsInst inst, TranslationContext context) { var arg = Translate(inst.Argument); - if (inst.Type.IsReferenceType == false) { + if (inst.Type.IsReferenceType == false) + { // isinst with a value type results in an expression of "boxed value type", // which is not supported in C#. // Note that several other instructions special-case isinst arguments: // unbox.any T(isinst T(expr)) ==> "expr as T" for nullable value types and class-constrained generic types // comp(isinst T(expr) != null) ==> "expr is T" // on block level (StatementBuilder.VisitIsInst) => "expr is T" - if (SemanticHelper.IsPure(inst.Argument.Flags)) { + if (SemanticHelper.IsPure(inst.Argument.Flags)) + { // We can emulate isinst using // expr is T ? expr : null return new ConditionalExpression( @@ -320,7 +364,9 @@ namespace ICSharpCode.Decompiler.CSharp arg.Expression.Clone(), new NullReferenceExpression() ).WithoutILInstruction().WithRR(new ResolveResult(arg.Type)); - } else { + } + else + { return ErrorExpression("isinst with value type is only supported in some contexts"); } } @@ -335,7 +381,8 @@ namespace ICSharpCode.Decompiler.CSharp if (arg.Expression is CastExpression cast && arg.Type.IsKnownType(KnownTypeCode.Object) && arg.ResolveResult is ConversionResolveResult crr - && crr.Conversion.IsBoxingConversion) { + && crr.Conversion.IsBoxingConversion) + { // When 'is' or 'as' is used with a value type or type parameter, // the C# compiler implicitly boxes the input. arg = arg.UnwrapChild(cast.Expression); @@ -347,8 +394,10 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitNewObj(NewObj inst, TranslationContext context) { var type = inst.Method.DeclaringType; - if (type.IsKnownType(KnownTypeCode.SpanOfT) || type.IsKnownType(KnownTypeCode.ReadOnlySpanOfT)) { - if (inst.Arguments.Count == 2 && inst.Arguments[0] is Block b && b.Kind == BlockKind.StackAllocInitializer) { + if (type.IsKnownType(KnownTypeCode.SpanOfT) || type.IsKnownType(KnownTypeCode.ReadOnlySpanOfT)) + { + if (inst.Arguments.Count == 2 && inst.Arguments[0] is Block b && b.Kind == BlockKind.StackAllocInitializer) + { return TranslateStackAllocInitializer(b, type.TypeArguments[0]); } } @@ -365,7 +414,8 @@ namespace ICSharpCode.Decompiler.CSharp var dimensions = inst.Indices.Count; var args = inst.Indices.Select(arg => TranslateArrayIndex(arg)).ToArray(); var expr = new ArrayCreateExpression { Type = ConvertType(inst.Type) }; - if (expr.Type is ComposedType ct) { + if (expr.Type is ComposedType ct) + { // change "new (int[,])[10] to new int[10][,]" ct.ArraySpecifiers.MoveTo(expr.AdditionalArraySpecifiers); } @@ -407,7 +457,9 @@ namespace ICSharpCode.Decompiler.CSharp // Determine the element type from the sizeof countExpression = Translate(left.UnwrapConv(ConversionKind.ZeroExtend)); pointerType = new PointerType(elementType); - } else { + } + else + { // Determine the element type from the expected pointer type in this context pointerType = typeHint as PointerType; if (pointerType != null && GetPointerArithmeticOffset( @@ -418,7 +470,9 @@ namespace ICSharpCode.Decompiler.CSharp { countExpression = offset; elementType = pointerType.ElementType; - } else { + } + else + { elementType = compilation.FindType(KnownTypeCode.Byte); pointerType = new PointerType(elementType); countExpression = Translate(inst.Argument); @@ -430,16 +484,19 @@ namespace ICSharpCode.Decompiler.CSharp CountExpression = countExpression }; } - + protected internal override TranslatedExpression VisitLdcI4(LdcI4 inst, TranslationContext context) { ResolveResult rr; - if (context.TypeHint.GetSign() == Sign.Unsigned) { + if (context.TypeHint.GetSign() == Sign.Unsigned) + { rr = new ConstantResolveResult( compilation.FindType(KnownTypeCode.UInt32), unchecked((uint)inst.Value) ); - } else { + } + else + { rr = new ConstantResolveResult( compilation.FindType(KnownTypeCode.Int32), inst.Value @@ -447,10 +504,13 @@ namespace ICSharpCode.Decompiler.CSharp } rr = AdjustConstantToType(rr, context.TypeHint); astBuilder.PrintIntegralValuesAsHex = ShouldDisplayAsHex(inst.Value, inst.Parent); - try { + try + { return ConvertConstantValue(rr, allowImplicitConversion: true) .WithILInstruction(inst); - } finally { + } + finally + { astBuilder.PrintIntegralValuesAsHex = false; } } @@ -458,12 +518,15 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitLdcI8(LdcI8 inst, TranslationContext context) { ResolveResult rr; - if (context.TypeHint.GetSign() == Sign.Unsigned) { + if (context.TypeHint.GetSign() == Sign.Unsigned) + { rr = new ConstantResolveResult( compilation.FindType(KnownTypeCode.UInt64), unchecked((ulong)inst.Value) ); - } else { + } + else + { rr = new ConstantResolveResult( compilation.FindType(KnownTypeCode.Int64), inst.Value @@ -471,10 +534,13 @@ namespace ICSharpCode.Decompiler.CSharp } rr = AdjustConstantToType(rr, context.TypeHint); astBuilder.PrintIntegralValuesAsHex = ShouldDisplayAsHex(inst.Value, inst.Parent); - try { + try + { return ConvertConstantValue(rr, allowImplicitConversion: true) .WithILInstruction(inst); - } finally { + } + finally + { astBuilder.PrintIntegralValuesAsHex = false; } } @@ -485,7 +551,8 @@ namespace ICSharpCode.Decompiler.CSharp parent = conv.Parent; if (value <= 9) return false; - switch (parent) { + switch (parent) + { case BinaryNumericInstruction bni: if (bni.Operator == BinaryNumericOperator.BitAnd || bni.Operator == BinaryNumericOperator.BitOr @@ -513,7 +580,7 @@ namespace ICSharpCode.Decompiler.CSharp var expr = astBuilder.ConvertConstantValue(compilation.FindType(KnownTypeCode.Decimal), inst.Value); return new TranslatedExpression(expr.WithILInstruction(inst)); } - + protected internal override TranslatedExpression VisitLdStr(LdStr inst, TranslationContext context) { return new PrimitiveExpression(inst.Value) @@ -536,25 +603,28 @@ namespace ICSharpCode.Decompiler.CSharp Expression expr; IType constantType; object constantValue; - if (type.IsReferenceType == true || type.IsKnownType(KnownTypeCode.NullableOfT)) { + if (type.IsReferenceType == true || type.IsKnownType(KnownTypeCode.NullableOfT)) + { expr = new NullReferenceExpression(); constantType = SpecialType.NullType; constantValue = null; - } else { + } + else + { expr = new DefaultValueExpression(ConvertType(type)); constantType = type; constantValue = CSharpResolver.GetDefaultValue(type); } return expr.WithRR(new ConstantResolveResult(constantType, constantValue)); } - + protected internal override TranslatedExpression VisitSizeOf(SizeOf inst, TranslationContext context) { return new SizeOfExpression(ConvertType(inst.Type)) .WithILInstruction(inst) .WithRR(new SizeOfResolveResult(compilation.FindType(KnownTypeCode.Int32), inst.Type, null)); } - + protected internal override TranslatedExpression VisitLdTypeToken(LdTypeToken inst, TranslationContext context) { var typeofExpr = new TypeOfExpression(ConvertType(inst.Type)) @@ -563,7 +633,7 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(new TypeOfResolveResult(compilation.FindType(new TopLevelTypeName("System", "RuntimeTypeHandle")), inst.Type)); } - + protected internal override TranslatedExpression VisitBitNot(BitNot inst, TranslationContext context) { var argument = Translate(inst.Argument); @@ -581,21 +651,23 @@ namespace ICSharpCode.Decompiler.CSharp // (those don't undergo numeric promotion in C# the way non-enum small integer types do). // Same if the type is one that does not support ~ (IntPtr, bool and char). Sign sign = context.TypeHint.GetSign(); - if (sign == Sign.None) { + if (sign == Sign.None) + { sign = argUType.GetSign(); } IType targetType = FindArithmeticType(inst.UnderlyingResultType, sign); - if (inst.IsLifted) { + if (inst.IsLifted) + { targetType = NullableType.Create(compilation, targetType); } argument = argument.ConvertTo(targetType, this); } - + return new UnaryOperatorExpression(UnaryOperatorType.BitNot, argument) .WithRR(resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, argument.ResolveResult)) .WithILInstruction(inst); } - + internal ExpressionWithResolveResult LogicNot(TranslatedExpression expr) { // "!expr" implicitly converts to bool so we can remove the cast; @@ -604,17 +676,18 @@ namespace ICSharpCode.Decompiler.CSharp return new UnaryOperatorExpression(UnaryOperatorType.Not, expr.Expression) .WithRR(new OperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), ExpressionType.Not, expr.ResolveResult)); } - + readonly HashSet loadedVariablesSet = new HashSet(); - + protected internal override TranslatedExpression VisitLdLoc(LdLoc inst, TranslationContext context) { - if (inst.Variable.Kind == VariableKind.StackSlot && inst.Variable.IsSingleDefinition) { + if (inst.Variable.Kind == VariableKind.StackSlot && inst.Variable.IsSingleDefinition) + { loadedVariablesSet.Add(inst.Variable); } return ConvertVariable(inst.Variable).WithILInstruction(inst); } - + protected internal override TranslatedExpression VisitLdLoca(LdLoca inst, TranslationContext context) { var expr = ConvertVariable(inst.Variable).WithILInstruction(inst); @@ -624,23 +697,28 @@ namespace ICSharpCode.Decompiler.CSharp .WithoutILInstruction() .WithRR(new ByReferenceResolveResult(expr.ResolveResult, ReferenceKind.Ref)); } - + protected internal override TranslatedExpression VisitStLoc(StLoc inst, TranslationContext context) { var translatedValue = Translate(inst.Value, typeHint: inst.Variable.Type); - if (inst.Variable.Kind == VariableKind.StackSlot && !loadedVariablesSet.Contains(inst.Variable)) { + if (inst.Variable.Kind == VariableKind.StackSlot && !loadedVariablesSet.Contains(inst.Variable)) + { // Stack slots in the ILAst have inaccurate types (e.g. System.Object for StackType.O) // so we should replace them with more accurate types where possible: if (CanUseTypeForStackSlot(inst.Variable, translatedValue.Type) && inst.Variable.StackType == translatedValue.Type.GetStackType() - && translatedValue.Type.Kind != TypeKind.Null) { + && translatedValue.Type.Kind != TypeKind.Null) + { inst.Variable.Type = translatedValue.Type; - } else if (inst.Value.MatchDefaultValue(out var type) && IsOtherValueType(type)) { + } + else if (inst.Value.MatchDefaultValue(out var type) && IsOtherValueType(type)) + { inst.Variable.Type = type; } } var lhs = ConvertVariable(inst.Variable).WithoutILInstruction(); - if (lhs.Expression is DirectionExpression dirExpr && lhs.ResolveResult is ByReferenceResolveResult lhsRefRR) { + if (lhs.Expression is DirectionExpression dirExpr && lhs.ResolveResult is ByReferenceResolveResult lhsRefRR) + { // ref (re-)assignment, emit "ref (a = ref b)". lhs = lhs.UnwrapChild(dirExpr.Expression); translatedValue = translatedValue.ConvertTo(lhsRefRR.Type, this, allowImplicitConversion: true); @@ -648,7 +726,9 @@ namespace ICSharpCode.Decompiler.CSharp .WithRR(new OperatorResolveResult(lhs.Type, ExpressionType.Assign, lhsRefRR, translatedValue.ResolveResult)); return new DirectionExpression(FieldDirection.Ref, assign) .WithoutILInstruction().WithRR(lhsRefRR); - } else { + } + else + { return Assignment(lhs, translatedValue).WithILInstruction(inst); } @@ -668,7 +748,8 @@ namespace ICSharpCode.Decompiler.CSharp bool AllStoresUseConsistentType(IReadOnlyList storeInstructions, IType expectedType) { expectedType = expectedType.AcceptVisitor(NormalizeTypeVisitor.TypeErasure); - foreach (var store in storeInstructions) { + foreach (var store in storeInstructions) + { if (!(store is StLoc stloc)) return false; IType type = stloc.Value.InferType(compilation).AcceptVisitor(NormalizeTypeVisitor.TypeErasure); @@ -678,11 +759,13 @@ namespace ICSharpCode.Decompiler.CSharp return true; } } - + protected internal override TranslatedExpression VisitComp(Comp inst, TranslationContext context) { - if (inst.LiftingKind == ComparisonLiftingKind.ThreeValuedLogic) { - if (inst.Kind == ComparisonKind.Equality && inst.Right.MatchLdcI4(0)) { + if (inst.LiftingKind == ComparisonLiftingKind.ThreeValuedLogic) + { + if (inst.Kind == ComparisonKind.Equality && inst.Right.MatchLdcI4(0)) + { // lifted logic.not var targetType = NullableType.Create(compilation, compilation.FindType(KnownTypeCode.Boolean)); var arg = Translate(inst.Left, targetType).ConvertTo(targetType, this); @@ -692,17 +775,20 @@ namespace ICSharpCode.Decompiler.CSharp } return ErrorExpression("Nullable comparisons with three-valued-logic not supported in C#"); } - if (inst.Kind.IsEqualityOrInequality()) { + if (inst.Kind.IsEqualityOrInequality()) + { var result = TranslateCeq(inst, out bool negateOutput); if (negateOutput) return LogicNot(result).WithILInstruction(inst); else return result; - } else { + } + else + { return TranslateComp(inst); } } - + /// /// Translates the equality comparison between left and right. /// @@ -711,39 +797,49 @@ namespace ICSharpCode.Decompiler.CSharp Debug.Assert(inst.Kind.IsEqualityOrInequality()); // Translate '(e as T) == null' to '!(e is T)'. // This is necessary for correctness when T is a value type. - if (inst.Left.OpCode == OpCode.IsInst && inst.Right.OpCode == OpCode.LdNull) { + if (inst.Left.OpCode == OpCode.IsInst && inst.Right.OpCode == OpCode.LdNull) + { negateOutput = inst.Kind == ComparisonKind.Equality; return IsType((IsInst)inst.Left); - } else if (inst.Right.OpCode == OpCode.IsInst && inst.Left.OpCode == OpCode.LdNull) { + } + else if (inst.Right.OpCode == OpCode.IsInst && inst.Left.OpCode == OpCode.LdNull) + { negateOutput = inst.Kind == ComparisonKind.Equality; return IsType((IsInst)inst.Right); } - + var left = Translate(inst.Left); var right = Translate(inst.Right); - + // Remove redundant bool comparisons - if (left.Type.IsKnownType(KnownTypeCode.Boolean)) { - if (inst.Right.MatchLdcI4(0)) { + if (left.Type.IsKnownType(KnownTypeCode.Boolean)) + { + if (inst.Right.MatchLdcI4(0)) + { // 'b == 0' => '!b' // 'b != 0' => 'b' negateOutput = inst.Kind == ComparisonKind.Equality; return left; } - if (inst.Right.MatchLdcI4(1)) { + if (inst.Right.MatchLdcI4(1)) + { // 'b == 1' => 'b' // 'b != 1' => '!b' negateOutput = inst.Kind == ComparisonKind.Inequality; return left; } - } else if (right.Type.IsKnownType(KnownTypeCode.Boolean)) { - if (inst.Left.MatchLdcI4(0)) { + } + else if (right.Type.IsKnownType(KnownTypeCode.Boolean)) + { + if (inst.Left.MatchLdcI4(0)) + { // '0 == b' => '!b' // '0 != b' => 'b' negateOutput = inst.Kind == ComparisonKind.Equality; return right; } - if (inst.Left.MatchLdcI4(1)) { + if (inst.Left.MatchLdcI4(1)) + { // '1 == b' => 'b' // '1 != b' => '!b' negateOutput = inst.Kind == ComparisonKind.Inequality; @@ -751,13 +847,16 @@ namespace ICSharpCode.Decompiler.CSharp } } // Handle comparisons between unsafe pointers and null: - if (left.Type.Kind == TypeKind.Pointer && inst.Right.MatchLdcI(0)) { + if (left.Type.Kind == TypeKind.Pointer && inst.Right.MatchLdcI(0)) + { negateOutput = false; right = new NullReferenceExpression().WithRR(new ConstantResolveResult(SpecialType.NullType, null)) .WithILInstruction(inst.Right); return CreateBuiltinBinaryOperator(left, inst.Kind.ToBinaryOperatorType(), right) .WithILInstruction(inst); - } else if (right.Type.Kind == TypeKind.Pointer && inst.Left.MatchLdcI(0)) { + } + else if (right.Type.Kind == TypeKind.Pointer && inst.Left.MatchLdcI(0)) + { negateOutput = false; left = new NullReferenceExpression().WithRR(new ConstantResolveResult(SpecialType.NullType, null)) .WithILInstruction(inst.Left); @@ -768,8 +867,9 @@ namespace ICSharpCode.Decompiler.CSharp // Special case comparisons with enum and char literals left = TryUniteEqualityOperandType(left, right); right = TryUniteEqualityOperandType(right, left); - - if (IsSpecialCasedReferenceComparisonWithNull(left, right)) { + + if (IsSpecialCasedReferenceComparisonWithNull(left, right)) + { // When comparing a string/delegate with null, the C# compiler generates a reference comparison. negateOutput = false; return CreateBuiltinBinaryOperator(left, inst.Kind.ToBinaryOperatorType(), right) @@ -777,36 +877,51 @@ namespace ICSharpCode.Decompiler.CSharp } OperatorResolveResult rr; - if (left.Type.IsKnownType(KnownTypeCode.String) && right.Type.IsKnownType(KnownTypeCode.String)) { + if (left.Type.IsKnownType(KnownTypeCode.String) && right.Type.IsKnownType(KnownTypeCode.String)) + { rr = null; // it's a string comparison by-value, which is not a reference comparison - } else { + } + else + { rr = resolver.ResolveBinaryOperator(inst.Kind.ToBinaryOperatorType(), left.ResolveResult, right.ResolveResult) as OperatorResolveResult; } if (rr == null || rr.IsError || rr.UserDefinedOperatorMethod != null - || NullableType.GetUnderlyingType(rr.Operands[0].Type).GetStackType() != inst.InputType - || !rr.Type.IsKnownType(KnownTypeCode.Boolean)) + || NullableType.GetUnderlyingType(rr.Operands[0].Type).GetStackType() != inst.InputType + || !rr.Type.IsKnownType(KnownTypeCode.Boolean)) { IType targetType; - if (inst.InputType == StackType.O) { + if (inst.InputType == StackType.O) + { targetType = compilation.FindType(KnownTypeCode.Object); - } else { + } + else + { var leftUType = NullableType.GetUnderlyingType(left.Type); var rightUType = NullableType.GetUnderlyingType(right.Type); - if (leftUType.GetStackType() == inst.InputType && !leftUType.IsSmallIntegerType()) { + if (leftUType.GetStackType() == inst.InputType && !leftUType.IsSmallIntegerType()) + { targetType = leftUType; - } else if (rightUType.GetStackType() == inst.InputType && !rightUType.IsSmallIntegerType()) { + } + else if (rightUType.GetStackType() == inst.InputType && !rightUType.IsSmallIntegerType()) + { targetType = rightUType; - } else { + } + else + { targetType = FindType(inst.InputType, leftUType.GetSign()); } } - if (inst.IsLifted) { + if (inst.IsLifted) + { targetType = NullableType.Create(compilation, targetType); } - if (targetType.Equals(left.Type)) { + if (targetType.Equals(left.Type)) + { right = right.ConvertTo(targetType, this); - } else { + } + else + { left = left.ConvertTo(targetType, this); } rr = resolver.ResolveBinaryOperator(inst.Kind.ToBinaryOperatorType(), @@ -842,7 +957,8 @@ namespace ICSharpCode.Decompiler.CSharp binaryExpr.Operator == BinaryOperatorType.BitwiseAnd) { return AdjustConstantExpressionToType(left, compilation.FindType(KnownTypeCode.Int32)); - } else + } + else return AdjustConstantExpressionToType(left, right.Type); } @@ -864,7 +980,7 @@ namespace ICSharpCode.Decompiler.CSharp BinaryOperatorExpression.GetLinqNodeType(type, checkForOverflow), left.ResolveResult, right.ResolveResult)); } - + /// /// Handle Comp instruction, operators other than equality/inequality. /// @@ -874,7 +990,8 @@ namespace ICSharpCode.Decompiler.CSharp var left = Translate(inst.Left); var right = Translate(inst.Right); - if (left.Type.Kind == TypeKind.Pointer && right.Type.Kind == TypeKind.Pointer) { + if (left.Type.Kind == TypeKind.Pointer && right.Type.Kind == TypeKind.Pointer) + { return CreateBuiltinBinaryOperator(left, op, right) .WithILInstruction(inst); } @@ -889,19 +1006,23 @@ namespace ICSharpCode.Decompiler.CSharp // attempt comparison without any additional casts var rr = resolver.ResolveBinaryOperator(inst.Kind.ToBinaryOperatorType(), left.ResolveResult, right.ResolveResult) as OperatorResolveResult; - if (rr != null && !rr.IsError) { + if (rr != null && !rr.IsError) + { IType compUType = NullableType.GetUnderlyingType(rr.Operands[0].Type); - if (compUType.GetSign() == inst.Sign && compUType.GetStackType() == inst.InputType) { + if (compUType.GetSign() == inst.Sign && compUType.GetStackType() == inst.InputType) + { return new BinaryOperatorExpression(left.Expression, op, right.Expression) .WithILInstruction(inst) .WithRR(rr); } } - if (inst.InputType.IsIntegerType()) { + if (inst.InputType.IsIntegerType()) + { // Ensure the inputs have the correct sign: IType inputType = FindArithmeticType(inst.InputType, inst.Sign); - if (inst.IsLifted) { + if (inst.IsLifted) + { inputType = NullableType.Create(compilation, inputType); } left = left.ConvertTo(inputType, this); @@ -910,8 +1031,8 @@ namespace ICSharpCode.Decompiler.CSharp return new BinaryOperatorExpression(left.Expression, op, right.Expression) .WithILInstruction(inst) .WithRR(new OperatorResolveResult(compilation.FindType(TypeCode.Boolean), - BinaryOperatorExpression.GetLinqNodeType(op, false), - left.ResolveResult, right.ResolveResult)); + BinaryOperatorExpression.GetLinqNodeType(op, false), + left.ResolveResult, right.ResolveResult)); } protected internal override TranslatedExpression VisitThreeValuedBoolAnd(ThreeValuedBoolAnd inst, TranslationContext context) @@ -930,14 +1051,20 @@ namespace ICSharpCode.Decompiler.CSharp var right = Translate(inst.Right); IType boolType = compilation.FindType(KnownTypeCode.Boolean); IType nullableBoolType = NullableType.Create(compilation, boolType); - if (NullableType.IsNullable(left.Type)) { + if (NullableType.IsNullable(left.Type)) + { left = left.ConvertTo(nullableBoolType, this); - if (NullableType.IsNullable(right.Type)) { + if (NullableType.IsNullable(right.Type)) + { right = right.ConvertTo(nullableBoolType, this); - } else { + } + else + { right = right.ConvertTo(boolType, this); } - } else { + } + else + { left = left.ConvertTo(boolType, this); right = right.ConvertTo(nullableBoolType, this); } @@ -958,11 +1085,16 @@ namespace ICSharpCode.Decompiler.CSharp var left = Translate(inst.Left, inst.Method.Parameters[0].Type).ConvertTo(inst.Method.Parameters[0].Type, this); var right = Translate(inst.Right, inst.Method.Parameters[1].Type).ConvertTo(inst.Method.Parameters[1].Type, this); BinaryOperatorType op; - if (inst.Method.Name == "op_BitwiseAnd") { + if (inst.Method.Name == "op_BitwiseAnd") + { op = BinaryOperatorType.ConditionalAnd; - } else if (inst.Method.Name == "op_BitwiseOr") { + } + else if (inst.Method.Name == "op_BitwiseOr") + { op = BinaryOperatorType.ConditionalOr; - } else { + } + else + { throw new InvalidOperationException("Invalid method name"); } return new BinaryOperatorExpression(left.Expression, op, right.Expression) @@ -976,10 +1108,11 @@ namespace ICSharpCode.Decompiler.CSharp return new AssignmentExpression(left.Expression, right.Expression) .WithRR(new OperatorResolveResult(left.Type, ExpressionType.Assign, left.ResolveResult, right.ResolveResult)); } - + protected internal override TranslatedExpression VisitBinaryNumericInstruction(BinaryNumericInstruction inst, TranslationContext context) { - switch (inst.Operator) { + switch (inst.Operator) + { case BinaryNumericOperator.Add: return HandleBinaryNumeric(inst, BinaryOperatorType.Add, context); case BinaryNumericOperator.Sub: @@ -1025,27 +1158,35 @@ namespace ICSharpCode.Decompiler.CSharp PointerType pointerType; ILInstruction byteOffsetInst; TranslatedExpression byteOffsetExpr; - if (left.Type.Kind == TypeKind.Pointer) { + if (left.Type.Kind == TypeKind.Pointer) + { byteOffsetInst = inst.Right; byteOffsetExpr = right; pointerType = (PointerType)left.Type; - } else if (right.Type.Kind == TypeKind.Pointer) { + } + else if (right.Type.Kind == TypeKind.Pointer) + { if (inst.Operator != BinaryNumericOperator.Add) return null; byteOffsetInst = inst.Left; byteOffsetExpr = left; pointerType = (PointerType)right.Type; - } else { + } + else + { return null; } TranslatedExpression offsetExpr = GetPointerArithmeticOffset(byteOffsetInst, byteOffsetExpr, pointerType.ElementType, inst.CheckForOverflow) ?? FallBackToBytePointer(); - if (left.Type.Kind == TypeKind.Pointer) { + if (left.Type.Kind == TypeKind.Pointer) + { Debug.Assert(inst.Operator == BinaryNumericOperator.Add || inst.Operator == BinaryNumericOperator.Sub); left = left.ConvertTo(pointerType, this); right = offsetExpr; - } else { + } + else + { Debug.Assert(inst.Operator == BinaryNumericOperator.Add); Debug.Assert(right.Type.Kind == TypeKind.Pointer); left = offsetExpr; @@ -1078,22 +1219,26 @@ namespace ICSharpCode.Decompiler.CSharp return null; if (inst.CheckForOverflow || inst.IsLifted) return null; - if (inst.Operator == BinaryNumericOperator.Sub && inst.LeftInputType == StackType.Ref && inst.RightInputType == StackType.Ref) { + if (inst.Operator == BinaryNumericOperator.Sub && inst.LeftInputType == StackType.Ref && inst.RightInputType == StackType.Ref) + { // ref - ref => i return CallUnsafeIntrinsic("ByteOffset", new[] { // ByteOffset() expects the parameters the wrong way around, so order using named arguments - new NamedArgumentExpression("target", left.Expression), - new NamedArgumentExpression("origin", right.Expression) + new NamedArgumentExpression("target", left.Expression), + new NamedArgumentExpression("origin", right.Expression) }, compilation.FindType(KnownTypeCode.IntPtr), inst); } if (inst.LeftInputType == StackType.Ref && inst.RightInputType.IsIntegerType() - && left.Type is ByReferenceType brt) { + && left.Type is ByReferenceType brt) + { // ref [+-] int string name = (inst.Operator == BinaryNumericOperator.Sub ? "Subtract" : "Add"); ILInstruction offsetInst = PointerArithmeticOffset.Detect(inst.Right, brt.ElementType, inst.CheckForOverflow); - if (offsetInst != null) { + if (offsetInst != null) + { if (settings.FixedBuffers && inst.Operator == BinaryNumericOperator.Add && inst.Left is LdFlda ldFlda - && ldFlda.Target is LdFlda nestedLdFlda && CSharpDecompiler.IsFixedField(nestedLdFlda.Field, out var elementType, out _)) { + && ldFlda.Target is LdFlda nestedLdFlda && CSharpDecompiler.IsFixedField(nestedLdFlda.Field, out var elementType, out _)) + { Expression fieldAccess = ConvertField(nestedLdFlda.Field, nestedLdFlda.Target); var mrr = (MemberResolveResult)fieldAccess.GetResolveResult(); fieldAccess.RemoveAnnotations(); @@ -1106,21 +1251,27 @@ namespace ICSharpCode.Decompiler.CSharp .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref)); } return CallUnsafeIntrinsic(name, new[] { left.Expression, Translate(offsetInst).Expression }, brt, inst); - } else { + } + else + { return CallUnsafeIntrinsic(name + "ByteOffset", new[] { left.Expression, right.Expression }, brt, inst); } } brt = right.Type as ByReferenceType; if (inst.LeftInputType == StackType.I && inst.RightInputType == StackType.Ref && brt != null - && inst.Operator == BinaryNumericOperator.Add) { + && inst.Operator == BinaryNumericOperator.Add) + { // int + ref ILInstruction offsetInst = PointerArithmeticOffset.Detect(inst.Left, brt.ElementType, inst.CheckForOverflow); - if (offsetInst != null) { + if (offsetInst != null) + { return CallUnsafeIntrinsic("Add", new[] { new NamedArgumentExpression("elementOffset", Translate(offsetInst)), new NamedArgumentExpression("source", right) }, brt, inst); - } else { + } + else + { return CallUnsafeIntrinsic("AddByteOffset", new[] { new NamedArgumentExpression("byteOffset", left.Expression), new NamedArgumentExpression("source", right) @@ -1136,23 +1287,28 @@ namespace ICSharpCode.Decompiler.CSharp Target = new TypeReferenceExpression(astBuilder.ConvertType(compilation.FindType(KnownTypeCode.Unsafe))), MemberName = name }; - if (typeArguments != null) { + if (typeArguments != null) + { target.TypeArguments.AddRange(typeArguments.Select(astBuilder.ConvertType)); } var invocationExpr = new InvocationExpression(target, arguments); - var invocation = inst != null ? invocationExpr.WithILInstruction(inst) : invocationExpr.WithoutILInstruction(); - if (returnType is ByReferenceType brt) { + var invocation = inst != null ? invocationExpr.WithILInstruction(inst) : invocationExpr.WithoutILInstruction(); + if (returnType is ByReferenceType brt) + { return WrapInRef(invocation.WithRR(new ResolveResult(brt.ElementType)), brt); - } else { + } + else + { return invocation.WithRR(new ResolveResult(returnType)); } } TranslatedExpression EnsureIntegerType(TranslatedExpression expr) { - if (!expr.Type.IsCSharpPrimitiveIntegerType() && !expr.Type.IsCSharpNativeIntegerType()) { + if (!expr.Type.IsCSharpPrimitiveIntegerType() && !expr.Type.IsCSharpNativeIntegerType()) + { // pointer arithmetic accepts all primitive integer types, but no enums etc. - expr = expr.ConvertTo(FindArithmeticType(expr.Type.GetStackType(), expr.Type.GetSign()), this); + expr = expr.ConvertTo(FindArithmeticType(expr.Type.GetStackType(), expr.Type.GetSign()), this); } return expr; } @@ -1163,12 +1319,16 @@ namespace ICSharpCode.Decompiler.CSharp var countOffsetInst = PointerArithmeticOffset.Detect(byteOffsetInst, pointerElementType, checkForOverflow: checkForOverflow, unwrapZeroExtension: unwrapZeroExtension); - if (countOffsetInst == null) { + if (countOffsetInst == null) + { return null; } - if (countOffsetInst == byteOffsetInst) { + if (countOffsetInst == byteOffsetInst) + { return EnsureIntegerType(byteOffsetExpr); - } else { + } + else + { TranslatedExpression expr = Translate(countOffsetInst); // Keep original ILInstruction as annotation expr.Expression.RemoveAnnotations(); @@ -1193,26 +1353,38 @@ namespace ICSharpCode.Decompiler.CSharp return null; // First, attempt to parse the 'sizeof' on the RHS IType elementType; - if (inst.Right.MatchLdcI(out long elementSize)) { + if (inst.Right.MatchLdcI(out long elementSize)) + { elementType = null; // OK, might be pointer subtraction if the element size matches - } else if (inst.Right.UnwrapConv(ConversionKind.SignExtend).MatchSizeOf(out elementType)) { + } + else if (inst.Right.UnwrapConv(ConversionKind.SignExtend).MatchSizeOf(out elementType)) + { // OK, might be pointer subtraction if the element type matches - } else { + } + else + { return null; } var left = Translate(sub.Left); var right = Translate(sub.Right); IType pointerType; - if (IsMatchingPointerType(left.Type)) { + if (IsMatchingPointerType(left.Type)) + { pointerType = left.Type; - } else if (IsMatchingPointerType(right.Type)) { + } + else if (IsMatchingPointerType(right.Type)) + { pointerType = right.Type; - } else if (elementSize == 1 && left.Type.Kind == TypeKind.Pointer && right.Type.Kind == TypeKind.Pointer) { + } + else if (elementSize == 1 && left.Type.Kind == TypeKind.Pointer && right.Type.Kind == TypeKind.Pointer) + { // two pointers (neither matching), we're dividing by 1 (debug builds only), // -> subtract two byte pointers pointerType = new PointerType(compilation.FindType(KnownTypeCode.Byte)); - } else { + } + else + { // neither is a matching pointer type // -> not a pointer subtraction after all return null; @@ -1233,7 +1405,8 @@ namespace ICSharpCode.Decompiler.CSharp bool IsMatchingPointerType(IType type) { - if (type is PointerType pt) { + if (type is PointerType pt) + { if (elementType != null) return elementType.Equals(pt.ElementType); else if (elementSize > 0) @@ -1242,19 +1415,21 @@ namespace ICSharpCode.Decompiler.CSharp return false; } } - + TranslatedExpression HandleBinaryNumeric(BinaryNumericInstruction inst, BinaryOperatorType op, TranslationContext context) { var resolverWithOverflowCheck = resolver.WithCheckForOverflow(inst.CheckForOverflow); var left = Translate(inst.Left); var right = Translate(inst.Right); - if (left.Type.Kind == TypeKind.ByReference || right.Type.Kind == TypeKind.ByReference) { + if (left.Type.Kind == TypeKind.ByReference || right.Type.Kind == TypeKind.ByReference) + { var ptrResult = HandleManagedPointerArithmetic(inst, left, right); if (ptrResult != null) return ptrResult.Value; } - if (left.Type.Kind == TypeKind.Pointer || right.Type.Kind == TypeKind.Pointer) { + if (left.Type.Kind == TypeKind.Pointer || right.Type.Kind == TypeKind.Pointer) + { var ptrResult = HandlePointerArithmetic(inst, left, right); if (ptrResult != null) return ptrResult.Value; @@ -1263,10 +1438,12 @@ namespace ICSharpCode.Decompiler.CSharp left = PrepareArithmeticArgument(left, inst.LeftInputType, inst.Sign, inst.IsLifted); right = PrepareArithmeticArgument(right, inst.RightInputType, inst.Sign, inst.IsLifted); - if (op == BinaryOperatorType.Subtract && inst.Left.MatchLdcI(0)) { + if (op == BinaryOperatorType.Subtract && inst.Left.MatchLdcI(0)) + { IType rightUType = NullableType.GetUnderlyingType(right.Type); - if (rightUType.IsKnownType(KnownTypeCode.Int32) || rightUType.IsKnownType(KnownTypeCode.Int64) - || rightUType.IsCSharpSmallIntegerType() || rightUType.IsCSharpNativeIntegerType()) { + if (rightUType.IsKnownType(KnownTypeCode.Int32) || rightUType.IsKnownType(KnownTypeCode.Int64) + || rightUType.IsCSharpSmallIntegerType() || rightUType.IsCSharpNativeIntegerType()) + { // unary minus is supported on signed int and long, and on the small integer types (since they promote to int) var uoe = new UnaryOperatorExpression(UnaryOperatorType.Minus, right.Expression); uoe.AddAnnotation(inst.CheckForOverflow ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); @@ -1279,31 +1456,36 @@ namespace ICSharpCode.Decompiler.CSharp right.ResolveResult)); } } - if (op.IsBitwise() - && left.Type.IsKnownType(KnownTypeCode.Boolean) + if (op.IsBitwise() + && left.Type.IsKnownType(KnownTypeCode.Boolean) && right.Type.IsKnownType(KnownTypeCode.Boolean) && SemanticHelper.IsPure(inst.Right.Flags)) { // Undo the C# compiler's optimization of "a && b" to "a & b". - if (op == BinaryOperatorType.BitwiseAnd) { + if (op == BinaryOperatorType.BitwiseAnd) + { op = BinaryOperatorType.ConditionalAnd; - } else if (op == BinaryOperatorType.BitwiseOr) { + } + else if (op == BinaryOperatorType.BitwiseOr) + { op = BinaryOperatorType.ConditionalOr; } } - if (op.IsBitwise() && (left.Type.Kind == TypeKind.Enum || right.Type.Kind == TypeKind.Enum)) { + if (op.IsBitwise() && (left.Type.Kind == TypeKind.Enum || right.Type.Kind == TypeKind.Enum)) + { left = AdjustConstantExpressionToType(left, right.Type); right = AdjustConstantExpressionToType(right, left.Type); } var rr = resolverWithOverflowCheck.ResolveBinaryOperator(op, left.ResolveResult, right.ResolveResult); if (rr.IsError || NullableType.GetUnderlyingType(rr.Type).GetStackType() != inst.UnderlyingResultType - || !IsCompatibleWithSign(left.Type, inst.Sign) || !IsCompatibleWithSign(right.Type, inst.Sign)) + || !IsCompatibleWithSign(left.Type, inst.Sign) || !IsCompatibleWithSign(right.Type, inst.Sign)) { // Left and right operands are incompatible, so convert them to a common type Sign sign = inst.Sign; - if (sign == Sign.None) { + if (sign == Sign.None) + { // If the sign doesn't matter, try to use the same sign as expected by the context sign = context.TypeHint.GetSign(); } @@ -1315,7 +1497,8 @@ namespace ICSharpCode.Decompiler.CSharp var resultExpr = new BinaryOperatorExpression(left.Expression, op, right.Expression) .WithILInstruction(inst) .WithRR(rr); - if (BinaryOperatorMightCheckForOverflow(op) && !inst.UnderlyingResultType.IsFloatType()) { + if (BinaryOperatorMightCheckForOverflow(op) && !inst.UnderlyingResultType.IsFloatType()) + { resultExpr.Expression.AddAnnotation(inst.CheckForOverflow ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); } return resultExpr; @@ -1326,9 +1509,12 @@ namespace ICSharpCode.Decompiler.CSharp /// IType FindType(StackType stackType, Sign sign) { - if (stackType == StackType.I && settings.NativeIntegers) { + if (stackType == StackType.I && settings.NativeIntegers) + { return sign == Sign.Unsigned ? SpecialType.NUInt : SpecialType.NInt; - } else { + } + else + { return compilation.FindType(stackType.ToKnownTypeCode(sign)); } } @@ -1343,14 +1529,18 @@ namespace ICSharpCode.Decompiler.CSharp /// IType FindArithmeticType(StackType stackType, Sign sign) { - if (stackType == StackType.I) { - if (settings.NativeIntegers) { + if (stackType == StackType.I) + { + if (settings.NativeIntegers) + { return sign == Sign.Unsigned ? SpecialType.NUInt : SpecialType.NInt; - } else { + } + else + { // If native integers are not available, use 64-bit arithmetic instead stackType = StackType.I8; } - } + } return compilation.FindType(stackType.ToKnownTypeCode(sign)); } @@ -1359,11 +1549,13 @@ namespace ICSharpCode.Decompiler.CSharp /// TranslatedExpression PrepareArithmeticArgument(TranslatedExpression arg, StackType argStackType, Sign sign, bool isLifted) { - if (isLifted && !NullableType.IsNullable(arg.Type)) { + if (isLifted && !NullableType.IsNullable(arg.Type)) + { isLifted = false; // don't cast to nullable if this input wasn't already nullable } IType argUType = isLifted ? NullableType.GetUnderlyingType(arg.Type) : arg.Type; - if (argStackType.IsIntegerType() && argStackType.GetSize() < argUType.GetSize()) { + if (argStackType.IsIntegerType() && argStackType.GetSize() < argUType.GetSize()) + { // If the argument is oversized (needs truncation to match stack size of its ILInstruction), // perform the truncation now. IType targetType = FindType(argStackType, sign); @@ -1372,7 +1564,8 @@ namespace ICSharpCode.Decompiler.CSharp targetType = NullableType.Create(compilation, targetType); arg = arg.ConvertTo(targetType, this); } - if (argUType.IsKnownType(KnownTypeCode.IntPtr) || argUType.IsKnownType(KnownTypeCode.UIntPtr)) { + if (argUType.IsKnownType(KnownTypeCode.IntPtr) || argUType.IsKnownType(KnownTypeCode.UIntPtr)) + { // None of the operators we might want to apply are supported by IntPtr/UIntPtr. // Also, pointer arithmetic has different semantics (works in number of elements, not bytes). // So any inputs of size StackType.I must be converted to long/ulong. @@ -1383,7 +1576,7 @@ namespace ICSharpCode.Decompiler.CSharp } return arg; } - + /// /// Gets whether has the specified . /// If is None, always returns true. @@ -1392,10 +1585,11 @@ namespace ICSharpCode.Decompiler.CSharp { return sign == Sign.None || NullableType.GetUnderlyingType(type).GetSign() == sign; } - + static bool BinaryOperatorMightCheckForOverflow(BinaryOperatorType op) { - switch (op) { + switch (op) + { case BinaryOperatorType.BitwiseAnd: case BinaryOperatorType.BitwiseOr: case BinaryOperatorType.ExclusiveOr: @@ -1416,26 +1610,34 @@ namespace ICSharpCode.Decompiler.CSharp Sign sign = inst.Sign; var leftUType = NullableType.GetUnderlyingType(left.Type); - if (leftUType.IsCSharpSmallIntegerType() && sign != Sign.Unsigned && inst.UnderlyingResultType == StackType.I4) { + if (leftUType.IsCSharpSmallIntegerType() && sign != Sign.Unsigned && inst.UnderlyingResultType == StackType.I4) + { // With small integer types, C# will promote to int and perform signed shifts. // We thus don't need any casts in this case. - } else { + } + else + { // Insert cast to target type. - if (sign == Sign.None) { + if (sign == Sign.None) + { // if we don't need a specific sign, prefer keeping that of the input: sign = leftUType.GetSign(); } IType targetType = FindArithmeticType(inst.UnderlyingResultType, sign); - if (NullableType.IsNullable(left.Type)) { + if (NullableType.IsNullable(left.Type)) + { targetType = NullableType.Create(compilation, targetType); } left = left.ConvertTo(targetType, this); } // Shift operators in C# always expect type 'int' on the right-hand-side - if (NullableType.IsNullable(right.Type)) { + if (NullableType.IsNullable(right.Type)) + { right = right.ConvertTo(NullableType.Create(compilation, compilation.FindType(KnownTypeCode.Int32)), this); - } else { + } + else + { right = right.ConvertTo(compilation.FindType(KnownTypeCode.Int32), this); } @@ -1448,19 +1650,25 @@ namespace ICSharpCode.Decompiler.CSharp { IType loadType = inst.Method.Parameters[0].Type; ExpressionWithResolveResult target; - if (inst.TargetKind == CompoundTargetKind.Address) { + if (inst.TargetKind == CompoundTargetKind.Address) + { target = LdObj(inst.Target, loadType); - } else { + } + else + { target = Translate(inst.Target, loadType); } - if (UserDefinedCompoundAssign.IsStringConcat(inst.Method)) { + if (UserDefinedCompoundAssign.IsStringConcat(inst.Method)) + { Debug.Assert(inst.Method.Parameters.Count == 2); var value = Translate(inst.Value).ConvertTo(inst.Method.Parameters[1].Type, this, allowImplicitConversion: true); var valueExpr = ReplaceMethodCallsWithOperators.RemoveRedundantToStringInConcat(value, inst.Method, isLastArgument: true).Detach(); return new AssignmentExpression(target, AssignmentOperatorType.Add, valueExpr) .WithILInstruction(inst) .WithRR(new OperatorResolveResult(inst.Method.ReturnType, ExpressionType.AddAssign, inst.Method, inst.IsLifted, new[] { target.ResolveResult, value.ResolveResult })); - } else if (inst.Method.Parameters.Count == 2) { + } + else if (inst.Method.Parameters.Count == 2) + { var value = Translate(inst.Value).ConvertTo(inst.Method.Parameters[1].Type, this); AssignmentOperatorType? op = GetAssignmentOperatorTypeFromMetadataName(inst.Method.Name); Debug.Assert(op != null); @@ -1468,7 +1676,9 @@ namespace ICSharpCode.Decompiler.CSharp return new AssignmentExpression(target, op.Value, value) .WithILInstruction(inst) .WithRR(new OperatorResolveResult(inst.Method.ReturnType, AssignmentExpression.GetLinqNodeType(op.Value, false), inst.Method, inst.IsLifted, new[] { target.ResolveResult, value.ResolveResult })); - } else { + } + else + { UnaryOperatorType? op = GetUnaryOperatorTypeFromMetadataName(inst.Method.Name, inst.EvalMode == CompoundEvalMode.EvaluatesToOldValue); Debug.Assert(op != null); @@ -1480,7 +1690,8 @@ namespace ICSharpCode.Decompiler.CSharp internal static AssignmentOperatorType? GetAssignmentOperatorTypeFromMetadataName(string name) { - switch (name) { + switch (name) + { case "op_Addition": return AssignmentOperatorType.Add; case "op_Subtraction": @@ -1508,7 +1719,8 @@ namespace ICSharpCode.Decompiler.CSharp internal static UnaryOperatorType? GetUnaryOperatorTypeFromMetadataName(string name, bool isPostfix) { - switch (name) { + switch (name) + { case "op_Increment": return isPostfix ? UnaryOperatorType.PostIncrement : UnaryOperatorType.Increment; case "op_Decrement": @@ -1520,7 +1732,8 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitNumericCompoundAssign(NumericCompoundAssign inst, TranslationContext context) { - switch (inst.Operator) { + switch (inst.Operator) + { case BinaryNumericOperator.Add: return HandleCompoundAssignment(inst, AssignmentOperatorType.Add); case BinaryNumericOperator.Sub: @@ -1545,46 +1758,62 @@ namespace ICSharpCode.Decompiler.CSharp throw new ArgumentOutOfRangeException(); } } - + TranslatedExpression HandleCompoundAssignment(NumericCompoundAssign inst, AssignmentOperatorType op) { ExpressionWithResolveResult target; - if (inst.TargetKind == CompoundTargetKind.Address) { + if (inst.TargetKind == CompoundTargetKind.Address) + { target = LdObj(inst.Target, inst.Type); - } else { + } + else + { target = Translate(inst.Target, inst.Type); } TranslatedExpression resultExpr; - if (inst.EvalMode == CompoundEvalMode.EvaluatesToOldValue) { + if (inst.EvalMode == CompoundEvalMode.EvaluatesToOldValue) + { Debug.Assert(op == AssignmentOperatorType.Add || op == AssignmentOperatorType.Subtract); Debug.Assert(inst.Value.MatchLdcI(1) || inst.Value.MatchLdcF4(1) || inst.Value.MatchLdcF8(1)); UnaryOperatorType unary; ExpressionType exprType; - if (op == AssignmentOperatorType.Add) { + if (op == AssignmentOperatorType.Add) + { unary = UnaryOperatorType.PostIncrement; exprType = ExpressionType.PostIncrementAssign; - } else { + } + else + { unary = UnaryOperatorType.PostDecrement; exprType = ExpressionType.PostDecrementAssign; } resultExpr = new UnaryOperatorExpression(unary, target) .WithILInstruction(inst) .WithRR(new OperatorResolveResult(target.Type, exprType, target.ResolveResult)); - } else { + } + else + { var value = Translate(inst.Value); value = PrepareArithmeticArgument(value, inst.RightInputType, inst.Sign, inst.IsLifted); - switch (op) { + switch (op) + { case AssignmentOperatorType.Add: case AssignmentOperatorType.Subtract: - if (target.Type.Kind == TypeKind.Pointer) { + if (target.Type.Kind == TypeKind.Pointer) + { var pao = GetPointerArithmeticOffset(inst.Value, value, ((PointerType)target.Type).ElementType, inst.CheckForOverflow); - if (pao != null) { + if (pao != null) + { value = pao.Value; - } else { + } + else + { value.Expression.AddChild(new Comment("ILSpy Error: GetPointerArithmeticOffset() failed", CommentType.MultiLine), Roles.Comment); } - } else { + } + else + { IType targetType = NullableType.GetUnderlyingType(target.Type).GetEnumUnderlyingType(); value = ConvertValue(value, targetType); } @@ -1594,17 +1823,19 @@ namespace ICSharpCode.Decompiler.CSharp case AssignmentOperatorType.Modulus: case AssignmentOperatorType.BitwiseAnd: case AssignmentOperatorType.BitwiseOr: - case AssignmentOperatorType.ExclusiveOr: { - IType targetType = NullableType.GetUnderlyingType(target.Type); - value = ConvertValue(value, targetType); - break; - } + case AssignmentOperatorType.ExclusiveOr: + { + IType targetType = NullableType.GetUnderlyingType(target.Type); + value = ConvertValue(value, targetType); + break; + } } resultExpr = new AssignmentExpression(target.Expression, op, value.Expression) .WithILInstruction(inst) .WithRR(new OperatorResolveResult(target.Type, AssignmentExpression.GetLinqNodeType(op, inst.CheckForOverflow), target.ResolveResult, value.ResolveResult)); } - if (AssignmentOperatorMightCheckForOverflow(op) && !inst.UnderlyingResultType.IsFloatType()) { + if (AssignmentOperatorMightCheckForOverflow(op) && !inst.UnderlyingResultType.IsFloatType()) + { resultExpr.Expression.AddAnnotation(inst.CheckForOverflow ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); } return resultExpr; @@ -1612,33 +1843,41 @@ namespace ICSharpCode.Decompiler.CSharp TranslatedExpression ConvertValue(TranslatedExpression value, IType targetType) { bool allowImplicitConversion = true; - if (targetType.GetStackType() == StackType.I) { + if (targetType.GetStackType() == StackType.I) + { // Force explicit cast for (U)IntPtr, keep allowing implicit conversion only for n(u)int allowImplicitConversion = targetType.IsCSharpNativeIntegerType(); targetType = targetType.GetSign() == Sign.Unsigned ? SpecialType.NUInt : SpecialType.NInt; } - if (NullableType.IsNullable(value.Type)) { + if (NullableType.IsNullable(value.Type)) + { targetType = NullableType.Create(compilation, targetType); } return value.ConvertTo(targetType, this, inst.CheckForOverflow, allowImplicitConversion); } } - + TranslatedExpression HandleCompoundShift(NumericCompoundAssign inst, AssignmentOperatorType op) { Debug.Assert(inst.EvalMode == CompoundEvalMode.EvaluatesToNewValue); ExpressionWithResolveResult target; - if (inst.TargetKind == CompoundTargetKind.Address) { + if (inst.TargetKind == CompoundTargetKind.Address) + { target = LdObj(inst.Target, inst.Type); - } else { + } + else + { target = Translate(inst.Target, inst.Type); } var value = Translate(inst.Value); // Shift operators in C# always expect type 'int' on the right-hand-side - if (NullableType.IsNullable(value.Type)) { + if (NullableType.IsNullable(value.Type)) + { value = value.ConvertTo(NullableType.Create(compilation, compilation.FindType(KnownTypeCode.Int32)), this); - } else { + } + else + { value = value.ConvertTo(compilation.FindType(KnownTypeCode.Int32), this); } @@ -1646,10 +1885,11 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(resolver.ResolveAssignment(op, target.ResolveResult, value.ResolveResult)); } - + static bool AssignmentOperatorMightCheckForOverflow(AssignmentOperatorType op) { - switch (op) { + switch (op) + { case AssignmentOperatorType.BitwiseAnd: case AssignmentOperatorType.BitwiseOr: case AssignmentOperatorType.ExclusiveOr: @@ -1660,11 +1900,12 @@ namespace ICSharpCode.Decompiler.CSharp return true; } } - + protected internal override TranslatedExpression VisitConv(Conv inst, TranslationContext context) { Sign hintSign = inst.InputSign; - if (hintSign == Sign.None) { + if (hintSign == Sign.None) + { hintSign = context.TypeHint.GetSign(); } var arg = Translate(inst.Argument, typeHint: FindArithmeticType(inst.InputType, hintSign)); @@ -1687,22 +1928,28 @@ namespace ICSharpCode.Decompiler.CSharp { IType type = compilation.FindType(typeCode); // Prefer n(u)int over (U)IntPtr - if (typeCode == KnownTypeCode.IntPtr && settings.NativeIntegers && !type.Equals(context.TypeHint)) { + if (typeCode == KnownTypeCode.IntPtr && settings.NativeIntegers && !type.Equals(context.TypeHint)) + { type = SpecialType.NInt; - } else if (typeCode == KnownTypeCode.UIntPtr && settings.NativeIntegers && !type.Equals(context.TypeHint)) { + } + else if (typeCode == KnownTypeCode.UIntPtr && settings.NativeIntegers && !type.Equals(context.TypeHint)) + { type = SpecialType.NUInt; } - if (inst.IsLifted) { + if (inst.IsLifted) + { type = NullableType.Create(compilation, type); } return type; } - if (inst.CheckForOverflow || inst.Kind == ConversionKind.IntToFloat) { + if (inst.CheckForOverflow || inst.Kind == ConversionKind.IntToFloat) + { // We need to first convert the argument to the expected sign. // We also need to perform any input narrowing conversion so that it doesn't get mixed up with the overflow check. Debug.Assert(inst.InputSign != Sign.None); - if (inputType.GetSize() > inputStackType.GetSize() || inputType.GetSign() != inst.InputSign) { + if (inputType.GetSize() > inputStackType.GetSize() || inputType.GetSign() != inst.InputSign) + { arg = arg.ConvertTo(GetType(inputStackType.ToKnownTypeCode(inst.InputSign)), this); } // Because casts with overflow check match C# semantics (zero/sign-extension depends on source type), @@ -1710,38 +1957,48 @@ namespace ICSharpCode.Decompiler.CSharp return arg.ConvertTo(GetType(inst.TargetType.ToKnownTypeCode()), this, inst.CheckForOverflow) .WithILInstruction(inst); } - - switch (inst.Kind) { + + switch (inst.Kind) + { case ConversionKind.StartGCTracking: // A "start gc tracking" conversion is inserted in the ILAst whenever // some instruction expects a managed pointer, but we pass an unmanaged pointer. // We'll leave the C#-level conversion (from T* to ref T) to the consumer that expects the managed pointer. return arg; case ConversionKind.StopGCTracking: - if (inputType.Kind == TypeKind.ByReference) { - if (PointerArithmeticOffset.IsFixedVariable(inst.Argument)) { + if (inputType.Kind == TypeKind.ByReference) + { + if (PointerArithmeticOffset.IsFixedVariable(inst.Argument)) + { // cast to corresponding pointer type: var pointerType = new PointerType(((ByReferenceType)inputType).ElementType); return arg.ConvertTo(pointerType, this).WithILInstruction(inst); - } else { + } + else + { // emit Unsafe.AsPointer() intrinsic: return CallUnsafeIntrinsic("AsPointer", arguments: new Expression[] { arg }, returnType: new PointerType(compilation.FindType(KnownTypeCode.Void)), inst: inst); } - } else if (arg.Type.GetStackType().IsIntegerType()) { + } + else if (arg.Type.GetStackType().IsIntegerType()) + { // ConversionKind.StopGCTracking should only be used with managed references, // but it's possible that we're supposed to stop tracking something we just started to track. return arg; - } else { + } + else + { goto default; } case ConversionKind.SignExtend: // We just need to ensure the input type before the conversion is signed. // Also, if the argument was translated into an oversized C# type, // we need to perform the truncatation to the input stack type. - if (inputType.GetSign() != Sign.Signed || ValueMightBeOversized(arg.ResolveResult, inputStackType)) { + if (inputType.GetSign() != Sign.Signed || ValueMightBeOversized(arg.ResolveResult, inputStackType)) + { // Note that an undersized C# type is handled just fine: // If it is unsigned we'll zero-extend it to the width of the inputStackType here, // and it is signed we just combine the two sign-extensions into a single sign-extending conversion. @@ -1753,7 +2010,8 @@ namespace ICSharpCode.Decompiler.CSharp return arg.WithILInstruction(inst); case ConversionKind.ZeroExtend: // If overflow check cannot fail, handle this just like sign extension (except for swapped signs) - if (inputType.GetSign() != Sign.Unsigned || inputType.GetSize() > inputStackType.GetSize()) { + if (inputType.GetSign() != Sign.Unsigned || inputType.GetSize() > inputStackType.GetSize()) + { arg = arg.ConvertTo(GetType(inputStackType.ToKnownTypeCode(Sign.Unsigned)), this); } return arg.WithILInstruction(inst); @@ -1773,32 +2031,39 @@ namespace ICSharpCode.Decompiler.CSharp // In cases 1-3, the overall conversion is a truncation or no-op. // In case 4, the overall conversion is a zero/sign extension, but to a smaller // size than the original conversion. - if (inst.TargetType.IsSmallIntegerType()) { + if (inst.TargetType.IsSmallIntegerType()) + { // If the target type is a small integer type, IL will implicitly sign- or zero-extend // the result after the truncation back to StackType.I4. // (which means there's actually 3 conversions involved!) // Note that we must handle truncation to small integer types ourselves: // our caller only sees the StackType.I4 and doesn't know to truncate to the small type. - - if (inputType.GetSize() <= inst.TargetType.GetSize() && inputType.GetSign() == inst.TargetType.GetSign()) { + + if (inputType.GetSize() <= inst.TargetType.GetSize() && inputType.GetSign() == inst.TargetType.GetSign()) + { // There's no actual truncation involved, and the result of the Conv instruction is extended // the same way as the original instruction // -> we can return arg directly return arg.WithILInstruction(inst); - } else { + } + else + { // We need to actually truncate; *or* we need to change the sign for the remaining extension to I4. goto default; // Emit simple cast to inst.TargetType } - } else { + } + else + { Debug.Assert(inst.TargetType.GetSize() == inst.UnderlyingResultType.GetSize()); // For non-small integer types, we can let the whole unchecked truncation // get handled by our caller (using the ExpressionBuilder post-condition). - + // Case 4 (left-over extension from implicit conversion) can also be handled by our caller. return arg.WithILInstruction(inst); } case ConversionKind.Invalid: - if (inst.InputType == StackType.Unknown && inst.TargetType == IL.PrimitiveType.None && arg.Type.Kind == TypeKind.Unknown) { + if (inst.InputType == StackType.Unknown && inst.TargetType == IL.PrimitiveType.None && arg.Type.Kind == TypeKind.Unknown) + { // Unknown -> O conversion. // Our post-condition allows us to also use expressions with unknown type where O is expected, // so avoid introducing an `(object)` cast because we're likely to cast back to the same unknown type, @@ -1806,25 +2071,33 @@ namespace ICSharpCode.Decompiler.CSharp return arg.WithILInstruction(inst); } goto default; - default: { - // We need to convert to inst.TargetType, or to an equivalent type. - IType targetType; - if (inst.TargetType == NullableType.GetUnderlyingType(context.TypeHint).ToPrimitiveType() - && NullableType.IsNullable(context.TypeHint) == inst.IsLifted) { - targetType = context.TypeHint; - } else if (inst.TargetType == IL.PrimitiveType.Ref) { - // converting to unknown ref-type - targetType = new ByReferenceType(compilation.FindType(KnownTypeCode.Byte)); - } else if (inst.TargetType == IL.PrimitiveType.None) { - // convert to some object type - // (e.g. invalid I4->O conversion) - targetType = compilation.FindType(KnownTypeCode.Object); - } else { - targetType = GetType(inst.TargetType.ToKnownTypeCode()); - } - return arg.ConvertTo(targetType, this, inst.CheckForOverflow) - .WithILInstruction(inst); + default: + { + // We need to convert to inst.TargetType, or to an equivalent type. + IType targetType; + if (inst.TargetType == NullableType.GetUnderlyingType(context.TypeHint).ToPrimitiveType() + && NullableType.IsNullable(context.TypeHint) == inst.IsLifted) + { + targetType = context.TypeHint; + } + else if (inst.TargetType == IL.PrimitiveType.Ref) + { + // converting to unknown ref-type + targetType = new ByReferenceType(compilation.FindType(KnownTypeCode.Byte)); + } + else if (inst.TargetType == IL.PrimitiveType.None) + { + // convert to some object type + // (e.g. invalid I4->O conversion) + targetType = compilation.FindType(KnownTypeCode.Object); } + else + { + targetType = GetType(inst.TargetType.ToKnownTypeCode()); + } + return arg.ConvertTo(targetType, this, inst.CheckForOverflow) + .WithILInstruction(inst); + } } } @@ -1834,12 +2107,14 @@ namespace ICSharpCode.Decompiler.CSharp bool ValueMightBeOversized(ResolveResult rr, StackType stackType) { IType inputType = NullableType.GetUnderlyingType(rr.Type); - if (inputType.GetSize() <= stackType.GetSize()) { + if (inputType.GetSize() <= stackType.GetSize()) + { // The input type is smaller or equal to the stack type, // it can't be an oversized value. return false; } - if (rr is OperatorResolveResult orr) { + if (rr is OperatorResolveResult orr) + { if (stackType == StackType.I && orr.OperatorType == ExpressionType.Subtract && orr.Operands.Count == 2 && orr.Operands[0].Type.Kind == TypeKind.Pointer @@ -1866,7 +2141,8 @@ namespace ICSharpCode.Decompiler.CSharp TranslatedExpression WrapInRef(TranslatedExpression expr, IType type) { - if (type.Kind == TypeKind.ByReference) { + if (type.Kind == TypeKind.ByReference) + { return new DirectionExpression(FieldDirection.Ref, expr.Expression) .WithoutILInstruction() .WithRR(new ByReferenceResolveResult(expr.ResolveResult, ReferenceKind.Ref)); @@ -1877,7 +2153,8 @@ namespace ICSharpCode.Decompiler.CSharp internal bool IsCurrentOrContainingType(ITypeDefinition type) { var currentTypeDefinition = decompilationContext.CurrentTypeDefinition; - while (currentTypeDefinition != null) { + while (currentTypeDefinition != null) + { if (type == currentTypeDefinition) return true; currentTypeDefinition = currentTypeDefinition.DeclaringTypeDefinition; @@ -1898,15 +2175,19 @@ namespace ICSharpCode.Decompiler.CSharp var body = builder.ConvertAsBlock(function.Body); Comment prev = null; - foreach (string warning in function.Warnings) { + foreach (string warning in function.Warnings) + { body.InsertChildAfter(prev, prev = new Comment(warning), Roles.Comment); } bool isLambda = false; - if (ame.Parameters.Any(p => p.Type.IsNull)) { + if (ame.Parameters.Any(p => p.Type.IsNull)) + { // if there is an anonymous type involved, we are forced to use a lambda expression. isLambda = true; - } else if (settings.UseLambdaSyntax && ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None)) { + } + else if (settings.UseLambdaSyntax && ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None)) + { // otherwise use lambda only if an expression lambda is possible isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement); } @@ -1916,32 +2197,40 @@ namespace ICSharpCode.Decompiler.CSharp let v = ident.GetILVariable() where v != null && v.Function == function && v.Kind == VariableKind.Parameter select ident; - if (!isLambda && !parameterReferencingIdentifiers.Any()) { + if (!isLambda && !parameterReferencingIdentifiers.Any()) + { ame.Parameters.Clear(); ame.HasParameterList = false; } Expression replacement; IType inferredReturnType; - if (isLambda) { + if (isLambda) + { LambdaExpression lambda = new LambdaExpression(); lambda.IsAsync = ame.IsAsync; lambda.CopyAnnotationsFrom(ame); ame.Parameters.MoveTo(lambda.Parameters); - if (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement returnStmt) { + if (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement returnStmt) + { lambda.Body = returnStmt.Expression.Detach(); inferredReturnType = lambda.Body.GetResolveResult().Type; - } else { + } + else + { lambda.Body = body; inferredReturnType = InferReturnType(body); } replacement = lambda; - } else { + } + else + { ame.Body = body; inferredReturnType = InferReturnType(body); replacement = ame; } - if (ame.IsAsync) { + if (ame.IsAsync) + { inferredReturnType = GetTaskType(inferredReturnType); } @@ -1973,15 +2262,20 @@ namespace ICSharpCode.Decompiler.CSharp void CollectReturnExpressions(AstNode node) { - if (node is ReturnStatement ret) { - if (!ret.Expression.IsNull) { + if (node is ReturnStatement ret) + { + if (!ret.Expression.IsNull) + { returnExpressions.Add(ret.Expression.GetResolveResult()); } - } else if (node is LambdaExpression || node is AnonymousMethodExpression) { + } + else if (node is LambdaExpression || node is AnonymousMethodExpression) + { // do not recurse into nested lambdas return; } - foreach (var child in node.Children) { + foreach (var child in node.Children) + { CollectReturnExpressions(child); } } @@ -2005,9 +2299,11 @@ namespace ICSharpCode.Decompiler.CSharp { var variables = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index); int i = 0; - foreach (var parameter in parameters) { + foreach (var parameter in parameters) + { var pd = astBuilder.ConvertParameter(parameter); - if (string.IsNullOrEmpty(pd.Name) && !pd.Type.IsArgList()) { + if (string.IsNullOrEmpty(pd.Name) && !pd.Type.IsArgList()) + { // needs to be consistent with logic in ILReader.CreateILVarable(ParameterDefinition) pd.Name = "P_" + i; } @@ -2029,7 +2325,8 @@ namespace ICSharpCode.Decompiler.CSharp statementBuilder.currentReturnContainer = container; statementBuilder.currentResultType = context.TypeHint; statementBuilder.currentIsIterator = false; - try { + try + { var body = statementBuilder.ConvertAsBlock(container); body.InsertChildAfter(null, new Comment(" Could not convert BlockContainer to single expression"), Roles.Comment); var ame = new AnonymousMethodExpression { Body = body }; @@ -2039,16 +2336,21 @@ namespace ICSharpCode.Decompiler.CSharp var invocationTarget = new CastExpression(ConvertType(delegateType), ame); ResolveResult rr; // This might happen when trying to decompile an assembly built for a target framework where System.Func does not exist yet. - if (systemFuncType.Kind == TypeKind.Unknown) { + if (systemFuncType.Kind == TypeKind.Unknown) + { rr = new ResolveResult(blockReturnType); - } else { + } + else + { var invokeMethod = delegateType.GetDelegateInvokeMethod(); rr = new CSharpInvocationResolveResult(new ResolveResult(delegateType), invokeMethod, EmptyList.Instance); } return new InvocationExpression(new MemberReferenceExpression(invocationTarget, "Invoke")) .WithILInstruction(container) .WithRR(rr); - } finally { + } + finally + { statementBuilder.currentReturnContainer = oldReturnContainer; statementBuilder.currentResultType = oldResultType; statementBuilder.currentIsIterator = oldIsIterator; @@ -2060,26 +2362,35 @@ namespace ICSharpCode.Decompiler.CSharp { // If references are missing member.IsStatic might not be set correctly. // Additionally check target for null, in order to avoid a crash. - if (!memberStatic && target != null) { - if (ShouldUseBaseReference()) { + if (!memberStatic && target != null) + { + if (ShouldUseBaseReference()) + { return new BaseReferenceExpression() .WithILInstruction(target) .WithRR(new ThisResolveResult(memberDeclaringType, nonVirtualInvocation)); - } else { + } + else + { var translatedTarget = Translate(target, memberDeclaringType); - if (CallInstruction.ExpectedTypeForThisPointer(memberDeclaringType) == StackType.Ref) { + if (CallInstruction.ExpectedTypeForThisPointer(memberDeclaringType) == StackType.Ref) + { // When accessing members on value types, ensure we use a reference of the correct type, // and not a pointer or a reference to a different type (issue #1333) - if (!(translatedTarget.Type is ByReferenceType brt && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(brt.ElementType, memberDeclaringType))) { + if (!(translatedTarget.Type is ByReferenceType brt && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(brt.ElementType, memberDeclaringType))) + { translatedTarget = translatedTarget.ConvertTo(new ByReferenceType(memberDeclaringType), this); } } - if (translatedTarget.Expression is DirectionExpression) { + if (translatedTarget.Expression is DirectionExpression) + { // (ref x).member => x.member translatedTarget = translatedTarget.UnwrapChild(((DirectionExpression)translatedTarget).Expression); - } else if (translatedTarget.Expression is UnaryOperatorExpression uoe - && uoe.Operator == UnaryOperatorType.NullConditional - && uoe.Expression is DirectionExpression) { + } + else if (translatedTarget.Expression is UnaryOperatorExpression uoe + && uoe.Operator == UnaryOperatorType.NullConditional + && uoe.Expression is DirectionExpression) + { // (ref x)?.member => x?.member translatedTarget = translatedTarget.UnwrapChild(((DirectionExpression)uoe.Expression).Expression); // note: we need to create a new ResolveResult for the null-conditional operator, @@ -2091,7 +2402,9 @@ namespace ICSharpCode.Decompiler.CSharp translatedTarget = EnsureTargetNotNullable(translatedTarget, target); return translatedTarget; } - } else { + } + else + { return new TypeReferenceExpression(ConvertType(memberDeclaringType)) .WithoutILInstruction() .WithRR(new TypeResolveResult(memberDeclaringType)); @@ -2113,7 +2426,8 @@ namespace ICSharpCode.Decompiler.CSharp // ldloc this if (inst.MatchLdThis()) return true; - if (resolver.CurrentTypeDefinition.Kind == TypeKind.Struct) { + if (resolver.CurrentTypeDefinition.Kind == TypeKind.Struct) + { // box T(ldobj T(ldloc this)) if (!inst.MatchBox(out var arg, out var type)) return false; @@ -2130,11 +2444,14 @@ namespace ICSharpCode.Decompiler.CSharp private TranslatedExpression EnsureTargetNotNullable(TranslatedExpression expr, ILInstruction inst) { // inst is the instruction that got translated into expr. - if (expr.Type.Nullability == Nullability.Nullable) { - if (expr.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.NullConditional) { + if (expr.Type.Nullability == Nullability.Nullable) + { + if (expr.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.NullConditional) + { return expr; } - if (inst.HasFlag(InstructionFlags.MayUnwrapNull)) { + if (inst.HasFlag(InstructionFlags.MayUnwrapNull)) + { // We can't use ! in the chain of operators after a NullConditional, due to // https://github.com/dotnet/roslyn/issues/43659 return expr; @@ -2157,21 +2474,30 @@ namespace ICSharpCode.Decompiler.CSharp ExpressionWithResolveResult LdObj(ILInstruction address, IType loadType) { var target = Translate(address); - if (TypeUtils.IsCompatiblePointerTypeForMemoryAccess(target.Type, loadType)) { + if (TypeUtils.IsCompatiblePointerTypeForMemoryAccess(target.Type, loadType)) + { ExpressionWithResolveResult result; - if (target.Expression is DirectionExpression dirExpr) { + if (target.Expression is DirectionExpression dirExpr) + { // we can dereference the managed reference by stripping away the 'ref' result = target.UnwrapChild(dirExpr.Expression); - } else if (target.Type is PointerType pointerType) { - if (target.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.AddressOf) { + } + else if (target.Type is PointerType pointerType) + { + if (target.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.AddressOf) + { // We can dereference the pointer by stripping away the '&' result = target.UnwrapChild(uoe.Expression); - } else { + } + else + { // Dereference the existing pointer result = new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression) .WithRR(new ResolveResult(pointerType.ElementType)); } - } else { + } + else + { // reference type behind non-DirectionExpression? // this case should be impossible, but we can use a pointer cast // just to make sure @@ -2183,7 +2509,9 @@ namespace ICSharpCode.Decompiler.CSharp // might be inaccurate (it's often System.Object for all reference types), // and our parent node should already insert casts where necessary return result; - } else { + } + else + { // We need to cast the pointer type: target = target.ConvertTo(new PointerType(loadType), this); return new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression) @@ -2196,29 +2524,40 @@ namespace ICSharpCode.Decompiler.CSharp var pointer = Translate(inst.Target); TranslatedExpression target; TranslatedExpression value = default; - if (pointer.Expression is DirectionExpression && TypeUtils.IsCompatiblePointerTypeForMemoryAccess(pointer.Type, inst.Type)) { + if (pointer.Expression is DirectionExpression && TypeUtils.IsCompatiblePointerTypeForMemoryAccess(pointer.Type, inst.Type)) + { // we can deference the managed reference by stripping away the 'ref' target = pointer.UnwrapChild(((DirectionExpression)pointer.Expression).Expression); - } else { + } + else + { // Cast pointer type if necessary: - if (!TypeUtils.IsCompatiblePointerTypeForMemoryAccess(pointer.Type, inst.Type)) { + if (!TypeUtils.IsCompatiblePointerTypeForMemoryAccess(pointer.Type, inst.Type)) + { value = Translate(inst.Value, typeHint: inst.Type); - if (TypeUtils.IsCompatibleTypeForMemoryAccess(value.Type, inst.Type)) { + if (TypeUtils.IsCompatibleTypeForMemoryAccess(value.Type, inst.Type)) + { pointer = pointer.ConvertTo(new PointerType(value.Type), this); - } else { + } + else + { pointer = pointer.ConvertTo(new PointerType(inst.Type), this); } } - if (pointer.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.AddressOf) { + if (pointer.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.AddressOf) + { // *&ptr -> ptr target = pointer.UnwrapChild(uoe.Expression); - } else { + } + else + { target = new UnaryOperatorExpression(UnaryOperatorType.Dereference, pointer.Expression) .WithoutILInstruction() .WithRR(new ResolveResult(((TypeWithElementType)pointer.Type).ElementType)); } } - if (value.Expression == null) { + if (value.Expression == null) + { value = Translate(inst.Value, typeHint: target.Type); } return Assignment(target, value).WithILInstruction(inst); @@ -2228,16 +2567,20 @@ namespace ICSharpCode.Decompiler.CSharp { IType arrayType = compilation.FindType(KnownTypeCode.Array); TranslatedExpression arrayExpr = Translate(inst.Array, typeHint: arrayType); - if (arrayExpr.Type.Kind != TypeKind.Array) { + if (arrayExpr.Type.Kind != TypeKind.Array) + { arrayExpr = arrayExpr.ConvertTo(arrayType, this); } arrayExpr = EnsureTargetNotNullable(arrayExpr, inst.Array); string memberName; KnownTypeCode code; - if (inst.ResultType == StackType.I4) { + if (inst.ResultType == StackType.I4) + { memberName = "Length"; code = KnownTypeCode.Int32; - } else { + } + else + { memberName = "LongLength"; code = KnownTypeCode.Int64; } @@ -2249,7 +2592,7 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(rr); } - + protected internal override TranslatedExpression VisitLdFlda(LdFlda inst, TranslationContext context) { if (settings.FixedBuffers && inst.Field.Name == "FixedElementField" @@ -2261,22 +2604,28 @@ namespace ICSharpCode.Decompiler.CSharp fieldAccess.RemoveAnnotations(); var result = fieldAccess.WithRR(new MemberResolveResult(mrr.TargetResult, mrr.Member, new PointerType(elementType))) .WithILInstruction(inst); - if (inst.ResultType == StackType.Ref) { + if (inst.ResultType == StackType.Ref) + { // convert pointer back to ref return result.ConvertTo(new ByReferenceType(elementType), this); - } else { + } + else + { return result; } } TranslatedExpression expr; - if (TupleTransform.MatchTupleFieldAccess(inst, out IType underlyingTupleType, out var target, out int position)) { + if (TupleTransform.MatchTupleFieldAccess(inst, out IType underlyingTupleType, out var target, out int position)) + { var translatedTarget = TranslateTarget(target, nonVirtualInvocation: true, memberStatic: false, memberDeclaringType: underlyingTupleType); - if (translatedTarget.Type is TupleType tupleType && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(tupleType, underlyingTupleType) && position <= tupleType.ElementNames.Length) { + if (translatedTarget.Type is TupleType tupleType && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(tupleType, underlyingTupleType) && position <= tupleType.ElementNames.Length) + { string elementName = tupleType.ElementNames[position - 1]; - if (elementName == null) { + if (elementName == null) + { elementName = "Item" + position; } // tupleType.ElementTypes are more accurate w.r.t. nullability/dynamic than inst.Field.Type @@ -2284,45 +2633,56 @@ namespace ICSharpCode.Decompiler.CSharp returnTypeOverride: tupleType.ElementTypes[position - 1]); expr = new MemberReferenceExpression(translatedTarget, elementName) .WithRR(rr).WithILInstruction(inst); - } else { + } + else + { expr = ConvertField(inst.Field, inst.Target).WithILInstruction(inst); } - } else { + } + else + { expr = ConvertField(inst.Field, inst.Target).WithILInstruction(inst); } - if (inst.ResultType == StackType.I) { + if (inst.ResultType == StackType.I) + { // ldflda producing native pointer return new UnaryOperatorExpression(UnaryOperatorType.AddressOf, expr) .WithoutILInstruction().WithRR(new ResolveResult(new PointerType(expr.Type))); - } else { + } + else + { // ldflda producing managed pointer return new DirectionExpression(FieldDirection.Ref, expr) .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.ResolveResult, ReferenceKind.Ref)); } } - + protected internal override TranslatedExpression VisitLdsFlda(LdsFlda inst, TranslationContext context) { var expr = ConvertField(inst.Field).WithILInstruction(inst); return new DirectionExpression(FieldDirection.Ref, expr) .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref)); } - + protected internal override TranslatedExpression VisitLdElema(LdElema inst, TranslationContext context) { TranslatedExpression arrayExpr = Translate(inst.Array); var arrayType = arrayExpr.Type as ArrayType; - if (arrayType == null || !TypeUtils.IsCompatibleTypeForMemoryAccess(arrayType.ElementType, inst.Type)) { + if (arrayType == null || !TypeUtils.IsCompatibleTypeForMemoryAccess(arrayType.ElementType, inst.Type)) + { arrayType = new ArrayType(compilation, inst.Type, inst.Indices.Count); arrayExpr = arrayExpr.ConvertTo(arrayType, this); } IndexerExpression indexerExpr; - if (inst.WithSystemIndex) { + if (inst.WithSystemIndex) + { var systemIndex = compilation.FindType(KnownTypeCode.Index); indexerExpr = new IndexerExpression( arrayExpr, inst.Indices.Select(i => Translate(i, typeHint: systemIndex).ConvertTo(systemIndex, this).Expression) ); - } else { + } + else + { indexerExpr = new IndexerExpression( arrayExpr, inst.Indices.Select(i => TranslateArrayIndex(i).Expression) ); @@ -2331,17 +2691,18 @@ namespace ICSharpCode.Decompiler.CSharp return new DirectionExpression(FieldDirection.Ref, expr) .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref)); } - + TranslatedExpression TranslateArrayIndex(ILInstruction i) { var input = Translate(i); - if (i.ResultType == StackType.I4 && input.Type.IsSmallIntegerType() && input.Type.Kind != TypeKind.Enum) { + if (i.ResultType == StackType.I4 && input.Type.IsSmallIntegerType() && input.Type.Kind != TypeKind.Enum) + { return input; // we don't need a cast, just let small integers be promoted to int } IType targetType = FindArithmeticType(i.ResultType, input.Type.GetSign()); return input.ConvertTo(targetType, this); } - + internal static bool IsUnboxAnyWithIsInst(UnboxAny unboxAny, IsInst isInst) { return unboxAny.Type.Equals(isInst.Type) @@ -2351,7 +2712,8 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitUnboxAny(UnboxAny inst, TranslationContext context) { TranslatedExpression arg; - if (inst.Argument is IsInst isInst && IsUnboxAnyWithIsInst(inst, isInst)) { + if (inst.Argument is IsInst isInst && IsUnboxAnyWithIsInst(inst, isInst)) + { // unbox.any T(isinst T(expr)) ==> expr as T // This is used for generic types and nullable value types arg = UnwrapBoxingConversion(Translate(isInst.Argument)); @@ -2362,15 +2724,19 @@ namespace ICSharpCode.Decompiler.CSharp arg = Translate(inst.Argument); IType targetType = inst.Type; - if (targetType.Kind == TypeKind.TypeParameter) { + if (targetType.Kind == TypeKind.TypeParameter) + { var rr = resolver.ResolveCast(targetType, arg.ResolveResult); - if (rr.IsError) { + if (rr.IsError) + { // C# 6.2.7 Explicit conversions involving type parameters: // if we can't directly convert to a type parameter, // try via its effective base class. arg = arg.ConvertTo(((ITypeParameter)targetType).EffectiveBaseClass, this); } - } else { + } + else + { // Before unboxing arg must be a object arg = arg.ConvertTo(compilation.FindType(KnownTypeCode.Object), this); } @@ -2379,7 +2745,7 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(new ConversionResolveResult(targetType, arg.ResolveResult, Conversion.UnboxingConversion)); } - + protected internal override TranslatedExpression VisitUnbox(Unbox inst, TranslationContext context) { var arg = Translate(inst.Argument); @@ -2394,10 +2760,14 @@ namespace ICSharpCode.Decompiler.CSharp { IType targetType = inst.Type; var arg = Translate(inst.Argument, typeHint: targetType); - if (settings.NativeIntegers && !arg.Type.Equals(targetType)) { - if (targetType.IsKnownType(KnownTypeCode.IntPtr)) { + if (settings.NativeIntegers && !arg.Type.Equals(targetType)) + { + if (targetType.IsKnownType(KnownTypeCode.IntPtr)) + { targetType = SpecialType.NInt; - } else if (targetType.IsKnownType(KnownTypeCode.UIntPtr)) { + } + else if (targetType.IsKnownType(KnownTypeCode.UIntPtr)) + { targetType = SpecialType.NUInt; } } @@ -2407,7 +2777,7 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(new ConversionResolveResult(obj, arg.ResolveResult, Conversion.BoxingConversion)); } - + protected internal override TranslatedExpression VisitCastClass(CastClass inst, TranslationContext context) { return Translate(inst.Argument).ConvertTo(inst.Type, this); @@ -2424,11 +2794,12 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(new TypeResolveResult(compilation.FindType(new TopLevelTypeName("System", "RuntimeArgumentHandle")))); } - + protected internal override TranslatedExpression VisitMakeRefAny(MakeRefAny inst, TranslationContext context) { var arg = Translate(inst.Argument).Expression; - if (arg is DirectionExpression) { + if (arg is DirectionExpression) + { arg = ((DirectionExpression)arg).Expression; } return new UndocumentedExpression { @@ -2438,7 +2809,7 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(new TypeResolveResult(compilation.FindType(new TopLevelTypeName("System", "TypedReference")))); } - + protected internal override TranslatedExpression VisitRefAnyType(RefAnyType inst, TranslationContext context) { return new MemberReferenceExpression(new UndocumentedExpression { @@ -2448,7 +2819,7 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(new TypeResolveResult(compilation.FindType(new TopLevelTypeName("System", "RuntimeTypeHandle")))); } - + protected internal override TranslatedExpression VisitRefAnyValue(RefAnyValue inst, TranslationContext context) { var expr = new UndocumentedExpression { @@ -2458,10 +2829,11 @@ namespace ICSharpCode.Decompiler.CSharp return new DirectionExpression(FieldDirection.Ref, expr.WithILInstruction(inst)).WithoutILInstruction() .WithRR(new ByReferenceResolveResult(inst.Type, ReferenceKind.Ref)); } - + protected internal override TranslatedExpression VisitBlock(Block block, TranslationContext context) { - switch (block.Kind) { + switch (block.Kind) + { case BlockKind.ArrayInitializer: return TranslateArrayInitializer(block); case BlockKind.StackAllocInitializer: @@ -2487,7 +2859,8 @@ namespace ICSharpCode.Decompiler.CSharp private TranslatedExpression TranslateSetterCallAssignment(Block block) { - if (!block.MatchInlineAssignBlock(out var call, out var value)) { + if (!block.MatchInlineAssignBlock(out var call, out var value)) + { // should never happen unless the ILAst is invalid return ErrorExpression("Error: MatchInlineAssignBlock() returned false"); } @@ -2509,7 +2882,8 @@ namespace ICSharpCode.Decompiler.CSharp InitializedObjectResolveResult initObjRR; TranslatedExpression expr; // Detect type of initializer - switch (stloc.Value) { + switch (stloc.Value) + { case NewObj newObjInst: initObjRR = new InitializedObjectResolveResult(newObjInst.Method.DeclaringType); expr = new CallBuilder(this, typeSystem, settings).Build(newObjInst); @@ -2533,9 +2907,11 @@ namespace ICSharpCode.Decompiler.CSharp elementsStack.Push(elements); List currentPath = null; var indexVariables = new Dictionary(); - foreach (var inst in block.Instructions.Skip(1)) { + foreach (var inst in block.Instructions.Skip(1)) + { // Collect indexer variables (for C# 6 dictionary initializers) - if (inst is StLoc indexStore) { + if (inst is StLoc indexStore) + { indexVariables.Add(indexStore.Variable, indexStore.Value); continue; } @@ -2543,16 +2919,21 @@ namespace ICSharpCode.Decompiler.CSharp var info = IL.Transforms.AccessPathElement.GetAccessPath(inst, initObjRR.Type, settings: settings); // This should not happen, because the IL transform should not create invalid access paths, // but we leave it here as sanity check. - if (info.Kind == IL.Transforms.AccessPathKind.Invalid) continue; + if (info.Kind == IL.Transforms.AccessPathKind.Invalid) + continue; // Calculate "difference" to previous path - if (currentPath == null) { + if (currentPath == null) + { currentPath = info.Path; - } else { + } + else + { int minLen = Math.Min(currentPath.Count, info.Path.Count); int firstDifferenceIndex = 0; while (firstDifferenceIndex < minLen && info.Path[firstDifferenceIndex] == currentPath[firstDifferenceIndex]) firstDifferenceIndex++; - while (elementsStack.Count - 1 > firstDifferenceIndex) { + while (elementsStack.Count - 1 > firstDifferenceIndex) + { var methodElement = currentPath[elementsStack.Count - 1]; var pathElement = currentPath[elementsStack.Count - 2]; var values = elementsStack.Pop(); @@ -2565,7 +2946,8 @@ namespace ICSharpCode.Decompiler.CSharp elementsStack.Push(new List()); var lastElement = currentPath.Last(); var memberRR = new MemberResolveResult(initObjRR, lastElement.Member); - switch (info.Kind) { + switch (info.Kind) + { case IL.Transforms.AccessPathKind.Adder: Debug.Assert(lastElement.Member is IMethod); elementsStack.Peek().Add( @@ -2576,7 +2958,8 @@ namespace ICSharpCode.Decompiler.CSharp break; case IL.Transforms.AccessPathKind.Setter: Debug.Assert(lastElement.Member is IProperty || lastElement.Member is IField); - if (lastElement.Indices?.Length > 0) { + if (lastElement.Indices?.Length > 0) + { var property = (IProperty)lastElement.Member; Debug.Assert(property.IsIndexer); elementsStack.Peek().Add( @@ -2584,7 +2967,9 @@ namespace ICSharpCode.Decompiler.CSharp .BuildDictionaryInitializerExpression(lastElement.OpCode, property.Setter, initObjRR, GetIndices(lastElement.Indices, indexVariables).ToList(), info.Values.Single()) .WithILInstruction(inst) ); - } else { + } + else + { var value = Translate(info.Values.Single(), typeHint: memberRR.Type) .ConvertTo(memberRR.Type, this, allowImplicitConversion: true); var assignment = new NamedExpression(lastElement.Member.Name, value) @@ -2594,7 +2979,8 @@ namespace ICSharpCode.Decompiler.CSharp break; } } - while (elementsStack.Count > 1) { + while (elementsStack.Count > 1) + { var methodElement = currentPath[elementsStack.Count - 1]; var pathElement = currentPath[elementsStack.Count - 2]; var values = elementsStack.Pop(); @@ -2609,7 +2995,8 @@ namespace ICSharpCode.Decompiler.CSharp IEnumerable GetIndices(IEnumerable indices, Dictionary indexVariables) { - foreach (var inst in indices) { + foreach (var inst in indices) + { if (inst is LdLoc ld && indexVariables.TryGetValue(ld.Variable, out var newInst)) yield return newInst; else @@ -2622,29 +3009,40 @@ namespace ICSharpCode.Decompiler.CSharp Dictionary indexVariables) { TranslatedExpression value; - if (memberPath.Member is IMethod method && method.Name == "Add") { + if (memberPath.Member is IMethod method && method.Name == "Add") + { value = new ArrayInitializerExpression(values.Select(v => v.Expression)) .WithRR(new ResolveResult(SpecialType.UnknownType)) .WithoutILInstruction(); - } else if (values.Count == 1 && !(values[0].Expression is AssignmentExpression || values[0].Expression is NamedExpression)) { + } + else if (values.Count == 1 && !(values[0].Expression is AssignmentExpression || values[0].Expression is NamedExpression)) + { value = values[0]; - } else { + } + else + { value = new ArrayInitializerExpression(values.Select(v => v.Expression)) .WithRR(new ResolveResult(SpecialType.UnknownType)) .WithoutILInstruction(); } - if (valuePath.Indices?.Length > 0) { + if (valuePath.Indices?.Length > 0) + { Expression index; - if (memberPath.Member is IProperty property) { + if (memberPath.Member is IProperty property) + { index = new CallBuilder(this, typeSystem, settings) .BuildDictionaryInitializerExpression(valuePath.OpCode, property.Setter, rr, GetIndices(valuePath.Indices, indexVariables).ToList()); - } else { + } + else + { index = new IndexerExpression(null, GetIndices(valuePath.Indices, indexVariables).Select(i => Translate(i).Expression)); } return new AssignmentExpression(index, value) .WithRR(new MemberResolveResult(rr, memberPath.Member)) .WithoutILInstruction(); - } else { + } + else + { return new NamedExpression(valuePath.Member.Name, value) .WithRR(new MemberResolveResult(rr, valuePath.Member)) .WithoutILInstruction(); @@ -2685,14 +3083,16 @@ namespace ICSharpCode.Decompiler.CSharp container.Push(root); var elementResolveResults = new List(); - for (int i = 1; i < block.Instructions.Count; i++) { + for (int i = 1; i < block.Instructions.Count; i++) + { if (!block.Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out IType t) || !type.Equals(t)) throw new ArgumentException("given Block is invalid!"); if (!target.MatchLdElema(out t, out ILInstruction array) || !type.Equals(t)) throw new ArgumentException("given Block is invalid!"); if (!array.MatchLdLoc(out ILVariable v) || v != final.Variable) throw new ArgumentException("given Block is invalid!"); - while (container.Count < dimensions) { + while (container.Count < dimensions) + { var aie = new ArrayInitializerExpression(); var parentInitializer = container.Peek(); if (parentInitializer.CurrentElementCount > 0) @@ -2703,10 +3103,13 @@ namespace ICSharpCode.Decompiler.CSharp } TranslatedExpression val; var old = astBuilder.UseSpecialConstants; - try { + try + { astBuilder.UseSpecialConstants = !type.IsCSharpPrimitiveIntegerType() && !type.IsKnownType(KnownTypeCode.Decimal); val = Translate(value, typeHint: type).ConvertTo(type, this, allowImplicitConversion: true); - } finally { + } + finally + { astBuilder.UseSpecialConstants = old; } var currentInitializer = container.Peek(); @@ -2715,21 +3118,28 @@ namespace ICSharpCode.Decompiler.CSharp currentInitializer.Expression.Elements.Add(val); currentInitializer.CurrentElementCount++; elementResolveResults.Add(val.ResolveResult); - while (container.Count > 0 && container.Peek().CurrentElementCount == dimensionSizes[container.Count - 1]) { + while (container.Count > 0 && container.Peek().CurrentElementCount == dimensionSizes[container.Count - 1]) + { container.Pop(); } } ArraySpecifier[] additionalSpecifiers; AstType typeExpression; - if (settings.AnonymousTypes && type.ContainsAnonymousType()) { + if (settings.AnonymousTypes && type.ContainsAnonymousType()) + { typeExpression = null; additionalSpecifiers = new[] { new ArraySpecifier() }; - } else { + } + else + { typeExpression = ConvertType(type); - if (typeExpression is ComposedType compType && compType.ArraySpecifiers.Count > 0) { + if (typeExpression is ComposedType compType && compType.ArraySpecifiers.Count > 0) + { additionalSpecifiers = compType.ArraySpecifiers.Select(a => (ArraySpecifier)a.Clone()).ToArray(); compType.ArraySpecifiers.Clear(); - } else { + } + else + { additionalSpecifiers = Empty.Array; } } @@ -2754,10 +3164,12 @@ namespace ICSharpCode.Decompiler.CSharp IType elementType; if (block.Instructions.Count < 2 || !block.Instructions[1].MatchStObj(out _, out _, out var t)) throw new ArgumentException("given Block is invalid!"); - if (typeHint is PointerType pt && !TypeUtils.IsCompatibleTypeForMemoryAccess(t, pt.ElementType)) { + if (typeHint is PointerType pt && !TypeUtils.IsCompatibleTypeForMemoryAccess(t, pt.ElementType)) + { typeHint = new PointerType(t); } - switch (stloc.Value) { + switch (stloc.Value) + { case LocAlloc locAlloc: stackAllocExpression = TranslateLocAlloc(locAlloc, typeHint, out elementType); break; @@ -2771,14 +3183,16 @@ namespace ICSharpCode.Decompiler.CSharp var pointerType = new PointerType(elementType); long expectedOffset = 0; - for (int i = 1; i < block.Instructions.Count; i++) { + for (int i = 1; i < block.Instructions.Count; i++) + { // stobj type(binary.add.i(ldloc I_0, conv i4->i (ldc.i4 offset)), value) if (!block.Instructions[i].MatchStObj(out var target, out var value, out t) || !TypeUtils.IsCompatibleTypeForMemoryAccess(elementType, t)) throw new ArgumentException("given Block is invalid!"); long offset = 0; target = target.UnwrapConv(ConversionKind.StopGCTracking); - if (!target.MatchLdLoc(stloc.Variable)) { + if (!target.MatchLdLoc(stloc.Variable)) + { if (!target.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out var left, out var right)) throw new ArgumentException("given Block is invalid!"); var binary = (BinaryNumericInstruction)target; @@ -2789,7 +3203,8 @@ namespace ICSharpCode.Decompiler.CSharp if (!offsetInst.MatchLdcI(out offset)) throw new ArgumentException("given Block is invalid!"); } - while (expectedOffset < offset) { + while (expectedOffset < offset) + { initializer.Elements.Add(Translate(IL.Transforms.TransformArrayInitializers.GetNullExpression(elementType), typeHint: elementType)); expectedOffset++; } @@ -2809,32 +3224,44 @@ namespace ICSharpCode.Decompiler.CSharp TranslatedExpression AdjustConstantExpressionToType(TranslatedExpression expr, IType typeHint) { var newRR = AdjustConstantToType(expr.ResolveResult, typeHint); - if (newRR == expr.ResolveResult) { + if (newRR == expr.ResolveResult) + { return expr; - } else { + } + else + { return ConvertConstantValue(newRR, allowImplicitConversion: true).WithILInstruction(expr.ILInstructions); } } - + private ResolveResult AdjustConstantToType(ResolveResult rr, IType typeHint) { - if (!rr.IsCompileTimeConstant) { + if (!rr.IsCompileTimeConstant) + { return rr; } typeHint = NullableType.GetUnderlyingType(typeHint); - if (rr.Type.Equals(typeHint)) { + if (rr.Type.Equals(typeHint)) + { return rr; } // Convert to type hint, if this is possible without loss of accuracy - if (typeHint.IsKnownType(KnownTypeCode.Boolean)) { - if (object.Equals(rr.ConstantValue, 0) || object.Equals(rr.ConstantValue, 0u)) { + if (typeHint.IsKnownType(KnownTypeCode.Boolean)) + { + if (object.Equals(rr.ConstantValue, 0) || object.Equals(rr.ConstantValue, 0u)) + { rr = new ConstantResolveResult(typeHint, false); - } else if (object.Equals(rr.ConstantValue, 1) || object.Equals(rr.ConstantValue, 1u)) { + } + else if (object.Equals(rr.ConstantValue, 1) || object.Equals(rr.ConstantValue, 1u)) + { rr = new ConstantResolveResult(typeHint, true); } - } else if (typeHint.Kind == TypeKind.Enum || typeHint.IsKnownType(KnownTypeCode.Char) || typeHint.IsCSharpSmallIntegerType()) { + } + else if (typeHint.Kind == TypeKind.Enum || typeHint.IsKnownType(KnownTypeCode.Char) || typeHint.IsCSharpSmallIntegerType()) + { var castRR = resolver.WithCheckForOverflow(true).ResolveCast(typeHint, rr); - if (castRR.IsCompileTimeConstant && !castRR.IsError) { + if (castRR.IsCompileTimeConstant && !castRR.IsError) + { rr = castRR; } } @@ -2847,23 +3274,35 @@ namespace ICSharpCode.Decompiler.CSharp var fallback = Translate(inst.FallbackInst); fallback = AdjustConstantExpressionToType(fallback, value.Type); var rr = resolver.ResolveBinaryOperator(BinaryOperatorType.NullCoalescing, value.ResolveResult, fallback.ResolveResult); - if (rr.IsError) { + if (rr.IsError) + { IType targetType; - if (fallback.Expression is ThrowExpression && fallback.Type.Equals(SpecialType.NoType)) { + if (fallback.Expression is ThrowExpression && fallback.Type.Equals(SpecialType.NoType)) + { targetType = NullableType.GetUnderlyingType(value.Type); - } else if (!value.Type.Equals(SpecialType.NullType) && !fallback.Type.Equals(SpecialType.NullType) && !value.Type.Equals(fallback.Type)) { + } + else if (!value.Type.Equals(SpecialType.NullType) && !fallback.Type.Equals(SpecialType.NullType) && !value.Type.Equals(fallback.Type)) + { targetType = compilation.FindType(inst.UnderlyingResultType.ToKnownTypeCode()); - } else { + } + else + { targetType = value.Type.Equals(SpecialType.NullType) ? fallback.Type : value.Type; } - if (inst.Kind != NullCoalescingKind.Ref) { + if (inst.Kind != NullCoalescingKind.Ref) + { value = value.ConvertTo(NullableType.Create(compilation, targetType), this); - } else { + } + else + { value = value.ConvertTo(targetType, this); } - if (inst.Kind == NullCoalescingKind.Nullable) { + if (inst.Kind == NullCoalescingKind.Nullable) + { value = value.ConvertTo(NullableType.Create(compilation, targetType), this); - } else { + } + else + { fallback = fallback.ConvertTo(targetType, this); } rr = new ResolveResult(targetType); @@ -2881,11 +3320,14 @@ namespace ICSharpCode.Decompiler.CSharp BinaryOperatorType op = BinaryOperatorType.Any; TranslatedExpression rhs = default(TranslatedExpression); - if (inst.MatchLogicAnd(out var lhsInst, out var rhsInst) && !rhsInst.MatchLdcI4(1)) { + if (inst.MatchLogicAnd(out var lhsInst, out var rhsInst) && !rhsInst.MatchLdcI4(1)) + { op = BinaryOperatorType.ConditionalAnd; Debug.Assert(rhsInst == inst.TrueInst); rhs = trueBranch; - } else if (inst.MatchLogicOr(out lhsInst, out rhsInst) && !rhsInst.MatchLdcI4(0)) { + } + else if (inst.MatchLogicOr(out lhsInst, out rhsInst) && !rhsInst.MatchLdcI4(0)) + { op = BinaryOperatorType.ConditionalOr; Debug.Assert(rhsInst == inst.FalseInst); rhs = falseBranch; @@ -2893,7 +3335,8 @@ namespace ICSharpCode.Decompiler.CSharp // ILAst LogicAnd/LogicOr can return a different value than 0 or 1 // if the rhs is evaluated. // We can only correctly translate it to C# if the rhs is of type boolean: - if (op != BinaryOperatorType.Any && (rhs.Type.IsKnownType(KnownTypeCode.Boolean) || IfInstruction.IsInConditionSlot(inst))) { + if (op != BinaryOperatorType.Any && (rhs.Type.IsKnownType(KnownTypeCode.Boolean) || IfInstruction.IsInConditionSlot(inst))) + { rhs = rhs.ConvertToBoolean(this); return new BinaryOperatorExpression(condition, op, rhs) .WithILInstruction(inst) @@ -2905,34 +3348,48 @@ namespace ICSharpCode.Decompiler.CSharp falseBranch = AdjustConstantExpressionToType(falseBranch, trueBranch.Type); var rr = resolver.ResolveConditional(condition.ResolveResult, trueBranch.ResolveResult, falseBranch.ResolveResult); - if (rr.IsError) { + if (rr.IsError) + { IType targetType; - if (!trueBranch.Type.Equals(SpecialType.NullType) && !falseBranch.Type.Equals(SpecialType.NullType) && !trueBranch.Type.Equals(falseBranch.Type)) { + if (!trueBranch.Type.Equals(SpecialType.NullType) && !falseBranch.Type.Equals(SpecialType.NullType) && !trueBranch.Type.Equals(falseBranch.Type)) + { targetType = typeInference.GetBestCommonType(new[] { trueBranch.ResolveResult, falseBranch.ResolveResult }, out bool success); - if (!success || targetType.GetStackType() != inst.ResultType) { + if (!success || targetType.GetStackType() != inst.ResultType) + { // Figure out the target type based on inst.ResultType. - if (inst.ResultType == StackType.Ref) { + if (inst.ResultType == StackType.Ref) + { // targetType should be a ref-type - if (trueBranch.Type.Kind == TypeKind.ByReference) { + if (trueBranch.Type.Kind == TypeKind.ByReference) + { targetType = trueBranch.Type; - } else if (falseBranch.Type.Kind == TypeKind.ByReference) { + } + else if (falseBranch.Type.Kind == TypeKind.ByReference) + { targetType = falseBranch.Type; - } else { + } + else + { // fall back to 'ref byte' if we can't determine a referenced type otherwise targetType = new ByReferenceType(compilation.FindType(KnownTypeCode.Byte)); } - } else { + } + else + { targetType = compilation.FindType(inst.ResultType.ToKnownTypeCode()); } } - } else { + } + else + { targetType = trueBranch.Type.Equals(SpecialType.NullType) ? falseBranch.Type : trueBranch.Type; } trueBranch = trueBranch.ConvertTo(targetType, this); falseBranch = falseBranch.ConvertTo(targetType, this); rr = new ResolveResult(targetType); } - if (rr.Type.Kind == TypeKind.ByReference) { + if (rr.Type.Kind == TypeKind.ByReference) + { // C# conditional ref looks like this: // ref (arr != null ? ref trueBranch : ref falseBranch); var conditionalResolveResult = new ResolveResult(((ByReferenceType)rr.Type).ElementType); @@ -2941,7 +3398,9 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(conditionalResolveResult) ).WithoutILInstruction().WithRR(new ByReferenceResolveResult(conditionalResolveResult, ReferenceKind.Ref)); - } else { + } + else + { return new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression) .WithILInstruction(inst) .WithRR(rr); @@ -2951,9 +3410,12 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitSwitchInstruction(SwitchInstruction inst, TranslationContext context) { TranslatedExpression value; - if (inst.Value is StringToInt strToInt) { + if (inst.Value is StringToInt strToInt) + { value = Translate(strToInt.Argument); - } else { + } + else + { strToInt = null; value = Translate(inst.Value); } @@ -2962,20 +3424,27 @@ namespace ICSharpCode.Decompiler.CSharp SwitchExpression switchExpr = new SwitchExpression(); switchExpr.Expression = value; IType resultType; - if (context.TypeHint.Kind != TypeKind.Unknown && context.TypeHint.GetStackType() == inst.ResultType) { + if (context.TypeHint.Kind != TypeKind.Unknown && context.TypeHint.GetStackType() == inst.ResultType) + { resultType = context.TypeHint; - } else { + } + else + { resultType = compilation.FindType(inst.ResultType.ToKnownTypeCode()); } - - foreach (var section in inst.Sections) { + + foreach (var section in inst.Sections) + { if (section == defaultSection) continue; var ses = new SwitchExpressionSection(); - if (section.HasNullLabel) { + if (section.HasNullLabel) + { Debug.Assert(section.Labels.IsEmpty); ses.Pattern = new NullReferenceExpression(); - } else { + } + else + { long val = section.Labels.Values.Single(); var rr = statementBuilder.CreateTypedCaseLabel(val, value.Type, strToInt?.Map).Single(); ses.Pattern = astBuilder.ConvertConstantValue(rr); @@ -3011,20 +3480,26 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitAwait(Await inst, TranslationContext context) { IType expectedType = null; - if (inst.GetAwaiterMethod != null) { - if (inst.GetAwaiterMethod.IsStatic) { + if (inst.GetAwaiterMethod != null) + { + if (inst.GetAwaiterMethod.IsStatic) + { expectedType = inst.GetAwaiterMethod.Parameters.FirstOrDefault()?.Type; - } else { + } + else + { expectedType = inst.GetAwaiterMethod.DeclaringType; } } var value = Translate(inst.Value, typeHint: expectedType); - if (value.Expression is DirectionExpression) { + if (value.Expression is DirectionExpression) + { // we can deference the managed reference by stripping away the 'ref' value = value.UnwrapChild(((DirectionExpression)value.Expression).Expression); } - if (expectedType != null) { + if (expectedType != null) + { value = value.ConvertTo(expectedType, this, allowImplicitConversion: true); } return new UnaryOperatorExpression(UnaryOperatorType.Await, value.Expression) @@ -3036,7 +3511,8 @@ namespace ICSharpCode.Decompiler.CSharp { var arg = Translate(inst.Argument); IType type = arg.Type; - if (NullableType.IsNonNullableValueType(type)) { + if (NullableType.IsNonNullableValueType(type)) + { type = NullableType.Create(compilation, type); } return new UnaryOperatorExpression(UnaryOperatorType.NullConditionalRewrap, arg) @@ -3047,7 +3523,8 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitNullableUnwrap(NullableUnwrap inst, TranslationContext context) { var arg = Translate(inst.Argument); - if (inst.RefInput && !inst.RefOutput && arg.Expression is DirectionExpression dir) { + if (inst.RefInput && !inst.RefOutput && arg.Expression is DirectionExpression dir) + { arg = arg.UnwrapChild(dir.Expression); } return new UnaryOperatorExpression(UnaryOperatorType.NullConditional, arg) @@ -3118,20 +3595,23 @@ namespace ICSharpCode.Decompiler.CSharp Debug.Assert(!argumentInfo.HasFlag(CSharpArgumentInfoFlags.NamedArgument)); Debug.Assert(!argumentInfo.HasFlag(CSharpArgumentInfoFlags.IsOut)); - if (argumentInfo.HasFlag(CSharpArgumentInfoFlags.IsStaticType) && IL.Transforms.TransformExpressionTrees.MatchGetTypeFromHandle(inst, out var callTargetType)) { + if (argumentInfo.HasFlag(CSharpArgumentInfoFlags.IsStaticType) && IL.Transforms.TransformExpressionTrees.MatchGetTypeFromHandle(inst, out var callTargetType)) + { return new TypeReferenceExpression(ConvertType(callTargetType)) .WithoutILInstruction() .WithRR(new TypeResolveResult(callTargetType)); } IType targetType = SpecialType.Dynamic; - if (argumentInfo.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType)) { + if (argumentInfo.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType)) + { targetType = argumentInfo.CompileTimeType; } var translatedTarget = Translate(inst, targetType).ConvertTo(targetType, this); - if (argumentInfo.HasFlag(CSharpArgumentInfoFlags.IsRef) && translatedTarget.Expression is DirectionExpression) { + if (argumentInfo.HasFlag(CSharpArgumentInfoFlags.IsRef) && translatedTarget.Expression is DirectionExpression) + { // (ref x).member => x.member translatedTarget = translatedTarget.UnwrapChild(((DirectionExpression)translatedTarget).Expression); } @@ -3141,7 +3621,8 @@ namespace ICSharpCode.Decompiler.CSharp IEnumerable TranslateDynamicArguments(IEnumerable arguments, IEnumerable argumentInfo) { - foreach (var (argument, info) in arguments.Zip(argumentInfo)) { + foreach (var (argument, info) in arguments.Zip(argumentInfo)) + { yield return TranslateDynamicArgument(argument, info); } } @@ -3151,17 +3632,21 @@ namespace ICSharpCode.Decompiler.CSharp Debug.Assert(!info.HasFlag(CSharpArgumentInfoFlags.IsStaticType)); IType typeHint = SpecialType.Dynamic; - if (info.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType)) { + if (info.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType)) + { typeHint = info.CompileTimeType; } var translatedExpression = Translate(argument, typeHint); - if (!(typeHint.Equals(SpecialType.Dynamic) && translatedExpression.Type.Equals(SpecialType.NullType))) { + if (!(typeHint.Equals(SpecialType.Dynamic) && translatedExpression.Type.Equals(SpecialType.NullType))) + { translatedExpression = translatedExpression.ConvertTo(typeHint, this); } - if (info.HasFlag(CSharpArgumentInfoFlags.IsOut)) { + if (info.HasFlag(CSharpArgumentInfoFlags.IsOut)) + { translatedExpression = ChangeDirectionExpressionTo(translatedExpression, ReferenceKind.Out); } - if (info.HasFlag(CSharpArgumentInfoFlags.NamedArgument) && !string.IsNullOrWhiteSpace(info.Name)) { + if (info.HasFlag(CSharpArgumentInfoFlags.NamedArgument) && !string.IsNullOrWhiteSpace(info.Name)) + { translatedExpression = new TranslatedExpression(new NamedArgumentExpression(info.Name, translatedExpression.Expression)); } @@ -3206,7 +3691,8 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitDynamicBinaryOperatorInstruction(DynamicBinaryOperatorInstruction inst, TranslationContext context) { - switch (inst.Operation) { + switch (inst.Operation) + { case ExpressionType.Add: case ExpressionType.AddAssign: return CreateBinaryOperator(BinaryOperatorType.Add, isChecked: inst.BinderFlags.HasFlag(CSharpBinderFlags.CheckedContext)); @@ -3278,11 +3764,16 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitDynamicLogicOperatorInstruction(DynamicLogicOperatorInstruction inst, TranslationContext context) { BinaryOperatorType operatorType; - if (inst.Operation == ExpressionType.AndAlso) { + if (inst.Operation == ExpressionType.AndAlso) + { operatorType = BinaryOperatorType.ConditionalAnd; - } else if (inst.Operation == ExpressionType.OrElse) { + } + else if (inst.Operation == ExpressionType.OrElse) + { operatorType = BinaryOperatorType.ConditionalOr; - } else { + } + else + { Debug.Fail("Unknown operation for DynamicLogicOperatorInstruction"); return base.VisitDynamicLogicOperatorInstruction(inst, context); } @@ -3294,7 +3785,8 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitDynamicUnaryOperatorInstruction(DynamicUnaryOperatorInstruction inst, TranslationContext context) { - switch (inst.Operation) { + switch (inst.Operation) + { case ExpressionType.Not: return CreateUnaryOperator(UnaryOperatorType.Not); case ExpressionType.Decrement: @@ -3310,10 +3802,13 @@ namespace ICSharpCode.Decompiler.CSharp case ExpressionType.IsTrue: var operand = TranslateDynamicArgument(inst.Operand, inst.OperandArgumentInfo); Expression expr; - if (inst.SlotInfo == IfInstruction.ConditionSlot) { + if (inst.SlotInfo == IfInstruction.ConditionSlot) + { // We rely on the context implicitly invoking "operator true". expr = new UnaryOperatorExpression(UnaryOperatorType.IsTrue, operand); - } else { + } + else + { // Create a dummy conditional to ensure "operator true" will be invoked. expr = new ConditionalExpression(operand, new PrimitiveExpression(true), new PrimitiveExpression(false)); } @@ -3344,9 +3839,12 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitDynamicCompoundAssign(DynamicCompoundAssign inst, TranslationContext context) { ExpressionWithResolveResult target; - if (inst.TargetKind == CompoundTargetKind.Address) { + if (inst.TargetKind == CompoundTargetKind.Address) + { target = LdObj(inst.Target, SpecialType.Dynamic); - } else { + } + else + { target = TranslateDynamicArgument(inst.Target, inst.TargetArgumentInfo); } var value = TranslateDynamicArgument(inst.Value, inst.ValueArgumentInfo); @@ -3378,20 +3876,24 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitCallIndirect(CallIndirect inst, TranslationContext context) { - if (inst.IsInstance) { + if (inst.IsInstance) + { return ErrorExpression("calli with instance method signature not supportd"); } var ty = new FunctionPointerType(); - if (inst.CallingConvention != System.Reflection.Metadata.SignatureCallingConvention.Default) { + if (inst.CallingConvention != System.Reflection.Metadata.SignatureCallingConvention.Default) + { ty.CallingConvention = inst.CallingConvention.ToString().ToLowerInvariant(); } - foreach (var parameterType in inst.ParameterTypes) { + foreach (var parameterType in inst.ParameterTypes) + { ty.TypeArguments.Add(astBuilder.ConvertType(parameterType)); } ty.TypeArguments.Add(astBuilder.ConvertType(inst.ReturnType)); var functionPointer = Translate(inst.FunctionPointer); var invocation = new InvocationExpression(new CastExpression(ty, functionPointer)); - foreach (var (arg, paramType) in inst.Arguments.Zip(inst.ParameterTypes)) { + foreach (var (arg, paramType) in inst.Arguments.Zip(inst.ParameterTypes)) + { invocation.Arguments.Add(Translate(arg, typeHint: paramType).ConvertTo(paramType, this, allowImplicitConversion: true)); } return invocation.WithRR(new ResolveResult(inst.ReturnType)).WithILInstruction(inst); @@ -3409,7 +3911,8 @@ namespace ICSharpCode.Decompiler.CSharp Dictionary conversionMapping = new Dictionary(); - foreach (var conv in inst.Conversions.Instructions) { + foreach (var conv in inst.Conversions.Instructions) + { if (!DeconstructInstruction.IsConversionStLoc(conv, out var outputVariable, out var inputVariable)) continue; conversionMapping.Add(inputVariable, outputVariable); @@ -3424,17 +3927,24 @@ namespace ICSharpCode.Decompiler.CSharp TupleExpression ConstructTuple(MatchInstruction matchInstruction) { var expr = new TupleExpression(); - foreach (var subPattern in matchInstruction.SubPatterns.Cast()) { - if (subPattern.IsVar) { - if (subPattern.HasDesignator) { - if (!conversionMapping.TryGetValue(subPattern.Variable, out ILVariable value)) { + foreach (var subPattern in matchInstruction.SubPatterns.Cast()) + { + if (subPattern.IsVar) + { + if (subPattern.HasDesignator) + { + if (!conversionMapping.TryGetValue(subPattern.Variable, out ILVariable value)) + { value = subPattern.Variable; } expr.Elements.Add(ConstructAssignmentTarget(assignments[assignmentPos], value)); assignmentPos++; - } else + } + else expr.Elements.Add(new IdentifierExpression("_")); - } else { + } + else + { expr.Elements.Add(ConstructTuple(subPattern)); } } @@ -3443,12 +3953,14 @@ namespace ICSharpCode.Decompiler.CSharp TranslatedExpression ConstructAssignmentTarget(ILInstruction assignment, ILVariable value) { - switch (assignment) { + switch (assignment) + { case StLoc stloc: Debug.Assert(stloc.Value.MatchLdLoc(value)); break; case CallInstruction call: - for (int i = 0; i < call.Arguments.Count - 1; i++) { + for (int i = 0; i < call.Arguments.Count - 1; i++) + { ReplaceAssignmentTarget(call.Arguments[i]); } Debug.Assert(call.Arguments.Last().MatchLdLoc(value)); @@ -3482,10 +3994,12 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitInvalidBranch(InvalidBranch inst, TranslationContext context) { string message = "Error"; - if (inst.StartILOffset != 0) { + if (inst.StartILOffset != 0) + { message += $" near IL_{inst.StartILOffset:x4}"; } - if (!string.IsNullOrEmpty(inst.Message)) { + if (!string.IsNullOrEmpty(inst.Message)) + { message += ": " + inst.Message; } return ErrorExpression(message); @@ -3494,10 +4008,12 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitInvalidExpression(InvalidExpression inst, TranslationContext context) { string message = "Error"; - if (inst.StartILOffset != 0) { + if (inst.StartILOffset != 0) + { message += $" near IL_{inst.StartILOffset:x4}"; } - if (!string.IsNullOrEmpty(inst.Message)) { + if (!string.IsNullOrEmpty(inst.Message)) + { message += ": " + inst.Message; } return ErrorExpression(message); @@ -3507,7 +4023,7 @@ namespace ICSharpCode.Decompiler.CSharp { return ErrorExpression("OpCode not supported: " + inst.OpCode); } - + static TranslatedExpression ErrorExpression(string message) { var e = new ErrorExpression(); diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs index 71506af61..c966c2c87 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs @@ -62,9 +62,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor if (entityDecl != null) PrintModifiers(entityDecl.Modifiers, writer); - if ((ConversionFlags & ConversionFlags.ShowDefinitionKeyword) == ConversionFlags.ShowDefinitionKeyword) { - if (node is TypeDeclaration) { - switch (((TypeDeclaration)node).ClassType) { + if ((ConversionFlags & ConversionFlags.ShowDefinitionKeyword) == ConversionFlags.ShowDefinitionKeyword) + { + if (node is TypeDeclaration) + { + switch (((TypeDeclaration)node).ClassType) + { case ClassType.Class: writer.WriteKeyword(Roles.ClassKeyword, "class"); break; @@ -81,22 +84,30 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor throw new Exception("Invalid value for ClassType"); } writer.Space(); - } else if (node is DelegateDeclaration) { + } + else if (node is DelegateDeclaration) + { writer.WriteKeyword(Roles.DelegateKeyword, "delegate"); writer.Space(); - } else if (node is EventDeclaration) { + } + else if (node is EventDeclaration) + { writer.WriteKeyword(EventDeclaration.EventKeywordRole, "event"); writer.Space(); - } else if (node is NamespaceDeclaration) { + } + else if (node is NamespaceDeclaration) + { writer.WriteKeyword(Roles.NamespaceKeyword, "namespace"); writer.Space(); } } if ((ConversionFlags & ConversionFlags.PlaceReturnTypeAfterParameterList) != ConversionFlags.PlaceReturnTypeAfterParameterList - && (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) { + && (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) + { var rt = node.GetChildByRole(Roles.Type); - if (!rt.IsNull) { + if (!rt.IsNull) + { rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy)); writer.Space(); } @@ -109,19 +120,26 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor else writer.WriteIdentifier(Identifier.Create(symbol.Name)); - if ((ConversionFlags & ConversionFlags.ShowParameterList) == ConversionFlags.ShowParameterList && HasParameters(symbol)) { + if ((ConversionFlags & ConversionFlags.ShowParameterList) == ConversionFlags.ShowParameterList && HasParameters(symbol)) + { writer.WriteToken(symbol.SymbolKind == SymbolKind.Indexer ? Roles.LBracket : Roles.LPar, symbol.SymbolKind == SymbolKind.Indexer ? "[" : "("); bool first = true; - foreach (var param in node.GetChildrenByRole(Roles.Parameter)) { - if ((ConversionFlags & ConversionFlags.ShowParameterModifiers) == 0) { + foreach (var param in node.GetChildrenByRole(Roles.Parameter)) + { + if ((ConversionFlags & ConversionFlags.ShowParameterModifiers) == 0) + { param.ParameterModifier = ParameterModifier.None; } - if ((ConversionFlags & ConversionFlags.ShowParameterDefaultValues) == 0) { + if ((ConversionFlags & ConversionFlags.ShowParameterDefaultValues) == 0) + { param.DefaultExpression.Detach(); } - if (first) { + if (first) + { first = false; - } else { + } + else + { writer.WriteToken(Roles.Comma, ","); writer.Space(); } @@ -131,40 +149,51 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } if ((ConversionFlags & ConversionFlags.PlaceReturnTypeAfterParameterList) == ConversionFlags.PlaceReturnTypeAfterParameterList - && (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) { + && (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) + { var rt = node.GetChildByRole(Roles.Type); - if (!rt.IsNull) { + if (!rt.IsNull) + { writer.Space(); writer.WriteToken(Roles.Colon, ":"); writer.Space(); - if (symbol is IField f && CSharpDecompiler.IsFixedField(f, out var type, out int elementCount)) { + if (symbol is IField f && CSharpDecompiler.IsFixedField(f, out var type, out int elementCount)) + { rt = astBuilder.ConvertType(type); new IndexerExpression(new TypeReferenceExpression(rt), astBuilder.ConvertConstantValue(f.Compilation.FindType(KnownTypeCode.Int32), elementCount)) .AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy)); - } else { + } + else + { rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy)); } } } - if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody && !(node is TypeDeclaration)) { + if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody && !(node is TypeDeclaration)) + { IProperty property = symbol as IProperty; - if (property != null) { + if (property != null) + { writer.Space(); writer.WriteToken(Roles.LBrace, "{"); writer.Space(); - if (property.CanGet) { + if (property.CanGet) + { writer.WriteKeyword(PropertyDeclaration.GetKeywordRole, "get"); writer.WriteToken(Roles.Semicolon, ";"); writer.Space(); } - if (property.CanSet) { + if (property.CanSet) + { writer.WriteKeyword(PropertyDeclaration.SetKeywordRole, "set"); writer.WriteToken(Roles.Semicolon, ";"); writer.Space(); } writer.WriteToken(Roles.RBrace, "}"); - } else { + } + else + { writer.WriteToken(Roles.Semicolon, ";"); } writer.EndNode(node); @@ -173,7 +202,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor static bool HasParameters(ISymbol e) { - switch (e.SymbolKind) { + switch (e.SymbolKind) + { case SymbolKind.TypeDefinition: return ((ITypeDefinition)e).Kind == TypeKind.Delegate; case SymbolKind.Indexer: @@ -206,11 +236,15 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor EntityDeclaration node = astBuilder.ConvertEntity(typeDef); if (typeDef.DeclaringTypeDefinition != null && ((ConversionFlags & ConversionFlags.ShowDeclaringType) == ConversionFlags.ShowDeclaringType || - (ConversionFlags & ConversionFlags.UseFullyQualifiedEntityNames) == ConversionFlags.UseFullyQualifiedEntityNames)) { + (ConversionFlags & ConversionFlags.UseFullyQualifiedEntityNames) == ConversionFlags.UseFullyQualifiedEntityNames)) + { WriteTypeDeclarationName(typeDef.DeclaringTypeDefinition, writer, formattingPolicy); writer.WriteToken(Roles.Dot, "."); - } else if ((ConversionFlags & ConversionFlags.UseFullyQualifiedEntityNames) == ConversionFlags.UseFullyQualifiedEntityNames) { - if (!string.IsNullOrEmpty(typeDef.Namespace)) { + } + else if ((ConversionFlags & ConversionFlags.UseFullyQualifiedEntityNames) == ConversionFlags.UseFullyQualifiedEntityNames) + { + if (!string.IsNullOrEmpty(typeDef.Namespace)) + { WriteQualifiedName(typeDef.Namespace, writer, formattingPolicy); writer.WriteToken(Roles.Dot, "."); } @@ -223,11 +257,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { TypeSystemAstBuilder astBuilder = CreateAstBuilder(); EntityDeclaration node = astBuilder.ConvertEntity(member); - if ((ConversionFlags & ConversionFlags.ShowDeclaringType) == ConversionFlags.ShowDeclaringType && member.DeclaringType != null && !(member is LocalFunctionMethod)) { + if ((ConversionFlags & ConversionFlags.ShowDeclaringType) == ConversionFlags.ShowDeclaringType && member.DeclaringType != null && !(member is LocalFunctionMethod)) + { ConvertType(member.DeclaringType, writer, formattingPolicy); writer.WriteToken(Roles.Dot, "."); } - switch (member.SymbolKind) { + switch (member.SymbolKind) + { case SymbolKind.Indexer: writer.WriteKeyword(Roles.Identifier, "this"); break; @@ -239,7 +275,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteQualifiedName(member.DeclaringType.Name, writer, formattingPolicy); break; case SymbolKind.Operator: - switch (member.Name) { + switch (member.Name) + { case "op_Implicit": writer.WriteKeyword(OperatorDeclaration.ImplicitRole, "implicit"); writer.Space(); @@ -274,10 +311,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor void WriteTypeParameters(EntityDeclaration node, TokenWriter writer, CSharpFormattingOptions formattingPolicy) { - if ((ConversionFlags & ConversionFlags.ShowTypeParameterList) == ConversionFlags.ShowTypeParameterList) { + if ((ConversionFlags & ConversionFlags.ShowTypeParameterList) == ConversionFlags.ShowTypeParameterList) + { var outputVisitor = new CSharpOutputVisitor(writer, formattingPolicy); IEnumerable typeParameters = node.GetChildrenByRole(Roles.TypeParameter); - if ((ConversionFlags & ConversionFlags.ShowTypeParameterVarianceModifier) == 0) { + if ((ConversionFlags & ConversionFlags.ShowTypeParameterVarianceModifier) == 0) + { typeParameters = typeParameters.Select(RemoveVarianceModifier); } outputVisitor.WriteTypeParameters(typeParameters); @@ -292,8 +331,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor void PrintModifiers(Modifiers modifiers, TokenWriter writer) { - foreach (var m in CSharpModifierToken.AllModifiers) { - if ((modifiers & m) == m) { + foreach (var m in CSharpModifierToken.AllModifiers) + { + if ((modifiers & m) == m) + { writer.WriteKeyword(EntityDeclaration.ModifierRole, CSharpModifierToken.GetModifierName(m)); writer.Space(); } diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpFormattingOptions.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpFormattingOptions.cs index 4b45749ad..37bc0a074 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpFormattingOptions.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpFormattingOptions.cs @@ -46,25 +46,29 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor ForceNewLine } - public enum Wrapping { + public enum Wrapping + { DoNotChange, DoNotWrap, WrapAlways, WrapIfTooLong } - public enum NewLinePlacement { + public enum NewLinePlacement + { DoNotCare, NewLine, SameLine } - public enum UsingPlacement { + public enum UsingPlacement + { TopOfFile, InsideNamespace } - public enum EmptyLineFormatting { + public enum EmptyLineFormatting + { DoNotChange, Indent, DoNotIndent @@ -83,9 +87,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor set; } - public CSharpFormattingOptions Clone () + public CSharpFormattingOptions Clone() { - return (CSharpFormattingOptions)MemberwiseClone (); + return (CSharpFormattingOptions)MemberwiseClone(); } #region Indentation @@ -193,7 +197,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor set; } #endregion - + #region Braces public BraceStyle NamespaceBraceStyle { // tested get; @@ -347,7 +351,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } } #endregion - + #region Spaces // Methods public bool SpaceBeforeMethodDeclarationParentheses { // tested @@ -374,7 +378,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor get; set; } - + // Method calls public bool SpaceBeforeMethodCallParentheses { // tested get; @@ -400,9 +404,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor get; set; } - + // fields - + public bool SpaceBeforeFieldDeclarationComma { // tested get; set; @@ -412,9 +416,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor get; set; } - + // local variables - + public bool SpaceBeforeLocalVariableDeclarationComma { // tested get; set; @@ -424,9 +428,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor get; set; } - + // constructors - + public bool SpaceBeforeConstructorDeclarationParentheses { // tested get; set; @@ -461,7 +465,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor get; set; } - + // indexer public bool SpaceBeforeIndexerDeclarationBracket { // tested get; @@ -482,9 +486,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor get; set; } - + // delegates - + public bool SpaceBeforeDelegateDeclarationParentheses { get; set; @@ -729,7 +733,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor get; set; } - + // brackets public bool SpacesWithinBrackets { // tested get; @@ -786,7 +790,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor set; } #endregion - + #region Blank Lines public int MinimumBlankLinesBeforeUsings { get; diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs index 243fcbc22..a2e230d66 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -21,10 +21,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; + using Attribute = ICSharpCode.Decompiler.CSharp.Syntax.Attribute; namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -40,10 +42,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public CSharpOutputVisitor(TextWriter textWriter, CSharpFormattingOptions formattingPolicy) { - if (textWriter == null) { + if (textWriter == null) + { throw new ArgumentNullException(nameof(textWriter)); } - if (formattingPolicy == null) { + if (formattingPolicy == null) + { throw new ArgumentNullException(nameof(formattingPolicy)); } this.writer = TokenWriter.Create(textWriter, formattingPolicy.IndentationString); @@ -52,10 +56,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public CSharpOutputVisitor(TokenWriter writer, CSharpFormattingOptions formattingPolicy) { - if (writer == null) { + if (writer == null) + { throw new ArgumentNullException(nameof(writer)); } - if (formattingPolicy == null) { + if (formattingPolicy == null) + { throw new ArgumentNullException(nameof(formattingPolicy)); } this.writer = new InsertSpecialsDecorator(new InsertRequiredSpacesDecorator(writer)); @@ -102,10 +108,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void OptionalComma(AstNode pos) { // Look if there's a comma after the current node, and insert it if it exists. - while (pos != null && pos.NodeType == NodeType.Whitespace) { + while (pos != null && pos.NodeType == NodeType.Whitespace) + { pos = pos.NextSibling; } - if (pos != null && pos.Role == Roles.Comma) { + if (pos != null && pos.Role == Roles.Comma) + { Comma(null, noSpaceAfterComma: true); } } @@ -116,10 +124,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void OptionalSemicolon(AstNode pos) { // Look if there's a semicolon after the current node, and insert it if it exists. - while (pos != null && pos.NodeType == NodeType.Whitespace) { + while (pos != null && pos.NodeType == NodeType.Whitespace) + { pos = pos.PrevSibling; } - if (pos != null && pos.Role == Roles.Semicolon) { + if (pos != null && pos.Role == Roles.Semicolon) + { Semicolon(); } } @@ -127,10 +137,14 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void WriteCommaSeparatedList(IEnumerable list) { bool isFirst = true; - foreach (AstNode node in list) { - if (isFirst) { + foreach (AstNode node in list) + { + if (isFirst) + { isFirst = false; - } else { + } + else + { Comma(node); } node.AcceptVisitor(this); @@ -140,7 +154,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void WriteCommaSeparatedListInParenthesis(IEnumerable list, bool spaceWithin) { LPar(); - if (list.Any()) { + if (list.Any()) + { Space(spaceWithin); WriteCommaSeparatedList(list); Space(spaceWithin); @@ -151,7 +166,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void WriteCommaSeparatedListInBrackets(IEnumerable list, bool spaceWithin) { WriteToken(Roles.LBracket); - if (list.Any()) { + if (list.Any()) + { Space(spaceWithin); WriteCommaSeparatedList(list); Space(spaceWithin); @@ -162,7 +178,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void WriteCommaSeparatedListInBrackets(IEnumerable list) { WriteToken(Roles.LBracket); - if (list.Any()) { + if (list.Any()) + { Space(policy.SpacesWithinBrackets); WriteCommaSeparatedList(list); Space(policy.SpacesWithinBrackets); @@ -233,7 +250,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { Role role = containerStack.Peek().Role; // get the role of the current node - if (!(role == ForStatement.InitializerRole || role == ForStatement.IteratorRole || role == UsingStatement.ResourceAcquisitionRole)) { + if (!(role == ForStatement.InitializerRole || role == ForStatement.IteratorRole || role == UsingStatement.ResourceAcquisitionRole)) + { WriteToken(Roles.Semicolon); NewLine(); } @@ -244,7 +262,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor /// protected virtual void Space(bool addSpace = true) { - if (addSpace && !isAfterSpace) { + if (addSpace && !isAfterSpace) + { writer.Space(); isAfterSpace = true; } @@ -262,7 +281,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor int callChainLength = 0; var node = expr; - while (node.Target is InvocationExpression invocation && invocation.Target is MemberReferenceExpression mre && callChainLength < 4) { + while (node.Target is InvocationExpression invocation && invocation.Target is MemberReferenceExpression mre && callChainLength < 4) + { node = mre; callChainLength++; } @@ -272,7 +292,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual bool InsertNewLineWhenInMethodCallChain(MemberReferenceExpression expr) { int callChainLength = GetCallChainLengthLimited(expr); - if (callChainLength < 3) return false; + if (callChainLength < 3) + return false; if (expr.GetParent(n => n is Statement || n is LambdaExpression || n is InterpolatedStringContent) is InterpolatedStringContent) return false; if (callChainLength == 3) @@ -286,7 +307,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void OpenBrace(BraceStyle style) { - switch (style) { + switch (style) + { case BraceStyle.DoNotChange: case BraceStyle.EndOfLine: case BraceStyle.BannerStyle: @@ -322,7 +344,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void CloseBrace(BraceStyle style) { - switch (style) { + switch (style) + { case BraceStyle.DoNotChange: case BraceStyle.EndOfLine: case BraceStyle.EndOfLineWithoutSpace: @@ -375,25 +398,33 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public static bool IsKeyword(string identifier, AstNode context) { // only 2-10 char lower-case identifiers can be keywords - if (identifier.Length > maxKeywordLength || identifier.Length < 2 || identifier[0] < 'a') { + if (identifier.Length > maxKeywordLength || identifier.Length < 2 || identifier[0] < 'a') + { return false; } - if (unconditionalKeywords.Contains(identifier)) { + if (unconditionalKeywords.Contains(identifier)) + { return true; } - if (queryKeywords.Contains(identifier)) { + if (queryKeywords.Contains(identifier)) + { return context.Ancestors.Any(ancestor => ancestor is QueryExpression); } - if (identifier == "await") { - foreach (AstNode ancestor in context.Ancestors) { + if (identifier == "await") + { + foreach (AstNode ancestor in context.Ancestors) + { // with lambdas/anonymous methods, - if (ancestor is LambdaExpression) { + if (ancestor is LambdaExpression) + { return ((LambdaExpression)ancestor).IsAsync; } - if (ancestor is AnonymousMethodExpression) { + if (ancestor is AnonymousMethodExpression) + { return ((AnonymousMethodExpression)ancestor).IsAsync; } - if (ancestor is EntityDeclaration) { + if (ancestor is EntityDeclaration) + { return (((EntityDeclaration)ancestor).Modifiers & Modifiers.Async) == Modifiers.Async; } } @@ -405,7 +436,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor #region Write constructs protected virtual void WriteTypeArguments(IEnumerable typeArguments) { - if (typeArguments.Any()) { + if (typeArguments.Any()) + { WriteToken(Roles.LChevron); WriteCommaSeparatedList(typeArguments); WriteToken(Roles.RChevron); @@ -414,7 +446,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void WriteTypeParameters(IEnumerable typeParameters) { - if (typeParameters.Any()) { + if (typeParameters.Any()) + { WriteToken(Roles.LChevron); WriteCommaSeparatedList(typeParameters); WriteToken(Roles.RChevron); @@ -423,7 +456,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void WriteModifiers(IEnumerable modifierTokens) { - foreach (CSharpModifierToken modifier in modifierTokens) { + foreach (CSharpModifierToken modifier in modifierTokens) + { modifier.AcceptVisitor(this); Space(); } @@ -432,10 +466,14 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void WriteQualifiedIdentifier(IEnumerable identifiers) { bool first = true; - foreach (Identifier ident in identifiers) { - if (first) { + foreach (Identifier ident in identifiers) + { + if (first) + { first = false; - } else { + } + else + { writer.WriteToken(Roles.Dot, "."); } writer.WriteIdentifier(ident); @@ -454,19 +492,26 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor /// protected virtual void WriteEmbeddedStatement(Statement embeddedStatement, NewLinePlacement nlp = NewLinePlacement.NewLine) { - if (embeddedStatement.IsNull) { + if (embeddedStatement.IsNull) + { NewLine(); return; } BlockStatement block = embeddedStatement as BlockStatement; - if (block != null) { + if (block != null) + { WriteBlock(block, policy.StatementBraceStyle); - if (nlp == NewLinePlacement.SameLine) { + if (nlp == NewLinePlacement.SameLine) + { Space(); // if not a trailing newline, then at least a trailing space - } else { + } + else + { NewLine(); } - } else { + } + else + { NewLine(); writer.Indent(); embeddedStatement.AcceptVisitor(this); @@ -476,9 +521,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void WriteMethodBody(BlockStatement body, BraceStyle style) { - if (body.IsNull) { + if (body.IsNull) + { Semicolon(); - } else { + } + else + { WriteBlock(body, style); NewLine(); } @@ -486,14 +534,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void WriteAttributes(IEnumerable attributes) { - foreach (AttributeSection attr in attributes) { + foreach (AttributeSection attr in attributes) + { attr.AcceptVisitor(this); } } protected virtual void WritePrivateImplementationType(AstType privateImplementationType) { - if (!privateImplementationType.IsNull) { + if (!privateImplementationType.IsNull) + { privateImplementationType.AcceptVisitor(this); WriteToken(Roles.Dot); } @@ -505,12 +555,14 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression) { StartNode(anonymousMethodExpression); - if (anonymousMethodExpression.IsAsync) { + if (anonymousMethodExpression.IsAsync) + { WriteKeyword(AnonymousMethodExpression.AsyncModifierRole); Space(); } WriteKeyword(AnonymousMethodExpression.DelegateKeywordRole); - if (anonymousMethodExpression.HasParameterList) { + if (anonymousMethodExpression.HasParameterList) + { Space(policy.SpaceBeforeMethodDeclarationParentheses); WriteCommaSeparatedListInParenthesis(anonymousMethodExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); } @@ -521,7 +573,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression) { StartNode(undocumentedExpression); - switch (undocumentedExpression.UndocumentedExpressionType) { + switch (undocumentedExpression.UndocumentedExpressionType) + { case UndocumentedExpressionType.ArgList: case UndocumentedExpressionType.ArgListAccess: WriteKeyword(UndocumentedExpression.ArglistKeywordRole); @@ -536,7 +589,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteKeyword(UndocumentedExpression.RefvalueKeywordRole); break; } - if (undocumentedExpression.UndocumentedExpressionType != UndocumentedExpressionType.ArgListAccess) { + if (undocumentedExpression.UndocumentedExpressionType != UndocumentedExpressionType.ArgListAccess) + { Space(policy.SpaceBeforeMethodCallParentheses); WriteCommaSeparatedListInParenthesis(undocumentedExpression.Arguments, policy.SpaceWithinMethodCallParentheses); } @@ -548,10 +602,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor StartNode(arrayCreateExpression); WriteKeyword(ArrayCreateExpression.NewKeywordRole); arrayCreateExpression.Type.AcceptVisitor(this); - if (arrayCreateExpression.Arguments.Count > 0) { + if (arrayCreateExpression.Arguments.Count > 0) + { WriteCommaSeparatedListInBrackets(arrayCreateExpression.Arguments); } - foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) { + foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) + { specifier.AcceptVisitor(this); } arrayCreateExpression.Initializer.AcceptVisitor(this); @@ -569,9 +625,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor bool bracesAreOptional = arrayInitializerExpression.Elements.Count == 1 && IsObjectOrCollectionInitializer(arrayInitializerExpression.Parent) && !CanBeConfusedWithObjectInitializer(arrayInitializerExpression.Elements.Single()); - if (bracesAreOptional && arrayInitializerExpression.LBraceToken.IsNull) { + if (bracesAreOptional && arrayInitializerExpression.LBraceToken.IsNull) + { arrayInitializerExpression.Elements.Single().AcceptVisitor(this); - } else { + } + else + { PrintInitializerElements(arrayInitializerExpression.Elements); } EndNode(arrayInitializerExpression); @@ -587,13 +646,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected bool IsObjectOrCollectionInitializer(AstNode node) { - if (!(node is ArrayInitializerExpression)) { + if (!(node is ArrayInitializerExpression)) + { return false; } - if (node.Parent is ObjectCreateExpression) { + if (node.Parent is ObjectCreateExpression) + { return node.Role == ObjectCreateExpression.InitializerRole; } - if (node.Parent is NamedExpression) { + if (node.Parent is NamedExpression) + { return node.Role == Roles.Expression; } return false; @@ -602,18 +664,25 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected virtual void PrintInitializerElements(AstNodeCollection elements) { BraceStyle style; - if (policy.ArrayInitializerWrapping == Wrapping.WrapAlways) { + if (policy.ArrayInitializerWrapping == Wrapping.WrapAlways) + { style = BraceStyle.NextLine; - } else { + } + else + { style = BraceStyle.EndOfLine; } OpenBrace(style); bool isFirst = true; AstNode last = null; - foreach (AstNode node in elements) { - if (isFirst) { + foreach (AstNode node in elements) + { + if (isFirst) + { isFirst = false; - } else { + } + else + { Comma(node, noSpaceAfterComma: true); NewLine(); } @@ -660,7 +729,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor StartNode(binaryOperatorExpression); binaryOperatorExpression.Left.AcceptVisitor(this); bool spacePolicy; - switch (binaryOperatorExpression.Operator) { + switch (binaryOperatorExpression.Operator) + { case BinaryOperatorType.BitwiseAnd: case BinaryOperatorType.BitwiseOr: case BinaryOperatorType.ExclusiveOr: @@ -772,7 +842,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(directionExpression); - switch (directionExpression.FieldDirection) { + switch (directionExpression.FieldDirection) + { case FieldDirection.Out: WriteKeyword(DirectionExpression.OutKeywordRole); break; @@ -838,8 +909,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor invocationExpression.Target.AcceptVisitor(this); Space(policy.SpaceBeforeMethodCallParentheses); WriteCommaSeparatedListInParenthesis(invocationExpression.Arguments, policy.SpaceWithinMethodCallParentheses); - if (!(invocationExpression.Parent is MemberReferenceExpression)) { - if (invocationExpression.Target is MemberReferenceExpression mre) { + if (!(invocationExpression.Parent is MemberReferenceExpression)) + { + if (invocationExpression.Target is MemberReferenceExpression mre) + { if (GetCallChainLengthLimited(mre) >= 3) writer.Unindent(); } @@ -860,20 +933,27 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitLambdaExpression(LambdaExpression lambdaExpression) { StartNode(lambdaExpression); - if (lambdaExpression.IsAsync) { + if (lambdaExpression.IsAsync) + { WriteKeyword(LambdaExpression.AsyncModifierRole); Space(); } - if (LambdaNeedsParenthesis(lambdaExpression)) { + if (LambdaNeedsParenthesis(lambdaExpression)) + { WriteCommaSeparatedListInParenthesis(lambdaExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); - } else { + } + else + { lambdaExpression.Parameters.Single().AcceptVisitor(this); } Space(); WriteToken(Roles.Arrow); - if (lambdaExpression.Body is BlockStatement) { + if (lambdaExpression.Body is BlockStatement) + { WriteBlock((BlockStatement)lambdaExpression.Body, policy.AnonymousMethodBraceStyle); - } else { + } + else + { Space(); lambdaExpression.Body.AcceptVisitor(this); } @@ -882,7 +962,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected bool LambdaNeedsParenthesis(LambdaExpression lambdaExpression) { - if (lambdaExpression.Parameters.Count != 1) { + if (lambdaExpression.Parameters.Count != 1) + { return true; } var p = lambdaExpression.Parameters.Single(); @@ -897,7 +978,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteToken(Roles.Dot); WriteIdentifier(memberReferenceExpression.MemberNameToken); WriteTypeArguments(memberReferenceExpression.TypeArguments); - if (insertedNewLine && !(memberReferenceExpression.Parent is InvocationExpression)) { + if (insertedNewLine && !(memberReferenceExpression.Parent is InvocationExpression)) + { writer.Unindent(); } EndNode(memberReferenceExpression); @@ -939,10 +1021,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor objectCreateExpression.Type.AcceptVisitor(this); bool useParenthesis = objectCreateExpression.Arguments.Any() || objectCreateExpression.Initializer.IsNull; // also use parenthesis if there is an '(' token - if (!objectCreateExpression.LParToken.IsNull) { + if (!objectCreateExpression.LParToken.IsNull) + { useParenthesis = true; } - if (useParenthesis) { + if (useParenthesis) + { Space(policy.SpaceBeforeMethodCallParentheses); WriteCommaSeparatedListInParenthesis(objectCreateExpression.Arguments, policy.SpaceWithinMethodCallParentheses); } @@ -993,7 +1077,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor StartNode(interpolatedStringExpression); writer.WriteToken(InterpolatedStringExpression.OpenQuote, "$\""); - foreach (var element in interpolatedStringExpression.Content) { + foreach (var element in interpolatedStringExpression.Content) + { element.AcceptVisitor(this); } writer.WriteToken(InterpolatedStringExpression.CloseQuote, "\""); @@ -1008,7 +1093,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor writer.WriteToken(Interpolation.LBrace, "{"); interpolation.Expression.AcceptVisitor(this); - if (interpolation.Suffix != null) { + if (interpolation.Suffix != null) + { writer.WriteToken(Roles.Colon, ":"); writer.WriteInterpolatedText(interpolation.Suffix); } @@ -1101,14 +1187,18 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor StartNode(unaryOperatorExpression); UnaryOperatorType opType = unaryOperatorExpression.Operator; var opSymbol = UnaryOperatorExpression.GetOperatorRole(opType); - if (opType == UnaryOperatorType.Await) { + if (opType == UnaryOperatorType.Await) + { WriteKeyword(opSymbol); Space(); - } else if (!IsPostfixOperator(opType) && opSymbol != null) { + } + else if (!IsPostfixOperator(opType) && opSymbol != null) + { WriteToken(opSymbol); } unaryOperatorExpression.Expression.AcceptVisitor(this); - if (IsPostfixOperator(opType)) { + if (IsPostfixOperator(opType)) + { WriteToken(opSymbol); } EndNode(unaryOperatorExpression); @@ -1143,11 +1233,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor if (queryExpression.Role != QueryContinuationClause.PrecedingQueryRole) writer.Indent(); bool first = true; - foreach (var clause in queryExpression.Clauses) { - if (first) { + foreach (var clause in queryExpression.Clauses) + { + if (first) + { first = false; - } else { - if (!(clause is QueryContinuationClause)) { + } + else + { + if (!(clause is QueryContinuationClause)) + { NewLine(); } } @@ -1224,7 +1319,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteKeyword(QueryJoinClause.EqualsKeywordRole); Space(); queryJoinClause.EqualsExpression.AcceptVisitor(this); - if (queryJoinClause.IsGroupJoin) { + if (queryJoinClause.IsGroupJoin) + { Space(); WriteKeyword(QueryJoinClause.IntoKeywordRole); WriteIdentifier(queryJoinClause.IntoIdentifierToken); @@ -1245,7 +1341,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(queryOrdering); queryOrdering.Expression.AcceptVisitor(this); - switch (queryOrdering.Direction) { + switch (queryOrdering.Direction) + { case QueryOrderingDirection.Ascending: Space(); WriteKeyword(QueryOrdering.AscendingKeywordRole); @@ -1287,7 +1384,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(attribute); attribute.Type.AcceptVisitor(this); - if (attribute.Arguments.Count != 0 || attribute.HasArgumentList) { + if (attribute.Arguments.Count != 0 || attribute.HasArgumentList) + { Space(policy.SpaceBeforeMethodCallParentheses); WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.SpaceWithinMethodCallParentheses); } @@ -1298,14 +1396,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(attributeSection); WriteToken(Roles.LBracket); - if (!string.IsNullOrEmpty(attributeSection.AttributeTarget)) { + if (!string.IsNullOrEmpty(attributeSection.AttributeTarget)) + { WriteKeyword(attributeSection.AttributeTarget, Roles.Identifier); WriteToken(Roles.Colon); Space(); } WriteCommaSeparatedList(attributeSection.Attributes); WriteToken(Roles.RBracket); - switch (attributeSection.Parent) { + switch (attributeSection.Parent) + { case ParameterDeclaration _: case TypeParameterDeclaration _: case ComposedType _: @@ -1330,7 +1430,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteTypeParameters(delegateDeclaration.TypeParameters); Space(policy.SpaceBeforeDelegateDeclarationParentheses); WriteCommaSeparatedListInParenthesis(delegateDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); - foreach (Constraint constraint in delegateDeclaration.Constraints) { + foreach (Constraint constraint in delegateDeclaration.Constraints) + { constraint.AcceptVisitor(this); } Semicolon(); @@ -1343,7 +1444,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteKeyword(Roles.NamespaceKeyword); namespaceDeclaration.NamespaceName.AcceptVisitor(this); OpenBrace(policy.NamespaceBraceStyle); - foreach (var member in namespaceDeclaration.Members) { + foreach (var member in namespaceDeclaration.Members) + { member.AcceptVisitor(this); MaybeNewLinesAfterUsings(member); } @@ -1359,7 +1461,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteAttributes(typeDeclaration.Attributes); WriteModifiers(typeDeclaration.ModifierTokens); BraceStyle braceStyle; - switch (typeDeclaration.ClassType) { + switch (typeDeclaration.ClassType) + { case ClassType.Enum: WriteKeyword(Roles.EnumKeyword); braceStyle = policy.EnumBraceStyle; @@ -1379,23 +1482,30 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } WriteIdentifier(typeDeclaration.NameToken); WriteTypeParameters(typeDeclaration.TypeParameters); - if (typeDeclaration.BaseTypes.Any()) { + if (typeDeclaration.BaseTypes.Any()) + { Space(); WriteToken(Roles.Colon); Space(); WriteCommaSeparatedList(typeDeclaration.BaseTypes); } - foreach (Constraint constraint in typeDeclaration.Constraints) { + foreach (Constraint constraint in typeDeclaration.Constraints) + { constraint.AcceptVisitor(this); } OpenBrace(braceStyle); - if (typeDeclaration.ClassType == ClassType.Enum) { + if (typeDeclaration.ClassType == ClassType.Enum) + { bool first = true; AstNode last = null; - foreach (var member in typeDeclaration.Members) { - if (first) { + foreach (var member in typeDeclaration.Members) + { + if (first) + { first = false; - } else { + } + else + { Comma(member, noSpaceAfterComma: true); NewLine(); } @@ -1405,10 +1515,14 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor if (last != null) OptionalComma(last.NextSibling); NewLine(); - } else { + } + else + { bool first = true; - foreach (var member in typeDeclaration.Members) { - if (!first) { + foreach (var member in typeDeclaration.Members) + { + if (!first) + { for (int i = 0; i < policy.MinimumBlankLinesBetweenMembers; i++) NewLine(); } @@ -1475,7 +1589,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(blockStatement); OpenBrace(style); - foreach (var node in blockStatement.Statements) { + foreach (var node in blockStatement.Statements) + { node.AcceptVisitor(this); } CloseBrace(style); @@ -1591,7 +1706,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor forStatement.Condition.AcceptVisitor(this); Space(policy.SpaceBeforeForSemicolon); WriteToken(Roles.Semicolon); - if (forStatement.Iterators.Any()) { + if (forStatement.Iterators.Any()) + { Space(policy.SpaceAfterForSemicolon); WriteCommaSeparatedList(forStatement.Iterators); } @@ -1642,15 +1758,21 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor Space(policy.SpacesWithinIfParentheses); RPar(); - if (ifElseStatement.FalseStatement.IsNull) { + if (ifElseStatement.FalseStatement.IsNull) + { WriteEmbeddedStatement(ifElseStatement.TrueStatement); - } else { + } + else + { WriteEmbeddedStatement(ifElseStatement.TrueStatement, policy.ElseNewLinePlacement); WriteKeyword(IfElseStatement.ElseKeywordRole); - if (ifElseStatement.FalseStatement is IfElseStatement) { + if (ifElseStatement.FalseStatement is IfElseStatement) + { // don't put newline between 'else' and 'if' ifElseStatement.FalseStatement.AcceptVisitor(this); - } else { + } + else + { WriteEmbeddedStatement(ifElseStatement.FalseStatement); } } @@ -1663,12 +1785,15 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteIdentifier(labelStatement.GetChildByRole(Roles.Identifier)); WriteToken(Roles.Colon); bool foundLabelledStatement = false; - for (AstNode tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling) { - if (tmp.Role == labelStatement.Role) { + for (AstNode tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling) + { + if (tmp.Role == labelStatement.Role) + { foundLabelledStatement = true; } } - if (!foundLabelledStatement) { + if (!foundLabelledStatement) + { // introduce an EmptyStatement so that the output becomes syntactically valid WriteToken(Roles.Semicolon); } @@ -1694,7 +1819,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(returnStatement); WriteKeyword(ReturnStatement.ReturnKeywordRole); - if (!returnStatement.Expression.IsNull) { + if (!returnStatement.Expression.IsNull) + { Space(); returnStatement.Expression.AcceptVisitor(this); } @@ -1713,15 +1839,18 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor Space(policy.SpacesWithinSwitchParentheses); RPar(); OpenBrace(policy.StatementBraceStyle); - if (!policy.IndentSwitchBody) { + if (!policy.IndentSwitchBody) + { writer.Unindent(); } - foreach (var section in switchStatement.SwitchSections) { + foreach (var section in switchStatement.SwitchSections) + { section.AcceptVisitor(this); } - if (!policy.IndentSwitchBody) { + if (!policy.IndentSwitchBody) + { writer.Indent(); } CloseBrace(policy.StatementBraceStyle); @@ -1733,26 +1862,31 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(switchSection); bool first = true; - foreach (var label in switchSection.CaseLabels) { - if (!first) { + foreach (var label in switchSection.CaseLabels) + { + if (!first) + { NewLine(); } label.AcceptVisitor(this); first = false; } bool isBlock = switchSection.Statements.Count == 1 && switchSection.Statements.Single() is BlockStatement; - if (policy.IndentCaseBody && !isBlock) { + if (policy.IndentCaseBody && !isBlock) + { writer.Indent(); } if (!isBlock) NewLine(); - foreach (var statement in switchSection.Statements) { + foreach (var statement in switchSection.Statements) + { statement.AcceptVisitor(this); } - if (policy.IndentCaseBody && !isBlock) { + if (policy.IndentCaseBody && !isBlock) + { writer.Unindent(); } @@ -1762,9 +1896,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitCaseLabel(CaseLabel caseLabel) { StartNode(caseLabel); - if (caseLabel.Expression.IsNull) { + if (caseLabel.Expression.IsNull) + { WriteKeyword(CaseLabel.DefaultKeywordRole); - } else { + } + else + { WriteKeyword(CaseLabel.CaseKeywordRole); Space(); caseLabel.Expression.AcceptVisitor(this); @@ -1780,7 +1917,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor Space(); WriteKeyword(SwitchExpression.SwitchKeywordRole); OpenBrace(BraceStyle.EndOfLine); - foreach (AstNode node in switchExpression.SwitchSections) { + foreach (AstNode node in switchExpression.SwitchSections) + { node.AcceptVisitor(this); Comma(node); NewLine(); @@ -1804,7 +1942,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(throwStatement); WriteKeyword(ThrowStatement.ThrowKeywordRole); - if (!throwStatement.Expression.IsNull) { + if (!throwStatement.Expression.IsNull) + { Space(); throwStatement.Expression.AcceptVisitor(this); } @@ -1817,14 +1956,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor StartNode(tryCatchStatement); WriteKeyword(TryCatchStatement.TryKeywordRole); WriteBlock(tryCatchStatement.TryBlock, policy.StatementBraceStyle); - foreach (var catchClause in tryCatchStatement.CatchClauses) { + foreach (var catchClause in tryCatchStatement.CatchClauses) + { if (policy.CatchNewLinePlacement == NewLinePlacement.SameLine) Space(); else NewLine(); catchClause.AcceptVisitor(this); } - if (!tryCatchStatement.FinallyBlock.IsNull) { + if (!tryCatchStatement.FinallyBlock.IsNull) + { if (policy.FinallyNewLinePlacement == NewLinePlacement.SameLine) Space(); else @@ -1840,19 +1981,22 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(catchClause); WriteKeyword(CatchClause.CatchKeywordRole); - if (!catchClause.Type.IsNull) { + if (!catchClause.Type.IsNull) + { Space(policy.SpaceBeforeCatchParentheses); LPar(); Space(policy.SpacesWithinCatchParentheses); catchClause.Type.AcceptVisitor(this); - if (!string.IsNullOrEmpty(catchClause.VariableName)) { + if (!string.IsNullOrEmpty(catchClause.VariableName)) + { Space(); WriteIdentifier(catchClause.VariableNameToken); } Space(policy.SpacesWithinCatchParentheses); RPar(); } - if (!catchClause.Condition.IsNull) { + if (!catchClause.Condition.IsNull) + { Space(); WriteKeyword(CatchClause.WhenKeywordRole); Space(policy.SpaceBeforeIfParentheses); @@ -1885,13 +2029,17 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitUsingStatement(UsingStatement usingStatement) { StartNode(usingStatement); - if (usingStatement.IsAsync) { + if (usingStatement.IsAsync) + { WriteKeyword(UsingStatement.AwaitRole); } WriteKeyword(UsingStatement.UsingKeywordRole); - if (usingStatement.IsEnhanced) { + if (usingStatement.IsEnhanced) + { Space(); - } else { + } + else + { Space(policy.SpaceBeforeUsingParentheses); LPar(); Space(policy.SpacesWithinUsingParentheses); @@ -1899,24 +2047,34 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor usingStatement.ResourceAcquisition.AcceptVisitor(this); - if (usingStatement.IsEnhanced) { + if (usingStatement.IsEnhanced) + { Semicolon(); - } else { + } + else + { Space(policy.SpacesWithinUsingParentheses); RPar(); } - if (usingStatement.IsEnhanced) { - if (usingStatement.EmbeddedStatement is BlockStatement blockStatement) { + if (usingStatement.IsEnhanced) + { + if (usingStatement.EmbeddedStatement is BlockStatement blockStatement) + { StartNode(blockStatement); - foreach (var node in blockStatement.Statements) { + foreach (var node in blockStatement.Statements) + { node.AcceptVisitor(this); } EndNode(blockStatement); - } else { + } + else + { usingStatement.EmbeddedStatement.AcceptVisitor(this); } - } else { + } + else + { WriteEmbeddedStatement(usingStatement.EmbeddedStatement); } @@ -1984,20 +2142,30 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteAttributes(accessor.Attributes); WriteModifiers(accessor.ModifierTokens); BraceStyle style = policy.StatementBraceStyle; - if (accessor.Role == PropertyDeclaration.GetterRole) { + if (accessor.Role == PropertyDeclaration.GetterRole) + { WriteKeyword("get", PropertyDeclaration.GetKeywordRole); style = policy.PropertyGetBraceStyle; - } else if (accessor.Role == PropertyDeclaration.SetterRole) { - if (accessor.Keyword.Role == PropertyDeclaration.InitKeywordRole) { + } + else if (accessor.Role == PropertyDeclaration.SetterRole) + { + if (accessor.Keyword.Role == PropertyDeclaration.InitKeywordRole) + { WriteKeyword("init", PropertyDeclaration.InitKeywordRole); - } else { + } + else + { WriteKeyword("set", PropertyDeclaration.SetKeywordRole); } style = policy.PropertySetBraceStyle; - } else if (accessor.Role == CustomEventDeclaration.AddAccessorRole) { + } + else if (accessor.Role == CustomEventDeclaration.AddAccessorRole) + { WriteKeyword("add", CustomEventDeclaration.AddKeywordRole); style = policy.EventAddBraceStyle; - } else if (accessor.Role == CustomEventDeclaration.RemoveAccessorRole) { + } + else if (accessor.Role == CustomEventDeclaration.RemoveAccessorRole) + { WriteKeyword("remove", CustomEventDeclaration.RemoveKeywordRole); style = policy.EventRemoveBraceStyle; } @@ -2017,7 +2185,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteIdentifier(constructorDeclaration.NameToken); Space(policy.SpaceBeforeConstructorDeclarationParentheses); WriteCommaSeparatedListInParenthesis(constructorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); - if (!constructorDeclaration.Initializer.IsNull) { + if (!constructorDeclaration.Initializer.IsNull) + { NewLine(); writer.Indent(); constructorDeclaration.Initializer.AcceptVisitor(this); @@ -2032,9 +2201,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor StartNode(constructorInitializer); WriteToken(Roles.Colon); Space(); - if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.This) { + if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.This) + { WriteKeyword(ConstructorInitializer.ThisKeywordRole); - } else { + } + else + { WriteKeyword(ConstructorInitializer.BaseKeywordRole); } Space(policy.SpaceBeforeMethodCallParentheses); @@ -2047,7 +2219,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor StartNode(destructorDeclaration); WriteAttributes(destructorDeclaration.Attributes); WriteModifiers(destructorDeclaration.ModifierTokens); - if (destructorDeclaration.ModifierTokens.Any()) { + if (destructorDeclaration.ModifierTokens.Any()) + { Space(); } WriteToken(DestructorDeclaration.TildeRole); @@ -2069,7 +2242,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteAttributes(enumMemberDeclaration.Attributes); WriteModifiers(enumMemberDeclaration.ModifierTokens); WriteIdentifier(enumMemberDeclaration.NameToken); - if (!enumMemberDeclaration.Initializer.IsNull) { + if (!enumMemberDeclaration.Initializer.IsNull) + { Space(policy.SpaceAroundAssignment); WriteToken(Roles.Assign); Space(policy.SpaceAroundAssignment); @@ -2103,8 +2277,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteIdentifier(customEventDeclaration.NameToken); OpenBrace(policy.EventBraceStyle); // output add/remove in their original order - foreach (AstNode node in customEventDeclaration.Children) { - if (node.Role == CustomEventDeclaration.AddAccessorRole || node.Role == CustomEventDeclaration.RemoveAccessorRole) { + foreach (AstNode node in customEventDeclaration.Children) + { + if (node.Role == CustomEventDeclaration.AddAccessorRole || node.Role == CustomEventDeclaration.RemoveAccessorRole) + { node.AcceptVisitor(this); } } @@ -2143,7 +2319,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(fixedVariableInitializer); WriteIdentifier(fixedVariableInitializer.NameToken); - if (!fixedVariableInitializer.CountExpression.IsNull) { + if (!fixedVariableInitializer.CountExpression.IsNull) + { WriteToken(Roles.LBracket); Space(policy.SpacesWithinBrackets); fixedVariableInitializer.CountExpression.AcceptVisitor(this); @@ -2165,17 +2342,22 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor Space(policy.SpaceBeforeMethodDeclarationParentheses); WriteCommaSeparatedListInBrackets(indexerDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); - if (indexerDeclaration.ExpressionBody.IsNull) { + if (indexerDeclaration.ExpressionBody.IsNull) + { OpenBrace(policy.PropertyBraceStyle); // output get/set in their original order - foreach (AstNode node in indexerDeclaration.Children) { - if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) { + foreach (AstNode node in indexerDeclaration.Children) + { + if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) + { node.AcceptVisitor(this); } } CloseBrace(policy.PropertyBraceStyle); NewLine(); - } else { + } + else + { Space(); WriteToken(Roles.Arrow); Space(); @@ -2197,7 +2379,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WriteTypeParameters(methodDeclaration.TypeParameters); Space(policy.SpaceBeforeMethodDeclarationParentheses); WriteCommaSeparatedListInParenthesis(methodDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); - foreach (Constraint constraint in methodDeclaration.Constraints) { + foreach (Constraint constraint in methodDeclaration.Constraints) + { constraint.AcceptVisitor(this); } WriteMethodBody(methodDeclaration.Body, policy.MethodBraceStyle); @@ -2209,19 +2392,27 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor StartNode(operatorDeclaration); WriteAttributes(operatorDeclaration.Attributes); WriteModifiers(operatorDeclaration.ModifierTokens); - if (operatorDeclaration.OperatorType == OperatorType.Explicit) { + if (operatorDeclaration.OperatorType == OperatorType.Explicit) + { WriteKeyword(OperatorDeclaration.ExplicitRole); - } else if (operatorDeclaration.OperatorType == OperatorType.Implicit) { + } + else if (operatorDeclaration.OperatorType == OperatorType.Implicit) + { WriteKeyword(OperatorDeclaration.ImplicitRole); - } else { + } + else + { operatorDeclaration.ReturnType.AcceptVisitor(this); } WriteKeyword(OperatorDeclaration.OperatorKeywordRole); Space(); if (operatorDeclaration.OperatorType == OperatorType.Explicit - || operatorDeclaration.OperatorType == OperatorType.Implicit) { + || operatorDeclaration.OperatorType == OperatorType.Implicit) + { operatorDeclaration.ReturnType.AcceptVisitor(this); - } else { + } + else + { WriteToken(OperatorDeclaration.GetToken(operatorDeclaration.OperatorType), OperatorDeclaration.GetRole(operatorDeclaration.OperatorType)); } Space(policy.SpaceBeforeMethodDeclarationParentheses); @@ -2234,11 +2425,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(parameterDeclaration); WriteAttributes(parameterDeclaration.Attributes); - if (parameterDeclaration.HasThisModifier) { + if (parameterDeclaration.HasThisModifier) + { WriteKeyword(ParameterDeclaration.ThisModifierRole); Space(); } - switch (parameterDeclaration.ParameterModifier) { + switch (parameterDeclaration.ParameterModifier) + { case ParameterModifier.Ref: WriteKeyword(ParameterDeclaration.RefModifierRole); Space(); @@ -2257,13 +2450,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor break; } parameterDeclaration.Type.AcceptVisitor(this); - if (!parameterDeclaration.Type.IsNull && !string.IsNullOrEmpty(parameterDeclaration.Name)) { + if (!parameterDeclaration.Type.IsNull && !string.IsNullOrEmpty(parameterDeclaration.Name)) + { Space(); } - if (!string.IsNullOrEmpty(parameterDeclaration.Name)) { + if (!string.IsNullOrEmpty(parameterDeclaration.Name)) + { WriteIdentifier(parameterDeclaration.NameToken); } - if (!parameterDeclaration.DefaultExpression.IsNull) { + if (!parameterDeclaration.DefaultExpression.IsNull) + { Space(policy.SpaceAroundAssignment); WriteToken(Roles.Assign); Space(policy.SpaceAroundAssignment); @@ -2281,16 +2477,20 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor Space(); WritePrivateImplementationType(propertyDeclaration.PrivateImplementationType); WriteIdentifier(propertyDeclaration.NameToken); - if (propertyDeclaration.ExpressionBody.IsNull) { + if (propertyDeclaration.ExpressionBody.IsNull) + { OpenBrace(policy.PropertyBraceStyle); // output get/set in their original order - foreach (AstNode node in propertyDeclaration.Children) { - if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) { + foreach (AstNode node in propertyDeclaration.Children) + { + if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) + { node.AcceptVisitor(this); } } CloseBrace(policy.PropertyBraceStyle); - if (!propertyDeclaration.Initializer.IsNull) { + if (!propertyDeclaration.Initializer.IsNull) + { Space(policy.SpaceAroundAssignment); WriteToken(Roles.Assign); Space(policy.SpaceAroundAssignment); @@ -2298,7 +2498,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor Semicolon(); } NewLine(); - } else { + } + else + { Space(); WriteToken(Roles.Arrow); Space(); @@ -2315,7 +2517,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(variableInitializer); WriteIdentifier(variableInitializer.NameToken); - if (!variableInitializer.Initializer.IsNull) { + if (!variableInitializer.Initializer.IsNull) + { Space(policy.SpaceAroundAssignment); WriteToken(Roles.Assign); Space(policy.SpaceAroundAssignment); @@ -2328,7 +2531,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { var nextSibling = node.NextSibling; - if ((node is UsingDeclaration || node is UsingAliasDeclaration) && !(nextSibling is UsingDeclaration || nextSibling is UsingAliasDeclaration)) { + if ((node is UsingDeclaration || node is UsingAliasDeclaration) && !(nextSibling is UsingDeclaration || nextSibling is UsingAliasDeclaration)) + { for (int i = 0; i < policy.MinimumBlankLinesAfterUsings; i++) NewLine(); } @@ -2337,7 +2541,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitSyntaxTree(SyntaxTree syntaxTree) { // don't do node tracking as we visit all children directly - foreach (AstNode node in syntaxTree.Children) { + foreach (AstNode node in syntaxTree.Children) + { node.AcceptVisitor(this); MaybeNewLinesAfterUsings(node); } @@ -2355,9 +2560,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(memberType); memberType.Target.AcceptVisitor(this); - if (memberType.IsDoubleColon) { + if (memberType.IsDoubleColon) + { WriteToken(Roles.DoubleColon); - } else { + } + else + { WriteToken(Roles.Dot); } WriteIdentifier(memberType.MemberNameToken); @@ -2379,7 +2587,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(tupleTypeElement); tupleTypeElement.Type.AcceptVisitor(this); - if (!tupleTypeElement.NameToken.IsNull) { + if (!tupleTypeElement.NameToken.IsNull) + { Space(); tupleTypeElement.NameToken.AcceptVisitor(this); } @@ -2391,7 +2600,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor StartNode(functionPointerType); WriteKeyword(Roles.DelegateKeyword); WriteToken(FunctionPointerType.PointerRole); - if (!functionPointerType.CallingConventionIdentifier.IsNull) { + if (!functionPointerType.CallingConventionIdentifier.IsNull) + { Space(); WriteIdentifier(functionPointerType.CallingConventionIdentifier); } @@ -2402,25 +2612,32 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitComposedType(ComposedType composedType) { StartNode(composedType); - if (composedType.Attributes.Any()) { - foreach (var attr in composedType.Attributes) { + if (composedType.Attributes.Any()) + { + foreach (var attr in composedType.Attributes) + { attr.AcceptVisitor(this); } } - if (composedType.HasRefSpecifier) { + if (composedType.HasRefSpecifier) + { WriteKeyword(ComposedType.RefRole); } - if (composedType.HasReadOnlySpecifier) { + if (composedType.HasReadOnlySpecifier) + { WriteKeyword(ComposedType.ReadonlyRole); } composedType.BaseType.AcceptVisitor(this); - if (composedType.HasNullableSpecifier) { + if (composedType.HasNullableSpecifier) + { WriteToken(ComposedType.NullableRole); } - for (int i = 0; i < composedType.PointerRank; i++) { + for (int i = 0; i < composedType.PointerRank; i++) + { WriteToken(ComposedType.PointerRole); } - foreach (var node in composedType.ArraySpecifiers) { + foreach (var node in composedType.ArraySpecifiers) + { node.AcceptVisitor(this); } EndNode(composedType); @@ -2430,7 +2647,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(arraySpecifier); WriteToken(Roles.LBracket); - foreach (var comma in arraySpecifier.GetChildrenByRole(Roles.Comma)) { + foreach (var comma in arraySpecifier.GetChildrenByRole(Roles.Comma)) + { writer.WriteToken(Roles.Comma, ","); } WriteToken(Roles.RBracket); @@ -2478,7 +2696,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { StartNode(typeParameterDeclaration); WriteAttributes(typeParameterDeclaration.Attributes); - switch (typeParameterDeclaration.Variance) { + switch (typeParameterDeclaration.Variance) + { case VarianceModifier.Invariant: break; case VarianceModifier.Covariant: @@ -2510,11 +2729,14 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode) { CSharpModifierToken mod = cSharpTokenNode as CSharpModifierToken; - if (mod != null) { + if (mod != null) + { // ITokenWriter assumes that each node processed between a // StartNode(parentNode)-EndNode(parentNode)-pair is a child of parentNode. WriteKeyword(CSharpModifierToken.GetModifierName(mod.Modifier), cSharpTokenNode.Role); - } else { + } + else + { throw new NotSupportedException("Should never visit individual tokens"); } } @@ -2548,7 +2770,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor void VisitAnyNode(AnyNode anyNode) { - if (!string.IsNullOrEmpty(anyNode.GroupName)) { + if (!string.IsNullOrEmpty(anyNode.GroupName)) + { WriteIdentifier(anyNode.GroupName); WriteToken(Roles.Colon); } @@ -2577,9 +2800,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor LPar(); NewLine(); writer.Indent(); - foreach (INode alternative in choice) { + foreach (INode alternative in choice) + { VisitNodeInPattern(alternative); - if (alternative != choice.Last()) { + if (alternative != choice.Last()) + { WriteToken(Roles.Comma); } NewLine(); @@ -2590,7 +2815,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor void VisitNamedNode(NamedNode namedNode) { - if (!string.IsNullOrEmpty(namedNode.GroupName)) { + if (!string.IsNullOrEmpty(namedNode.GroupName)) + { WriteIdentifier(namedNode.GroupName); WriteToken(Roles.Colon); } @@ -2601,7 +2827,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { WriteKeyword("repeat"); LPar(); - if (repeat.MinCount != 0 || repeat.MaxCount != int.MaxValue) { + if (repeat.MinCount != 0 || repeat.MaxCount != int.MaxValue) + { WriteIdentifier(repeat.MinCount.ToString()); WriteToken(Roles.Comma); WriteIdentifier(repeat.MaxCount.ToString()); @@ -2621,23 +2848,40 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor void VisitNodeInPattern(INode childNode) { - if (childNode is AstNode) { + if (childNode is AstNode) + { ((AstNode)childNode).AcceptVisitor(this); - } else if (childNode is IdentifierExpressionBackreference) { + } + else if (childNode is IdentifierExpressionBackreference) + { VisitIdentifierExpressionBackreference((IdentifierExpressionBackreference)childNode); - } else if (childNode is Choice) { + } + else if (childNode is Choice) + { VisitChoice((Choice)childNode); - } else if (childNode is AnyNode) { + } + else if (childNode is AnyNode) + { VisitAnyNode((AnyNode)childNode); - } else if (childNode is Backreference) { + } + else if (childNode is Backreference) + { VisitBackreference((Backreference)childNode); - } else if (childNode is NamedNode) { + } + else if (childNode is NamedNode) + { VisitNamedNode((NamedNode)childNode); - } else if (childNode is OptionalNode) { + } + else if (childNode is OptionalNode) + { VisitOptionalNode((OptionalNode)childNode); - } else if (childNode is Repeat) { + } + else if (childNode is Repeat) + { VisitRepeat((Repeat)childNode); - } else { + } + else + { writer.WritePrimitiveValue(childNode); } } @@ -2647,13 +2891,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitDocumentationReference(DocumentationReference documentationReference) { StartNode(documentationReference); - if (!documentationReference.DeclaringType.IsNull) { + if (!documentationReference.DeclaringType.IsNull) + { documentationReference.DeclaringType.AcceptVisitor(this); - if (documentationReference.SymbolKind != SymbolKind.TypeDefinition) { + if (documentationReference.SymbolKind != SymbolKind.TypeDefinition) + { WriteToken(Roles.Dot); } } - switch (documentationReference.SymbolKind) { + switch (documentationReference.SymbolKind) + { case SymbolKind.TypeDefinition: // we already printed the DeclaringType break; @@ -2662,16 +2909,22 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor break; case SymbolKind.Operator: var opType = documentationReference.OperatorType; - if (opType == OperatorType.Explicit) { + if (opType == OperatorType.Explicit) + { WriteKeyword(OperatorDeclaration.ExplicitRole); - } else if (opType == OperatorType.Implicit) { + } + else if (opType == OperatorType.Implicit) + { WriteKeyword(OperatorDeclaration.ImplicitRole); } WriteKeyword(OperatorDeclaration.OperatorKeywordRole); Space(); - if (opType == OperatorType.Explicit || opType == OperatorType.Implicit) { + if (opType == OperatorType.Explicit || opType == OperatorType.Implicit) + { documentationReference.ConversionOperatorReturnType.AcceptVisitor(this); - } else { + } + else + { WriteToken(OperatorDeclaration.GetToken(opType), OperatorDeclaration.GetRole(opType)); } break; @@ -2680,11 +2933,15 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor break; } WriteTypeArguments(documentationReference.TypeArguments); - if (documentationReference.HasParameterList) { + if (documentationReference.HasParameterList) + { Space(policy.SpaceBeforeMethodDeclarationParentheses); - if (documentationReference.SymbolKind == SymbolKind.Indexer) { + if (documentationReference.SymbolKind == SymbolKind.Indexer) + { WriteCommaSeparatedListInBrackets(documentationReference.Parameters, policy.SpaceWithinMethodDeclarationParentheses); - } else { + } + else + { WriteCommaSeparatedListInParenthesis(documentationReference.Parameters, policy.SpaceWithinMethodDeclarationParentheses); } } diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/FormattingOptionsFactory.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/FormattingOptionsFactory.cs index 6391cf62f..f7775172b 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/FormattingOptionsFactory.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/FormattingOptionsFactory.cs @@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor ConstructorBraceStyle = BraceStyle.NextLine, DestructorBraceStyle = BraceStyle.NextLine, AnonymousMethodBraceStyle = BraceStyle.EndOfLine, - + PropertyBraceStyle = BraceStyle.EndOfLine, PropertyGetBraceStyle = BraceStyle.EndOfLine, PropertySetBraceStyle = BraceStyle.EndOfLine, @@ -81,7 +81,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor AllowEventAddBlockInline = true, AllowEventRemoveBlockInline = true, StatementBraceStyle = BraceStyle.EndOfLine, - + ElseNewLinePlacement = NewLinePlacement.SameLine, ElseIfNewLinePlacement = NewLinePlacement.SameLine, CatchNewLinePlacement = NewLinePlacement.SameLine, @@ -103,7 +103,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor SpacesBetweenEmptyNewParentheses = false, SpaceBeforeNewParameterComma = false, SpaceAfterNewParameterComma = true, - + SpaceBeforeIfParentheses = true, SpaceBeforeWhileParentheses = true, SpaceBeforeForParentheses = true, @@ -140,16 +140,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor SpaceAfterConditionalOperatorCondition = true, SpaceBeforeConditionalOperatorSeparator = true, SpaceAfterConditionalOperatorSeparator = true, - + SpacesWithinBrackets = false, SpacesBeforeBrackets = true, SpaceBeforeBracketComma = false, SpaceAfterBracketComma = true, - + SpaceBeforeForSemicolon = false, SpaceAfterForSemicolon = true, SpaceAfterTypecast = false, - + AlignEmbeddedStatements = true, SimplePropertyFormatting = PropertyFormatting.AllowOneLine, AutoPropertyFormatting = PropertyFormatting.AllowOneLine, @@ -161,19 +161,19 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor SpaceAfterFieldDeclarationComma = true, SpaceBeforeLocalVariableDeclarationComma = false, SpaceAfterLocalVariableDeclarationComma = true, - + SpaceBeforeIndexerDeclarationBracket = true, SpaceWithinIndexerDeclarationBracket = false, SpaceBeforeIndexerDeclarationParameterComma = false, SpaceInNamedArgumentAfterDoubleColon = true, RemoveEndOfLineWhiteSpace = true, - + SpaceAfterIndexerDeclarationParameterComma = true, - + MinimumBlankLinesBeforeUsings = 0, MinimumBlankLinesAfterUsings = 1, UsingPlacement = UsingPlacement.TopOfFile, - + MinimumBlankLinesBeforeFirstDeclaration = 0, MinimumBlankLinesBetweenTypes = 1, MinimumBlankLinesBetweenFields = 0, @@ -242,14 +242,14 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor PropertySetBraceStyle = BraceStyle.EndOfLine, SimpleGetBlockFormatting = PropertyFormatting.AllowOneLine, SimpleSetBlockFormatting = PropertyFormatting.AllowOneLine, - + EventBraceStyle = BraceStyle.EndOfLine, EventAddBraceStyle = BraceStyle.EndOfLine, EventRemoveBraceStyle = BraceStyle.EndOfLine, AllowEventAddBlockInline = true, AllowEventRemoveBlockInline = true, StatementBraceStyle = BraceStyle.EndOfLine, - + ElseNewLinePlacement = NewLinePlacement.SameLine, ElseIfNewLinePlacement = NewLinePlacement.SameLine, CatchNewLinePlacement = NewLinePlacement.SameLine, @@ -257,7 +257,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor WhileNewLinePlacement = NewLinePlacement.SameLine, ArrayInitializerWrapping = Wrapping.WrapIfTooLong, ArrayInitializerBraceStyle = BraceStyle.EndOfLine, - + SpaceBeforeMethodCallParentheses = false, SpaceBeforeMethodDeclarationParentheses = false, SpaceBeforeConstructorDeclarationParentheses = false, @@ -267,13 +267,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor SpaceAfterConstructorDeclarationParameterComma = true, NewLineBeforeConstructorInitializerColon = NewLinePlacement.NewLine, NewLineAfterConstructorInitializerColon = NewLinePlacement.SameLine, - + SpaceBeforeNewParentheses = false, SpacesWithinNewParentheses = false, SpacesBetweenEmptyNewParentheses = false, SpaceBeforeNewParameterComma = false, SpaceAfterNewParameterComma = true, - + SpaceBeforeIfParentheses = true, SpaceBeforeWhileParentheses = true, SpaceBeforeForParentheses = true, @@ -317,11 +317,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor SpacesBeforeBrackets = false, SpaceBeforeBracketComma = false, SpaceAfterBracketComma = true, - + SpaceBeforeForSemicolon = false, SpaceAfterForSemicolon = true, SpaceAfterTypecast = false, - + AlignEmbeddedStatements = true, SimplePropertyFormatting = PropertyFormatting.AllowOneLine, AutoPropertyFormatting = PropertyFormatting.AllowOneLine, @@ -333,14 +333,14 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor SpaceAfterFieldDeclarationComma = true, SpaceBeforeLocalVariableDeclarationComma = false, SpaceAfterLocalVariableDeclarationComma = true, - + SpaceWithinIndexerDeclarationBracket = false, SpaceBeforeIndexerDeclarationParameterComma = false, SpaceInNamedArgumentAfterDoubleColon = true, - + SpaceAfterIndexerDeclarationParameterComma = true, RemoveEndOfLineWhiteSpace = true, - + MinimumBlankLinesBeforeUsings = 0, MinimumBlankLinesAfterUsings = 1, @@ -351,7 +351,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor MinimumBlankLinesBetweenMembers = 1, MinimumBlankLinesAroundRegion = 1, MinimumBlankLinesInsideRegion = 1, - + KeepCommentsAtFirstColumn = true, ChainedMethodCallWrapping = Wrapping.DoNotChange, MethodCallArgumentWrapping = Wrapping.DoNotChange, @@ -401,7 +401,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public static CSharpFormattingOptions CreateWhitesmiths() { var baseOptions = CreateKRStyle(); - + baseOptions.NamespaceBraceStyle = BraceStyle.NextLineShifted; baseOptions.ClassBraceStyle = BraceStyle.NextLineShifted; baseOptions.InterfaceBraceStyle = BraceStyle.NextLineShifted; @@ -414,7 +414,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor baseOptions.PropertyBraceStyle = BraceStyle.NextLineShifted; baseOptions.PropertyGetBraceStyle = BraceStyle.NextLineShifted; baseOptions.PropertySetBraceStyle = BraceStyle.NextLineShifted; - + baseOptions.EventBraceStyle = BraceStyle.NextLineShifted; baseOptions.EventAddBraceStyle = BraceStyle.NextLineShifted; baseOptions.EventRemoveBraceStyle = BraceStyle.NextLineShifted; diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs index f621e99b3..74e99d8c0 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/GenericGrammarAmbiguityVisitor.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -35,8 +36,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor /// public static void ResolveAmbiguities(AstNode rootNode) { - foreach (var node in rootNode.Descendants.OfType()) { - if (CausesAmbiguityWithGenerics(node)) { + foreach (var node in rootNode.Descendants.OfType()) + { + if (CausesAmbiguityWithGenerics(node)) + { node.ReplaceWith(n => new ParenthesizedExpression(n)); } } @@ -50,7 +53,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor var v = new GenericGrammarAmbiguityVisitor(); v.genericNestingLevel = 1; - for (AstNode node = binaryOperatorExpression.Right; node != null; node = node.GetNextNode()) { + for (AstNode node = binaryOperatorExpression.Right; node != null; node = node.GetNextNode()) + { if (node.AcceptVisitor(v)) return v.ambiguityFound; } @@ -63,11 +67,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected override bool VisitChildren(AstNode node) { // unhandled node: probably not syntactically valid in a typename - + // These are preconditions for all recursive Visit() calls. Debug.Assert(genericNestingLevel > 0); Debug.Assert(!ambiguityFound); - + // The return value merely indicates whether to stop visiting. return true; // stop visiting, no ambiguity found } @@ -77,7 +81,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor if (binaryOperatorExpression.Left.AcceptVisitor(this)) return true; Debug.Assert(genericNestingLevel > 0); - switch (binaryOperatorExpression.Operator) { + switch (binaryOperatorExpression.Operator) + { case BinaryOperatorType.LessThan: genericNestingLevel += 1; break; @@ -90,7 +95,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor default: return true; // stop visiting, no ambiguity found } - if (genericNestingLevel == 0) { + if (genericNestingLevel == 0) + { // Of the all tokens that might follow `>` and trigger the ambiguity to be resolved in favor of generics, // `(` is the only one that might start an expression. ambiguityFound = binaryOperatorExpression.Right is ParenthesizedExpression; diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/ITokenWriter.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/ITokenWriter.cs index 4d9bd0f43..40586e61d 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/ITokenWriter.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/ITokenWriter.cs @@ -18,6 +18,7 @@ using System; using System.IO; + using ICSharpCode.Decompiler.CSharp.Syntax; namespace ICSharpCode.Decompiler.CSharp.OutputVisitor diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs index c40094a20..8b637218d 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -27,55 +28,65 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor readonly Stack> nodes = new Stack>(); List currentList; readonly ILocatable locationProvider; - + public InsertMissingTokensDecorator(TokenWriter writer, ILocatable locationProvider) : base(writer) { this.locationProvider = locationProvider; currentList = new List(); } - + public override void StartNode(AstNode node) { // ignore whitespace: these don't need to be processed. // StartNode/EndNode is only called for them to support folding of comments. - if (node.NodeType != NodeType.Whitespace) { + if (node.NodeType != NodeType.Whitespace) + { currentList.Add(node); nodes.Push(currentList); currentList = new List(); - } else if (node is Comment comment) { + } + else if (node is Comment comment) + { comment.SetStartLocation(locationProvider.Location); } - if (node is ErrorExpression error) { + if (node is ErrorExpression error) + { error.Location = locationProvider.Location; } base.StartNode(node); } - + public override void EndNode(AstNode node) { // ignore whitespace: these don't need to be processed. // StartNode/EndNode is only called for them to support folding of comments. - if (node.NodeType != NodeType.Whitespace) { + if (node.NodeType != NodeType.Whitespace) + { System.Diagnostics.Debug.Assert(currentList != null); - foreach (var removable in node.Children.Where(n => n is CSharpTokenNode)) { + foreach (var removable in node.Children.Where(n => n is CSharpTokenNode)) + { removable.Remove(); } - foreach (var child in currentList) { + foreach (var child in currentList) + { System.Diagnostics.Debug.Assert(child.Parent == null || node == child.Parent); child.Remove(); node.AddChildWithExistingRole(child); } currentList = nodes.Pop(); - } else if (node is Comment comment) { + } + else if (node is Comment comment) + { comment.SetEndLocation(locationProvider.Location); } base.EndNode(node); } - + public override void WriteToken(Role role, string token) { - switch (nodes.Peek().LastOrDefault()) { + switch (nodes.Peek().LastOrDefault()) + { case EmptyStatement emptyStatement: emptyStatement.Location = locationProvider.Location; break; @@ -90,7 +101,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } base.WriteToken(role, token); } - + public override void WriteKeyword(Role role, string keyword) { TextLocation start = locationProvider.Location; @@ -99,22 +110,26 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor t = new CSharpTokenNode(start, (TokenRole)role); else if (role == EntityDeclaration.ModifierRole) t = new CSharpModifierToken(start, CSharpModifierToken.GetModifierValue(keyword)); - else if (keyword == "this") { + else if (keyword == "this") + { ThisReferenceExpression node = nodes.Peek().LastOrDefault() as ThisReferenceExpression; if (node != null) node.Location = start; - } else if (keyword == "base") { + } + else if (keyword == "base") + { BaseReferenceExpression node = nodes.Peek().LastOrDefault() as BaseReferenceExpression; if (node != null) node.Location = start; } - if (t != null) { + if (t != null) + { currentList.Add(t); t.Role = role; } base.WriteKeyword(role, keyword); } - + public override void WriteIdentifier(Identifier identifier) { if (!identifier.IsNull) @@ -122,16 +137,18 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor currentList.Add(identifier); base.WriteIdentifier(identifier); } - + public override void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None) { Expression node = nodes.Peek().LastOrDefault() as Expression; var startLocation = locationProvider.Location; base.WritePrimitiveValue(value, format); - if (node is PrimitiveExpression) { + if (node is PrimitiveExpression) + { ((PrimitiveExpression)node).SetLocation(startLocation, locationProvider.Location); } - if (node is NullReferenceExpression) { + if (node is NullReferenceExpression) + { ((NullReferenceExpression)node).SetStartLocation(startLocation); } } diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs index 99e4ff8b7..c266d677a 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.CSharp.Syntax; namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -35,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor /// If this property is false, it will insert parentheses only where strictly required by the language spec. /// public bool InsertParenthesesForReadability { get; set; } - + enum PrecedenceLevel { // Higher integer value = higher precedence. @@ -59,20 +60,23 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor NullableRewrap, Primary } - + /// /// Gets the row number in the C# 4.0 spec operator precedence table. /// static PrecedenceLevel GetPrecedence(Expression expr) { // Note: the operator precedence table on MSDN is incorrect - if (expr is QueryExpression) { + if (expr is QueryExpression) + { // Not part of the table in the C# spec, but we need to ensure that queries within // primary expressions get parenthesized. return PrecedenceLevel.QueryOrLambda; } - if (expr is UnaryOperatorExpression uoe) { - switch (uoe.Operator) { + if (expr is UnaryOperatorExpression uoe) + { + switch (uoe.Operator) + { case UnaryOperatorType.PostDecrement: case UnaryOperatorType.PostIncrement: case UnaryOperatorType.NullConditional: @@ -88,7 +92,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } if (expr is CastExpression) return PrecedenceLevel.Unary; - if (expr is PrimitiveExpression primitive) { + if (expr is PrimitiveExpression primitive) + { var value = primitive.Value; if (value is int i && i < 0) return PrecedenceLevel.Unary; @@ -102,8 +107,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor return PrecedenceLevel.Unary; return PrecedenceLevel.Primary; } - if (expr is BinaryOperatorExpression boe) { - switch (boe.Operator) { + if (expr is BinaryOperatorExpression boe) + { + switch (boe.Operator) + { case BinaryOperatorType.Range: return PrecedenceLevel.Range; case BinaryOperatorType.Multiply: @@ -151,13 +158,14 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor // anything else: primary expression return PrecedenceLevel.Primary; } - + /// /// Parenthesizes the expression if it does not have the minimum required precedence. /// static void ParenthesizeIfRequired(Expression expr, PrecedenceLevel minimumPrecedence) { - if (GetPrecedence(expr) < minimumPrecedence) { + if (GetPrecedence(expr) < minimumPrecedence) + { Parenthesize(expr); } } @@ -166,30 +174,31 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { expr.ReplaceWith(e => new ParenthesizedExpression { Expression = e }); } - + // Primary expressions public override void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) { ParenthesizeIfRequired(memberReferenceExpression.Target, PrecedenceLevel.Primary); base.VisitMemberReferenceExpression(memberReferenceExpression); } - + public override void VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression) { ParenthesizeIfRequired(pointerReferenceExpression.Target, PrecedenceLevel.Primary); base.VisitPointerReferenceExpression(pointerReferenceExpression); } - + public override void VisitInvocationExpression(InvocationExpression invocationExpression) { ParenthesizeIfRequired(invocationExpression.Target, PrecedenceLevel.Primary); base.VisitInvocationExpression(invocationExpression); } - + public override void VisitIndexerExpression(IndexerExpression indexerExpression) { ParenthesizeIfRequired(indexerExpression.Target, PrecedenceLevel.Primary); - switch (indexerExpression.Target) { + switch (indexerExpression.Target) + { case ArrayCreateExpression ace when InsertParenthesesForReadability || ace.Initializer.IsNull: // require parentheses for "(new int[1])[0]" Parenthesize(indexerExpression.Target); @@ -201,7 +210,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } base.VisitIndexerExpression(indexerExpression); } - + // Unary expressions public override void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression) { @@ -211,26 +220,31 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor Parenthesize(child); base.VisitUnaryOperatorExpression(unaryOperatorExpression); } - + public override void VisitCastExpression(CastExpression castExpression) { // Even in readability mode, don't parenthesize casts of casts. - if (!(castExpression.Expression is CastExpression)) { + if (!(castExpression.Expression is CastExpression)) + { ParenthesizeIfRequired(castExpression.Expression, InsertParenthesesForReadability ? PrecedenceLevel.NullableRewrap : PrecedenceLevel.Unary); } // There's a nasty issue in the C# grammar: cast expressions including certain operators are ambiguous in some cases // "(int)-1" is fine, but "(A)-b" is not a cast. UnaryOperatorExpression uoe = castExpression.Expression as UnaryOperatorExpression; - if (uoe != null && !(uoe.Operator == UnaryOperatorType.BitNot || uoe.Operator == UnaryOperatorType.Not)) { - if (TypeCanBeMisinterpretedAsExpression(castExpression.Type)) { + if (uoe != null && !(uoe.Operator == UnaryOperatorType.BitNot || uoe.Operator == UnaryOperatorType.Not)) + { + if (TypeCanBeMisinterpretedAsExpression(castExpression.Type)) + { Parenthesize(castExpression.Expression); } } // The above issue can also happen with PrimitiveExpressions representing negative values: PrimitiveExpression pe = castExpression.Expression as PrimitiveExpression; - if (pe != null && pe.Value != null && TypeCanBeMisinterpretedAsExpression(castExpression.Type)) { + if (pe != null && pe.Value != null && TypeCanBeMisinterpretedAsExpression(castExpression.Type)) + { TypeCode typeCode = Type.GetTypeCode(pe.Value.GetType()); - switch (typeCode) { + switch (typeCode) + { case TypeCode.SByte: if ((sbyte)pe.Value < 0) Parenthesize(castExpression.Expression); @@ -263,7 +277,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } base.VisitCastExpression(castExpression); } - + static bool TypeCanBeMisinterpretedAsExpression(AstType type) { // SimpleTypes can always be misinterpreted as IdentifierExpressions @@ -275,36 +289,51 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor else return type is SimpleType; } - + // Binary Operators public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { PrecedenceLevel precedence = GetPrecedence(binaryOperatorExpression); - if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing) { - if (InsertParenthesesForReadability) { + if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing) + { + if (InsertParenthesesForReadability) + { ParenthesizeIfRequired(binaryOperatorExpression.Left, PrecedenceLevel.NullableRewrap); - if (GetBinaryOperatorType(binaryOperatorExpression.Right) == BinaryOperatorType.NullCoalescing) { + if (GetBinaryOperatorType(binaryOperatorExpression.Right) == BinaryOperatorType.NullCoalescing) + { ParenthesizeIfRequired(binaryOperatorExpression.Right, precedence); - } else { + } + else + { ParenthesizeIfRequired(binaryOperatorExpression.Right, PrecedenceLevel.NullableRewrap); } - } else { + } + else + { // ?? is right-associative ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence + 1); ParenthesizeIfRequired(binaryOperatorExpression.Right, precedence); } - } else { - if (InsertParenthesesForReadability && precedence < PrecedenceLevel.Equality) { + } + else + { + if (InsertParenthesesForReadability && precedence < PrecedenceLevel.Equality) + { // In readable mode, boost the priority of the left-hand side if the operator // there isn't the same as the operator on this expression. PrecedenceLevel boostTo = IsBitwise(binaryOperatorExpression.Operator) ? PrecedenceLevel.Unary : PrecedenceLevel.Equality; - if (GetBinaryOperatorType(binaryOperatorExpression.Left) == binaryOperatorExpression.Operator) { + if (GetBinaryOperatorType(binaryOperatorExpression.Left) == binaryOperatorExpression.Operator) + { ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence); - } else { + } + else + { ParenthesizeIfRequired(binaryOperatorExpression.Left, boostTo); } ParenthesizeIfRequired(binaryOperatorExpression.Right, boostTo); - } else { + } + else + { // all other binary operators are left-associative ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence); ParenthesizeIfRequired(binaryOperatorExpression.Right, precedence + 1); @@ -328,34 +357,41 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor else return null; } - + public override void VisitIsExpression(IsExpression isExpression) { - if (InsertParenthesesForReadability) { + if (InsertParenthesesForReadability) + { // few people know the precedence of 'is', so always put parentheses in nice-looking mode. ParenthesizeIfRequired(isExpression.Expression, PrecedenceLevel.NullableRewrap); - } else { + } + else + { ParenthesizeIfRequired(isExpression.Expression, PrecedenceLevel.RelationalAndTypeTesting); } base.VisitIsExpression(isExpression); } - + public override void VisitAsExpression(AsExpression asExpression) { - if (InsertParenthesesForReadability) { + if (InsertParenthesesForReadability) + { // few people know the precedence of 'as', so always put parentheses in nice-looking mode. ParenthesizeIfRequired(asExpression.Expression, PrecedenceLevel.NullableRewrap); - } else { + } + else + { ParenthesizeIfRequired(asExpression.Expression, PrecedenceLevel.RelationalAndTypeTesting); } base.VisitAsExpression(asExpression); } - + // Conditional operator public override void VisitConditionalExpression(ConditionalExpression conditionalExpression) { // Inside of string interpolation ?: always needs parentheses. - if (conditionalExpression.Parent is Interpolation) { + if (conditionalExpression.Parent is Interpolation) + { Parenthesize(conditionalExpression); } @@ -363,12 +399,15 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor // (a ? b : c ? d : e) == (a ? b : (c ? d : e)) // (a ? b ? c : d : e) == (a ? (b ? c : d) : e) // Only ((a ? b : c) ? d : e) strictly needs the additional parentheses - if (InsertParenthesesForReadability && !IsConditionalRefExpression(conditionalExpression)) { + if (InsertParenthesesForReadability && !IsConditionalRefExpression(conditionalExpression)) + { // Precedence of ?: can be confusing; so always put parentheses in nice-looking mode. ParenthesizeIfRequired(conditionalExpression.Condition, PrecedenceLevel.NullableRewrap); ParenthesizeIfRequired(conditionalExpression.TrueExpression, PrecedenceLevel.NullableRewrap); ParenthesizeIfRequired(conditionalExpression.FalseExpression, PrecedenceLevel.NullableRewrap); - } else { + } + else + { ParenthesizeIfRequired(conditionalExpression.Condition, PrecedenceLevel.Conditional + 1); ParenthesizeIfRequired(conditionalExpression.TrueExpression, PrecedenceLevel.Conditional); ParenthesizeIfRequired(conditionalExpression.FalseExpression, PrecedenceLevel.Conditional); @@ -386,16 +425,19 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { // assignment is right-associative ParenthesizeIfRequired(assignmentExpression.Left, PrecedenceLevel.Assignment + 1); - if (InsertParenthesesForReadability && !(assignmentExpression.Right is DirectionExpression)) { + if (InsertParenthesesForReadability && !(assignmentExpression.Right is DirectionExpression)) + { ParenthesizeIfRequired(assignmentExpression.Right, PrecedenceLevel.RelationalAndTypeTesting + 1); - } else { + } + else + { ParenthesizeIfRequired(assignmentExpression.Right, PrecedenceLevel.Assignment); } base.VisitAssignmentExpression(assignmentExpression); } - + // don't need to handle lambdas, they have lowest precedence and unambiguous associativity - + public override void VisitQueryExpression(QueryExpression queryExpression) { // Query expressions are strange beasts: @@ -407,7 +449,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor Parenthesize(queryExpression); if (queryExpression.Parent is IsExpression || queryExpression.Parent is AsExpression) Parenthesize(queryExpression); - if (InsertParenthesesForReadability) { + if (InsertParenthesesForReadability) + { // when readability is desired, always parenthesize query expressions within unary or binary operators if (queryExpression.Parent is UnaryOperatorExpression || queryExpression.Parent is BinaryOperatorExpression) Parenthesize(queryExpression); @@ -415,12 +458,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor base.VisitQueryExpression(queryExpression); } - public override void VisitNamedExpression (NamedExpression namedExpression) + public override void VisitNamedExpression(NamedExpression namedExpression) { - if (InsertParenthesesForReadability) { + if (InsertParenthesesForReadability) + { ParenthesizeIfRequired(namedExpression.Expression, PrecedenceLevel.RelationalAndTypeTesting + 1); } - base.VisitNamedExpression (namedExpression); + base.VisitNamedExpression(namedExpression); } public override void VisitSwitchExpression(SwitchExpression switchExpression) diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs index e5e83f0a2..ede737fd9 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertRequiredSpacesDecorator.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.CSharp.Syntax; namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -27,7 +28,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor /// Used to insert the minimal amount of spaces so that the lexer recognizes the tokens that were written. /// LastWritten lastWritten; - + enum LastWritten { Whitespace, @@ -39,36 +40,41 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor QuestionMark, Division } - + public InsertRequiredSpacesDecorator(TokenWriter writer) : base(writer) { } - + public override void WriteIdentifier(Identifier identifier) { - if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) { - if (lastWritten == LastWritten.KeywordOrIdentifier) { + if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) + { + if (lastWritten == LastWritten.KeywordOrIdentifier) + { // this space is not strictly required, so we call Space() Space(); } - } else if (lastWritten == LastWritten.KeywordOrIdentifier) { + } + else if (lastWritten == LastWritten.KeywordOrIdentifier) + { // this space is strictly required, so we directly call the formatter base.Space(); } base.WriteIdentifier(identifier); lastWritten = LastWritten.KeywordOrIdentifier; } - + public override void WriteKeyword(Role role, string keyword) { - if (lastWritten == LastWritten.KeywordOrIdentifier) { + if (lastWritten == LastWritten.KeywordOrIdentifier) + { Space(); } base.WriteKeyword(role, keyword); lastWritten = LastWritten.KeywordOrIdentifier; } - + public override void WriteToken(Role role, string token) { // Avoid that two +, - or ? tokens are combined into a ++, -- or ?? token. @@ -78,43 +84,56 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor // 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] == '*') { + lastWritten == LastWritten.Minus && token[0] == '-' || + lastWritten == LastWritten.Ampersand && token[0] == '&' || + lastWritten == LastWritten.QuestionMark && token[0] == '?' || + lastWritten == LastWritten.Division && token[0] == '*') + { base.Space(); } base.WriteToken(role, token); - if (token == "+") { + if (token == "+") + { lastWritten = LastWritten.Plus; - } else if (token == "-") { + } + else if (token == "-") + { lastWritten = LastWritten.Minus; - } else if (token == "&") { + } + else if (token == "&") + { lastWritten = LastWritten.Ampersand; - } else if (token == "?") { + } + else if (token == "?") + { lastWritten = LastWritten.QuestionMark; - } else if (token == "/") { + } + else if (token == "/") + { lastWritten = LastWritten.Division; - } else { + } + else + { lastWritten = LastWritten.Other; } } - + public override void Space() { base.Space(); lastWritten = LastWritten.Whitespace; } - + public override void NewLine() { base.NewLine(); lastWritten = LastWritten.Whitespace; } - + public override void WriteComment(CommentType commentType, string content) { - if (lastWritten == LastWritten.Division) { + if (lastWritten == LastWritten.Division) + { // When there's a comment starting after a division operator // "1.0 / /*comment*/a", then we need to insert a space in front of the comment. base.Space(); @@ -122,55 +141,75 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor base.WriteComment(commentType, content); lastWritten = LastWritten.Whitespace; } - + public override void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument) { base.WritePreProcessorDirective(type, argument); lastWritten = LastWritten.Whitespace; } - + public override void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None) { - if (lastWritten == LastWritten.KeywordOrIdentifier) { + if (lastWritten == LastWritten.KeywordOrIdentifier) + { Space(); } base.WritePrimitiveValue(value, format); if (value == null || value is bool) return; - if (value is string) { + if (value is string) + { lastWritten = LastWritten.Other; - } else if (value is char) { + } + else if (value is char) + { lastWritten = LastWritten.Other; - } else if (value is decimal) { + } + else if (value is decimal) + { lastWritten = LastWritten.Other; - } else if (value is float) { + } + else if (value is float) + { float f = (float)value; - if (float.IsInfinity(f) || float.IsNaN(f)) return; + if (float.IsInfinity(f) || float.IsNaN(f)) + return; lastWritten = LastWritten.Other; - } else if (value is double) { + } + else if (value is double) + { double f = (double)value; - if (double.IsInfinity(f) || double.IsNaN(f)) return; + if (double.IsInfinity(f) || double.IsNaN(f)) + return; // needs space if identifier follows number; // this avoids mistaking the following identifier as type suffix lastWritten = LastWritten.KeywordOrIdentifier; - } else if (value is IFormattable) { + } + else if (value is IFormattable) + { // needs space if identifier follows number; // this avoids mistaking the following identifier as type suffix lastWritten = LastWritten.KeywordOrIdentifier; - } else { + } + else + { lastWritten = LastWritten.Other; } } - + public override void WritePrimitiveType(string type) { - if (lastWritten == LastWritten.KeywordOrIdentifier) { + if (lastWritten == LastWritten.KeywordOrIdentifier) + { Space(); } base.WritePrimitiveType(type); - if (type == "new") { + if (type == "new") + { lastWritten = LastWritten.Other; - } else { + } + else + { lastWritten = LastWritten.KeywordOrIdentifier; } } diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertSpecialsDecorator.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertSpecialsDecorator.cs index 34b7288e2..61901cc9c 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertSpecialsDecorator.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertSpecialsDecorator.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Diagnostics; + using ICSharpCode.Decompiler.CSharp.Syntax; namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -26,20 +27,21 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { readonly Stack positionStack = new Stack(); int visitorWroteNewLine = 0; - + public InsertSpecialsDecorator(TokenWriter writer) : base(writer) { } - + public override void StartNode(AstNode node) { - if (positionStack.Count > 0) { + if (positionStack.Count > 0) + { WriteSpecialsUpToNode(node); } positionStack.Push(node.FirstChild); base.StartNode(node); } - + public override void EndNode(AstNode node) { base.EndNode(node); @@ -47,42 +49,45 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor Debug.Assert(pos == null || pos.Parent == node); WriteSpecials(pos, null); } - + public override void WriteKeyword(Role role, string keyword) { - if (role != null) { + if (role != null) + { WriteSpecialsUpToRole(role); } base.WriteKeyword(role, keyword); } - + public override void WriteIdentifier(Identifier identifier) { WriteSpecialsUpToRole(identifier.Role ?? Roles.Identifier); base.WriteIdentifier(identifier); } - + public override void WriteToken(Role role, string token) { WriteSpecialsUpToRole(role); base.WriteToken(role, token); } - + public override void NewLine() { if (visitorWroteNewLine >= 0) base.NewLine(); visitorWroteNewLine++; } - + #region WriteSpecials /// /// Writes all specials from start to end (exclusive). Does not touch the positionStack. /// void WriteSpecials(AstNode start, AstNode end) { - for (AstNode pos = start; pos != end; pos = pos.NextSibling) { - if (pos.Role == Roles.Comment) { + for (AstNode pos = start; pos != end; pos = pos.NextSibling) + { + if (pos.Role == Roles.Comment) + { var node = (Comment)pos; base.StartNode(node); base.WriteComment(node.CommentType, node.Content); @@ -94,7 +99,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor // base.NewLine(); // visitorWroteNewLine--; // } - if (pos.Role == Roles.PreProcessorDirective) { + if (pos.Role == Roles.PreProcessorDirective) + { var node = (PreProcessorDirective)pos; base.StartNode(node); base.WritePreProcessorDirective(node.Type, node.Argument); @@ -102,7 +108,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } } } - + /// /// Writes all specials between the current position (in the positionStack) and the next /// node with the specified role. Advances the current position. @@ -111,15 +117,18 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { WriteSpecialsUpToRole(role, null); } - + void WriteSpecialsUpToRole(Role role, AstNode nextNode) { - if (positionStack.Count == 0) { + if (positionStack.Count == 0) + { return; } // 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 == role) { + for (AstNode pos = positionStack.Peek(); pos != null && pos != nextNode; pos = pos.NextSibling) + { + if (pos.Role == role) + { WriteSpecials(positionStack.Pop(), pos); // Push the next sibling because the node matching the role is not a special, // and should be considered to be already handled. @@ -129,18 +138,21 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } } } - + /// /// Writes all specials between the current position (in the positionStack) and the specified node. /// Advances the current position. /// void WriteSpecialsUpToNode(AstNode node) { - if (positionStack.Count == 0) { + if (positionStack.Count == 0) + { return; } - for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) { - if (pos == node) { + for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) + { + if (pos == node) + { WriteSpecials(positionStack.Pop(), pos); // Push the next sibling because the node itself is not a special, // and should be considered to be already handled. diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs index 0e3bd552d..fc837a163 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs @@ -20,6 +20,7 @@ using System; using System.Globalization; using System.IO; using System.Text; + using ICSharpCode.Decompiler.CSharp.Syntax; namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -57,7 +58,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public override void WriteIdentifier(Identifier identifier) { WriteIndentation(); - if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) { + if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) + { textWriter.Write('@'); column++; Length++; @@ -97,9 +99,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor protected void WriteIndentation() { - if (needsIndent) { + if (needsIndent) + { needsIndent = false; - for (int i = 0; i < Indentation; i++) { + for (int i = 0; i < Indentation; i++) + { textWriter.Write(this.IndentationString); } column += Indentation * IndentationString.Length; @@ -130,7 +134,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public override void WriteComment(CommentType commentType, string content) { WriteIndentation(); - switch (commentType) { + switch (commentType) + { case CommentType.SingleLine: textWriter.Write("//"); textWriter.WriteLine(content); @@ -181,9 +186,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor { if (string.IsNullOrEmpty(content)) return; - for (int i = 0; i < content.Length; i++) { + for (int i = 0; i < content.Length; i++) + { char ch = content[i]; - switch (ch) { + switch (ch) + { case '\r': if (i + 1 < content.Length && content[i + 1] == '\n') i++; @@ -208,7 +215,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor textWriter.Write(directive); column += 1 + directive.Length; Length += 1 + directive.Length; - if (!string.IsNullOrEmpty(argument)) { + if (!string.IsNullOrEmpty(argument)) + { textWriter.Write(' '); textWriter.Write(argument); column += 1 + argument.Length; @@ -224,10 +232,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor tokenWriter.WritePrimitiveValue(value); return writer.ToString(); } - + public override void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None) { - if (value == null) { + if (value == null) + { // usually NullReferenceExpression should be used for this, but we'll handle it anyways textWriter.Write("null"); column += 4; @@ -235,12 +244,16 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor return; } - if (value is bool) { - if ((bool)value) { + if (value is bool) + { + if ((bool)value) + { textWriter.Write("true"); column += 4; Length += 4; - } else { + } + else + { textWriter.Write("false"); column += 5; Length += 5; @@ -248,43 +261,56 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor return; } - if (value is string) { + if (value is string) + { string tmp = ConvertString(value.ToString()); column += tmp.Length + 2; Length += tmp.Length + 2; textWriter.Write('"'); textWriter.Write(tmp); textWriter.Write('"'); - } else if (value is char) { + } + else if (value is char) + { string tmp = ConvertCharLiteral((char)value); column += tmp.Length + 2; Length += tmp.Length + 2; textWriter.Write('\''); textWriter.Write(tmp); textWriter.Write('\''); - } else if (value is decimal) { + } + else if (value is decimal) + { string str = ((decimal)value).ToString(NumberFormatInfo.InvariantInfo) + "m"; column += str.Length; Length += str.Length; textWriter.Write(str); - } else if (value is float) { + } + else if (value is float) + { float f = (float)value; - if (float.IsInfinity(f) || float.IsNaN(f)) { + 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. textWriter.Write("float"); column += 5; Length += 5; WriteToken(Roles.Dot, "."); - if (float.IsPositiveInfinity(f)) { + if (float.IsPositiveInfinity(f)) + { textWriter.Write("PositiveInfinity"); column += "PositiveInfinity".Length; Length += "PositiveInfinity".Length; - } else if (float.IsNegativeInfinity(f)) { + } + else if (float.IsNegativeInfinity(f)) + { textWriter.Write("NegativeInfinity"); column += "NegativeInfinity".Length; Length += "NegativeInfinity".Length; - } else { + } + else + { textWriter.Write("NaN"); column += 3; Length += 3; @@ -292,7 +318,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor return; } var str = f.ToString("R", NumberFormatInfo.InvariantInfo) + "f"; - if (f == 0 && 1 / f == float.NegativeInfinity && str[0] != '-') { + if (f == 0 && 1 / f == float.NegativeInfinity && str[0] != '-') + { // negative zero is a special case // (again, not a primitive expression, but it's better to handle // the special case here than to do it in all code generators) @@ -301,24 +328,32 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor column += str.Length; Length += str.Length; textWriter.Write(str); - } else if (value is double) { + } + else if (value is double) + { double f = (double)value; - if (double.IsInfinity(f) || double.IsNaN(f)) { + 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. textWriter.Write("double"); column += 6; Length += 6; WriteToken(Roles.Dot, "."); - if (double.IsPositiveInfinity(f)) { + if (double.IsPositiveInfinity(f)) + { textWriter.Write("PositiveInfinity"); column += "PositiveInfinity".Length; Length += "PositiveInfinity".Length; - } else if (double.IsNegativeInfinity(f)) { + } + else if (double.IsNegativeInfinity(f)) + { textWriter.Write("NegativeInfinity"); column += "NegativeInfinity".Length; Length += "NegativeInfinity".Length; - } else { + } + else + { textWriter.Write("NaN"); column += 3; Length += 3; @@ -326,36 +361,47 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor return; } string number = f.ToString("R", NumberFormatInfo.InvariantInfo); - if (f == 0 && 1 / f == double.NegativeInfinity && number[0] != '-') { + if (f == 0 && 1 / f == double.NegativeInfinity && number[0] != '-') + { // negative zero is a special case // (again, not a primitive expression, but it's better to handle // the special case here than to do it in all code generators) number = '-' + number; } - if (number.IndexOf('.') < 0 && number.IndexOf('E') < 0) { + if (number.IndexOf('.') < 0 && number.IndexOf('E') < 0) + { number += ".0"; } textWriter.Write(number); column += number.Length; Length += number.Length; - } else if (value is IFormattable) { + } + else if (value is IFormattable) + { StringBuilder b = new StringBuilder(); - if (format == LiteralFormat.HexadecimalNumber) { + if (format == LiteralFormat.HexadecimalNumber) + { b.Append("0x"); b.Append(((IFormattable)value).ToString("X", NumberFormatInfo.InvariantInfo)); - } else { + } + else + { b.Append(((IFormattable)value).ToString(null, NumberFormatInfo.InvariantInfo)); } - if (value is uint || value is ulong) { + if (value is uint || value is ulong) + { b.Append("u"); } - if (value is long || value is ulong) { + if (value is long || value is ulong) + { b.Append("L"); } textWriter.Write(b.ToString()); column += b.Length; Length += b.Length; - } else { + } + else + { textWriter.Write(value.ToString()); int length = value.ToString().Length; column += length; @@ -374,7 +420,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor /// public static string ConvertCharLiteral(char ch) { - if (ch == '\'') { + if (ch == '\'') + { return "\\'"; } return ConvertChar(ch) ?? ch.ToString(); @@ -386,7 +433,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor /// This method does not convert ' or ". static string ConvertChar(char ch) { - switch (ch) { + switch (ch) + { case '\\': return "\\\\"; case '\0': @@ -415,7 +463,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor case '\ufffd': return "\\u" + ((int)ch).ToString("x4"); default: - switch (char.GetUnicodeCategory(ch)) { + switch (char.GetUnicodeCategory(ch)) + { case UnicodeCategory.NonSpacingMark: case UnicodeCategory.SpacingCombiningMark: case UnicodeCategory.EnclosingMark: @@ -442,10 +491,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public static string ConvertString(string str) { StringBuilder sb = new StringBuilder(); - foreach (char ch in str) { + foreach (char ch in str) + { string s = ch == '"' ? "\\\"" : ConvertChar(ch); - if (s != null) sb.Append(s); - else sb.Append(ch); + if (s != null) + sb.Append(s); + else + sb.Append(ch); } return sb.ToString(); } @@ -455,19 +507,29 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor if (string.IsNullOrEmpty(identifier)) return identifier; StringBuilder sb = new StringBuilder(); - for (int i = 0; i < identifier.Length; i++) { - if (IsPrintableIdentifierChar(identifier, i)) { - if (char.IsSurrogatePair(identifier, i)) { + for (int i = 0; i < identifier.Length; i++) + { + if (IsPrintableIdentifierChar(identifier, i)) + { + if (char.IsSurrogatePair(identifier, i)) + { sb.Append(identifier.Substring(i, 2)); i++; - } else { + } + else + { sb.Append(identifier[i]); } - } else { - if (char.IsSurrogatePair(identifier, i)) { + } + else + { + if (char.IsSurrogatePair(identifier, i)) + { sb.AppendFormat("\\U{0:x8}", char.ConvertToUtf32(identifier, i)); i++; - } else { + } + else + { sb.AppendFormat("\\u{0:x4}", (int)identifier[i]); } } @@ -480,7 +542,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor if (string.IsNullOrEmpty(identifier)) return false; - for (int i = 0; i < identifier.Length; i++) { + for (int i = 0; i < identifier.Length; i++) + { if (char.IsWhiteSpace(identifier[i])) return true; if (!IsPrintableIdentifierChar(identifier, i)) @@ -492,7 +555,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor static bool IsPrintableIdentifierChar(string identifier, int index) { - switch (identifier[index]) { + switch (identifier[index]) + { case '\\': return false; case ' ': @@ -501,7 +565,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor case '^': return true; } - switch (char.GetUnicodeCategory(identifier, index)) { + switch (char.GetUnicodeCategory(identifier, index)) + { case UnicodeCategory.NonSpacingMark: case UnicodeCategory.SpacingCombiningMark: case UnicodeCategory.EnclosingMark: @@ -526,7 +591,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor textWriter.Write(type); column += type.Length; Length += type.Length; - if (type == "new") { + if (type == "new") + { textWriter.Write("()"); column += 2; Length += 2; diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs index 9dbef8595..d5542fb6e 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectFileWriter.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.IO; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectInfoProvider.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectInfoProvider.cs index 6eb47a102..c9d2513de 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectInfoProvider.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectInfoProvider.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs index 6f21f0567..2e5a61ba1 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs @@ -22,6 +22,7 @@ using System.IO; using System.Linq; using System.Reflection.PortableExecutable; using System.Xml; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Solution; @@ -54,7 +55,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler typeGuids.Add(ProjectTypeGuids.PortableLibrary); typeGuids.Add(ProjectTypeGuids.CSharpWindows); - using (XmlTextWriter w = new XmlTextWriter(target)) { + using (XmlTextWriter w = new XmlTextWriter(target)) + { w.Formatting = Formatting.Indented; w.WriteStartDocument(); w.WriteStartElement("Project", ns); @@ -75,10 +77,14 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler w.WriteValue(platformName); w.WriteEndElement(); // - if (module.Reader.PEHeaders.IsDll) { + if (module.Reader.PEHeaders.IsDll) + { w.WriteElementString("OutputType", "Library"); - } else { - switch (module.Reader.PEHeaders.PEHeader.Subsystem) { + } + else + { + switch (module.Reader.PEHeaders.PEHeader.Subsystem) + { case Subsystem.WindowsGui: w.WriteElementString("OutputType", "WinExe"); break; @@ -103,7 +109,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler w.WriteElementString("WarningLevel", "4"); w.WriteElementString("AllowUnsafeBlocks", "True"); - if (project.StrongNameKeyFile != null) { + if (project.StrongNameKeyFile != null) + { w.WriteElementString("SignAssembly", "True"); w.WriteElementString("AssemblyOriginatorKeyFile", Path.GetFileName(project.StrongNameKeyFile)); } @@ -113,7 +120,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler w.WriteStartElement("PropertyGroup"); // platform-specific w.WriteAttributeString("Condition", " '$(Platform)' == '" + platformName + "' "); w.WriteElementString("PlatformTarget", platformName); - if (targetFramework.VersionNumber > 400 && platformName == "AnyCPU" && (module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) == 0) { + if (targetFramework.VersionNumber > 400 && platformName == "AnyCPU" && (module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) == 0) + { w.WriteElementString("Prefer32Bit", "false"); } w.WriteEndElement(); // (platform-specific) @@ -136,12 +144,15 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler w.WriteStartElement("ItemGroup"); // References - foreach (var r in module.AssemblyReferences) { - if (r.Name != "mscorlib") { + foreach (var r in module.AssemblyReferences) + { + if (r.Name != "mscorlib") + { w.WriteStartElement("Reference"); w.WriteAttributeString("Include", r.Name); var asm = project.AssemblyResolver.Resolve(r); - if (asm != null && !project.AssemblyResolver.IsGacAssembly(r)) { + if (asm != null && !project.AssemblyResolver.IsGacAssembly(r)) + { w.WriteElementString("HintPath", asm.FileName); } w.WriteEndElement(); @@ -149,20 +160,25 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler } w.WriteEndElement(); // (References) - foreach (IGrouping gr in from f in files group f.fileName by f.itemType into g orderby g.Key select g) { + foreach (IGrouping gr in from f in files group f.fileName by f.itemType into g orderby g.Key select g) + { w.WriteStartElement("ItemGroup"); - foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)) { + foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)) + { w.WriteStartElement(gr.Key); w.WriteAttributeString("Include", file); w.WriteEndElement(); } w.WriteEndElement(); } - if (targetFramework.IsPortableClassLibrary) { + if (targetFramework.IsPortableClassLibrary) + { w.WriteStartElement("Import"); w.WriteAttributeString("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\Portable\\$(TargetFrameworkVersion)\\Microsoft.Portable.CSharp.targets"); w.WriteEndElement(); - } else { + } + else + { w.WriteStartElement("Import"); w.WriteAttributeString("Project", "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"); w.WriteEndElement(); diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs index 479acc419..d3969f200 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs @@ -22,6 +22,7 @@ using System.IO; using System.Linq; using System.Reflection.PortableExecutable; using System.Xml; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -67,7 +68,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler IEnumerable<(string itemType, string fileName)> files, PEFile module) { - using (XmlTextWriter xmlWriter = new XmlTextWriter(target)) { + using (XmlTextWriter xmlWriter = new XmlTextWriter(target)) + { xmlWriter.Formatting = Formatting.Indented; Write(xmlWriter, project, module); } @@ -90,9 +92,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler static void PlaceIntoTag(string tagName, XmlTextWriter xml, Action content) { xml.WriteStartElement(tagName); - try { + try + { content(); - } finally { + } + finally + { xml.WriteEndElement(); } } @@ -105,7 +110,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler xml.WriteElementString("GenerateAssemblyInfo", FalseString); // 'Library' is default, so only need to specify output type for executables - if (!module.Reader.PEHeaders.IsDll) { + if (!module.Reader.PEHeaders.IsDll) + { WriteOutputType(xml, module.Reader.PEHeaders.PEHeader.Subsystem); } @@ -114,25 +120,29 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler string platformName = TargetServices.GetPlatformName(module); var targetFramework = TargetServices.DetectTargetFramework(module); - if (targetFramework.Moniker == null) { + if (targetFramework.Moniker == null) + { throw new NotSupportedException($"Cannot decompile this assembly to a SDK style project. Use default project format instead."); } xml.WriteElementString("TargetFramework", targetFramework.Moniker); // 'AnyCPU' is default, so only need to specify platform if it differs - if (platformName != AnyCpuString) { + if (platformName != AnyCpuString) + { xml.WriteElementString("PlatformTarget", platformName); } - if (platformName == AnyCpuString && (module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) != 0) { + if (platformName == AnyCpuString && (module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) != 0) + { xml.WriteElementString("Prefer32Bit", TrueString); } } static void WriteOutputType(XmlTextWriter xml, Subsystem moduleSubsystem) { - switch (moduleSubsystem) { + switch (moduleSubsystem) + { case Subsystem.WindowsGui: xml.WriteElementString("OutputType", "WinExe"); break; @@ -144,9 +154,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler static void WriteDesktopExtensions(XmlTextWriter xml, ProjectType projectType) { - if (projectType == ProjectType.Wpf) { + if (projectType == ProjectType.Wpf) + { xml.WriteElementString("UseWPF", TrueString); - } else if (projectType == ProjectType.WinForms) { + } + else if (projectType == ProjectType.WinForms) + { xml.WriteElementString("UseWindowsForms", TrueString); } } @@ -156,7 +169,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler xml.WriteElementString("LangVersion", project.LanguageVersion.ToString().Replace("CSharp", "").Replace('_', '.')); xml.WriteElementString("AllowUnsafeBlocks", TrueString); - if (project.StrongNameKeyFile != null) { + if (project.StrongNameKeyFile != null) + { xml.WriteElementString("SignAssembly", TrueString); xml.WriteElementString("AssemblyOriginatorKeyFile", Path.GetFileName(project.StrongNameKeyFile)); } @@ -164,12 +178,14 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler static void WriteReferences(XmlTextWriter xml, PEFile module, IProjectInfoProvider project) { - foreach (var reference in module.AssemblyReferences.Where(r => !ImplicitReferences.Contains(r.Name))) { + foreach (var reference in module.AssemblyReferences.Where(r => !ImplicitReferences.Contains(r.Name))) + { xml.WriteStartElement("Reference"); xml.WriteAttributeString("Include", reference.Name); - + var asembly = project.AssemblyResolver.Resolve(reference); - if (asembly != null) { + if (asembly != null) + { xml.WriteElementString("HintPath", asembly.FileName); } @@ -179,7 +195,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler static string GetSdkString(ProjectType projectType) { - switch (projectType) { + switch (projectType) + { case ProjectType.WinForms: case ProjectType.Wpf: return "Microsoft.NET.Sdk.WindowsDesktop"; @@ -192,16 +209,20 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler static ProjectType GetProjectType(PEFile module) { - foreach (var referenceName in module.AssemblyReferences.Select(r => r.Name)) { - if (referenceName.StartsWith(AspNetCorePrefix, StringComparison.Ordinal)) { + foreach (var referenceName in module.AssemblyReferences.Select(r => r.Name)) + { + if (referenceName.StartsWith(AspNetCorePrefix, StringComparison.Ordinal)) + { return ProjectType.Web; } - if (referenceName == PresentationFrameworkName) { + if (referenceName == PresentationFrameworkName) + { return ProjectType.Wpf; } - if (referenceName == WindowsFormsName) { + if (referenceName == WindowsFormsName) + { return ProjectType.WinForms; } } diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetFramework.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetFramework.cs index c340578e3..66279bbd3 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetFramework.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetFramework.cs @@ -36,7 +36,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler /// The framework profile. Can be null. public TargetFramework(string identifier, int version, string profile) { - if (version < 100) { + if (version < 100) + { throw new ArgumentException("The version number must be greater than or equal to 100", nameof(version)); } @@ -52,7 +53,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler /// Gets the target framework identifier. Can be null if not defined. /// public string Identifier { get; } - + /// /// Gets the target framework moniker. Can be null if not supported. /// @@ -81,7 +82,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler static string GetTargetFrameworkMoniker(string frameworkIdentifier, int version) { // Reference: https://docs.microsoft.com/en-us/dotnet/standard/frameworks - switch (frameworkIdentifier) { + switch (frameworkIdentifier) + { case null: case ".NETFramework": return "net" + GetVersionString(version, withDots: false); @@ -115,21 +117,25 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler int minor = version % 100 / 10; int patch = version % 10; - if (omitMinorWhenZero && minor == 0 && patch == 0) { + if (omitMinorWhenZero && minor == 0 && patch == 0) + { return major.ToString(); } var versionBuilder = new StringBuilder(8); versionBuilder.Append(major); - if (withDots) { + if (withDots) + { versionBuilder.Append('.'); } versionBuilder.Append(minor); - if (patch != 0) { - if (withDots) { + if (patch != 0) + { + if (withDots) + { versionBuilder.Append('.'); } diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs index 94d1dc296..a1a0fc47f 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/TargetServices.cs @@ -19,6 +19,7 @@ using System; using System.Linq; using System.Reflection.PortableExecutable; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -39,12 +40,14 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler /// public static TargetFramework DetectTargetFramework(PEFile module) { - if (module is null) { + if (module is null) + { throw new ArgumentNullException(nameof(module)); } int versionNumber; - switch (module.GetRuntime()) { + switch (module.GetRuntime()) + { case TargetRuntime.Net_1_0: versionNumber = 100; break; @@ -67,14 +70,17 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler string targetFrameworkProfile = null; string targetFramework = module.DetectTargetFrameworkId(); - if (!string.IsNullOrEmpty(targetFramework)) { + if (!string.IsNullOrEmpty(targetFramework)) + { string[] frameworkParts = targetFramework.Split(','); targetFrameworkIdentifier = frameworkParts.FirstOrDefault(a => !a.StartsWith(VersionToken, StringComparison.OrdinalIgnoreCase) && !a.StartsWith(ProfileToken, StringComparison.OrdinalIgnoreCase)); string frameworkVersion = frameworkParts.FirstOrDefault(a => a.StartsWith(VersionToken, StringComparison.OrdinalIgnoreCase)); - if (frameworkVersion != null) { + if (frameworkVersion != null) + { versionNumber = int.Parse(frameworkVersion.Substring(VersionToken.Length + 1).Replace(".", "")); - if (versionNumber < 100) versionNumber *= 10; + if (versionNumber < 100) + versionNumber *= 10; } string frameworkProfile = frameworkParts.FirstOrDefault(a => a.StartsWith(ProfileToken, StringComparison.OrdinalIgnoreCase)); @@ -92,7 +98,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler /// The platform name, e.g. "AnyCPU" or "x86". public static string GetPlatformName(PEFile module) { - if (module is null) { + if (module is null) + { throw new ArgumentNullException(nameof(module)); } @@ -101,7 +108,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler var characteristics = headers.CoffHeader.Characteristics; var corflags = headers.CorHeader.Flags; - switch (architecture) { + switch (architecture) + { case Machine.I386: if ((corflags & CorFlags.Prefers32Bit) != 0) return "AnyCPU"; diff --git a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs index 790c21da9..a817ddc3e 100644 --- a/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs @@ -17,23 +17,25 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection.Metadata; +using System.Text; +using System.Threading; using System.Threading.Tasks; + using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Transforms; +using ICSharpCode.Decompiler.DebugInfo; +using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; -using System.Threading; -using System.Text; -using System.Reflection.Metadata; + using static ICSharpCode.Decompiler.Metadata.MetadataExtensions; -using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.Decompiler.Solution; -using ICSharpCode.Decompiler.DebugInfo; -using System.Collections.Concurrent; namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler { @@ -124,26 +126,29 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler public void DecompileProject(PEFile moduleDefinition, string targetDirectory, CancellationToken cancellationToken = default(CancellationToken)) { string projectFileName = Path.Combine(targetDirectory, CleanUpFileName(moduleDefinition.Name) + ".csproj"); - using (var writer = new StreamWriter(projectFileName)) { + using (var writer = new StreamWriter(projectFileName)) + { DecompileProject(moduleDefinition, targetDirectory, writer, cancellationToken); } } public ProjectId DecompileProject(PEFile moduleDefinition, string targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken = default(CancellationToken)) { - if (string.IsNullOrEmpty(targetDirectory)) { + if (string.IsNullOrEmpty(targetDirectory)) + { throw new InvalidOperationException("Must set TargetDirectory"); } this.targetDirectory = targetDirectory; directories.Clear(); var files = WriteCodeFilesInProject(moduleDefinition, cancellationToken).ToList(); files.AddRange(WriteResourceFilesInProject(moduleDefinition)); - if (StrongNameKeyFile != null) { + if (StrongNameKeyFile != null) + { File.Copy(StrongNameKeyFile, Path.Combine(targetDirectory, Path.GetFileName(StrongNameKeyFile))); } projectWriter.Write(projectFileWriter, this, files, moduleDefinition); - + string platformName = TargetServices.GetPlatformName(moduleDefinition); return new ProjectId(platformName, ProjectGuid, ProjectTypeGuids.CSharpWindows); } @@ -180,7 +185,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler if (directories.Add(prop)) Directory.CreateDirectory(Path.Combine(targetDirectory, prop)); string assemblyInfo = Path.Combine(prop, "AssemblyInfo.cs"); - using (StreamWriter w = new StreamWriter(Path.Combine(targetDirectory, assemblyInfo))) { + using (StreamWriter w = new StreamWriter(Path.Combine(targetDirectory, assemblyInfo))) + { syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions)); } return new[] { ("Compile", assemblyInfo) }; @@ -193,9 +199,12 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler delegate (TypeDefinitionHandle h) { var type = metadata.GetTypeDefinition(h); string file = CleanUpFileName(metadata.GetString(type.Name)) + ".cs"; - if (string.IsNullOrEmpty(metadata.GetString(type.Namespace))) { + if (string.IsNullOrEmpty(metadata.GetString(type.Namespace))) + { return file; - } else { + } + else + { string dir = CleanUpFileName(metadata.GetString(type.Namespace)); if (directories.Add(dir)) Directory.CreateDirectory(Path.Combine(targetDirectory, dir)); @@ -212,13 +221,17 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler CancellationToken = cancellationToken }, delegate (IGrouping file) { - using (StreamWriter w = new StreamWriter(Path.Combine(targetDirectory, file.Key))) { - try { + using (StreamWriter w = new StreamWriter(Path.Combine(targetDirectory, file.Key))) + { + try + { CSharpDecompiler decompiler = CreateDecompiler(ts); decompiler.CancellationToken = cancellationToken; var syntaxTree = decompiler.DecompileTypes(file.ToArray()); syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions)); - } catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) { + } + catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) + { throw new DecompilerException(module, $"Error decompiling for '{file.Key}'", innerException); } } @@ -231,20 +244,26 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler #region WriteResourceFilesInProject protected virtual IEnumerable<(string itemType, string fileName)> WriteResourceFilesInProject(Metadata.PEFile module) { - foreach (var r in module.Resources.Where(r => r.ResourceType == Metadata.ResourceType.Embedded)) { + foreach (var r in module.Resources.Where(r => r.ResourceType == Metadata.ResourceType.Embedded)) + { Stream stream = r.TryOpenStream(); stream.Position = 0; - if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) { + if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) + { bool decodedIntoIndividualFiles; var individualResources = new List<(string itemType, string fileName)>(); - try { + try + { var resourcesFile = new ResourcesFile(stream); - if (resourcesFile.AllEntriesAreStreams()) { - foreach (var (name, value) in resourcesFile) { + if (resourcesFile.AllEntriesAreStreams()) + { + foreach (var (name, value) in resourcesFile) + { string fileName = Path.Combine(name.Split('/').Select(p => CleanUpFileName(p)).ToArray()); string dirName = Path.GetDirectoryName(fileName); - if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) { + if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) + { Directory.CreateDirectory(Path.Combine(targetDirectory, dirName)); } Stream entryStream = (Stream)value; @@ -253,28 +272,42 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler WriteResourceToFile(fileName, (string)name, entryStream)); } decodedIntoIndividualFiles = true; - } else { + } + else + { decodedIntoIndividualFiles = false; } - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { decodedIntoIndividualFiles = false; - } catch (EndOfStreamException) { + } + catch (EndOfStreamException) + { decodedIntoIndividualFiles = false; } - if (decodedIntoIndividualFiles) { - foreach (var entry in individualResources) { + if (decodedIntoIndividualFiles) + { + foreach (var entry in individualResources) + { yield return entry; } - } else { + } + else + { stream.Position = 0; string fileName = GetFileNameForResource(r.Name); - foreach (var entry in WriteResourceToFile(fileName, r.Name, stream)) { + foreach (var entry in WriteResourceToFile(fileName, r.Name, stream)) + { yield return entry; } } - } else { + } + else + { string fileName = GetFileNameForResource(r.Name); - using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write)) { + using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write)) + { stream.Position = 0; stream.CopyTo(fs); } @@ -285,23 +318,32 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler protected virtual IEnumerable<(string itemType, string fileName)> WriteResourceToFile(string fileName, string resourceName, Stream entryStream) { - if (fileName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) { + if (fileName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) + { string resx = Path.ChangeExtension(fileName, ".resx"); - try { + try + { using (FileStream fs = new FileStream(Path.Combine(targetDirectory, resx), FileMode.Create, FileAccess.Write)) - using (ResXResourceWriter writer = new ResXResourceWriter(fs)) { - foreach (var entry in new ResourcesFile(entryStream)) { + using (ResXResourceWriter writer = new ResXResourceWriter(fs)) + { + foreach (var entry in new ResourcesFile(entryStream)) + { writer.AddResource(entry.Key, entry.Value); } } return new[] { ("EmbeddedResource", resx) }; - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { // if the .resources can't be decoded, just save them as-is - } catch (EndOfStreamException) { + } + catch (EndOfStreamException) + { // if the .resources can't be decoded, just save them as-is } } - using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write)) { + using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write)) + { entryStream.CopyTo(fs); } return new[] { ("EmbeddedResource", fileName) }; @@ -311,9 +353,11 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler { string[] splitName = fullName.Split('.'); string fileName = CleanUpFileName(fullName); - for (int i = splitName.Length - 1; i > 0; i--) { + for (int i = splitName.Length - 1; i > 0; i--) + { string ns = string.Join(".", splitName, 0, i); - if (directories.Contains(ns)) { + if (directories.Contains(ns)) + { string name = string.Join(".", splitName, i, splitName.Length - i); fileName = Path.Combine(ns, CleanUpFileName(name)); break; @@ -337,7 +381,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler text = text.Trim(); // Whitelist allowed characters, replace everything else: StringBuilder b = new StringBuilder(text.Length); - foreach (var c in text) { + foreach (var c in text) + { if (char.IsLetterOrDigit(c) || c == '-' || c == '_') b.Append(c); else if (c == '.' && b.Length > 0 && b[b.Length - 1] != '.') @@ -360,7 +405,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler static bool IsReservedFileSystemName(string name) { - switch (name.ToUpperInvariant()) { + switch (name.ToUpperInvariant()) + { case "AUX": case "COM1": case "COM2": diff --git a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs index 2aa5dd8f7..3f3a363de 100644 --- a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs +++ b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -22,9 +23,11 @@ namespace ICSharpCode.Decompiler.CSharp public RequiredNamespaceCollector(HashSet namespaces) { this.namespaces = namespaces; - for (int i = 0; i < KnownTypeReference.KnownTypeCodeCount; i++) { + for (int i = 0; i < KnownTypeReference.KnownTypeCodeCount; i++) + { var ktr = KnownTypeReference.Get((KnownTypeCode)i); - if (ktr == null) continue; + if (ktr == null) + continue; namespaces.Add(ktr.Namespace); } } @@ -32,7 +35,8 @@ namespace ICSharpCode.Decompiler.CSharp public static void CollectNamespaces(MetadataModule module, HashSet namespaces) { var collector = new RequiredNamespaceCollector(namespaces); - foreach (var type in module.TypeDefinitions) { + foreach (var type in module.TypeDefinitions) + { collector.CollectNamespaces(type, module, (CodeMappingInfo)null); } collector.HandleAttributes(module.GetAssemblyAttributes()); @@ -58,33 +62,40 @@ namespace ICSharpCode.Decompiler.CSharp return; if (mappingInfo == null) mappingInfo = CSharpDecompiler.GetCodeMappingInfo(entity.ParentModule.PEFile, entity.MetadataToken); - switch (entity) { + switch (entity) + { case ITypeDefinition td: namespaces.Add(td.Namespace); HandleAttributes(td.GetAttributes()); HandleTypeParameters(td.TypeParameters); - foreach (var baseType in td.DirectBaseTypes) { + foreach (var baseType in td.DirectBaseTypes) + { CollectNamespacesForTypeReference(baseType); } - foreach (var nestedType in td.NestedTypes) { + foreach (var nestedType in td.NestedTypes) + { CollectNamespaces(nestedType, module, mappingInfo); } - foreach (var field in td.Fields) { + foreach (var field in td.Fields) + { CollectNamespaces(field, module, mappingInfo); } - foreach (var property in td.Properties) { + foreach (var property in td.Properties) + { CollectNamespaces(property, module, mappingInfo); } - foreach (var @event in td.Events) { + foreach (var @event in td.Events) + { CollectNamespaces(@event, module, mappingInfo); } - foreach (var method in td.Methods) { + foreach (var method in td.Methods) + { CollectNamespaces(method, module, mappingInfo); } break; @@ -95,23 +106,29 @@ namespace ICSharpCode.Decompiler.CSharp case IMethod method: var reader = module.PEFile.Reader; var parts = mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken).ToList(); - foreach (var part in parts) { + foreach (var part in parts) + { var partMethod = module.ResolveMethod(part, genericContext); HandleAttributes(partMethod.GetAttributes()); HandleAttributes(partMethod.GetReturnTypeAttributes()); CollectNamespacesForTypeReference(partMethod.ReturnType); - foreach (var param in partMethod.Parameters) { + foreach (var param in partMethod.Parameters) + { HandleAttributes(param.GetAttributes()); CollectNamespacesForTypeReference(param.Type); } HandleTypeParameters(partMethod.TypeParameters); HandleOverrides(part.GetMethodImplementations(module.metadata), module); var methodDef = module.metadata.GetMethodDefinition(part); - if (method.HasBody) { + if (method.HasBody) + { MethodBodyBlock body; - try { + try + { body = reader.GetMethodBody(methodDef.RelativeVirtualAddress); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { continue; } CollectNamespacesFromMethodBody(body, module); @@ -133,7 +150,8 @@ namespace ICSharpCode.Decompiler.CSharp void HandleOverrides(ImmutableArray immutableArray, MetadataModule module) { - foreach (var h in immutableArray) { + foreach (var h in immutableArray) + { var methodImpl = module.metadata.GetMethodImplementation(h); CollectNamespacesForTypeReference(module.ResolveType(methodImpl.Type, genericContext)); CollectNamespacesForMemberReference(module.ResolveMethod(methodImpl.MethodBody, genericContext)); @@ -145,7 +163,8 @@ namespace ICSharpCode.Decompiler.CSharp { if (!visitedTypes.Add(type)) return; - switch (type) { + switch (type) + { case ParameterizedType parameterizedType: namespaces.Add(parameterizedType.Namespace); CollectNamespacesForTypeReference(parameterizedType.GenericType); @@ -156,7 +175,8 @@ namespace ICSharpCode.Decompiler.CSharp CollectNamespacesForTypeReference(typeWithElementType.ElementType); break; case TupleType tupleType: - foreach (var elementType in tupleType.ElementTypes) { + foreach (var elementType in tupleType.ElementTypes) + { CollectNamespacesForTypeReference(elementType); } break; @@ -164,25 +184,30 @@ namespace ICSharpCode.Decompiler.CSharp namespaces.Add(type.Namespace); break; } - foreach (var baseType in type.GetAllBaseTypes()) { + foreach (var baseType in type.GetAllBaseTypes()) + { namespaces.Add(baseType.Namespace); } } public static void CollectNamespaces(EntityHandle entity, MetadataModule module, HashSet namespaces) { - if (entity.IsNil) return; + if (entity.IsNil) + return; CollectNamespaces(module.ResolveEntity(entity, genericContext), module, namespaces); } void HandleAttributes(IEnumerable attributes) { - foreach (var attr in attributes) { + foreach (var attr in attributes) + { namespaces.Add(attr.AttributeType.Namespace); - foreach (var arg in attr.FixedArguments) { + foreach (var arg in attr.FixedArguments) + { HandleAttributeValue(arg.Type, arg.Value); } - foreach (var arg in attr.NamedArguments) { + foreach (var arg in attr.NamedArguments) + { HandleAttributeValue(arg.Type, arg.Value); } } @@ -193,8 +218,10 @@ namespace ICSharpCode.Decompiler.CSharp CollectNamespacesForTypeReference(type); if (value is IType typeofType) CollectNamespacesForTypeReference(typeofType); - if (value is ImmutableArray> arr) { - foreach (var element in arr) { + if (value is ImmutableArray> arr) + { + foreach (var element in arr) + { HandleAttributeValue(element.Type, element.Value); } } @@ -202,10 +229,12 @@ namespace ICSharpCode.Decompiler.CSharp void HandleTypeParameters(IEnumerable typeParameters) { - foreach (var typeParam in typeParameters) { + foreach (var typeParam in typeParameters) + { HandleAttributes(typeParam.GetAttributes()); - foreach (var constraint in typeParam.DirectBaseTypes) { + foreach (var constraint in typeParam.DirectBaseTypes) + { CollectNamespacesForTypeReference(constraint); } } @@ -216,11 +245,15 @@ namespace ICSharpCode.Decompiler.CSharp var metadata = module.metadata; var instructions = method.GetILReader(); - if (!method.LocalSignature.IsNil) { + if (!method.LocalSignature.IsNil) + { ImmutableArray localSignature; - try { + try + { localSignature = module.DecodeLocalSignature(method.LocalSignature, genericContext); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { // Issue #1211: ignore invalid local signatures localSignature = ImmutableArray.Empty; } @@ -228,26 +261,35 @@ namespace ICSharpCode.Decompiler.CSharp CollectNamespacesForTypeReference(type); } - foreach (var region in method.ExceptionRegions) { + foreach (var region in method.ExceptionRegions) + { if (region.CatchType.IsNil) continue; IType ty; - try { + try + { ty = module.ResolveType(region.CatchType, genericContext); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { continue; } CollectNamespacesForTypeReference(ty); } - while (instructions.RemainingBytes > 0) { + while (instructions.RemainingBytes > 0) + { ILOpCode opCode; - try { + try + { opCode = instructions.DecodeOpCode(); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { return; } - switch (opCode.GetOperandType()) { + switch (opCode.GetOperandType()) + { case OperandType.Field: case OperandType.Method: case OperandType.Sig: @@ -256,14 +298,18 @@ namespace ICSharpCode.Decompiler.CSharp var handle = MetadataTokenHelpers.EntityHandleOrNil(instructions.ReadInt32()); if (handle.IsNil) break; - switch (handle.Kind) { + switch (handle.Kind) + { case HandleKind.TypeDefinition: case HandleKind.TypeReference: case HandleKind.TypeSpecification: IType type; - try { + try + { type = module.ResolveType(handle, genericContext); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { break; } CollectNamespacesForTypeReference(type); @@ -273,29 +319,40 @@ namespace ICSharpCode.Decompiler.CSharp case HandleKind.MethodSpecification: case HandleKind.MemberReference: IMember member; - try { + try + { member = module.ResolveEntity(handle, genericContext) as IMember; - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { break; } CollectNamespacesForMemberReference(member); break; case HandleKind.StandaloneSignature: StandaloneSignature sig; - try { + try + { sig = metadata.GetStandaloneSignature((StandaloneSignatureHandle)handle); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { break; } - if (sig.GetKind() == StandaloneSignatureKind.Method) { + if (sig.GetKind() == StandaloneSignatureKind.Method) + { MethodSignature methodSig; - try { + try + { methodSig = module.DecodeMethodSignature((StandaloneSignatureHandle)handle, genericContext); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { break; } CollectNamespacesForTypeReference(methodSig.ReturnType); - foreach (var paramType in methodSig.ParameterTypes) { + foreach (var paramType in methodSig.ParameterTypes) + { CollectNamespacesForTypeReference(paramType); } } @@ -303,9 +360,12 @@ namespace ICSharpCode.Decompiler.CSharp } break; default: - try { + try + { instructions.SkipOperand(opCode); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { return; } break; @@ -315,7 +375,8 @@ namespace ICSharpCode.Decompiler.CSharp void CollectNamespacesForMemberReference(IMember member) { - switch (member) { + switch (member) + { case IField field: CollectNamespacesForTypeReference(field.DeclaringType); CollectNamespacesForTypeReference(field.ReturnType); diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/AliasNamespaceResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/AliasNamespaceResolveResult.cs index 37b681193..5d6d1fd77 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/AliasNamespaceResolveResult.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/AliasNamespaceResolveResult.cs @@ -40,8 +40,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver get; private set; } - - public AliasNamespaceResolveResult(string alias, NamespaceResolveResult underlyingResult) : base (underlyingResult.Namespace) + + public AliasNamespaceResolveResult(string alias, NamespaceResolveResult underlyingResult) : base(underlyingResult.Namespace) { this.Alias = alias; } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/AliasTypeResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/AliasTypeResolveResult.cs index 85e5a3367..d8bb11d8a 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/AliasTypeResolveResult.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/AliasTypeResolveResult.cs @@ -40,8 +40,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver get; private set; } - - public AliasTypeResolveResult(string alias, TypeResolveResult underlyingResult) : base (underlyingResult.Type) + + public AliasTypeResolveResult(string alias, TypeResolveResult underlyingResult) : base(underlyingResult.Type) { this.Alias = alias; } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/AwaitResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/AwaitResolveResult.cs index 62d4e1d70..71ea5810c 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/AwaitResolveResult.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/AwaitResolveResult.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs index eae329895..e1555a96d 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs @@ -22,6 +22,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -56,7 +57,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new ArgumentNullException(nameof(compilation)); CacheManager cache = compilation.CacheManager; CSharpConversions operators = (CSharpConversions)cache.GetShared(typeof(CSharpConversions)); - if (operators == null) { + if (operators == null) + { operators = (CSharpConversions)cache.GetOrAddShared(typeof(CSharpConversions), new CSharpConversions(compilation)); } return operators; @@ -87,7 +89,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public override int GetHashCode() { - unchecked { + unchecked + { return 1000000007 * FromType.GetHashCode() + 1000000009 * ToType.GetHashCode(); } } @@ -98,42 +101,57 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver private Conversion ImplicitConversion(ResolveResult resolveResult, IType toType, bool allowUserDefined, bool allowTuple) { Conversion c; - if (resolveResult.IsCompileTimeConstant) { + if (resolveResult.IsCompileTimeConstant) + { c = ImplicitEnumerationConversion(resolveResult, toType); - if (c.IsValid) return c; + if (c.IsValid) + return c; if (ImplicitConstantExpressionConversion(resolveResult, toType)) return Conversion.ImplicitConstantExpressionConversion; c = StandardImplicitConversion(resolveResult.Type, toType, allowTuple); - if (c != Conversion.None) return c; - if (allowUserDefined) { + if (c != Conversion.None) + return c; + if (allowUserDefined) + { c = UserDefinedImplicitConversion(resolveResult, resolveResult.Type, toType); - if (c != Conversion.None) return c; + if (c != Conversion.None) + return c; } - } else { - if (allowTuple && resolveResult is TupleResolveResult tupleRR) { + } + else + { + if (allowTuple && resolveResult is TupleResolveResult tupleRR) + { c = TupleConversion(tupleRR, toType, isExplicit: false); if (c != Conversion.None) return c; } - if (resolveResult is ThrowResolveResult) { + if (resolveResult is ThrowResolveResult) + { return Conversion.ThrowExpressionConversion; } - if (allowUserDefined && allowTuple) { + if (allowUserDefined && allowTuple) + { // if allowUserDefined and allowTuple are true, we might as well use the cache c = ImplicitConversion(resolveResult.Type, toType); - } else { + } + else + { c = ImplicitConversion(resolveResult.Type, toType, allowUserDefined, allowTuple); } - if (c != Conversion.None) return c; + if (c != Conversion.None) + return c; } - if (resolveResult is InterpolatedStringResolveResult isrr) { + if (resolveResult is InterpolatedStringResolveResult isrr) + { if (toType.IsKnownType(KnownTypeCode.IFormattable) || toType.IsKnownType(KnownTypeCode.FormattableString)) return Conversion.ImplicitInterpolatedStringConversion; } if (resolveResult.Type.Kind == TypeKind.Dynamic) return Conversion.ImplicitDynamicConversion; c = AnonymousFunctionConversion(resolveResult, toType); - if (c != Conversion.None) return c; + if (c != Conversion.None) + return c; c = MethodGroupConversion(resolveResult, toType); return c; } @@ -142,7 +160,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { // C# 4.0 spec: §6.1 var c = StandardImplicitConversion(fromType, toType, allowTuple); - if (c == Conversion.None && allowUserDefined) { + if (c == Conversion.None && allowUserDefined) + { c = UserDefinedImplicitConversion(null, fromType, toType); } return c; @@ -197,14 +216,16 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return Conversion.ImplicitReferenceConversion; if (IsBoxingConversion(fromType, toType)) return Conversion.BoxingConversion; - if (ImplicitTypeParameterConversion(fromType, toType)) { + 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; - if (allowTupleConversion) { + if (allowTupleConversion) + { c = TupleConversion(fromType, toType, isExplicit: false); if (c != Conversion.None) return c; @@ -227,12 +248,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return true; if (ImplicitReferenceConversion(fromType, toType, 0)) return true; - if (NullableType.IsNullable(fromType)) { + if (NullableType.IsNullable(fromType)) + { // An 'object' constraint still allows nullable value types // (object constraints don't exist in C#, but are inserted by DefaultResolvedTypeParameter.DirectBaseTypes) if (toType.IsKnownType(KnownTypeCode.Object)) return true; - } else { + } + else + { if (IsBoxingConversion(fromType, toType)) return true; } @@ -255,7 +279,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Conversion c = ImplicitConversion(resolveResult, toType, allowUserDefined: false, allowTuple: false); if (c != Conversion.None) return c; - if (resolveResult is TupleResolveResult tupleRR) { + if (resolveResult is TupleResolveResult tupleRR) + { c = TupleConversion(tupleRR, toType, isExplicit: true); if (c != Conversion.None) return c; @@ -339,9 +364,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // C# 4.0 spec: §6.1.2 TypeCode from = ReflectionHelper.GetTypeCode(fromType); - if (from == TypeCode.Empty) { + if (from == TypeCode.Empty) + { // When converting from a native-sized integer, treat it as 64-bits - switch (fromType.Kind) { + switch (fromType.Kind) + { case TypeKind.NInt: from = TypeCode.Int64; break; @@ -351,9 +378,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } TypeCode to = ReflectionHelper.GetTypeCode(toType); - if (to == TypeCode.Empty) { + if (to == TypeCode.Empty) + { // When converting to a native-sized integer, only 32-bits can be stored safely - switch (toType.Kind) { + switch (toType.Kind) + { case TypeKind.NInt: to = TypeCode.Int32; break; @@ -362,12 +391,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver break; } } - if (to >= TypeCode.Single && to <= TypeCode.Decimal) { + 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 { + } + else + { // Conversions to integral types: look at the table return from >= TypeCode.Char && from <= TypeCode.UInt64 && to >= TypeCode.Int16 && to <= TypeCode.UInt64 @@ -377,7 +409,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver bool IsNumericType(IType type) { - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.NInt: case TypeKind.NUInt: return true; @@ -399,8 +432,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // 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) { - if (NullableType.GetUnderlyingType(toType).Kind == TypeKind.Enum) { + if (constantType >= TypeCode.SByte && constantType <= TypeCode.Decimal && Convert.ToDouble(rr.ConstantValue) == 0) + { + if (NullableType.GetUnderlyingType(toType).Kind == TypeKind.Enum) + { return Conversion.EnumerationConversion(true, NullableType.IsNullable(toType)); } } @@ -410,9 +445,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver bool ExplicitEnumerationConversion(IType fromType, IType toType) { // C# 4.0 spec: §6.2.2 - if (fromType.Kind == TypeKind.Enum) { + if (fromType.Kind == TypeKind.Enum) + { return toType.Kind == TypeKind.Enum || IsNumericType(toType); - } else if (IsNumericType(fromType)) { + } + else if (IsNumericType(fromType)) + { return toType.Kind == TypeKind.Enum; } return false; @@ -423,7 +461,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Conversion ImplicitNullableConversion(IType fromType, IType toType) { // C# 4.0 spec: §6.1.4 - if (NullableType.IsNullable(toType)) { + if (NullableType.IsNullable(toType)) + { IType t = NullableType.GetUnderlyingType(toType); IType s = NullableType.GetUnderlyingType(fromType); // might or might not be nullable if (IdentityConversion(s, t)) @@ -437,7 +476,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Conversion ExplicitNullableConversion(IType fromType, IType toType) { // C# 4.0 spec: §6.1.4 - if (NullableType.IsNullable(toType) || NullableType.IsNullable(fromType)) { + if (NullableType.IsNullable(toType) || NullableType.IsNullable(fromType)) + { IType t = NullableType.GetUnderlyingType(toType); IType s = NullableType.GetUnderlyingType(fromType); if (IdentityConversion(s, t)) @@ -455,9 +495,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver bool NullLiteralConversion(IType fromType, IType toType) { // C# 4.0 spec: §6.1.5 - if (fromType.Kind == TypeKind.Null) { + if (fromType.Kind == TypeKind.Null) + { return NullableType.IsNullable(toType) || toType.IsReferenceType == true; - } else { + } + else + { return false; } } @@ -481,16 +524,19 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return false; ArrayType fromArray = fromType as ArrayType; - if (fromArray != null) { + if (fromArray != null) + { ArrayType toArray = toType as ArrayType; - if (toArray != null) { + if (toArray != null) + { // array covariance (the broken kind) return fromArray.Dimensions == toArray.Dimensions && ImplicitReferenceConversion(fromArray.ElementType, toArray.ElementType, subtypeCheckNestingDepth); } // conversion from single-dimensional array S[] to IList: IType toTypeArgument = UnpackGenericArrayInterface(toType); - if (fromArray.Dimensions == 1 && toTypeArgument != null) { + if (fromArray.Dimensions == 1 && toTypeArgument != null) + { // array covariance plays a part here as well (string[] is IList) return IdentityConversion(fromArray.ElementType, toTypeArgument) || ImplicitReferenceConversion(fromArray.ElementType, toTypeArgument, subtypeCheckNestingDepth); @@ -511,8 +557,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IType UnpackGenericArrayInterface(IType interfaceType) { ParameterizedType pt = interfaceType as ParameterizedType; - if (pt != null) { - switch (pt.GetDefinition()?.KnownTypeCode) { + if (pt != null) + { + switch (pt.GetDefinition()?.KnownTypeCode) + { case KnownTypeCode.IListOfT: case KnownTypeCode.ICollectionOfT: case KnownTypeCode.IEnumerableOfT: @@ -531,7 +579,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // conversion to dynamic + object are always possible if (t.Kind == TypeKind.Dynamic || t.IsKnownType(KnownTypeCode.Object)) return true; - if (subtypeCheckNestingDepth > 10) { + 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. @@ -541,7 +590,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return false; } // let GetAllBaseTypes do the work for us - foreach (IType baseType in s.GetAllBaseTypes()) { + foreach (IType baseType in s.GetAllBaseTypes()) + { if (IdentityOrVarianceConversion(baseType, t, subtypeCheckNestingDepth + 1)) return true; } @@ -551,20 +601,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver bool IdentityOrVarianceConversion(IType s, IType t, int subtypeCheckNestingDepth) { ITypeDefinition def = s.GetDefinition(); - if (def != null) { + if (def != null) + { if (!def.Equals(t.GetDefinition())) return false; ParameterizedType ps = s as ParameterizedType; ParameterizedType pt = t as ParameterizedType; - if (ps != null && pt != null) { + if (ps != null && pt != null) + { // C# 4.0 spec: §13.1.3.2 Variance Conversion - for (int i = 0; i < def.TypeParameters.Count; i++) { + 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) { + switch (xi.Variance) + { case VarianceModifier.Covariant: if (!ImplicitReferenceConversion(si, ti, subtypeCheckNestingDepth)) return false; @@ -577,11 +631,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return false; } } - } else if (ps != null || pt != null) { + } + else if (ps != null || pt != null) + { return false; // only of of them is parameterized, or counts don't match? -> not valid conversion } return true; - } else { + } + else + { // not type definitions? we still need to check for equal types (e.g. s and t might be type parameters) return s.Equals(t); } @@ -596,7 +654,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // test that the types are reference types: if (toType.IsReferenceType != true) return false; - if (fromType.IsReferenceType != true) { + if (fromType.IsReferenceType != true) + { // special case: // converting from F to T is a reference conversion where T : class, F // (because F actually must be a reference type as well, even though C# doesn't treat it as one) @@ -605,9 +664,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return false; } - if (toType.Kind == TypeKind.Array) { + if (toType.Kind == TypeKind.Array) + { ArrayType toArray = (ArrayType)toType; - if (fromType.Kind == TypeKind.Array) { + if (fromType.Kind == TypeKind.Array) + { // Array covariance ArrayType fromArray = (ArrayType)fromType; if (fromArray.Dimensions != toArray.Dimensions) @@ -615,37 +676,46 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return ExplicitReferenceConversion(fromArray.ElementType, toArray.ElementType); } IType fromTypeArgument = UnpackGenericArrayInterface(fromType); - if (fromTypeArgument != null && toArray.Dimensions == 1) { + if (fromTypeArgument != null && toArray.Dimensions == 1) + { return ExplicitReferenceConversion(fromTypeArgument, toArray.ElementType) || IdentityConversion(fromTypeArgument, toArray.ElementType); } // Otherwise treat the array like a sealed class - require implicit conversion in the opposite direction return IsImplicitReferenceConversion(toType, fromType); - } else if (fromType.Kind == TypeKind.Array) { + } + else if (fromType.Kind == TypeKind.Array) + { ArrayType fromArray = (ArrayType)fromType; IType toTypeArgument = UnpackGenericArrayInterface(toType); - if (toTypeArgument != null && fromArray.Dimensions == 1) { + if (toTypeArgument != null && fromArray.Dimensions == 1) + { return ExplicitReferenceConversion(fromArray.ElementType, toTypeArgument); } // Otherwise treat the array like a sealed class return IsImplicitReferenceConversion(fromType, toType); - } else if (fromType.Kind == TypeKind.Delegate && toType.Kind == TypeKind.Delegate) { + } + else if (fromType.Kind == TypeKind.Delegate && toType.Kind == TypeKind.Delegate) + { ITypeDefinition def = fromType.GetDefinition(); if (def == null || !def.Equals(toType.GetDefinition())) return false; ParameterizedType ps = fromType as ParameterizedType; ParameterizedType pt = toType as ParameterizedType; - if (ps == null || pt == null) { + if (ps == null || pt == null) + { // non-generic delegate - return true for the identity conversion return ps == null && pt == null; } - for (int i = 0; i < def.TypeParameters.Count; i++) { + 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) { + switch (xi.Variance) + { case VarianceModifier.Covariant: if (!ExplicitReferenceConversion(si, ti)) return false; @@ -659,13 +729,19 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } return true; - } else if (IsSealedReferenceType(fromType)) { + } + else if (IsSealedReferenceType(fromType)) + { // If the source type is sealed, explicit conversions can't do anything more than implicit ones return IsImplicitReferenceConversion(fromType, toType); - } else if (IsSealedReferenceType(toType)) { + } + else if (IsSealedReferenceType(toType)) + { // The the target type is sealed, there must be an implicit conversion in the opposite direction return IsImplicitReferenceConversion(toType, fromType); - } else { + } + else + { if (fromType.Kind == TypeKind.Interface || toType.Kind == TypeKind.Interface) return true; else @@ -724,18 +800,23 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver TypeCode fromTypeCode = ReflectionHelper.GetTypeCode(rr.Type); toType = NullableType.GetUnderlyingType(toType); TypeCode toTypeCode = ReflectionHelper.GetTypeCode(toType); - if (toType.Kind == TypeKind.NUInt) { + if (toType.Kind == TypeKind.NUInt) + { toTypeCode = TypeCode.UInt32; } - if (fromTypeCode == TypeCode.Int64) { + if (fromTypeCode == TypeCode.Int64) + { long val = (long)rr.ConstantValue; return val >= 0 && toTypeCode == TypeCode.UInt64; - } else if (fromTypeCode == TypeCode.Int32) { + } + else if (fromTypeCode == TypeCode.Int32) + { object cv = rr.ConstantValue; if (cv == null) return false; int val = (int)cv; - switch (toTypeCode) { + switch (toTypeCode) + { case TypeCode.SByte: return val >= SByte.MinValue && val <= SByte.MaxValue; case TypeCode.Byte: @@ -769,12 +850,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Conversion ExplicitTypeParameterConversion(IType fromType, IType toType) { - if (toType.Kind == TypeKind.TypeParameter) { + if (toType.Kind == TypeKind.TypeParameter) + { // Explicit type parameter conversions that aren't also // reference conversions are considered to be unboxing conversions if (fromType.Kind == TypeKind.Interface || IsSubtypeOf(toType, fromType, 0)) return Conversion.UnboxingConversion; - } else { + } + else + { if (fromType.Kind == TypeKind.TypeParameter && toType.Kind == TypeKind.Interface) return Conversion.BoxingConversion; } @@ -796,16 +880,20 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver bool ExplicitPointerConversion(IType fromType, IType toType) { // C# 4.0 spec: §18.4 Pointer conversions - if (fromType.Kind == TypeKind.Pointer) { + if (fromType.Kind == TypeKind.Pointer) + { return toType.Kind == TypeKind.Pointer || IsIntegerType(toType); - } else { + } + else + { return toType.Kind == TypeKind.Pointer && IsIntegerType(fromType); } } bool IsIntegerType(IType type) { - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.NInt: case TypeKind.NUInt: return true; @@ -833,7 +921,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IType FindMostEncompassedType(IEnumerable candidates) { IType best = null; - foreach (var current in candidates) { + foreach (var current in candidates) + { if (best == null || IsEncompassedBy(current, best)) best = current; else if (!IsEncompassedBy(best, current)) @@ -845,7 +934,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IType FindMostEncompassingType(IEnumerable candidates) { IType best = null; - foreach (var current in candidates) { + foreach (var current in candidates) + { if (best == null || IsEncompassedBy(best, current)) best = current; else if (!IsEncompassedBy(current, best)) @@ -864,7 +954,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return Conversion.UserDefinedConversion(selected[0].Method, isLifted: selected[0].IsLifted, isImplicit: isImplicit, conversionBeforeUserDefinedOperator: ExplicitConversion(source, mostSpecificSource), conversionAfterUserDefinedOperator: ExplicitConversion(mostSpecificTarget, target)); int nNonLifted = selected.Count(s => !s.IsLifted); - if (nNonLifted == 1) { + if (nNonLifted == 1) + { var op = selected.First(s => !s.IsLifted); return Conversion.UserDefinedConversion(op.Method, isLifted: op.IsLifted, isImplicit: isImplicit, conversionBeforeUserDefinedOperator: ExplicitConversion(source, mostSpecificSource), conversionAfterUserDefinedOperator: ExplicitConversion(mostSpecificTarget, target)); } @@ -877,12 +968,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // C# 4.0 spec §6.4.4 User-defined implicit conversions var operators = GetApplicableConversionOperators(fromResult, fromType, toType, false); - if (operators.Count > 0) { + if (operators.Count > 0) + { var mostSpecificSource = operators.Any(op => op.SourceType.Equals(fromType)) ? fromType : FindMostEncompassedType(operators.Select(op => op.SourceType)); if (mostSpecificSource == null) return Conversion.UserDefinedConversion(operators[0].Method, isImplicit: true, isLifted: operators[0].IsLifted, isAmbiguous: true, conversionBeforeUserDefinedOperator: Conversion.None, conversionAfterUserDefinedOperator: Conversion.None); var mostSpecificTarget = operators.Any(op => op.TargetType.Equals(toType)) ? toType : FindMostEncompassingType(operators.Select(op => op.TargetType)); - if (mostSpecificTarget == null) { + if (mostSpecificTarget == null) + { if (NullableType.IsNullable(toType)) return UserDefinedImplicitConversion(fromResult, fromType, NullableType.GetUnderlyingType(toType)); else @@ -890,19 +983,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } var selected = SelectOperator(mostSpecificSource, mostSpecificTarget, operators, true, fromType, toType); - if (selected != Conversion.None) { - if (selected.IsLifted && NullableType.IsNullable(toType)) { + if (selected != Conversion.None) + { + if (selected.IsLifted && NullableType.IsNullable(toType)) + { // Prefer A -> B -> B? over A -> A? -> B? var other = UserDefinedImplicitConversion(fromResult, fromType, NullableType.GetUnderlyingType(toType)); if (other != Conversion.None) return other; } return selected; - } else if (NullableType.IsNullable(toType)) + } + else if (NullableType.IsNullable(toType)) return UserDefinedImplicitConversion(fromResult, fromType, NullableType.GetUnderlyingType(toType)); else return Conversion.None; - } else { + } + else + { return Conversion.None; } } @@ -911,11 +1009,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { // C# 4.0 spec §6.4.5 User-defined explicit conversions var operators = GetApplicableConversionOperators(fromResult, fromType, toType, true); - if (operators.Count > 0) { + if (operators.Count > 0) + { IType mostSpecificSource; - if (operators.Any(op => op.SourceType.Equals(fromType))) { + if (operators.Any(op => op.SourceType.Equals(fromType))) + { mostSpecificSource = fromType; - } else { + } + else + { var operatorsWithSourceEncompassingFromType = operators.Where(op => IsEncompassedBy(fromType, op.SourceType) || ImplicitConstantExpressionConversion(fromResult, NullableType.GetUnderlyingType(op.SourceType))).ToList(); if (operatorsWithSourceEncompassingFromType.Any()) mostSpecificSource = FindMostEncompassedType(operatorsWithSourceEncompassingFromType.Select(op => op.SourceType)); @@ -932,7 +1034,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver mostSpecificTarget = FindMostEncompassingType(operators.Where(op => IsEncompassedBy(op.TargetType, toType)).Select(op => op.TargetType)); else mostSpecificTarget = FindMostEncompassedType(operators.Select(op => op.TargetType)); - if (mostSpecificTarget == null) { + if (mostSpecificTarget == null) + { if (NullableType.IsNullable(toType)) return UserDefinedExplicitConversion(fromResult, fromType, NullableType.GetUnderlyingType(toType)); else @@ -940,21 +1043,26 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } var selected = SelectOperator(mostSpecificSource, mostSpecificTarget, operators, false, fromType, toType); - if (selected != Conversion.None) { - if (selected.IsLifted && NullableType.IsNullable(toType)) { + if (selected != Conversion.None) + { + if (selected.IsLifted && NullableType.IsNullable(toType)) + { // Prefer A -> B -> B? over A -> A? -> B? var other = UserDefinedImplicitConversion(fromResult, fromType, NullableType.GetUnderlyingType(toType)); if (other != Conversion.None) return other; } return selected; - } else if (NullableType.IsNullable(toType)) + } + else if (NullableType.IsNullable(toType)) return UserDefinedExplicitConversion(fromResult, fromType, NullableType.GetUnderlyingType(toType)); else if (NullableType.IsNullable(fromType)) return UserDefinedExplicitConversion(null, NullableType.GetUnderlyingType(fromType), toType); // A? -> A -> B else return Conversion.None; - } else { + } + else + { return Conversion.None; } } @@ -988,34 +1096,44 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver .Concat(NullableType.GetUnderlyingType(toType).GetMethods(opFilter)).Distinct(); // Determine whether one of them is applicable: List result = new List(); - foreach (IMethod op in operators) { + foreach (IMethod op in operators) + { IType sourceType = op.Parameters[0].Type; IType targetType = op.ReturnType; // Try if the operator is applicable: bool isApplicable; - if (isExplicit) { + if (isExplicit) + { isApplicable = (IsEncompassingOrEncompassedBy(fromType, sourceType) || ImplicitConstantExpressionConversion(fromResult, sourceType)) && IsEncompassingOrEncompassedBy(targetType, toType); - } else { + } + else + { isApplicable = (IsEncompassedBy(fromType, sourceType) || ImplicitConstantExpressionConversion(fromResult, sourceType)) && IsEncompassedBy(targetType, toType); } // Try if the operator is applicable in lifted form: - if (isApplicable) { + if (isApplicable) + { result.Add(new OperatorInfo(op, sourceType, targetType, false)); } - if (NullableType.IsNonNullableValueType(sourceType)) { + if (NullableType.IsNonNullableValueType(sourceType)) + { // An operator can be applicable in both lifted and non-lifted form in case of explicit conversions IType liftedSourceType = NullableType.Create(compilation, sourceType); IType liftedTargetType = NullableType.IsNonNullableValueType(targetType) ? NullableType.Create(compilation, targetType) : targetType; - if (isExplicit) { + if (isExplicit) + { isApplicable = IsEncompassingOrEncompassedBy(fromType, liftedSourceType) && IsEncompassingOrEncompassedBy(liftedTargetType, toType); - } else { + } + else + { isApplicable = IsEncompassedBy(fromType, liftedSourceType) && IsEncompassedBy(liftedTargetType, toType); } - if (isApplicable) { + if (isApplicable) + { result.Add(new OperatorInfo(op, liftedSourceType, liftedTargetType, true)); } } @@ -1031,7 +1149,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver LambdaResolveResult f = resolveResult as LambdaResolveResult; if (f == null) return Conversion.None; - if (!f.IsAnonymousMethod) { + 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); @@ -1041,26 +1160,33 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return Conversion.None; IType[] dParamTypes = new IType[d.Parameters.Count]; - for (int i = 0; i < dParamTypes.Length; i++) { + for (int i = 0; i < dParamTypes.Length; i++) + { dParamTypes[i] = d.Parameters[i].Type; } IType dReturnType = d.ReturnType; - if (f.HasParameterList) { + 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.IsImplicitlyTyped) + { // If F has an implicitly typed parameter list, D has no ref or out parameters. - foreach (IParameter p in d.Parameters) { + foreach (IParameter p in d.Parameters) + { if (p.ReferenceKind != ReferenceKind.None) return Conversion.None; } - } else { + } + 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++) { + for (int i = 0; i < f.Parameters.Count; i++) + { IParameter pD = d.Parameters[i]; IParameter pF = f.Parameters[i]; if (pD.ReferenceKind != pF.ReferenceKind) @@ -1069,10 +1195,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return Conversion.None; } } - } else { + } + 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) { + foreach (IParameter p in d.Parameters) + { if (p.IsOut) return Conversion.None; } @@ -1084,9 +1213,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver static IType UnpackExpressionTreeType(IType type) { ParameterizedType pt = type as ParameterizedType; - if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Expression" && pt.Namespace == "System.Linq.Expressions") { + if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Expression" && pt.Namespace == "System.Linq.Expressions") + { return pt.GetTypeArgument(0); - } else { + } + else + { return type; } } @@ -1104,18 +1236,23 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return Conversion.None; ResolveResult[] args = new ResolveResult[invoke.Parameters.Count]; - for (int i = 0; i < args.Length; i++) { + for (int i = 0; i < args.Length; i++) + { IParameter param = invoke.Parameters[i]; IType parameterType = param.Type; - if (param.ReferenceKind != ReferenceKind.None && parameterType.Kind == TypeKind.ByReference) { + if (param.ReferenceKind != ReferenceKind.None && parameterType.Kind == TypeKind.ByReference) + { parameterType = ((ByReferenceType)parameterType).ElementType; args[i] = new ByReferenceResolveResult(parameterType, param.ReferenceKind); - } else { + } + else + { args[i] = new ResolveResult(parameterType); } } var or = rr.PerformOverloadResolution(compilation, args, allowExpandingParams: false, allowOptionalParameters: false, conversions: this); - if (or.FoundApplicableCandidate) { + if (or.FoundApplicableCandidate) + { IMethod method = (IMethod)or.GetBestCandidateWithSubstitutedTypeArguments(); var thisRR = rr.TargetResult as ThisResolveResult; bool isVirtual = method.IsOverridable && !(thisRR != null && thisRR.CausesNonVirtualInvocation); @@ -1125,7 +1262,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return Conversion.MethodGroupConversion(method, isVirtual, delegateCapturesFirstArgument); else return Conversion.InvalidMethodGroupConversion(method, isVirtual, delegateCapturesFirstArgument); - } else { + } + else + { return Conversion.None; } } @@ -1165,17 +1304,21 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver int firstParameterInM = isExtensionMethodInvocation ? 1 : 0; if (m.Parameters.Count - firstParameterInM != invoke.Parameters.Count) return false; - for (int i = 0; i < invoke.Parameters.Count; i++) { + for (int i = 0; i < invoke.Parameters.Count; i++) + { var pm = m.Parameters[firstParameterInM + i]; var pd = invoke.Parameters[i]; // ret/out/in must match if (pm.ReferenceKind != pd.ReferenceKind) return false; - if (pm.ReferenceKind != ReferenceKind.None) { + if (pm.ReferenceKind != ReferenceKind.None) + { // ref/out/in parameters must have same types if (!pm.Type.Equals(pd.Type)) return false; - } else { + } + else + { // non-ref/out parameters must have an identity or reference conversion from pd to pm if (!IdentityConversion(pd.Type, pm.Type) && !IsImplicitReferenceConversion(pd.Type, pm.Type)) return false; @@ -1195,11 +1338,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (toElements.IsDefault || fromElements.Length != toElements.Length) return Conversion.None; Conversion[] elementConversions = new Conversion[fromElements.Length]; - for (int i = 0; i < elementConversions.Length; i++) { + for (int i = 0; i < elementConversions.Length; i++) + { Conversion c; - if (isExplicit) { + if (isExplicit) + { c = ExplicitConversion(fromElements[i], toElements[i]); - } else { + } + else + { c = ImplicitConversion(fromElements[i], toElements[i]); } if (!c.IsValid) @@ -1218,11 +1365,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (toElements.IsDefault || fromElements.Length != toElements.Length) return Conversion.None; Conversion[] elementConversions = new Conversion[fromElements.Length]; - for (int i = 0; i < elementConversions.Length; i++) { + for (int i = 0; i < elementConversions.Length; i++) + { Conversion c; - if (isExplicit) { + if (isExplicit) + { c = ExplicitConversion(fromElements[i], toElements[i]); - } else { + } + else + { c = ImplicitConversion(fromElements[i], toElements[i]); } if (!c.IsValid) @@ -1241,8 +1392,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public int BetterConversion(ResolveResult resolveResult, IType t1, IType t2) { LambdaResolveResult lambda = resolveResult as LambdaResolveResult; - if (lambda != null) { - if (!lambda.IsAnonymousMethod) { + if (lambda != null) + { + if (!lambda.IsAnonymousMethod) + { t1 = UnpackExpressionTreeType(t1); t2 = UnpackExpressionTreeType(t2); } @@ -1253,7 +1406,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (m1.Parameters.Count != m2.Parameters.Count) return 0; IType[] parameterTypes = new IType[m1.Parameters.Count]; - for (int i = 0; i < parameterTypes.Length; i++) { + for (int i = 0; i < parameterTypes.Length; i++) + { parameterTypes[i] = m1.Parameters[i].Type; if (!parameterTypes[i].Equals(m2.Parameters[i].Type)) return 0; @@ -1270,7 +1424,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IType inferredRet = lambda.GetInferredReturnType(parameterTypes); int r = BetterConversion(inferredRet, ret1, ret2); - if (r == 0 && lambda.IsAsync) { + if (r == 0 && lambda.IsAsync) + { ret1 = UnpackTask(ret1); ret2 = UnpackTask(ret2); inferredRet = UnpackTask(inferredRet); @@ -1278,7 +1433,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver r = BetterConversion(inferredRet, ret1, ret2); } return r; - } else { + } + else + { return BetterConversion(resolveResult.Type, t1, t2); } } @@ -1289,7 +1446,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver static IType UnpackTask(IType type) { ParameterizedType pt = type as ParameterizedType; - if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Task" && pt.Namespace == "System.Threading.Tasks") { + if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Task" && pt.Namespace == "System.Threading.Tasks") + { return pt.GetTypeArgument(0); } return null; @@ -1334,7 +1492,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver bool IsBetterIntegralType(TypeCode t1, TypeCode t2) { // signed types are better than unsigned types - switch (t1) { + switch (t1) + { case TypeCode.SByte: return t2 == TypeCode.Byte || t2 == TypeCode.UInt16 || t2 == TypeCode.UInt32 || t2 == TypeCode.UInt64; case TypeCode.Int16: diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs index 61e64a7c0..b6fa7c0e3 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; @@ -31,24 +32,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver 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; readonly IReadOnlyList argumentToParameterMap; - + public CSharpInvocationResolveResult( ResolveResult targetResult, IParameterizedMember member, IList arguments, @@ -68,11 +69,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver 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. @@ -83,23 +84,28 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { return argumentToParameterMap; } - + public override IList GetArgumentsForCall() { ResolveResult[] results = new ResolveResult[Member.Parameters.Count]; List paramsArguments = IsExpandedForm ? new List() : null; // map arguments to parameters: - for (int i = 0; i < Arguments.Count; i++) { + for (int i = 0; i < Arguments.Count; i++) + { int mappedTo; if (argumentToParameterMap != null) mappedTo = argumentToParameterMap[i]; else mappedTo = IsExpandedForm ? Math.Min(i, results.Length - 1) : i; - - if (mappedTo >= 0 && mappedTo < results.Length) { - if (IsExpandedForm && mappedTo == results.Length - 1) { + + if (mappedTo >= 0 && mappedTo < results.Length) + { + if (IsExpandedForm && mappedTo == results.Length - 1) + { paramsArguments.Add(Arguments[i]); - } else { + } + else + { var narr = Arguments[i] as NamedArgumentResolveResult; if (narr != null) results[mappedTo] = narr.Argument; @@ -108,23 +114,29 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } } - if (IsExpandedForm){ + if (IsExpandedForm) + { IType arrayType = Member.Parameters.Last().Type; IType int32 = Member.Compilation.FindType(KnownTypeCode.Int32); ResolveResult[] sizeArguments = { new ConstantResolveResult(int32, paramsArguments.Count) }; results[results.Length - 1] = new ArrayCreateResolveResult(arrayType, sizeArguments, paramsArguments); } - - for (int i = 0; i < results.Length; i++) { - if (results[i] == null) { - if (Member.Parameters[i].IsOptional) { + + for (int i = 0; i < results.Length; i++) + { + if (results[i] == null) + { + if (Member.Parameters[i].IsOptional) + { results[i] = new ConstantResolveResult(Member.Parameters[i].Type, Member.Parameters[i].GetConstantValue()); - } else { + } + else + { results[i] = ErrorResolveResult.UnknownError; } } } - + return results; } } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs index 4962e13cd..2064c1f52 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -30,13 +31,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver sealed class CSharpOperators { readonly ICompilation compilation; - + private CSharpOperators(ICompilation compilation) { this.compilation = compilation; InitParameterArrays(); } - + /// /// Gets the CSharpOperators instance for the specified . /// This will make use of the context's cache manager (if available) to reuse the CSharpOperators instance. @@ -45,72 +46,77 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { CacheManager cache = compilation.CacheManager; CSharpOperators operators = (CSharpOperators)cache.GetShared(typeof(CSharpOperators)); - if (operators == null) { + if (operators == null) + { operators = (CSharpOperators)cache.GetOrAddShared(typeof(CSharpOperators), new CSharpOperators(compilation)); } return operators; } - + #region class OperatorMethod OperatorMethod[] Lift(params OperatorMethod[] methods) { List result = new List(methods); - foreach (OperatorMethod method in methods) { + foreach (OperatorMethod method in methods) + { OperatorMethod lifted = method.Lift(this); if (lifted != null) result.Add(lifted); } return result.ToArray(); } - + IParameter[] normalParameters = new IParameter[(int)(TypeCode.String + 1 - TypeCode.Object)]; IParameter[] nullableParameters = new IParameter[(int)(TypeCode.Decimal + 1 - TypeCode.Boolean)]; - + void InitParameterArrays() { - for (TypeCode i = TypeCode.Object; i <= TypeCode.String; i++) { + for (TypeCode i = TypeCode.Object; i <= TypeCode.String; i++) + { normalParameters[i - TypeCode.Object] = new DefaultParameter(compilation.FindType(i), string.Empty); } - for (TypeCode i = TypeCode.Boolean; i <= TypeCode.Decimal; i++) { + for (TypeCode i = TypeCode.Boolean; i <= TypeCode.Decimal; i++) + { IType type = NullableType.Create(compilation, compilation.FindType(i)); nullableParameters[i - TypeCode.Boolean] = new DefaultParameter(type, string.Empty); } } - + IParameter MakeParameter(TypeCode code) { return normalParameters[code - TypeCode.Object]; } - + IParameter MakeNullableParameter(IParameter normalParameter) { - for (TypeCode i = TypeCode.Boolean; i <= TypeCode.Decimal; i++) { + for (TypeCode i = TypeCode.Boolean; i <= TypeCode.Decimal; i++) + { if (normalParameter == normalParameters[i - TypeCode.Object]) return nullableParameters[i - TypeCode.Boolean]; } throw new ArgumentException(); } - + internal class OperatorMethod : IParameterizedMember { readonly ICompilation compilation; internal readonly List parameters = new List(); - + protected OperatorMethod(ICompilation compilation) { this.compilation = compilation; } - + public IReadOnlyList Parameters { get { return parameters; } } - + public IType ReturnType { get; internal set; } - + public ICompilation Compilation { get { return compilation; } } - + public virtual OperatorMethod Lift(CSharpOperators operators) { return null; @@ -121,11 +127,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver ITypeDefinition IEntity.DeclaringTypeDefinition { get { return null; } } - + IType IEntity.DeclaringType { get { return null; } } - + IMember IMember.MemberDefinition { get { return this; } } @@ -133,52 +139,52 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IEnumerable IMember.ExplicitlyImplementedInterfaceMembers { get { return EmptyList.Instance; } } - + bool IMember.IsVirtual { get { return false; } } - + bool IMember.IsOverride { get { return false; } } - + bool IMember.IsOverridable { get { return false; } } - + SymbolKind ISymbol.SymbolKind { get { return SymbolKind.Operator; } } - + IEnumerable IEntity.GetAttributes() { return EmptyList.Instance; } - + Accessibility IEntity.Accessibility { get { return Accessibility.Public; } } - + bool IEntity.IsStatic { get { return true; } } - + bool IEntity.IsAbstract { get { return false; } } - + bool IEntity.IsSealed { get { return false; } } - + bool IMember.IsExplicitInterfaceImplementation { get { return false; } } - + IModule IEntity.ParentModule { get { return compilation.MainModule; } } - + TypeParameterSubstitution IMember.Substitution { get { return TypeParameterSubstitution.Identity; @@ -195,24 +201,25 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver string INamedElement.FullName { get { return "operator"; } } - + public string Name { get { return "operator"; } } - + string INamedElement.Namespace { get { return string.Empty; } } - + string INamedElement.ReflectionName { get { return "operator"; } } - + public override string ToString() { StringBuilder b = new StringBuilder(); b.Append(ReturnType + " operator("); - for (int i = 0; i < parameters.Count; i++) { + for (int i = 0; i < parameters.Count; i++) + { if (i > 0) b.Append(", "); b.Append(parameters[i].Type); @@ -227,26 +234,26 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region Unary operator class definitions internal class UnaryOperatorMethod : OperatorMethod { public virtual bool CanEvaluateAtCompileTime { get { return false; } } - + public virtual object Invoke(CSharpResolver resolver, object input) { throw new NotSupportedException(); } - + public UnaryOperatorMethod(ICompilation compilation) : base(compilation) { } } - + sealed class LambdaUnaryOperatorMethod : UnaryOperatorMethod { readonly Func func; - + public LambdaUnaryOperatorMethod(CSharpOperators operators, Func func) : base(operators.compilation) { @@ -255,28 +262,28 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver parameters.Add(operators.MakeParameter(typeCode)); this.func = func; } - + public override bool CanEvaluateAtCompileTime { get { return true; } } - + public override object Invoke(CSharpResolver resolver, object input) { if (input == null) return null; return func((T)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T)), input)); } - + public override OperatorMethod Lift(CSharpOperators operators) { return new LiftedUnaryOperatorMethod(operators, this); } } - + sealed class LiftedUnaryOperatorMethod : UnaryOperatorMethod, ILiftedOperator { UnaryOperatorMethod baseMethod; - + public LiftedUnaryOperatorMethod(CSharpOperators operators, UnaryOperatorMethod baseMethod) : base(operators.compilation) { this.baseMethod = baseMethod; @@ -288,126 +295,142 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public IType NonLiftedReturnType => baseMethod.ReturnType; } #endregion - + #region Unary operator definitions // C# 4.0 spec: §7.7.1 Unary plus operator OperatorMethod[] unaryPlusOperators; - + public OperatorMethod[] UnaryPlusOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref unaryPlusOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref unaryPlusOperators, Lift( - new LambdaUnaryOperatorMethod (this, i => +i), - new LambdaUnaryOperatorMethod (this, i => +i), - new LambdaUnaryOperatorMethod (this, i => +i), - new LambdaUnaryOperatorMethod (this, i => +i), - new LambdaUnaryOperatorMethod (this, i => +i), - new LambdaUnaryOperatorMethod (this, i => +i), + new LambdaUnaryOperatorMethod(this, i => +i), + new LambdaUnaryOperatorMethod(this, i => +i), + new LambdaUnaryOperatorMethod(this, i => +i), + new LambdaUnaryOperatorMethod(this, i => +i), + new LambdaUnaryOperatorMethod(this, i => +i), + new LambdaUnaryOperatorMethod(this, i => +i), new LambdaUnaryOperatorMethod(this, i => +i) )); } } } - + // C# 4.0 spec: §7.7.2 Unary minus operator OperatorMethod[] uncheckedUnaryMinusOperators; - + public OperatorMethod[] UncheckedUnaryMinusOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref uncheckedUnaryMinusOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref uncheckedUnaryMinusOperators, Lift( - new LambdaUnaryOperatorMethod (this, i => unchecked(-i)), - new LambdaUnaryOperatorMethod (this, i => unchecked(-i)), - new LambdaUnaryOperatorMethod (this, i => unchecked(-i)), - new LambdaUnaryOperatorMethod (this, i => unchecked(-i)), + new LambdaUnaryOperatorMethod(this, i => unchecked(-i)), + new LambdaUnaryOperatorMethod(this, i => unchecked(-i)), + new LambdaUnaryOperatorMethod(this, i => unchecked(-i)), + new LambdaUnaryOperatorMethod(this, i => unchecked(-i)), new LambdaUnaryOperatorMethod(this, i => unchecked(-i)) )); } } } - + OperatorMethod[] checkedUnaryMinusOperators; - + public OperatorMethod[] CheckedUnaryMinusOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref checkedUnaryMinusOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref checkedUnaryMinusOperators, Lift( - new LambdaUnaryOperatorMethod (this, i => checked(-i)), - new LambdaUnaryOperatorMethod (this, i => checked(-i)), - new LambdaUnaryOperatorMethod (this, i => checked(-i)), - new LambdaUnaryOperatorMethod (this, i => checked(-i)), + new LambdaUnaryOperatorMethod(this, i => checked(-i)), + new LambdaUnaryOperatorMethod(this, i => checked(-i)), + new LambdaUnaryOperatorMethod(this, i => checked(-i)), + new LambdaUnaryOperatorMethod(this, i => checked(-i)), new LambdaUnaryOperatorMethod(this, i => checked(-i)) )); } } } - + // C# 4.0 spec: §7.7.3 Logical negation operator OperatorMethod[] logicalNegationOperators; - + public OperatorMethod[] LogicalNegationOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalNegationOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref logicalNegationOperators, Lift( new LambdaUnaryOperatorMethod(this, b => !b) )); } } } - + // C# 4.0 spec: §7.7.4 Bitwise complement operator OperatorMethod[] bitwiseComplementOperators; - + public OperatorMethod[] BitwiseComplementOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseComplementOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref bitwiseComplementOperators, Lift( - new LambdaUnaryOperatorMethod (this, i => ~i), - new LambdaUnaryOperatorMethod (this, i => ~i), - new LambdaUnaryOperatorMethod (this, i => ~i), + new LambdaUnaryOperatorMethod(this, i => ~i), + new LambdaUnaryOperatorMethod(this, i => ~i), + new LambdaUnaryOperatorMethod(this, i => ~i), new LambdaUnaryOperatorMethod(this, i => ~i) )); } } } #endregion - + #region Binary operator class definitions internal class BinaryOperatorMethod : OperatorMethod { public virtual bool CanEvaluateAtCompileTime { get { return false; } } - public virtual object Invoke(CSharpResolver resolver, object lhs, object rhs) { + public virtual object Invoke(CSharpResolver resolver, object lhs, object rhs) + { throw new NotSupportedException(); } - - public BinaryOperatorMethod(ICompilation compilation) : base(compilation) {} + + public BinaryOperatorMethod(ICompilation compilation) : base(compilation) { } } - + sealed class LambdaBinaryOperatorMethod : BinaryOperatorMethod { readonly Func checkedFunc; readonly Func uncheckedFunc; - + public LambdaBinaryOperatorMethod(CSharpOperators operators, Func func) : this(operators, func, func) { } - + public LambdaBinaryOperatorMethod(CSharpOperators operators, Func checkedFunc, Func uncheckedFunc) : base(operators.compilation) { @@ -418,30 +441,30 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver this.checkedFunc = checkedFunc; this.uncheckedFunc = uncheckedFunc; } - + public override bool CanEvaluateAtCompileTime { get { return true; } } - + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) { if (lhs == null || rhs == null) return null; Func func = resolver.CheckForOverflow ? checkedFunc : uncheckedFunc; return func((T1)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T1)), lhs), - (T2)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T2)), rhs)); + (T2)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T2)), rhs)); } - + public override OperatorMethod Lift(CSharpOperators operators) { return new LiftedBinaryOperatorMethod(operators, this); } } - + sealed class LiftedBinaryOperatorMethod : BinaryOperatorMethod, ILiftedOperator { readonly BinaryOperatorMethod baseMethod; - + public LiftedBinaryOperatorMethod(CSharpOperators operators, BinaryOperatorMethod baseMethod) : base(operators.compilation) { @@ -455,91 +478,103 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public IType NonLiftedReturnType => baseMethod.ReturnType; } #endregion - + #region Arithmetic operators // C# 4.0 spec: §7.8.1 Multiplication operator - + OperatorMethod[] multiplicationOperators; - + public OperatorMethod[] MultiplicationOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref multiplicationOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref multiplicationOperators, Lift( - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)), new LambdaBinaryOperatorMethod(this, (a, b) => checked(a * b), (a, b) => unchecked(a * b)) )); } } } - + // C# 4.0 spec: §7.8.2 Division operator OperatorMethod[] divisionOperators; - + public OperatorMethod[] DivisionOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref divisionOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref divisionOperators, Lift( - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)), new LambdaBinaryOperatorMethod(this, (a, b) => checked(a / b), (a, b) => unchecked(a / b)) )); } } } - + // C# 4.0 spec: §7.8.3 Remainder operator OperatorMethod[] remainderOperators; - + public OperatorMethod[] RemainderOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref remainderOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref remainderOperators, Lift( - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)), new LambdaBinaryOperatorMethod(this, (a, b) => checked(a % b), (a, b) => unchecked(a % b)) )); } } } - + // C# 4.0 spec: §7.8.3 Addition operator OperatorMethod[] additionOperators; - + public OperatorMethod[] AdditionOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref additionOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref additionOperators, Lift( - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), new LambdaBinaryOperatorMethod(this, (a, b) => checked(a + b), (a, b) => unchecked(a + b)), new StringConcatenation(this, TypeCode.String, TypeCode.String), new StringConcatenation(this, TypeCode.String, TypeCode.Object), @@ -548,12 +583,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } } - + // not in this list, but handled manually: enum addition, delegate combination sealed class StringConcatenation : BinaryOperatorMethod { bool canEvaluateAtCompileTime; - + public StringConcatenation(CSharpOperators operators, TypeCode p1, TypeCode p2) : base(operators.compilation) { @@ -562,83 +597,92 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver parameters.Add(operators.MakeParameter(p1)); parameters.Add(operators.MakeParameter(p2)); } - + public override bool CanEvaluateAtCompileTime { get { return canEvaluateAtCompileTime; } } - + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) { return string.Concat(lhs, rhs); } } - + // C# 4.0 spec: §7.8.4 Subtraction operator OperatorMethod[] subtractionOperators; - + public OperatorMethod[] SubtractionOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref subtractionOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref subtractionOperators, Lift( - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), - new LambdaBinaryOperatorMethod (this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod(this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)), new LambdaBinaryOperatorMethod(this, (a, b) => checked(a - b), (a, b) => unchecked(a - b)) )); } } } - + // C# 4.0 spec: §7.8.5 Shift operators OperatorMethod[] shiftLeftOperators; - + public OperatorMethod[] ShiftLeftOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref shiftLeftOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref shiftLeftOperators, Lift( - new LambdaBinaryOperatorMethod(this, (a, b) => a << b), - new LambdaBinaryOperatorMethod(this, (a, b) => a << b), - new LambdaBinaryOperatorMethod(this, (a, b) => a << b), + new LambdaBinaryOperatorMethod(this, (a, b) => a << b), + new LambdaBinaryOperatorMethod(this, (a, b) => a << b), + new LambdaBinaryOperatorMethod(this, (a, b) => a << b), new LambdaBinaryOperatorMethod(this, (a, b) => a << b) )); } } } - + OperatorMethod[] shiftRightOperators; - + public OperatorMethod[] ShiftRightOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref shiftRightOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref shiftRightOperators, Lift( - new LambdaBinaryOperatorMethod(this, (a, b) => a >> b), - new LambdaBinaryOperatorMethod(this, (a, b) => a >> b), - new LambdaBinaryOperatorMethod(this, (a, b) => a >> b), + new LambdaBinaryOperatorMethod(this, (a, b) => a >> b), + new LambdaBinaryOperatorMethod(this, (a, b) => a >> b), + new LambdaBinaryOperatorMethod(this, (a, b) => a >> b), new LambdaBinaryOperatorMethod(this, (a, b) => a >> b) )); } } } #endregion - + #region Equality operators sealed class EqualityOperatorMethod : BinaryOperatorMethod { public readonly TypeCode Type; public readonly bool Negate; - + public EqualityOperatorMethod(CSharpOperators operators, TypeCode type, bool negate) : base(operators.compilation) { @@ -648,11 +692,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver parameters.Add(operators.MakeParameter(type)); parameters.Add(operators.MakeParameter(type)); } - + public override bool CanEvaluateAtCompileTime { get { return Type != TypeCode.Object; } } - + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) { if (lhs == null && rhs == null) @@ -662,16 +706,21 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver lhs = resolver.CSharpPrimitiveCast(Type, lhs); rhs = resolver.CSharpPrimitiveCast(Type, rhs); bool equal; - if (Type == TypeCode.Single) { + if (Type == TypeCode.Single) + { equal = (float)lhs == (float)rhs; - } else if (Type == TypeCode.Double) { + } + else if (Type == TypeCode.Double) + { equal = (double)lhs == (double)rhs; - } else { + } + else + { equal = object.Equals(lhs, rhs); } return equal ^ Negate; } - + public override OperatorMethod Lift(CSharpOperators operators) { if (Type == TypeCode.Object || Type == TypeCode.String) @@ -680,11 +729,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return new LiftedEqualityOperatorMethod(operators, this); } } - + sealed class LiftedEqualityOperatorMethod : BinaryOperatorMethod, ILiftedOperator { readonly EqualityOperatorMethod baseMethod; - + public LiftedEqualityOperatorMethod(CSharpOperators operators, EqualityOperatorMethod baseMethod) : base(operators.compilation) { @@ -694,11 +743,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver parameters.Add(p); parameters.Add(p); } - + public override bool CanEvaluateAtCompileTime { get { return baseMethod.CanEvaluateAtCompileTime; } } - + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) { return baseMethod.Invoke(resolver, lhs, rhs); @@ -707,7 +756,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public IReadOnlyList NonLiftedParameters => baseMethod.Parameters; public IType NonLiftedReturnType => baseMethod.ReturnType; } - + // C# 4.0 spec: §7.10 Relational and type-testing operators static readonly TypeCode[] valueEqualityOperatorsFor = { TypeCode.Int32, TypeCode.UInt32, @@ -716,45 +765,54 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver TypeCode.Decimal, TypeCode.Boolean }; - + OperatorMethod[] valueEqualityOperators; - + public OperatorMethod[] ValueEqualityOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref valueEqualityOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref valueEqualityOperators, Lift( valueEqualityOperatorsFor.Select(c => new EqualityOperatorMethod(this, c, false)).ToArray() )); } } } - + OperatorMethod[] valueInequalityOperators; - + public OperatorMethod[] ValueInequalityOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref valueInequalityOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref valueInequalityOperators, Lift( valueEqualityOperatorsFor.Select(c => new EqualityOperatorMethod(this, c, true)).ToArray() )); } } } - + OperatorMethod[] referenceEqualityOperators; - + public OperatorMethod[] ReferenceEqualityOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref referenceEqualityOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref referenceEqualityOperators, Lift( new EqualityOperatorMethod(this, TypeCode.Object, false), new EqualityOperatorMethod(this, TypeCode.String, false) @@ -762,15 +820,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } } - + OperatorMethod[] referenceInequalityOperators; - + public OperatorMethod[] ReferenceInequalityOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref referenceInequalityOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref referenceInequalityOperators, Lift( new EqualityOperatorMethod(this, TypeCode.Object, true), new EqualityOperatorMethod(this, TypeCode.String, true) @@ -779,12 +840,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region Relational Operators sealed class RelationalOperatorMethod : BinaryOperatorMethod { readonly Func func; - + public RelationalOperatorMethod(CSharpOperators operators, Func func) : base(operators.compilation) { @@ -793,19 +854,19 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver parameters.Add(operators.MakeParameter(Type.GetTypeCode(typeof(T2)))); this.func = func; } - + public override bool CanEvaluateAtCompileTime { get { return true; } } - + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) { if (lhs == null || rhs == null) return null; return func((T1)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T1)), lhs), - (T2)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T2)), rhs)); + (T2)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T2)), rhs)); } - + public override OperatorMethod Lift(CSharpOperators operators) { var lifted = new LiftedBinaryOperatorMethod(operators, this); @@ -813,181 +874,208 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return lifted; } } - + OperatorMethod[] lessThanOperators; - + public OperatorMethod[] LessThanOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref lessThanOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref lessThanOperators, Lift( - new RelationalOperatorMethod (this, (a, b) => a < b), - new RelationalOperatorMethod (this, (a, b) => a < b), - new RelationalOperatorMethod (this, (a, b) => a < b), - new RelationalOperatorMethod (this, (a, b) => a < b), - new RelationalOperatorMethod (this, (a, b) => a < b), - new RelationalOperatorMethod (this, (a, b) => a < b), + new RelationalOperatorMethod(this, (a, b) => a < b), + new RelationalOperatorMethod(this, (a, b) => a < b), + new RelationalOperatorMethod(this, (a, b) => a < b), + new RelationalOperatorMethod(this, (a, b) => a < b), + new RelationalOperatorMethod(this, (a, b) => a < b), + new RelationalOperatorMethod(this, (a, b) => a < b), new RelationalOperatorMethod(this, (a, b) => a < b) )); } } } - + OperatorMethod[] lessThanOrEqualOperators; - + public OperatorMethod[] LessThanOrEqualOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref lessThanOrEqualOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref lessThanOrEqualOperators, Lift( - new RelationalOperatorMethod (this, (a, b) => a <= b), - new RelationalOperatorMethod (this, (a, b) => a <= b), - new RelationalOperatorMethod (this, (a, b) => a <= b), - new RelationalOperatorMethod (this, (a, b) => a <= b), - new RelationalOperatorMethod (this, (a, b) => a <= b), - new RelationalOperatorMethod (this, (a, b) => a <= b), + new RelationalOperatorMethod(this, (a, b) => a <= b), + new RelationalOperatorMethod(this, (a, b) => a <= b), + new RelationalOperatorMethod(this, (a, b) => a <= b), + new RelationalOperatorMethod(this, (a, b) => a <= b), + new RelationalOperatorMethod(this, (a, b) => a <= b), + new RelationalOperatorMethod(this, (a, b) => a <= b), new RelationalOperatorMethod(this, (a, b) => a <= b) )); } } } - + OperatorMethod[] greaterThanOperators; - + public OperatorMethod[] GreaterThanOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref greaterThanOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref greaterThanOperators, Lift( - new RelationalOperatorMethod (this, (a, b) => a > b), - new RelationalOperatorMethod (this, (a, b) => a > b), - new RelationalOperatorMethod (this, (a, b) => a > b), - new RelationalOperatorMethod (this, (a, b) => a > b), - new RelationalOperatorMethod (this, (a, b) => a > b), - new RelationalOperatorMethod (this, (a, b) => a > b), + new RelationalOperatorMethod(this, (a, b) => a > b), + new RelationalOperatorMethod(this, (a, b) => a > b), + new RelationalOperatorMethod(this, (a, b) => a > b), + new RelationalOperatorMethod(this, (a, b) => a > b), + new RelationalOperatorMethod(this, (a, b) => a > b), + new RelationalOperatorMethod(this, (a, b) => a > b), new RelationalOperatorMethod(this, (a, b) => a > b) )); } } } - + OperatorMethod[] greaterThanOrEqualOperators; - + public OperatorMethod[] GreaterThanOrEqualOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref greaterThanOrEqualOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref greaterThanOrEqualOperators, Lift( - new RelationalOperatorMethod (this, (a, b) => a >= b), - new RelationalOperatorMethod (this, (a, b) => a >= b), - new RelationalOperatorMethod (this, (a, b) => a >= b), - new RelationalOperatorMethod (this, (a, b) => a >= b), - new RelationalOperatorMethod (this, (a, b) => a >= b), - new RelationalOperatorMethod (this, (a, b) => a >= b), + new RelationalOperatorMethod(this, (a, b) => a >= b), + new RelationalOperatorMethod(this, (a, b) => a >= b), + new RelationalOperatorMethod(this, (a, b) => a >= b), + new RelationalOperatorMethod(this, (a, b) => a >= b), + new RelationalOperatorMethod(this, (a, b) => a >= b), + new RelationalOperatorMethod(this, (a, b) => a >= b), new RelationalOperatorMethod(this, (a, b) => a >= b) )); } } } #endregion - + #region Bitwise operators OperatorMethod[] logicalAndOperators; - + public OperatorMethod[] LogicalAndOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalAndOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref logicalAndOperators, new OperatorMethod[] { - new LambdaBinaryOperatorMethod(this, (a, b) => a & b) - }); + new LambdaBinaryOperatorMethod(this, (a, b) => a & b) + }); } } } - - + + OperatorMethod[] bitwiseAndOperators; - + public OperatorMethod[] BitwiseAndOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseAndOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref bitwiseAndOperators, Lift( - new LambdaBinaryOperatorMethod (this, (a, b) => a & b), - new LambdaBinaryOperatorMethod (this, (a, b) => a & b), - new LambdaBinaryOperatorMethod (this, (a, b) => a & b), + new LambdaBinaryOperatorMethod(this, (a, b) => a & b), + new LambdaBinaryOperatorMethod(this, (a, b) => a & b), + new LambdaBinaryOperatorMethod(this, (a, b) => a & b), new LambdaBinaryOperatorMethod(this, (a, b) => a & b), this.LogicalAndOperators[0] )); } } } - - + + OperatorMethod[] logicalOrOperators; - + public OperatorMethod[] LogicalOrOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalOrOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref logicalOrOperators, new OperatorMethod[] { - new LambdaBinaryOperatorMethod(this, (a, b) => a | b) - }); + new LambdaBinaryOperatorMethod(this, (a, b) => a | b) + }); } } } - + OperatorMethod[] bitwiseOrOperators; - + public OperatorMethod[] BitwiseOrOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseOrOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref bitwiseOrOperators, Lift( - new LambdaBinaryOperatorMethod (this, (a, b) => a | b), - new LambdaBinaryOperatorMethod (this, (a, b) => a | b), - new LambdaBinaryOperatorMethod (this, (a, b) => a | b), + new LambdaBinaryOperatorMethod(this, (a, b) => a | b), + new LambdaBinaryOperatorMethod(this, (a, b) => a | b), + new LambdaBinaryOperatorMethod(this, (a, b) => a | b), new LambdaBinaryOperatorMethod(this, (a, b) => a | b), this.LogicalOrOperators[0] )); } } } - + // Note: the logic for the lifted bool? bitwise operators is wrong; // we produce "true | null" = "null" when it should be true. However, this is irrelevant // because bool? cannot be a compile-time type. - + OperatorMethod[] bitwiseXorOperators; public OperatorMethod[] BitwiseXorOperators { get { OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseXorOperators); - if (ops != null) { + if (ops != null) + { return ops; - } else { + } + else + { return LazyInit.GetOrSet(ref bitwiseXorOperators, Lift( - new LambdaBinaryOperatorMethod (this, (a, b) => a ^ b), - new LambdaBinaryOperatorMethod (this, (a, b) => a ^ b), - new LambdaBinaryOperatorMethod (this, (a, b) => a ^ b), + new LambdaBinaryOperatorMethod(this, (a, b) => a ^ b), + new LambdaBinaryOperatorMethod(this, (a, b) => a ^ b), + new LambdaBinaryOperatorMethod(this, (a, b) => a ^ b), new LambdaBinaryOperatorMethod(this, (a, b) => a ^ b), - new LambdaBinaryOperatorMethod (this, (a, b) => a ^ b) + new LambdaBinaryOperatorMethod(this, (a, b) => a ^ b) )); } } @@ -997,14 +1085,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver #region User-defined operators public static IMethod LiftUserDefinedOperator(IMethod m) { - if (IsComparisonOperator(m)) { + if (IsComparisonOperator(m)) + { if (!m.ReturnType.IsKnownType(KnownTypeCode.Boolean)) return null; // cannot lift this operator - } else { + } + else + { if (!NullableType.IsNonNullableValueType(m.ReturnType)) return null; // cannot lift this operator } - for (int i = 0; i < m.Parameters.Count; i++) { + for (int i = 0; i < m.Parameters.Count; i++) + { if (!NullableType.IsNonNullableValueType(m.Parameters[i].Type)) return null; // cannot lift this operator } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs index d87e53b67..fd98642c0 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.Semantics; @@ -44,7 +45,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver readonly CSharpTypeResolveContext context; readonly bool checkForOverflow; readonly bool isWithinLambdaExpression; - + #region Constructor public CSharpResolver(ICompilation compilation) { @@ -54,7 +55,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver this.conversions = CSharpConversions.Get(compilation); this.context = new CSharpTypeResolveContext(compilation.MainModule); } - + public CSharpResolver(CSharpTypeResolveContext context) { if (context == null) @@ -65,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (context.CurrentTypeDefinition != null) currentTypeDefinitionCache = new TypeDefinitionCache(context.CurrentTypeDefinition); } - + private CSharpResolver(ICompilation compilation, CSharpConversions conversions, CSharpTypeResolveContext context, bool checkForOverflow, bool isWithinLambdaExpression, TypeDefinitionCache currentTypeDefinitionCache, ImmutableStack localVariableStack, ObjectInitializerContext objectInitializerStack) { this.compilation = compilation; @@ -78,7 +79,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver this.objectInitializerStack = objectInitializerStack; } #endregion - + #region Properties /// /// Gets the compilation used by the resolver. @@ -86,7 +87,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public ICompilation Compilation { get { return compilation; } } - + /// /// Gets the current type resolve context. /// @@ -97,19 +98,19 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IModule ITypeResolveContext.CurrentModule { get { return context.CurrentModule; } } - + CSharpResolver WithContext(CSharpTypeResolveContext newContext) { return new CSharpResolver(compilation, conversions, newContext, checkForOverflow, isWithinLambdaExpression, currentTypeDefinitionCache, localVariableStack, objectInitializerStack); } - + /// /// Gets whether the current context is checked. /// public bool CheckForOverflow { get { return checkForOverflow; } } - + /// /// Sets whether the current context is checked. /// @@ -119,14 +120,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return this; return new CSharpResolver(compilation, conversions, context, checkForOverflow, isWithinLambdaExpression, currentTypeDefinitionCache, localVariableStack, objectInitializerStack); } - + /// /// Gets whether the resolver is currently within a lambda expression or anonymous method. /// public bool IsWithinLambdaExpression { get { return isWithinLambdaExpression; } } - + /// /// Sets whether the resolver is currently within a lambda expression. /// @@ -134,7 +135,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { return new CSharpResolver(compilation, conversions, context, checkForOverflow, isWithinLambdaExpression, currentTypeDefinitionCache, localVariableStack, objectInitializerStack); } - + /// /// Gets the current member definition that is used to look up identifiers as parameters /// or type parameters. @@ -142,7 +143,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public IMember CurrentMember { get { return context.CurrentMember; } } - + /// /// Sets the current member definition. /// @@ -152,19 +153,19 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { return WithContext(context.WithCurrentMember(member)); } - + ITypeResolveContext ITypeResolveContext.WithCurrentMember(IMember member) { return WithCurrentMember(member); } - + /// /// Gets the current using scope that is used to look up identifiers as class names. /// public ResolvedUsingScope CurrentUsingScope { get { return context.CurrentUsingScope; } } - + /// /// Sets the current using scope that is used to look up identifiers as class names. /// @@ -173,17 +174,17 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return WithContext(context.WithUsingScope(usingScope)); } #endregion - + #region Per-CurrentTypeDefinition Cache readonly TypeDefinitionCache currentTypeDefinitionCache; - + /// /// Gets the current type definition. /// public ITypeDefinition CurrentTypeDefinition { get { return context.CurrentTypeDefinition; } } - + /// /// Sets the current type definition. /// @@ -191,49 +192,49 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { if (this.CurrentTypeDefinition == typeDefinition) return this; - + TypeDefinitionCache newTypeDefinitionCache; if (typeDefinition != null) newTypeDefinitionCache = new TypeDefinitionCache(typeDefinition); else newTypeDefinitionCache = null; - + return new CSharpResolver(compilation, conversions, context.WithCurrentTypeDefinition(typeDefinition), - checkForOverflow, isWithinLambdaExpression, newTypeDefinitionCache, localVariableStack, objectInitializerStack); + checkForOverflow, isWithinLambdaExpression, newTypeDefinitionCache, localVariableStack, objectInitializerStack); } - + ITypeResolveContext ITypeResolveContext.WithCurrentTypeDefinition(ITypeDefinition typeDefinition) { return WithCurrentTypeDefinition(typeDefinition); } - + 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 Local Variable Management - + // We store the local variables in an immutable stack. // The beginning of a block is marked by a null entry. - + // This data structure is used to allow efficient cloning of the resolver with its local variable context. readonly ImmutableStack localVariableStack = ImmutableStack.Empty; - + CSharpResolver WithLocalVariableStack(ImmutableStack stack) { return new CSharpResolver(compilation, conversions, context, checkForOverflow, isWithinLambdaExpression, currentTypeDefinitionCache, stack, objectInitializerStack); } - + /// /// Opens a new scope for local variables. /// @@ -241,7 +242,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { return WithLocalVariableStack(localVariableStack.Push(null)); } - + /// /// Closes the current scope for local variables; removing all variables in that scope. /// @@ -249,13 +250,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { var stack = localVariableStack; IVariable removedVar; - do { + do + { removedVar = stack.Peek(); stack = stack.Pop(); } while (removedVar != null); return WithLocalVariableStack(stack); } - + /// /// Adds a new variable or lambda parameter to the current block. /// @@ -265,7 +267,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new ArgumentNullException(nameof(variable)); return WithLocalVariableStack(localVariableStack.Push(variable)); } - + /// /// Removes the variable that was just added. /// @@ -275,7 +277,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new InvalidOperationException("There is no variable within the current block."); return WithLocalVariableStack(localVariableStack.Pop()); } - + /// /// Gets all currently visible local variables and lambda parameters. /// Does not include method parameters. @@ -286,27 +288,27 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region Object Initializer Context sealed class ObjectInitializerContext { internal readonly ResolveResult initializedObject; internal readonly ObjectInitializerContext prev; - + public ObjectInitializerContext(ResolveResult initializedObject, CSharpResolver.ObjectInitializerContext prev) { this.initializedObject = initializedObject; this.prev = prev; } } - + readonly ObjectInitializerContext objectInitializerStack; - + CSharpResolver WithObjectInitializerStack(ObjectInitializerContext stack) { return new CSharpResolver(compilation, conversions, context, checkForOverflow, isWithinLambdaExpression, currentTypeDefinitionCache, localVariableStack, stack); } - + /// /// Pushes the type of the object that is currently being initialized. /// @@ -316,21 +318,21 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new ArgumentNullException(nameof(initializedObject)); return WithObjectInitializerStack(new ObjectInitializerContext(initializedObject, objectInitializerStack)); } - + public CSharpResolver PopObjectInitializer() { if (objectInitializerStack == null) throw new InvalidOperationException(); return WithObjectInitializerStack(objectInitializerStack.prev); } - + /// /// Gets whether this context is within an object initializer. /// public bool IsInObjectInitializer { get { return objectInitializerStack != null; } } - + /// /// Gets the current object initializer. This usually is an /// or (for nested initializers) a semantic tree based on an . @@ -341,7 +343,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return objectInitializerStack != null ? objectInitializerStack.initializedObject : ErrorResult; } } - + /// /// Gets the type of the object currently being initialized. /// Returns SharedTypes.Unknown if no object initializer is currently open (or if the object initializer @@ -351,24 +353,29 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver get { return CurrentObjectInitializer.Type; } } #endregion - + #region ResolveUnaryOperator #region ResolveUnaryOperator method public ResolveResult ResolveUnaryOperator(UnaryOperatorType op, ResolveResult expression) { - if (expression.Type.Kind == TypeKind.Dynamic) { - if (op == UnaryOperatorType.Await) { + if (expression.Type.Kind == TypeKind.Dynamic) + { + if (op == UnaryOperatorType.Await) + { return new AwaitResolveResult(SpecialType.Dynamic, new DynamicInvocationResolveResult(new DynamicMemberResolveResult(expression, "GetAwaiter"), DynamicInvocationType.Invocation, EmptyList.Instance), SpecialType.Dynamic, null, null, null); } - else { + else + { return UnaryOperatorResolveResult(SpecialType.Dynamic, op, expression); } } - + // C# 4.0 spec: §7.3.3 Unary operator overload resolution string overloadableOperatorName = GetOverloadableOperatorName(op); - if (overloadableOperatorName == null) { - switch (op) { + if (overloadableOperatorName == null) + { + switch (op) + { case UnaryOperatorType.Dereference: PointerType p = expression.Type as PointerType; if (p != null) @@ -377,7 +384,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return ErrorResult; case UnaryOperatorType.AddressOf: return UnaryOperatorResolveResult(new PointerType(expression.Type), op, expression); - case UnaryOperatorType.Await: { + case UnaryOperatorType.Await: + { ResolveResult getAwaiterMethodGroup = ResolveMemberAccess(expression, "GetAwaiter", EmptyList.Instance, NameLookupMode.InvocationTarget); ResolveResult getAwaiterInvocation = ResolveInvocation(getAwaiterMethodGroup, Empty.Array, argumentNames: null, allowOptionalParameters: false); @@ -385,12 +393,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IMethod getResultMethod; IType awaitResultType; var getResultMethodGroup = lookup.Lookup(getAwaiterInvocation, "GetResult", EmptyList.Instance, true) as MethodGroupResolveResult; - if (getResultMethodGroup != null) { + if (getResultMethodGroup != null) + { var getResultOR = getResultMethodGroup.PerformOverloadResolution(compilation, Empty.Array, allowExtensionMethods: false, conversions: conversions); getResultMethod = getResultOR.FoundApplicableCandidate ? getResultOR.GetBestCandidateWithSubstitutedTypeArguments() as IMethod : null; awaitResultType = getResultMethod != null ? getResultMethod.ReturnType : SpecialType.UnknownType; } - else { + else + { getResultMethod = null; awaitResultType = SpecialType.UnknownType; } @@ -428,20 +438,23 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // If the type is nullable, get the underlying type: IType type = NullableType.GetUnderlyingType(expression.Type); bool isNullable = NullableType.IsNullable(expression.Type); - + // the operator is overloadable: OverloadResolution userDefinedOperatorOR = CreateOverloadResolution(new[] { expression }); - foreach (var candidate in GetUserDefinedOperatorCandidates(type, overloadableOperatorName)) { + foreach (var candidate in GetUserDefinedOperatorCandidates(type, overloadableOperatorName)) + { userDefinedOperatorOR.AddCandidate(candidate); } - if (userDefinedOperatorOR.FoundApplicableCandidate) { + if (userDefinedOperatorOR.FoundApplicableCandidate) + { return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR, UnaryOperatorExpression.GetLinqNodeType(op, this.CheckForOverflow)); } - + expression = UnaryNumericPromotion(op, ref type, isNullable, expression); CSharpOperators.OperatorMethod[] methodGroup; CSharpOperators operators = CSharpOperators.Get(compilation); - switch (op) { + switch (op) + { case UnaryOperatorType.Increment: case UnaryOperatorType.Decrement: case UnaryOperatorType.PostIncrement: @@ -454,13 +467,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver else return new ErrorResolveResult(expression.Type); case UnaryOperatorType.Plus: - if (type.IsCSharpNativeIntegerType()) { + if (type.IsCSharpNativeIntegerType()) + { return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable); } methodGroup = operators.UnaryPlusOperators; break; case UnaryOperatorType.Minus: - if (type.IsCSharpNativeIntegerType()) { + if (type.IsCSharpNativeIntegerType()) + { return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable); } methodGroup = CheckForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators; @@ -469,8 +484,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver methodGroup = operators.LogicalNegationOperators; break; case UnaryOperatorType.BitNot: - if (type.Kind == TypeKind.Enum) { - if (expression.IsCompileTimeConstant && !isNullable && expression.ConstantValue != null) { + if (type.Kind == TypeKind.Enum) + { + if (expression.IsCompileTimeConstant && !isNullable && expression.ConstantValue != null) + { // evaluate as (E)(~(U)x); var U = compilation.FindType(expression.ConstantValue.GetType()); var unpackedEnum = new ConstantResolveResult(U, expression.ConstantValue); @@ -480,9 +497,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return rr; } return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable); - } else if (type.IsCSharpNativeIntegerType()) { + } + else if (type.IsCSharpNativeIntegerType()) + { return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable); - } else { + } + else + { methodGroup = operators.BitwiseComplementOperators; break; } @@ -490,38 +511,52 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new InvalidOperationException(); } OverloadResolution builtinOperatorOR = CreateOverloadResolution(new[] { expression }); - foreach (var candidate in methodGroup) { + foreach (var candidate in methodGroup) + { builtinOperatorOR.AddCandidate(candidate); } CSharpOperators.UnaryOperatorMethod m = (CSharpOperators.UnaryOperatorMethod)builtinOperatorOR.BestCandidate; IType resultType = m.ReturnType; - if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) { - if (userDefinedOperatorOR.BestCandidate != null) { + if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) + { + if (userDefinedOperatorOR.BestCandidate != null) + { // If there are any user-defined operators, prefer those over the built-in operators. // It'll be a more informative error. return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR, UnaryOperatorExpression.GetLinqNodeType(op, this.CheckForOverflow)); - } else if (builtinOperatorOR.BestCandidateAmbiguousWith != null) { + } + else if (builtinOperatorOR.BestCandidateAmbiguousWith != null) + { // If the best candidate is ambiguous, just use the input type instead // of picking one of the ambiguous overloads. return new ErrorResolveResult(expression.Type); - } else { + } + else + { return new ErrorResolveResult(resultType); } - } else if (expression.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) { + } + else if (expression.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) + { object val; - try { + try + { val = m.Invoke(this, expression.ConstantValue); - } catch (ArithmeticException) { + } + catch (ArithmeticException) + { return new ErrorResolveResult(resultType); } return new ConstantResolveResult(resultType, val); - } else { + } + else + { expression = Convert(expression, m.Parameters[0].Type, builtinOperatorOR.ArgumentConversions[0]); return UnaryOperatorResolveResult(resultType, op, expression, - builtinOperatorOR.BestCandidate is ILiftedOperator); + builtinOperatorOR.BestCandidate is ILiftedOperator); } } - + OperatorResolveResult UnaryOperatorResolveResult(IType resultType, UnaryOperatorType op, ResolveResult expression, bool isLifted = false) { return new OperatorResolveResult( @@ -529,7 +564,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver null, isLifted, new[] { expression }); } #endregion - + #region UnaryNumericPromotion ResolveResult UnaryNumericPromotion(UnaryOperatorType op, ref IType type, bool isNullable, ResolveResult expression) { @@ -537,31 +572,35 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver TypeCode code = ReflectionHelper.GetTypeCode(type); if (isNullable && type.Kind == TypeKind.Null) code = TypeCode.SByte; // cause promotion of null to int32 - switch (op) { + switch (op) + { case UnaryOperatorType.Minus: - if (code == TypeCode.UInt32) { + if (code == TypeCode.UInt32) + { type = compilation.FindType(KnownTypeCode.Int64); return Convert(expression, MakeNullable(type, isNullable), - isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); + isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); } goto case UnaryOperatorType.Plus; case UnaryOperatorType.Plus: case UnaryOperatorType.BitNot: - if (code >= TypeCode.Char && code <= TypeCode.UInt16) { + if (code >= TypeCode.Char && code <= TypeCode.UInt16) + { type = compilation.FindType(KnownTypeCode.Int32); return Convert(expression, MakeNullable(type, isNullable), - isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); + isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); } break; } return expression; } #endregion - + #region GetOverloadableOperatorName static string GetOverloadableOperatorName(UnaryOperatorType op) { - switch (op) { + switch (op) + { case UnaryOperatorType.Not: return "op_LogicalNot"; case UnaryOperatorType.BitNot: @@ -582,67 +621,81 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } #endregion #endregion - + #region ResolveBinaryOperator #region ResolveBinaryOperator method public ResolveResult ResolveBinaryOperator(BinaryOperatorType op, ResolveResult lhs, ResolveResult rhs) { - if (lhs.Type.Kind == TypeKind.Dynamic || rhs.Type.Kind == TypeKind.Dynamic) { + if (lhs.Type.Kind == TypeKind.Dynamic || rhs.Type.Kind == TypeKind.Dynamic) + { lhs = Convert(lhs, SpecialType.Dynamic); rhs = Convert(rhs, SpecialType.Dynamic); return BinaryOperatorResolveResult(SpecialType.Dynamic, lhs, op, rhs); } - + // C# 4.0 spec: §7.3.4 Binary operator overload resolution string overloadableOperatorName = GetOverloadableOperatorName(op); - if (overloadableOperatorName == null) { - + if (overloadableOperatorName == null) + { + // Handle logical and/or exactly as bitwise and/or: // - If the user overloads a bitwise operator, that implicitly creates the corresponding logical operator. // - If both inputs are compile-time constants, it doesn't matter that we don't short-circuit. // - If inputs aren't compile-time constants, we don't evaluate anything, so again it doesn't matter that we don't short-circuit - if (op == BinaryOperatorType.ConditionalAnd) { + if (op == BinaryOperatorType.ConditionalAnd) + { overloadableOperatorName = GetOverloadableOperatorName(BinaryOperatorType.BitwiseAnd); - } else if (op == BinaryOperatorType.ConditionalOr) { + } + else if (op == BinaryOperatorType.ConditionalOr) + { overloadableOperatorName = GetOverloadableOperatorName(BinaryOperatorType.BitwiseOr); - } else if (op == BinaryOperatorType.NullCoalescing) { + } + else if (op == BinaryOperatorType.NullCoalescing) + { // null coalescing operator is not overloadable and needs to be handled separately return ResolveNullCoalescingOperator(lhs, rhs); - } else { + } + else + { return ErrorResolveResult.UnknownError; } } - + // If the type is nullable, get the underlying type: bool isNullable = NullableType.IsNullable(lhs.Type) || NullableType.IsNullable(rhs.Type); IType lhsType = NullableType.GetUnderlyingType(lhs.Type); IType rhsType = NullableType.GetUnderlyingType(rhs.Type); - + // the operator is overloadable: OverloadResolution userDefinedOperatorOR = CreateOverloadResolution(new[] { lhs, rhs }); HashSet userOperatorCandidates = new HashSet(); userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(lhsType, overloadableOperatorName)); userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(rhsType, overloadableOperatorName)); - foreach (var candidate in userOperatorCandidates) { + foreach (var candidate in userOperatorCandidates) + { userDefinedOperatorOR.AddCandidate(candidate); } - if (userDefinedOperatorOR.FoundApplicableCandidate) { + if (userDefinedOperatorOR.FoundApplicableCandidate) + { return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR, BinaryOperatorExpression.GetLinqNodeType(op, this.CheckForOverflow)); } - + if (lhsType.Kind == TypeKind.Null && rhsType.IsReferenceType == false - || lhsType.IsReferenceType == false && rhsType.Kind == TypeKind.Null) + || lhsType.IsReferenceType == false && rhsType.Kind == TypeKind.Null) { isNullable = true; } - if (op == BinaryOperatorType.ShiftLeft || op == BinaryOperatorType.ShiftRight) { + if (op == BinaryOperatorType.ShiftLeft || op == BinaryOperatorType.ShiftRight) + { // special case: the shift operators allow "var x = null << null", producing int?. if (lhsType.Kind == TypeKind.Null && rhsType.Kind == TypeKind.Null) isNullable = true; // for shift operators, do unary promotion independently on both arguments lhs = UnaryNumericPromotion(UnaryOperatorType.Plus, ref lhsType, isNullable, lhs); rhs = UnaryNumericPromotion(UnaryOperatorType.Plus, ref rhsType, isNullable, rhs); - } else { + } + else + { bool allowNullableConstants = op == BinaryOperatorType.Equality || op == BinaryOperatorType.InEquality; if (!BinaryNumericPromotion(isNullable, ref lhs, ref rhs, allowNullableConstants)) return new ErrorResolveResult(lhs.Type); @@ -650,10 +703,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // re-read underlying types after numeric promotion lhsType = NullableType.GetUnderlyingType(lhs.Type); rhsType = NullableType.GetUnderlyingType(rhs.Type); - + IEnumerable methodGroup; CSharpOperators operators = CSharpOperators.Get(compilation); - switch (op) { + switch (op) + { case BinaryOperatorType.Multiply: methodGroup = operators.MultiplicationOperators; break; @@ -666,36 +720,46 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver case BinaryOperatorType.Add: methodGroup = operators.AdditionOperators; { - if (lhsType.Kind == TypeKind.Enum) { + if (lhsType.Kind == TypeKind.Enum) + { // E operator +(E x, U y); IType underlyingType = MakeNullable(GetEnumUnderlyingType(lhsType), isNullable); - if (TryConvertEnum(ref rhs, underlyingType, ref isNullable, ref lhs)) { + if (TryConvertEnum(ref rhs, underlyingType, ref isNullable, ref lhs)) + { return HandleEnumOperator(isNullable, lhsType, op, lhs, rhs); } } - if (rhsType.Kind == TypeKind.Enum) { + if (rhsType.Kind == TypeKind.Enum) + { // E operator +(U x, E y); IType underlyingType = MakeNullable(GetEnumUnderlyingType(rhsType), isNullable); - if (TryConvertEnum(ref lhs, underlyingType, ref isNullable, ref rhs)) { + if (TryConvertEnum(ref lhs, underlyingType, ref isNullable, ref rhs)) + { return HandleEnumOperator(isNullable, rhsType, op, lhs, rhs); } } - - if (lhsType.Kind == TypeKind.Delegate && TryConvert(ref rhs, lhsType)) { + + if (lhsType.Kind == TypeKind.Delegate && TryConvert(ref rhs, lhsType)) + { return BinaryOperatorResolveResult(lhsType, lhs, op, rhs); - } else if (rhsType.Kind == TypeKind.Delegate && TryConvert(ref lhs, rhsType)) { + } + else if (rhsType.Kind == TypeKind.Delegate && TryConvert(ref lhs, rhsType)) + { return BinaryOperatorResolveResult(rhsType, lhs, op, rhs); } - - if (lhsType is PointerType) { - methodGroup = new [] { + + if (lhsType is PointerType) + { + methodGroup = new[] { PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.Int32), PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.UInt32), PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.Int64), PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.UInt64) }; - } else if (rhsType is PointerType) { - methodGroup = new [] { + } + else if (rhsType is PointerType) + { + methodGroup = new[] { PointerArithmeticOperator(rhsType, KnownTypeCode.Int32, rhsType), PointerArithmeticOperator(rhsType, KnownTypeCode.UInt32, rhsType), PointerArithmeticOperator(rhsType, KnownTypeCode.Int64, rhsType), @@ -709,54 +773,68 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver case BinaryOperatorType.Subtract: methodGroup = operators.SubtractionOperators; { - if (lhsType.Kind == TypeKind.Enum) { + if (lhsType.Kind == TypeKind.Enum) + { // U operator –(E x, E y); - if (TryConvertEnum(ref rhs, lhs.Type, ref isNullable, ref lhs, allowConversionFromConstantZero: false)) { + if (TryConvertEnum(ref rhs, lhs.Type, ref isNullable, ref lhs, allowConversionFromConstantZero: false)) + { return HandleEnumSubtraction(isNullable, lhsType, lhs, rhs); } // E operator –(E x, U y); IType underlyingType = MakeNullable(GetEnumUnderlyingType(lhsType), isNullable); - if (TryConvertEnum(ref rhs, underlyingType, ref isNullable, ref lhs)) { + if (TryConvertEnum(ref rhs, underlyingType, ref isNullable, ref lhs)) + { return HandleEnumOperator(isNullable, lhsType, op, lhs, rhs); } } - if (rhsType.Kind == TypeKind.Enum) { + if (rhsType.Kind == TypeKind.Enum) + { // U operator –(E x, E y); - if (TryConvertEnum(ref lhs, rhs.Type, ref isNullable, ref rhs)) { + if (TryConvertEnum(ref lhs, rhs.Type, ref isNullable, ref rhs)) + { return HandleEnumSubtraction(isNullable, rhsType, lhs, rhs); } // E operator -(U x, E y); IType underlyingType = MakeNullable(GetEnumUnderlyingType(rhsType), isNullable); - if (TryConvertEnum(ref lhs, underlyingType, ref isNullable, ref rhs)) { + if (TryConvertEnum(ref lhs, underlyingType, ref isNullable, ref rhs)) + { return HandleEnumOperator(isNullable, rhsType, op, lhs, rhs); } } - - if (lhsType.Kind == TypeKind.Delegate && TryConvert(ref rhs, lhsType)) { + + if (lhsType.Kind == TypeKind.Delegate && TryConvert(ref rhs, lhsType)) + { return BinaryOperatorResolveResult(lhsType, lhs, op, rhs); - } else if (rhsType.Kind == TypeKind.Delegate && TryConvert(ref lhs, rhsType)) { + } + else if (rhsType.Kind == TypeKind.Delegate && TryConvert(ref lhs, rhsType)) + { return BinaryOperatorResolveResult(rhsType, lhs, op, rhs); } - - if (lhsType is PointerType) { - if (rhsType is PointerType) { + + if (lhsType is PointerType) + { + if (rhsType is PointerType) + { IType int64 = compilation.FindType(KnownTypeCode.Int64); - if (lhsType.Equals(rhsType)) { + if (lhsType.Equals(rhsType)) + { return BinaryOperatorResolveResult(int64, lhs, op, rhs); - } else { + } + else + { return new ErrorResolveResult(int64); } } - methodGroup = new [] { + methodGroup = new[] { PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.Int32), PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.UInt32), PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.Int64), PointerArithmeticOperator(lhsType, lhsType, KnownTypeCode.UInt64) }; } - + if (lhsType.Kind == TypeKind.Null && rhsType.Kind == TypeKind.Null) return new ErrorResolveResult(SpecialType.NullType); } @@ -773,92 +851,109 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver case BinaryOperatorType.GreaterThan: case BinaryOperatorType.LessThanOrEqual: case BinaryOperatorType.GreaterThanOrEqual: + { + if (lhsType.Kind == TypeKind.Enum && TryConvert(ref 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.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 BinaryOperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), lhs, op, rhs); - } else if (lhsType.IsCSharpNativeIntegerType() || rhsType.IsCSharpNativeIntegerType()) { - if (lhsType.Equals(rhsType)) - return BinaryOperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), lhs, op, rhs, isLifted: isNullable); + // bool operator op(E x, E y); + return HandleEnumComparison(op, lhsType, isNullable, lhs, rhs); + } + 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 BinaryOperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), lhs, op, rhs); + } + else if (lhsType.IsCSharpNativeIntegerType() || rhsType.IsCSharpNativeIntegerType()) + { + if (lhsType.Equals(rhsType)) + return BinaryOperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), lhs, op, rhs, isLifted: isNullable); + else + return new ErrorResolveResult(compilation.FindType(KnownTypeCode.Boolean)); + } + if (op == BinaryOperatorType.Equality || op == BinaryOperatorType.InEquality) + { + if (lhsType.IsReferenceType == true && rhsType.IsReferenceType == true) + { + // If it's a reference comparison + if (op == BinaryOperatorType.Equality) + methodGroup = operators.ReferenceEqualityOperators; else - return new ErrorResolveResult(compilation.FindType(KnownTypeCode.Boolean)); - } - if (op == BinaryOperatorType.Equality || op == BinaryOperatorType.InEquality) { - if (lhsType.IsReferenceType == true && rhsType.IsReferenceType == true) { - // If it's a reference comparison - if (op == BinaryOperatorType.Equality) - methodGroup = operators.ReferenceEqualityOperators; - else - methodGroup = operators.ReferenceInequalityOperators; - break; - } else if (lhsType.Kind == TypeKind.Null && IsNullableTypeOrNonValueType(rhs.Type) - || IsNullableTypeOrNonValueType(lhs.Type) && rhsType.Kind == TypeKind.Null) { - // compare type parameter or nullable type with the null literal - return BinaryOperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), lhs, op, rhs); - } + methodGroup = operators.ReferenceInequalityOperators; + break; } - switch (op) { - case BinaryOperatorType.Equality: - methodGroup = operators.ValueEqualityOperators; - break; - case BinaryOperatorType.InEquality: - methodGroup = operators.ValueInequalityOperators; - break; - case BinaryOperatorType.LessThan: - methodGroup = operators.LessThanOperators; - break; - case BinaryOperatorType.GreaterThan: - methodGroup = operators.GreaterThanOperators; - break; - case BinaryOperatorType.LessThanOrEqual: - methodGroup = operators.LessThanOrEqualOperators; - break; - case BinaryOperatorType.GreaterThanOrEqual: - methodGroup = operators.GreaterThanOrEqualOperators; - break; - default: - throw new InvalidOperationException(); + else if (lhsType.Kind == TypeKind.Null && IsNullableTypeOrNonValueType(rhs.Type) + || IsNullableTypeOrNonValueType(lhs.Type) && rhsType.Kind == TypeKind.Null) + { + // compare type parameter or nullable type with the null literal + return BinaryOperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), lhs, op, rhs); } } - break; + switch (op) + { + case BinaryOperatorType.Equality: + methodGroup = operators.ValueEqualityOperators; + break; + case BinaryOperatorType.InEquality: + methodGroup = operators.ValueInequalityOperators; + break; + case BinaryOperatorType.LessThan: + methodGroup = operators.LessThanOperators; + break; + case BinaryOperatorType.GreaterThan: + methodGroup = operators.GreaterThanOperators; + break; + case BinaryOperatorType.LessThanOrEqual: + methodGroup = operators.LessThanOrEqualOperators; + break; + case BinaryOperatorType.GreaterThanOrEqual: + methodGroup = operators.GreaterThanOrEqualOperators; + break; + default: + throw new InvalidOperationException(); + } + } + break; case BinaryOperatorType.BitwiseAnd: case BinaryOperatorType.BitwiseOr: case BinaryOperatorType.ExclusiveOr: + { + if (lhsType.Kind == TypeKind.Enum) { - if (lhsType.Kind == TypeKind.Enum) { - // bool operator op(E x, E y); - if (TryConvertEnum(ref rhs, lhs.Type, ref isNullable, ref lhs)) { - return HandleEnumOperator(isNullable, lhsType, op, lhs, rhs); - } + // bool operator op(E x, E y); + if (TryConvertEnum(ref rhs, lhs.Type, ref isNullable, ref lhs)) + { + return HandleEnumOperator(isNullable, lhsType, op, lhs, rhs); } + } - if (rhsType.Kind == TypeKind.Enum) { - // bool operator op(E x, E y); - if (TryConvertEnum (ref lhs, rhs.Type, ref isNullable, ref rhs)) { - return HandleEnumOperator(isNullable, rhsType, op, lhs, rhs); - } - } - - switch (op) { - case BinaryOperatorType.BitwiseAnd: - methodGroup = operators.BitwiseAndOperators; - break; - case BinaryOperatorType.BitwiseOr: - methodGroup = operators.BitwiseOrOperators; - break; - case BinaryOperatorType.ExclusiveOr: - methodGroup = operators.BitwiseXorOperators; - break; - default: - throw new InvalidOperationException(); + if (rhsType.Kind == TypeKind.Enum) + { + // bool operator op(E x, E y); + if (TryConvertEnum(ref lhs, rhs.Type, ref isNullable, ref rhs)) + { + return HandleEnumOperator(isNullable, rhsType, op, lhs, rhs); } } - break; + + switch (op) + { + case BinaryOperatorType.BitwiseAnd: + methodGroup = operators.BitwiseAndOperators; + break; + case BinaryOperatorType.BitwiseOr: + methodGroup = operators.BitwiseOrOperators; + break; + case BinaryOperatorType.ExclusiveOr: + methodGroup = operators.BitwiseXorOperators; + break; + default: + throw new InvalidOperationException(); + } + } + break; case BinaryOperatorType.ConditionalAnd: methodGroup = operators.LogicalAndOperators; break; @@ -868,8 +963,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver default: throw new InvalidOperationException(); } - if (lhsType.IsCSharpNativeIntegerType() || rhsType.IsCSharpNativeIntegerType()) { - if (lhsType.Equals(rhsType)) { + if (lhsType.IsCSharpNativeIntegerType() || rhsType.IsCSharpNativeIntegerType()) + { + if (lhsType.Equals(rhsType)) + { return BinaryOperatorResolveResult( isNullable ? NullableType.Create(compilation, lhsType) : lhsType, lhs, op, rhs, isLifted: isNullable); @@ -878,39 +975,48 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return new ErrorResolveResult(lhsType); } OverloadResolution builtinOperatorOR = CreateOverloadResolution(new[] { lhs, rhs }); - foreach (var candidate in methodGroup) { + foreach (var candidate in methodGroup) + { builtinOperatorOR.AddCandidate(candidate); } CSharpOperators.BinaryOperatorMethod m = (CSharpOperators.BinaryOperatorMethod)builtinOperatorOR.BestCandidate; IType resultType = m.ReturnType; - if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) { + 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, BinaryOperatorExpression.GetLinqNodeType(op, this.CheckForOverflow)); else return new ErrorResolveResult(resultType); - } else if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) { + } + else if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) + { object val; - try { + try + { val = m.Invoke(this, lhs.ConstantValue, rhs.ConstantValue); - } catch (ArithmeticException) { + } + catch (ArithmeticException) + { return new ErrorResolveResult(resultType); } return new ConstantResolveResult(resultType, val); - } else { + } + else + { lhs = Convert(lhs, m.Parameters[0].Type, builtinOperatorOR.ArgumentConversions[0]); rhs = Convert(rhs, m.Parameters[1].Type, builtinOperatorOR.ArgumentConversions[1]); return BinaryOperatorResolveResult(resultType, lhs, op, rhs, - builtinOperatorOR.BestCandidate is ILiftedOperator); + builtinOperatorOR.BestCandidate is ILiftedOperator); } } - + bool IsNullableTypeOrNonValueType(IType type) { return NullableType.IsNullable(type) || type.IsReferenceType != false; } - + ResolveResult BinaryOperatorResolveResult(IType resultType, ResolveResult lhs, BinaryOperatorType op, ResolveResult rhs, bool isLifted = false) { return new OperatorResolveResult( @@ -918,18 +1024,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver null, isLifted, new[] { lhs, rhs }); } #endregion - + #region Pointer arithmetic CSharpOperators.BinaryOperatorMethod PointerArithmeticOperator(IType resultType, IType inputType1, KnownTypeCode inputType2) { return PointerArithmeticOperator(resultType, inputType1, compilation.FindType(inputType2)); } - + CSharpOperators.BinaryOperatorMethod PointerArithmeticOperator(IType resultType, KnownTypeCode inputType1, IType inputType2) { return PointerArithmeticOperator(resultType, compilation.FindType(inputType1), inputType2); } - + CSharpOperators.BinaryOperatorMethod PointerArithmeticOperator(IType resultType, IType inputType1, IType inputType2) { return new CSharpOperators.BinaryOperatorMethod(compilation) { @@ -941,14 +1047,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver }; } #endregion - + #region Enum helper methods IType GetEnumUnderlyingType(IType enumType) { ITypeDefinition def = enumType.GetDefinition(); return def != null ? def.EnumUnderlyingType : SpecialType.UnknownType; } - + /// /// Handle the case where an enum value is compared with another enum value /// bool operator op(E x, E y); @@ -957,7 +1063,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { // evaluate as ((U)x op (U)y) IType elementType = GetEnumUnderlyingType(enumType); - if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable && elementType.Kind != TypeKind.Enum) { + if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable && elementType.Kind != TypeKind.Enum) + { var rr = ResolveBinaryOperator(op, ResolveCast(elementType, lhs), ResolveCast(elementType, rhs)); if (rr.IsCompileTimeConstant) return rr; @@ -965,7 +1072,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IType resultType = compilation.FindType(KnownTypeCode.Boolean); return BinaryOperatorResolveResult(resultType, lhs, op, rhs, isNullable); } - + /// /// Handle the case where an enum value is subtracted from another enum value /// U operator –(E x, E y); @@ -974,7 +1081,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { // evaluate as (U)((U)x – (U)y) IType elementType = GetEnumUnderlyingType(enumType); - if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable && elementType.Kind != TypeKind.Enum) { + if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable && elementType.Kind != TypeKind.Enum) + { var rr = ResolveBinaryOperator(BinaryOperatorType.Subtract, ResolveCast(elementType, lhs), ResolveCast(elementType, rhs)); rr = WithCheckForOverflow(false).ResolveCast(elementType, rr); if (rr.IsCompileTimeConstant) @@ -983,7 +1091,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IType resultType = MakeNullable(elementType, isNullable); return BinaryOperatorResolveResult(resultType, lhs, BinaryOperatorType.Subtract, rhs, isNullable); } - + /// /// Handle the following enum operators: /// E operator +(E x, U y); @@ -996,9 +1104,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver 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) { + if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable) + { IType elementType = GetEnumUnderlyingType(enumType); - if (elementType.Kind != TypeKind.Enum) { + if (elementType.Kind != TypeKind.Enum) + { var rr = ResolveBinaryOperator(op, ResolveCast(elementType, lhs), ResolveCast(elementType, rhs)); rr = WithCheckForOverflow(false).ResolveCast(enumType, rr); if (rr.IsCompileTimeConstant) // only report result if it's a constant; use the regular OperatorResolveResult codepath otherwise @@ -1008,7 +1118,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IType resultType = MakeNullable(enumType, isNullable); return BinaryOperatorResolveResult(resultType, lhs, op, rhs, isNullable); } - + IType MakeNullable(IType type, bool isNullable) { if (isNullable) @@ -1017,7 +1127,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return type; } #endregion - + #region BinaryNumericPromotion bool BinaryNumericPromotion(bool isNullable, ref ResolveResult lhs, ref ResolveResult rhs, bool allowNullableConstants) { @@ -1028,54 +1138,80 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver TypeCode rhsCode = ReflectionHelper.GetTypeCode(rhsUType); // Treat C# 9 native integers as falling between int and long. // However they don't have a TypeCode, so we hack around that here: - if (lhsUType.Kind == TypeKind.NInt) { + if (lhsUType.Kind == TypeKind.NInt) + { lhsCode = TypeCode.Int32; - } else if (lhsUType.Kind == TypeKind.NUInt) { + } + else if (lhsUType.Kind == TypeKind.NUInt) + { lhsCode = TypeCode.UInt32; } - if (rhsUType.Kind == TypeKind.NInt) { + if (rhsUType.Kind == TypeKind.NInt) + { rhsCode = TypeCode.Int32; - } else if (rhsUType.Kind == TypeKind.NUInt) { + } + else if (rhsUType.Kind == TypeKind.NUInt) + { rhsCode = TypeCode.UInt32; } // if one of the inputs is the null literal, promote that to the type of the other operand - if (isNullable && lhs.Type.Kind == TypeKind.Null && rhsCode >= TypeCode.Boolean && rhsCode <= TypeCode.Decimal) { + if (isNullable && lhs.Type.Kind == TypeKind.Null && rhsCode >= TypeCode.Boolean && rhsCode <= TypeCode.Decimal) + { lhs = CastTo(rhsCode, isNullable, lhs, allowNullableConstants); lhsCode = rhsCode; - } else if (isNullable && rhs.Type.Kind == TypeKind.Null && lhsCode >= TypeCode.Boolean && lhsCode <= TypeCode.Decimal) { + } + else if (isNullable && rhs.Type.Kind == TypeKind.Null && lhsCode >= TypeCode.Boolean && lhsCode <= TypeCode.Decimal) + { rhs = CastTo(lhsCode, isNullable, rhs, allowNullableConstants); rhsCode = lhsCode; } bool bindingError = false; if (lhsCode >= TypeCode.Char && lhsCode <= TypeCode.Decimal - && rhsCode >= TypeCode.Char && rhsCode <= TypeCode.Decimal) + && rhsCode >= TypeCode.Char && rhsCode <= TypeCode.Decimal) { TypeCode targetType; - if (lhsCode == TypeCode.Decimal || rhsCode == TypeCode.Decimal) { + if (lhsCode == TypeCode.Decimal || rhsCode == TypeCode.Decimal) + { targetType = TypeCode.Decimal; bindingError = (lhsCode == TypeCode.Single || lhsCode == TypeCode.Double || rhsCode == TypeCode.Single || rhsCode == TypeCode.Double); - } else if (lhsCode == TypeCode.Double || rhsCode == TypeCode.Double) { + } + else if (lhsCode == TypeCode.Double || rhsCode == TypeCode.Double) + { targetType = TypeCode.Double; - } else if (lhsCode == TypeCode.Single || rhsCode == TypeCode.Single) { + } + else if (lhsCode == TypeCode.Single || rhsCode == TypeCode.Single) + { targetType = TypeCode.Single; - } else if (lhsCode == TypeCode.UInt64 || rhsCode == TypeCode.UInt64) { + } + else if (lhsCode == TypeCode.UInt64 || rhsCode == TypeCode.UInt64) + { targetType = TypeCode.UInt64; bindingError = IsSigned(lhsCode, lhs) || IsSigned(rhsCode, rhs); - } else if (lhsUType.Kind == TypeKind.NUInt || rhsUType.Kind == TypeKind.NUInt) { + } + else if (lhsUType.Kind == TypeKind.NUInt || rhsUType.Kind == TypeKind.NUInt) + { bindingError = IsSigned(lhsCode, lhs) || IsSigned(rhsCode, rhs); lhs = CastTo(SpecialType.NUInt, isNullable, lhs, allowNullableConstants); rhs = CastTo(SpecialType.NUInt, isNullable, rhs, allowNullableConstants); return !bindingError; - } else if (lhsCode == TypeCode.UInt32 || rhsCode == TypeCode.UInt32) { + } + else if (lhsCode == TypeCode.UInt32 || rhsCode == TypeCode.UInt32) + { targetType = (IsSigned(lhsCode, lhs) || IsSigned(rhsCode, rhs)) ? TypeCode.Int64 : TypeCode.UInt32; - } else if (lhsCode == TypeCode.Int64 || rhsCode == TypeCode.Int64) { + } + else if (lhsCode == TypeCode.Int64 || rhsCode == TypeCode.Int64) + { targetType = TypeCode.Int64; - } else if (lhsUType.Kind == TypeKind.NInt || rhsUType.Kind == TypeKind.NInt) { + } + else if (lhsUType.Kind == TypeKind.NInt || rhsUType.Kind == TypeKind.NInt) + { lhs = CastTo(SpecialType.NInt, isNullable, lhs, allowNullableConstants); rhs = CastTo(SpecialType.NInt, isNullable, rhs, allowNullableConstants); return !bindingError; - } else { + } + else + { targetType = TypeCode.Int32; } lhs = CastTo(targetType, isNullable, lhs, allowNullableConstants); @@ -1083,12 +1219,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } return !bindingError; } - + bool IsSigned(TypeCode code, ResolveResult rr) { // Determine whether the rr with code==ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(rr.Type)) // is a signed primitive type. - switch (code) { + switch (code) + { case TypeCode.SByte: case TypeCode.Int16: return true; @@ -1119,7 +1256,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IType nullableType = MakeNullable(targetType, isNullable); if (nullableType.Equals(expression.Type)) return expression; - if (allowNullableConstants && expression.IsCompileTimeConstant) { + if (allowNullableConstants && expression.IsCompileTimeConstant) + { if (expression.ConstantValue == null) return new ConstantResolveResult(nullableType, null); ResolveResult rr = ResolveCast(targetType, expression); @@ -1127,17 +1265,20 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return rr; Debug.Assert(rr.IsCompileTimeConstant); return new ConstantResolveResult(nullableType, rr.ConstantValue); - } else { + } + else + { return Convert(expression, nullableType, - isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); + isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); } } #endregion - + #region GetOverloadableOperatorName static string GetOverloadableOperatorName(BinaryOperatorType op) { - switch (op) { + switch (op) + { case BinaryOperatorType.Add: return "op_Addition"; case BinaryOperatorType.Subtract: @@ -1175,35 +1316,42 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region Null coalescing operator ResolveResult ResolveNullCoalescingOperator(ResolveResult lhs, ResolveResult rhs) { - if (NullableType.IsNullable(lhs.Type)) { + if (NullableType.IsNullable(lhs.Type)) + { IType a0 = NullableType.GetUnderlyingType(lhs.Type); - if (TryConvert(ref rhs, a0)) { + if (TryConvert(ref rhs, a0)) + { return BinaryOperatorResolveResult(a0, lhs, BinaryOperatorType.NullCoalescing, rhs); } } - if (TryConvert(ref rhs, lhs.Type)) { + if (TryConvert(ref rhs, lhs.Type)) + { return BinaryOperatorResolveResult(lhs.Type, lhs, BinaryOperatorType.NullCoalescing, rhs); } - if (TryConvert(ref lhs, rhs.Type)) { + if (TryConvert(ref lhs, rhs.Type)) + { return BinaryOperatorResolveResult(rhs.Type, lhs, BinaryOperatorType.NullCoalescing, rhs); - } else { + } + else + { return new ErrorResolveResult(lhs.Type); } } #endregion #endregion - + #region Get user-defined operator candidates public 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) { + 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; @@ -1213,37 +1361,41 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver LiftUserDefinedOperators(operators); return operators; } - + void LiftUserDefinedOperators(List operators) { int nonLiftedMethodCount = operators.Count; // Construct lifted operators - for (int i = 0; i < nonLiftedMethodCount; i++) { + for (int i = 0; i < nonLiftedMethodCount; i++) + { var liftedMethod = CSharpOperators.LiftUserDefinedOperator(operators[i]); if (liftedMethod != null) operators.Add(liftedMethod); } } - + ResolveResult CreateResolveResultForUserDefinedOperator(OverloadResolution r, System.Linq.Expressions.ExpressionType operatorType) { if (r.BestCandidateErrors != OverloadResolutionErrors.None) return r.CreateResolveResult(null); IMethod method = (IMethod)r.BestCandidate; return new OperatorResolveResult(method.ReturnType, operatorType, method, - isLiftedOperator: method is ILiftedOperator, - operands: r.GetArgumentsWithConversions()); + isLiftedOperator: method is ILiftedOperator, + operands: r.GetArgumentsWithConversions()); } #endregion - + #region ResolveCast bool TryConvert(ref ResolveResult rr, IType targetType) { Conversion c = conversions.ImplicitConversion(rr, targetType); - if (c.IsValid) { + if (c.IsValid) + { rr = Convert(rr, targetType, c); return true; - } else { + } + else + { return false; } } @@ -1265,10 +1417,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver bool TryConvertEnum(ref ResolveResult rr, IType targetType, ref bool isNullable, ref ResolveResult enumRR, bool allowConversionFromConstantZero = true) { Conversion c; - if (!isNullable) { + if (!isNullable) + { // Try non-nullable c = conversions.ImplicitConversion(rr, targetType); - if (c.IsValid && (allowConversionFromConstantZero || !c.IsEnumerationConversion)) { + if (c.IsValid && (allowConversionFromConstantZero || !c.IsEnumerationConversion)) + { rr = Convert(rr, targetType, c); return true; } @@ -1276,13 +1430,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // make targetType nullable if it isn't already: if (!targetType.IsKnownType(KnownTypeCode.NullableOfT)) targetType = NullableType.Create(compilation, targetType); - + c = conversions.ImplicitConversion(rr, targetType); - if (c.IsValid && (allowConversionFromConstantZero || !c.IsEnumerationConversion)) { + if (c.IsValid && (allowConversionFromConstantZero || !c.IsEnumerationConversion)) + { rr = Convert(rr, targetType, c); isNullable = true; // Also convert the enum-typed RR to nullable, if it isn't already - if (!enumRR.Type.IsKnownType(KnownTypeCode.NullableOfT)) { + if (!enumRR.Type.IsKnownType(KnownTypeCode.NullableOfT)) + { var nullableType = NullableType.Create(compilation, enumRR.Type); enumRR = new ConversionResolveResult(nullableType, enumRR, Conversion.ImplicitNullableConversion); } @@ -1290,12 +1446,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } return false; } - + ResolveResult Convert(ResolveResult rr, IType targetType) { return Convert(rr, targetType, conversions.ImplicitConversion(rr, targetType)); } - + ResolveResult Convert(ResolveResult rr, IType targetType, Conversion c) { if (c == Conversion.IdentityConversion) @@ -1305,106 +1461,134 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver else return new ConversionResolveResult(targetType, rr, c, checkForOverflow); } - + public ResolveResult ResolveCast(IType targetType, ResolveResult expression) { // C# 4.0 spec: §7.7.6 Cast expressions Conversion c = conversions.ExplicitConversion(expression, targetType); - if (expression.IsCompileTimeConstant && !c.IsUserDefined) { + if (expression.IsCompileTimeConstant && !c.IsUserDefined) + { IType underlyingType = targetType.GetEnumUnderlyingType(); TypeCode code = ReflectionHelper.GetTypeCode(underlyingType); - if (code >= TypeCode.Boolean && code <= TypeCode.Decimal && expression.ConstantValue != null) { - try { - return new ConstantResolveResult(targetType, CSharpPrimitiveCast(code, expression.ConstantValue)); - } catch (OverflowException) { + if (code >= TypeCode.Boolean && code <= TypeCode.Decimal && expression.ConstantValue != null) + { + try + { + return new ConstantResolveResult(targetType, CSharpPrimitiveCast(code, expression.ConstantValue)); + } + catch (OverflowException) + { return new ErrorResolveResult(targetType); - } catch (InvalidCastException) { + } + catch (InvalidCastException) + { return new ErrorResolveResult(targetType); } - } else if (code == TypeCode.String) { + } + else if (code == TypeCode.String) + { if (expression.ConstantValue == null || expression.ConstantValue is string) return new ConstantResolveResult(targetType, expression.ConstantValue); else return new ErrorResolveResult(targetType); - } else if ((underlyingType.Kind == TypeKind.NInt || underlyingType.Kind == TypeKind.NUInt) && expression.ConstantValue != null) { + } + else if ((underlyingType.Kind == TypeKind.NInt || underlyingType.Kind == TypeKind.NUInt) && expression.ConstantValue != null) + { code = (underlyingType.Kind == TypeKind.NInt ? TypeCode.Int32 : TypeCode.UInt32); - try { + try + { return new ConstantResolveResult(targetType, Util.CSharpPrimitiveCast.Cast(code, expression.ConstantValue, checkForOverflow: true)); - } catch (OverflowException) { + } + catch (OverflowException) + { // If constant value doesn't fit into 32-bits, the conversion is not a compile-time constant return new ConversionResolveResult(targetType, expression, c, checkForOverflow); - } catch (InvalidCastException) { + } + catch (InvalidCastException) + { return new ErrorResolveResult(targetType); } } } return new ConversionResolveResult(targetType, expression, c, checkForOverflow); } - + internal object CSharpPrimitiveCast(TypeCode targetType, object input) { return Util.CSharpPrimitiveCast.Cast(targetType, input, this.CheckForOverflow); } #endregion - + #region ResolveSimpleName public ResolveResult ResolveSimpleName(string identifier, IReadOnlyList typeArguments, bool isInvocationTarget = false) { // C# 4.0 spec: §7.6.2 Simple Names - + return LookupSimpleNameOrTypeName( identifier, typeArguments, isInvocationTarget ? NameLookupMode.InvocationTarget : NameLookupMode.Expression); } - + public ResolveResult LookupSimpleNameOrTypeName(string identifier, IReadOnlyList typeArguments, NameLookupMode lookupMode) { // C# 4.0 spec: §3.8 Namespace and type names; §7.6.2 Simple Names - + if (identifier == null) throw new ArgumentNullException(nameof(identifier)); if (typeArguments == null) throw new ArgumentNullException(nameof(typeArguments)); - + int k = typeArguments.Count; - - if (k == 0) { - if (lookupMode == NameLookupMode.Expression || lookupMode == NameLookupMode.InvocationTarget) { + + if (k == 0) + { + if (lookupMode == NameLookupMode.Expression || lookupMode == NameLookupMode.InvocationTarget) + { // Look in local variables - foreach (IVariable v in this.LocalVariables) { - if (v.Name == identifier) { + foreach (IVariable v in this.LocalVariables) + { + if (v.Name == identifier) + { return new LocalResolveResult(v); } } // 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) { + if (parameterizedMember != null) + { + foreach (IParameter p in parameterizedMember.Parameters) + { + if (p.Name == identifier) + { return new LocalResolveResult(p); } } } } - + // look in type parameters of current method IMethod m = this.CurrentMember as IMethod; - if (m != null) { - foreach (ITypeParameter tp in m.TypeParameters) { + if (m != null) + { + foreach (ITypeParameter tp in m.TypeParameters) + { if (tp.Name == identifier) return new TypeResolveResult(tp); } } } - + bool parameterizeResultType = !(typeArguments.Count != 0 && typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument)); - + ResolveResult r = null; - if (currentTypeDefinitionCache != null) { + if (currentTypeDefinitionCache != null) + { Dictionary cache = null; bool foundInCache = false; - if (k == 0) { - switch (lookupMode) { + if (k == 0) + { + switch (lookupMode) + { case NameLookupMode.Expression: cache = currentTypeDefinitionCache.SimpleNameLookupCacheExpression; break; @@ -1415,16 +1599,21 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver cache = currentTypeDefinitionCache.SimpleTypeLookupCache; break; } - if (cache != null) { + if (cache != null) + { lock (cache) foundInCache = cache.TryGetValue(identifier, out r); } } - if (foundInCache) { + if (foundInCache) + { r = (r != null ? r.ShallowClone() : null); - } else { + } + else + { r = LookInCurrentType(identifier, typeArguments, lookupMode, parameterizeResultType); - if (cache != null) { + if (cache != null) + { // also cache missing members (r==null) lock (cache) cache[identifier] = r; @@ -1433,69 +1622,89 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (r != null) return r; } - - if (context.CurrentUsingScope == null) { + + if (context.CurrentUsingScope == null) + { // If no using scope was specified, we still need to look in the global namespace: r = LookInUsingScopeNamespace(null, compilation.RootNamespace, identifier, typeArguments, parameterizeResultType); - } else { - if (k == 0 && lookupMode != NameLookupMode.TypeInUsingDeclaration) { - if (context.CurrentUsingScope.ResolveCache.TryGetValue(identifier, out r)) { + } + else + { + if (k == 0 && lookupMode != NameLookupMode.TypeInUsingDeclaration) + { + if (context.CurrentUsingScope.ResolveCache.TryGetValue(identifier, out r)) + { r = (r != null ? r.ShallowClone() : null); - } else { + } + else + { r = LookInCurrentUsingScope(identifier, typeArguments, false, false); context.CurrentUsingScope.ResolveCache.TryAdd(identifier, r); } - } else { + } + else + { r = LookInCurrentUsingScope(identifier, typeArguments, lookupMode == NameLookupMode.TypeInUsingDeclaration, parameterizeResultType); } } if (r != null) return r; - - if (typeArguments.Count == 0 && identifier == "dynamic") { + + if (typeArguments.Count == 0 && identifier == "dynamic") + { return new TypeResolveResult(SpecialType.Dynamic); - } else { + } + else + { return new UnknownIdentifierResolveResult(identifier, typeArguments.Count); } } - - public bool IsVariableReferenceWithSameType (ResolveResult rr, string identifier, out TypeResolveResult trr) + + public bool IsVariableReferenceWithSameType(ResolveResult rr, string identifier, out TypeResolveResult trr) { - if (!(rr is MemberResolveResult || rr is LocalResolveResult)) { + if (!(rr is MemberResolveResult || rr is LocalResolveResult)) + { trr = null; return false; } - trr = LookupSimpleNameOrTypeName (identifier, EmptyList.Instance, NameLookupMode.Type) as TypeResolveResult; - return trr != null && trr.Type.Equals (rr.Type); + trr = LookupSimpleNameOrTypeName(identifier, EmptyList.Instance, NameLookupMode.Type) as TypeResolveResult; + return trr != null && trr.Type.Equals(rr.Type); } - + ResolveResult LookInCurrentType(string identifier, IReadOnlyList typeArguments, NameLookupMode lookupMode, bool parameterizeResultType) { int k = typeArguments.Count; MemberLookup lookup = CreateMemberLookup(lookupMode); // look in current type definitions - for (ITypeDefinition t = this.CurrentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) { - if (k == 0) { + for (ITypeDefinition t = this.CurrentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) + { + if (k == 0) + { // Look for type parameter with that name var typeParameters = t.TypeParameters; // Look at all type parameters, including those copied from outer classes, // so that we can fetch the version with the correct owner. - for (int i = 0; i < typeParameters.Count; i++) { + for (int i = 0; i < typeParameters.Count; i++) + { if (typeParameters[i].Name == identifier) return new TypeResolveResult(typeParameters[i]); } } - - if (lookupMode == NameLookupMode.BaseTypeReference && t == this.CurrentTypeDefinition) { + + if (lookupMode == NameLookupMode.BaseTypeReference && t == this.CurrentTypeDefinition) + { // don't look in current type when resolving a base type reference continue; } - + ResolveResult r; - if (lookupMode == NameLookupMode.Expression || lookupMode == NameLookupMode.InvocationTarget) { + if (lookupMode == NameLookupMode.Expression || lookupMode == NameLookupMode.InvocationTarget) + { var targetResolveResult = (t == this.CurrentTypeDefinition ? ResolveThisReference() : new TypeResolveResult(t)); r = lookup.Lookup(targetResolveResult, identifier, typeArguments, lookupMode == NameLookupMode.InvocationTarget); - } else { + } + else + { r = lookup.LookupType(t, identifier, typeArguments, parameterizeResultType); } if (!(r is UnknownMemberResolveResult)) // but do return AmbiguousMemberResolveResult @@ -1503,44 +1712,56 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } return null; } - + ResolveResult LookInCurrentUsingScope(string identifier, IReadOnlyList typeArguments, bool isInUsingDeclaration, bool parameterizeResultType) { // look in current namespace definitions ResolvedUsingScope currentUsingScope = this.CurrentUsingScope; - for (ResolvedUsingScope u = currentUsingScope; u != null; u = u.Parent) { + for (ResolvedUsingScope u = currentUsingScope; u != null; u = u.Parent) + { var resultInNamespace = LookInUsingScopeNamespace(u, u.Namespace, identifier, typeArguments, parameterizeResultType); if (resultInNamespace != null) return resultInNamespace; // then look for aliases: - if (typeArguments.Count == 0) { - if (u.ExternAliases.Contains(identifier)) { + if (typeArguments.Count == 0) + { + if (u.ExternAliases.Contains(identifier)) + { return ResolveExternAlias(identifier); } - if (!(isInUsingDeclaration && u == currentUsingScope)) { - foreach (var pair in u.UsingAliases) { - if (pair.Key == identifier) { + if (!(isInUsingDeclaration && u == currentUsingScope)) + { + foreach (var pair in u.UsingAliases) + { + if (pair.Key == identifier) + { return pair.Value.ShallowClone(); } } } } // finally, look in the imported namespaces: - if (!(isInUsingDeclaration && u == currentUsingScope)) { + if (!(isInUsingDeclaration && u == currentUsingScope)) + { IType firstResult = null; - foreach (var importedNamespace in u.Usings) { + foreach (var importedNamespace in u.Usings) + { ITypeDefinition def = importedNamespace.GetTypeDefinition(identifier, typeArguments.Count); - if (def != null) { + if (def != null) + { IType resultType; if (parameterizeResultType && typeArguments.Count > 0) resultType = new ParameterizedType(def, typeArguments); else resultType = def; - - if (firstResult == null || !TopLevelTypeDefinitionIsAccessible(firstResult.GetDefinition())) { + + if (firstResult == null || !TopLevelTypeDefinitionIsAccessible(firstResult.GetDefinition())) + { if (TopLevelTypeDefinitionIsAccessible(resultType.GetDefinition())) firstResult = resultType; - } else if (TopLevelTypeDefinitionIsAccessible(def)) { + } + else if (TopLevelTypeDefinitionIsAccessible(def)) + { return new AmbiguousTypeResolveResult(firstResult); } } @@ -1559,9 +1780,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return null; // first look for a namespace int k = typeArguments.Count; - if (k == 0) { + if (k == 0) + { INamespace childNamespace = n.GetChildNamespace(identifier); - if (childNamespace != null) { + if (childNamespace != null) + { if (usingScope != null && usingScope.HasAlias(identifier)) return new AmbiguousTypeResolveResult(new UnknownType(null, identifier)); return new NamespaceResolveResult(childNamespace); @@ -1569,9 +1792,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } // then look for a type ITypeDefinition def = n.GetTypeDefinition(identifier, k); - if (def != null) { + if (def != null) + { IType result = def; - if (parameterizeResultType && k > 0) { + if (parameterizeResultType && k > 0) + { result = new ParameterizedType(def, typeArguments); } if (usingScope != null && usingScope.HasAlias(identifier)) @@ -1581,15 +1806,16 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } return null; } - + bool TopLevelTypeDefinitionIsAccessible(ITypeDefinition typeDef) { - if (typeDef.Accessibility == Accessibility.Internal) { + if (typeDef.Accessibility == Accessibility.Internal) + { return typeDef.ParentModule.InternalsVisibleTo(compilation.MainModule); } return true; } - + /// /// Looks up an alias (identifier in front of :: operator) /// @@ -1597,20 +1823,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { if (identifier == "global") return new NamespaceResolveResult(compilation.RootNamespace); - - for (ResolvedUsingScope n = this.CurrentUsingScope; n != null; n = n.Parent) { - if (n.ExternAliases.Contains(identifier)) { + + for (ResolvedUsingScope n = this.CurrentUsingScope; n != null; n = n.Parent) + { + if (n.ExternAliases.Contains(identifier)) + { return ResolveExternAlias(identifier); } - foreach (var pair in n.UsingAliases) { - if (pair.Key == identifier) { + foreach (var pair in n.UsingAliases) + { + if (pair.Key == identifier) + { return (pair.Value as NamespaceResolveResult) ?? ErrorResult; } } } return ErrorResult; } - + ResolveResult ResolveExternAlias(string alias) { INamespace ns = compilation.GetNamespaceForExternAlias(alias); @@ -1620,24 +1850,26 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return ErrorResult; } #endregion - + #region ResolveMemberAccess public ResolveResult ResolveMemberAccess(ResolveResult target, string identifier, IReadOnlyList typeArguments, NameLookupMode lookupMode = NameLookupMode.Expression) { // C# 4.0 spec: §7.6.4 - + bool parameterizeResultType = !(typeArguments.Count != 0 && typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument)); NamespaceResolveResult nrr = target as NamespaceResolveResult; - if (nrr != null) { + if (nrr != null) + { return ResolveMemberAccessOnNamespace(nrr, identifier, typeArguments, parameterizeResultType); } - + if (target.Type.Kind == TypeKind.Dynamic) return new DynamicMemberResolveResult(target, identifier); - + MemberLookup lookup = CreateMemberLookup(lookupMode); ResolveResult result; - switch (lookupMode) { + switch (lookupMode) + { case NameLookupMode.Expression: result = lookup.Lookup(target, identifier, typeArguments, isInvocation: false); break; @@ -1653,20 +1885,25 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver default: throw new NotSupportedException("Invalid value for NameLookupMode"); } - if (result is UnknownMemberResolveResult) { + if (result is UnknownMemberResolveResult) + { // We intentionally use all extension methods here, not just the eligible ones. // Proper eligibility checking is only possible for the full invocation // (after we know the remaining arguments). // The eligibility check in GetExtensionMethods is only intended for code completion. var extensionMethods = GetExtensionMethods(identifier, typeArguments); - if (extensionMethods.Count > 0) { + if (extensionMethods.Count > 0) + { return new MethodGroupResolveResult(target, identifier, EmptyList.Instance, typeArguments) { extensionMethods = extensionMethods }; } - } else { + } + else + { MethodGroupResolveResult mgrr = result as MethodGroupResolveResult; - if (mgrr != null) { + if (mgrr != null) + { Debug.Assert(mgrr.extensionMethods == null); // set the values that are necessary to make MethodGroupResolveResult.GetExtensionMethods() work mgrr.resolver = this; @@ -1674,16 +1911,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } return result; } - + ResolveResult ResolveMemberAccessOnNamespace(NamespaceResolveResult nrr, string identifier, IReadOnlyList typeArguments, bool parameterizeResultType) { - if (typeArguments.Count == 0) { + if (typeArguments.Count == 0) + { INamespace childNamespace = nrr.Namespace.GetChildNamespace(identifier); if (childNamespace != null) return new NamespaceResolveResult(childNamespace); } ITypeDefinition def = nrr.Namespace.GetTypeDefinition(identifier, typeArguments.Count); - if (def != null) { + if (def != null) + { if (parameterizeResultType && typeArguments.Count > 0) return new TypeResolveResult(new ParameterizedType(def, typeArguments)); else @@ -1691,7 +1930,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } return ErrorResult; } - + /// /// Creates a MemberLookup instance using this resolver's settings. /// @@ -1702,24 +1941,27 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver && currentTypeDefinition != null && currentTypeDefinition.Kind == TypeKind.Enum; return new MemberLookup(currentTypeDefinition, this.Compilation.MainModule, isInEnumMemberInitializer); } - + /// /// Creates a MemberLookup instance using this resolver's settings. /// public MemberLookup CreateMemberLookup(NameLookupMode lookupMode) { - if (lookupMode == NameLookupMode.BaseTypeReference && this.CurrentTypeDefinition != null) { + if (lookupMode == NameLookupMode.BaseTypeReference && this.CurrentTypeDefinition != null) + { // When looking up a base type reference, treat us as being outside the current type definition // for accessibility purposes. // This avoids a stack overflow when referencing a protected class nested inside the base class // of a parent class. (NameLookupTests.InnerClassInheritingFromProtectedBaseInnerClassShouldNotCauseStackOverflow) return new MemberLookup(this.CurrentTypeDefinition.DeclaringTypeDefinition, this.Compilation.MainModule, false); - } else { + } + else + { return CreateMemberLookup(); } } #endregion - + #region ResolveIdentifierInObjectInitializer public ResolveResult ResolveIdentifierInObjectInitializer(string identifier) { @@ -1737,39 +1979,52 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver ResolveResult getEnumeratorInvocation; ResolveResult currentRR = null; // C# 4.0 spec: §8.8.4 The foreach statement - if (expression.Type.Kind == TypeKind.Array || expression.Type.Kind == TypeKind.Dynamic) { + if (expression.Type.Kind == TypeKind.Array || expression.Type.Kind == TypeKind.Dynamic) + { collectionType = compilation.FindType(KnownTypeCode.IEnumerable); enumeratorType = compilation.FindType(KnownTypeCode.IEnumerator); - if (expression.Type.Kind == TypeKind.Array) { + if (expression.Type.Kind == TypeKind.Array) + { elementType = ((ArrayType)expression.Type).ElementType; - } else { + } + else + { elementType = SpecialType.Dynamic; } getEnumeratorInvocation = ResolveCast(collectionType, expression); getEnumeratorInvocation = ResolveMemberAccess(getEnumeratorInvocation, "GetEnumerator", EmptyList.Instance, NameLookupMode.InvocationTarget); getEnumeratorInvocation = ResolveInvocation(getEnumeratorInvocation, Empty.Array); - } else { + } + else + { var getEnumeratorMethodGroup = memberLookup.Lookup(expression, "GetEnumerator", EmptyList.Instance, true) as MethodGroupResolveResult; - if (getEnumeratorMethodGroup != null) { + if (getEnumeratorMethodGroup != null) + { var or = getEnumeratorMethodGroup.PerformOverloadResolution( compilation, Empty.Array, allowExtensionMethods: false, allowExpandingParams: false, allowOptionalParameters: false); - if (or.FoundApplicableCandidate && !or.IsAmbiguous && !or.BestCandidate.IsStatic && or.BestCandidate.Accessibility == Accessibility.Public) { + if (or.FoundApplicableCandidate && !or.IsAmbiguous && !or.BestCandidate.IsStatic && or.BestCandidate.Accessibility == Accessibility.Public) + { collectionType = expression.Type; getEnumeratorInvocation = or.CreateResolveResult(expression); enumeratorType = getEnumeratorInvocation.Type; currentRR = memberLookup.Lookup(new ResolveResult(enumeratorType), "Current", EmptyList.Instance, false); elementType = currentRR.Type; - } else { + } + else + { CheckForEnumerableInterface(expression, out collectionType, out enumeratorType, out elementType, out getEnumeratorInvocation); } - } else { + } + else + { CheckForEnumerableInterface(expression, out collectionType, out enumeratorType, out elementType, out getEnumeratorInvocation); } } IMethod moveNextMethod = null; var moveNextMethodGroup = memberLookup.Lookup(new ResolveResult(enumeratorType), "MoveNext", EmptyList.Instance, false) as MethodGroupResolveResult; - if (moveNextMethodGroup != null) { + if (moveNextMethodGroup != null) + { var or = moveNextMethodGroup.PerformOverloadResolution( compilation, Empty.Array, allowExtensionMethods: false, allowExpandingParams: false, allowOptionalParameters: false); @@ -1790,7 +2045,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver void CheckForEnumerableInterface(ResolveResult expression, out IType collectionType, out IType enumeratorType, out IType elementType, out ResolveResult getEnumeratorInvocation) { elementType = expression.Type.GetElementTypeFromIEnumerable(compilation, false, out bool? isGeneric); - if (isGeneric == true) { + if (isGeneric == true) + { ITypeDefinition enumerableOfT = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition(); if (enumerableOfT != null) collectionType = new ParameterizedType(enumerableOfT, new[] { elementType }); @@ -1802,10 +2058,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver enumeratorType = new ParameterizedType(enumeratorOfT, new[] { elementType }); else enumeratorType = SpecialType.UnknownType; - } else if (isGeneric == false) { + } + else if (isGeneric == false) + { collectionType = compilation.FindType(KnownTypeCode.IEnumerable); enumeratorType = compilation.FindType(KnownTypeCode.IEnumerator); - } else { + } + else + { collectionType = SpecialType.UnknownType; enumeratorType = SpecialType.UnknownType; } @@ -1837,7 +2097,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { return GetExtensionMethods(null, name, typeArguments); } - + /// /// Gets the extension methods that are called 'name' /// and are applicable with a first argument type of 'targetType'. @@ -1866,25 +2126,34 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { var lookup = CreateMemberLookup(); List> extensionMethodGroups = new List>(); - foreach (var inputGroup in GetAllExtensionMethods(lookup)) { + foreach (var inputGroup in GetAllExtensionMethods(lookup)) + { List outputGroup = new List(); - foreach (var method in inputGroup) { + foreach (var method in inputGroup) + { if (name != null && method.Name != name) continue; if (!lookup.IsAccessible(method, false)) continue; IType[] inferredTypes; - if (typeArguments != null && typeArguments.Count > 0) { + if (typeArguments != null && typeArguments.Count > 0) + { if (method.TypeParameters.Count != typeArguments.Count) continue; var sm = method.Specialize(new TypeParameterSubstitution(null, typeArguments)); if (IsEligibleExtensionMethod(compilation, conversions, targetType, sm, false, out inferredTypes)) outputGroup.Add(sm); - } else { - if (IsEligibleExtensionMethod(compilation, conversions, targetType, method, true, out inferredTypes)) { - if (substituteInferredTypes && inferredTypes != null) { + } + else + { + if (IsEligibleExtensionMethod(compilation, conversions, targetType, method, true, out inferredTypes)) + { + if (substituteInferredTypes && inferredTypes != null) + { outputGroup.Add(method.Specialize(new TypeParameterSubstitution(null, inferredTypes))); - } else { + } + else + { outputGroup.Add(method); } } @@ -1895,7 +2164,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } return extensionMethodGroups; } - + /// /// Checks whether the specified extension method is eligible on the target type. /// @@ -1920,7 +2189,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver var compilation = method.Compilation; return IsEligibleExtensionMethod(compilation, CSharpConversions.Get(compilation), targetType, method, useTypeInference, out outInferredTypes); } - + static bool IsEligibleExtensionMethod(ICompilation compilation, CSharpConversions conversions, IType targetType, IMethod method, bool useTypeInference, out IType[] outInferredTypes) { outInferredTypes = null; @@ -1929,7 +2198,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (method.Parameters.Count == 0) return false; IType thisParameterType = method.Parameters[0].Type; - if (useTypeInference && method.TypeParameters.Count > 0) { + if (useTypeInference && method.TypeParameters.Count > 0) + { // We need to infer type arguments from targetType: TypeInference ti = new TypeInference(compilation, conversions); ResolveResult[] arguments = { new ResolveResult(targetType) }; @@ -1938,12 +2208,16 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver var substitution = new TypeParameterSubstitution(null, inferredTypes); // Validate that the types that could be inferred (aren't unknown) satisfy the constraints: bool hasInferredTypes = false; - for (int i = 0; i < inferredTypes.Length; i++) { - if (inferredTypes[i].Kind != TypeKind.Unknown && inferredTypes[i].Kind != TypeKind.UnboundTypeArgument) { + for (int i = 0; i < inferredTypes.Length; i++) + { + if (inferredTypes[i].Kind != TypeKind.Unknown && inferredTypes[i].Kind != TypeKind.UnboundTypeArgument) + { hasInferredTypes = true; if (!OverloadResolution.ValidateConstraints(method.TypeParameters[i], inferredTypes[i], substitution, conversions)) return false; - } else { + } + else + { inferredTypes[i] = method.TypeParameters[i]; // do not substitute types that could not be inferred } } @@ -1954,7 +2228,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Conversion c = conversions.ImplicitConversion(targetType, thisParameterType); return c.IsValid && (c.IsIdentityConversion || c.IsReferenceConversion || c.IsBoxingConversion); } - + /// /// Gets all extension methods available in the current using scope. /// This list includes inaccessible methods. @@ -1965,29 +2239,32 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (currentUsingScope == null) return EmptyList>.Instance; List> extensionMethodGroups = LazyInit.VolatileRead(ref currentUsingScope.AllExtensionMethods); - if (extensionMethodGroups != null) { + if (extensionMethodGroups != null) + { return extensionMethodGroups; } extensionMethodGroups = new List>(); List m; - for (ResolvedUsingScope scope = currentUsingScope; scope != null; scope = scope.Parent) { + for (ResolvedUsingScope scope = currentUsingScope; scope != null; scope = scope.Parent) + { INamespace ns = scope.Namespace; - if (ns != null) { + if (ns != null) + { m = GetExtensionMethods(lookup, ns).ToList(); if (m.Count > 0) extensionMethodGroups.Add(m); } - + m = scope.Usings .Distinct() - .SelectMany(importedNamespace => GetExtensionMethods(lookup, importedNamespace)) + .SelectMany(importedNamespace => GetExtensionMethods(lookup, importedNamespace)) .ToList(); if (m.Count > 0) extensionMethodGroups.Add(m); } return LazyInit.GetOrSet(ref currentUsingScope.AllExtensionMethods, extensionMethodGroups); } - + IEnumerable GetExtensionMethods(MemberLookup lookup, INamespace ns) { // TODO: maybe make this a property on INamespace? @@ -1999,16 +2276,20 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver select m; } #endregion - + #region ResolveInvocation - IList AddArgumentNamesIfNecessary(ResolveResult[] arguments, string[] argumentNames) { - if (argumentNames == null) { + IList AddArgumentNamesIfNecessary(ResolveResult[] arguments, string[] argumentNames) + { + if (argumentNames == null) + { return arguments; } - else { + else + { var result = new ResolveResult[arguments.Length]; - for (int i = 0; i < arguments.Length; i++) { + for (int i = 0; i < arguments.Length; i++) + { result[i] = (argumentNames[i] != null ? new NamedArgumentResolveResult(argumentNames[i], arguments[i]) : arguments[i]); } return result; @@ -2018,20 +2299,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver private ResolveResult ResolveInvocation(ResolveResult target, ResolveResult[] arguments, string[] argumentNames, bool allowOptionalParameters) { // C# 4.0 spec: §7.6.5 - - if (target.Type.Kind == TypeKind.Dynamic) { + + if (target.Type.Kind == TypeKind.Dynamic) + { return new DynamicInvocationResolveResult(target, DynamicInvocationType.Invocation, AddArgumentNamesIfNecessary(arguments, argumentNames)); } - + bool isDynamic = arguments.Any(a => a.Type.Kind == TypeKind.Dynamic); MethodGroupResolveResult mgrr = target as MethodGroupResolveResult; - if (mgrr != null) { - if (isDynamic) { + if (mgrr != null) + { + if (isDynamic) + { // If we have dynamic arguments, we need to represent the invocation as a dynamic invocation if there is more than one applicable method. var or2 = CreateOverloadResolution(arguments, argumentNames, mgrr.TypeArguments.ToArray()); var applicableMethods = mgrr.MethodsGroupedByDeclaringType.SelectMany(m => m, (x, m) => new { x.DeclaringType, Method = m }).Where(x => OverloadResolution.IsApplicable(or2.AddCandidate(x.Method))).ToList(); - if (applicableMethods.Count > 1) { + if (applicableMethods.Count > 1) + { ResolveResult actualTarget; if (applicableMethods.All(x => x.Method.IsStatic) && !(mgrr.TargetResult is TypeResolveResult)) actualTarget = new TypeResolveResult(mgrr.TargetType); @@ -2039,7 +2324,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver actualTarget = mgrr.TargetResult; var l = new List(); - foreach (var m in applicableMethods) { + foreach (var m in applicableMethods) + { if (l.Count == 0 || l[l.Count - 1].DeclaringType != m.DeclaringType) l.Add(new MethodListWithDeclaringType(m.DeclaringType)); l[l.Count - 1].Add(m.Method); @@ -2049,12 +2335,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } OverloadResolution or = mgrr.PerformOverloadResolution(compilation, arguments, argumentNames, checkForOverflow: checkForOverflow, conversions: conversions, allowOptionalParameters: allowOptionalParameters); - if (or.BestCandidate != null) { + if (or.BestCandidate != null) + { if (or.BestCandidate.IsStatic && !or.IsExtensionMethodInvocation && !(mgrr.TargetResult is TypeResolveResult)) return or.CreateResolveResult(new TypeResolveResult(mgrr.TargetType), returnTypeOverride: isDynamic ? SpecialType.Dynamic : null); else return or.CreateResolveResult(mgrr.TargetResult, returnTypeOverride: isDynamic ? SpecialType.Dynamic : null); - } else { + } + else + { // No candidate found at all (not even an inapplicable one). // This can happen with empty method groups (as sometimes used with extension methods) return new UnknownMethodResolveResult( @@ -2062,15 +2351,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } UnknownMemberResolveResult umrr = target as UnknownMemberResolveResult; - if (umrr != null) { + if (umrr != null) + { return new UnknownMethodResolveResult(umrr.TargetType, umrr.MemberName, umrr.TypeArguments, CreateParameters(arguments, argumentNames)); } UnknownIdentifierResolveResult uirr = target as UnknownIdentifierResolveResult; - if (uirr != null && CurrentTypeDefinition != null) { + if (uirr != null && CurrentTypeDefinition != null) + { return new UnknownMethodResolveResult(CurrentTypeDefinition, uirr.Identifier, EmptyList.Instance, CreateParameters(arguments, argumentNames)); } IMethod invokeMethod = target.Type.GetDelegateInvokeMethod(); - if (invokeMethod != null) { + if (invokeMethod != null) + { OverloadResolution or = CreateOverloadResolution(arguments, argumentNames); or.AddCandidate(invokeMethod); return new CSharpInvocationResolveResult( @@ -2100,76 +2392,92 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { return ResolveInvocation(target, arguments, argumentNames, allowOptionalParameters: true); } - + List CreateParameters(ResolveResult[] arguments, string[] argumentNames) { List list = new List(); - if (argumentNames == null) { + if (argumentNames == null) + { argumentNames = new string[arguments.Length]; - } else { + } + else + { if (argumentNames.Length != arguments.Length) throw new ArgumentException(); argumentNames = (string[])argumentNames.Clone(); } - for (int i = 0; i < arguments.Length; i++) { + for (int i = 0; i < arguments.Length; i++) + { // invent argument names where necessary: - if (argumentNames[i] == null) { + if (argumentNames[i] == null) + { string newArgumentName = GuessParameterName(arguments[i]); - if (argumentNames.Contains(newArgumentName)) { + if (argumentNames.Contains(newArgumentName)) + { // disambiguate argument name (e.g. add a number) int num = 1; string newName; - do { + do + { newName = newArgumentName + num.ToString(); num++; - } while(argumentNames.Contains(newName)); + } while (argumentNames.Contains(newName)); newArgumentName = newName; } argumentNames[i] = newArgumentName; } - + // create the parameter: ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult; - if (brrr != null) { + if (brrr != null) + { list.Add(new DefaultParameter(arguments[i].Type, argumentNames[i], referenceKind: brrr.ReferenceKind)); - } else { + } + 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.Kind == TypeKind.Null || type.Kind == TypeKind.None) { + if (type.Kind == TypeKind.Null || type.Kind == TypeKind.None) + { list.Add(new DefaultParameter(compilation.FindType(KnownTypeCode.Object), argumentNames[i])); - } else { + } + else + { list.Add(new DefaultParameter(type, argumentNames[i])); } } } return list; } - + static string GuessParameterName(ResolveResult rr) { MemberResolveResult mrr = rr as MemberResolveResult; if (mrr != null) return mrr.Member.Name; - + UnknownMemberResolveResult umrr = rr as UnknownMemberResolveResult; if (umrr != null) return umrr.MemberName; - + MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult; if (mgrr != null) return mgrr.MethodName; - + LocalResolveResult vrr = rr as LocalResolveResult; if (vrr != null) return MakeParameterName(vrr.Variable.Name); - - if (rr.Type.Kind != TypeKind.Unknown && !string.IsNullOrEmpty(rr.Type.Name)) { + + if (rr.Type.Kind != TypeKind.Unknown && !string.IsNullOrEmpty(rr.Type.Name)) + { return MakeParameterName(rr.Type.Name); - } else { + } + else + { return "parameter"; } } - + static string MakeParameterName(string variableName) { if (string.IsNullOrEmpty(variableName)) @@ -2178,7 +2486,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver variableName = variableName.Substring(1); return char.ToLower(variableName[0]) + variableName.Substring(1); } - + OverloadResolution CreateOverloadResolution(ResolveResult[] arguments, string[] argumentNames = null, IType[] typeArguments = null) { var or = new OverloadResolution(compilation, arguments, argumentNames, typeArguments, conversions); @@ -2186,7 +2494,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return or; } #endregion - + #region ResolveIndexer /// /// Resolves an indexer access. @@ -2202,51 +2510,58 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// ArrayAccessResolveResult, InvocationResolveResult, or ErrorResolveResult public ResolveResult ResolveIndexer(ResolveResult target, ResolveResult[] arguments, string[] argumentNames = null) { - switch (target.Type.Kind) { + switch (target.Type.Kind) + { case TypeKind.Dynamic: return new DynamicInvocationResolveResult(target, DynamicInvocationType.Indexing, AddArgumentNamesIfNecessary(arguments, argumentNames)); - + 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); } - + // §7.6.6.2 Indexer access MemberLookup lookup = CreateMemberLookup(); var indexers = lookup.LookupIndexers(target); - if (arguments.Any(a => a.Type.Kind == TypeKind.Dynamic)) { + if (arguments.Any(a => a.Type.Kind == TypeKind.Dynamic)) + { // If we have dynamic arguments, we need to represent the invocation as a dynamic invocation if there is more than one applicable indexer. var or2 = CreateOverloadResolution(arguments, argumentNames, null); var applicableIndexers = indexers.SelectMany(x => x).Where(m => OverloadResolution.IsApplicable(or2.AddCandidate(m))).ToList(); - if (applicableIndexers.Count > 1) { + if (applicableIndexers.Count > 1) + { return new DynamicInvocationResolveResult(target, DynamicInvocationType.Indexing, AddArgumentNamesIfNecessary(arguments, argumentNames)); } } OverloadResolution or = CreateOverloadResolution(arguments, argumentNames); or.AddMethodLists(indexers); - if (or.BestCandidate != null) { + if (or.BestCandidate != null) + { return or.CreateResolveResult(target); - } else { + } + else + { return ErrorResult; } } - + /// /// Converts all arguments to int,uint,long or ulong. /// void AdjustArrayAccessArguments(ResolveResult[] arguments) { - for (int i = 0; i < arguments.Length; i++) { + for (int i = 0; i < arguments.Length; i++) + { if (!(TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.Int32)) || - TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.UInt32)) || - TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.Int64)) || - TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.UInt64)))) + TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.UInt32)) || + TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.Int64)) || + TryConvert(ref arguments[i], compilation.FindType(KnownTypeCode.UInt64)))) { // conversion failed arguments[i] = Convert(arguments[i], compilation.FindType(KnownTypeCode.Int32), Conversion.None); @@ -2254,7 +2569,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region ResolveObjectCreation /// /// Resolves an object creation. @@ -2278,10 +2593,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// InvocationResolveResult or ErrorResolveResult public ResolveResult ResolveObjectCreation(IType type, ResolveResult[] arguments, string[] argumentNames = null, bool allowProtectedAccess = false, IList initializerStatements = null) { - if (type.Kind == TypeKind.Delegate && arguments.Length == 1) { + if (type.Kind == TypeKind.Delegate && arguments.Length == 1) + { ResolveResult input = arguments[0]; IMethod invoke = input.Type.GetDelegateInvokeMethod(); - if (invoke != null) { + if (invoke != null) + { input = new MethodGroupResolveResult( input, invoke.Name, methods: new[] { new MethodListWithDeclaringType(input.Type) { invoke } }, @@ -2293,8 +2610,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver OverloadResolution or = CreateOverloadResolution(arguments, argumentNames); MemberLookup lookup = CreateMemberLookup(); var allApplicable = (arguments.Any(a => a.Type.Kind == TypeKind.Dynamic) ? new List() : null); - foreach (IMethod ctor in type.GetConstructors()) { - if (lookup.IsAccessible(ctor, allowProtectedAccess)) { + foreach (IMethod ctor in type.GetConstructors()) + { + if (lookup.IsAccessible(ctor, allowProtectedAccess)) + { var orErrors = or.AddCandidate(ctor); if (allApplicable != null && OverloadResolution.IsApplicable(orErrors)) allApplicable.Add(ctor); @@ -2303,19 +2622,23 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver or.AddCandidate(ctor, OverloadResolutionErrors.Inaccessible); } - if (allApplicable != null && allApplicable.Count > 1) { + if (allApplicable != null && allApplicable.Count > 1) + { // If we have dynamic arguments, we need to represent the invocation as a dynamic invocation if there is more than one applicable constructor. return new DynamicInvocationResolveResult(new MethodGroupResolveResult(null, allApplicable[0].Name, new[] { new MethodListWithDeclaringType(type, allApplicable) }, null), DynamicInvocationType.ObjectCreation, AddArgumentNamesIfNecessary(arguments, argumentNames), initializerStatements); } - if (or.BestCandidate != null) { + if (or.BestCandidate != null) + { return or.CreateResolveResult(null, initializerStatements); - } else { + } + else + { return new ErrorResolveResult(type); } } #endregion - + #region ResolveSizeOf /// /// Resolves 'sizeof(type)'. @@ -2326,7 +2649,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver int? size = null; var typeForConstant = (type.Kind == TypeKind.Enum) ? type.GetDefinition().EnumUnderlyingType : type; - switch (ReflectionHelper.GetTypeCode(typeForConstant)) { + switch (ReflectionHelper.GetTypeCode(typeForConstant)) + { case TypeCode.Boolean: case TypeCode.SByte: case TypeCode.Byte: @@ -2351,7 +2675,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return new SizeOfResolveResult(int32, type, size); } #endregion - + #region Resolve This/Base Reference /// /// Resolves 'this'. @@ -2359,26 +2683,33 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public ResolveResult ResolveThisReference() { ITypeDefinition t = CurrentTypeDefinition; - if (t != null) { - if (t.TypeParameterCount != 0) { + if (t != null) + { + if (t.TypeParameterCount != 0) + { // Self-parameterize the type return new ThisResolveResult(new ParameterizedType(t, t.TypeParameters)); - } else { + } + else + { return new ThisResolveResult(t); } } return ErrorResult; } - + /// /// Resolves 'base'. /// public ResolveResult ResolveBaseReference() { ITypeDefinition t = CurrentTypeDefinition; - if (t != null) { - foreach (IType baseType in t.DirectBaseTypes) { - if (baseType.Kind != TypeKind.Unknown && baseType.Kind != TypeKind.Interface) { + if (t != null) + { + foreach (IType baseType in t.DirectBaseTypes) + { + if (baseType.Kind != TypeKind.Unknown && baseType.Kind != TypeKind.Interface) + { return new ThisResolveResult(baseType, causesNonVirtualInvocation: true); } } @@ -2386,7 +2717,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return ErrorResult; } #endregion - + #region ResolveConditional /// /// Converts the input to bool using the rules for boolean expressions. @@ -2398,15 +2729,17 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new ArgumentNullException(nameof(input)); IType boolean = compilation.FindType(KnownTypeCode.Boolean); Conversion c = conversions.ImplicitConversion(input, boolean); - if (!c.IsValid) { + if (!c.IsValid) + { var opTrue = input.Type.GetMethods(m => m.IsOperator && m.Name == "op_True").FirstOrDefault(); - if (opTrue != null) { + if (opTrue != null) + { c = Conversion.UserDefinedConversion(opTrue, isImplicit: true, conversionBeforeUserDefinedOperator: Conversion.None, conversionAfterUserDefinedOperator: Conversion.None); } } return Convert(input, boolean, c); } - + /// /// Converts the negated input to bool using the rules for boolean expressions. /// Computes !(bool)input if the implicit cast to bool is valid; otherwise @@ -2418,55 +2751,73 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new ArgumentNullException(nameof(input)); IType boolean = compilation.FindType(KnownTypeCode.Boolean); Conversion c = conversions.ImplicitConversion(input, boolean); - if (!c.IsValid) { + if (!c.IsValid) + { var opFalse = input.Type.GetMethods(m => m.IsOperator && m.Name == "op_False").FirstOrDefault(); - if (opFalse != null) { + if (opFalse != null) + { c = Conversion.UserDefinedConversion(opFalse, isImplicit: true, conversionBeforeUserDefinedOperator: Conversion.None, conversionAfterUserDefinedOperator: Conversion.None); return Convert(input, boolean, c); } } return ResolveUnaryOperator(UnaryOperatorType.Not, Convert(input, boolean, c)); } - + public ResolveResult ResolveConditional(ResolveResult condition, ResolveResult trueExpression, ResolveResult falseExpression) { // C# 4.0 spec §7.14: Conditional operator - + bool isValid; IType resultType; - if (trueExpression.Type.Kind == TypeKind.Dynamic || falseExpression.Type.Kind == TypeKind.Dynamic) { + if (trueExpression.Type.Kind == TypeKind.Dynamic || falseExpression.Type.Kind == TypeKind.Dynamic) + { resultType = SpecialType.Dynamic; isValid = TryConvert(ref trueExpression, resultType) & TryConvert(ref falseExpression, resultType); - } else if (HasType(trueExpression) && HasType(falseExpression)) { + } + else if (HasType(trueExpression) && HasType(falseExpression)) + { Conversion t2f = conversions.ImplicitConversion(trueExpression, falseExpression.Type); Conversion f2t = conversions.ImplicitConversion(falseExpression, 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 - if (IsBetterConditionalConversion(t2f, f2t)) { + if (IsBetterConditionalConversion(t2f, f2t)) + { resultType = falseExpression.Type; isValid = true; trueExpression = Convert(trueExpression, resultType, t2f); - } else if (IsBetterConditionalConversion(f2t, t2f)) { + } + else if (IsBetterConditionalConversion(f2t, t2f)) + { resultType = trueExpression.Type; isValid = true; falseExpression = Convert(falseExpression, resultType, f2t); - } else { + } + else + { resultType = trueExpression.Type; isValid = trueExpression.Type.Equals(falseExpression.Type); } - } else if (HasType(trueExpression)) { + } + else if (HasType(trueExpression)) + { resultType = trueExpression.Type; isValid = TryConvert(ref falseExpression, resultType); - } else if (HasType(falseExpression)) { + } + else if (HasType(falseExpression)) + { resultType = falseExpression.Type; isValid = TryConvert(ref trueExpression, resultType); - } else { + } + else + { return ErrorResult; } condition = ResolveCondition(condition); - if (isValid) { - if (condition.IsCompileTimeConstant && trueExpression.IsCompileTimeConstant && falseExpression.IsCompileTimeConstant) { + if (isValid) + { + if (condition.IsCompileTimeConstant && trueExpression.IsCompileTimeConstant && falseExpression.IsCompileTimeConstant) + { bool? val = condition.ConstantValue as bool?; if (val == true) return trueExpression; @@ -2474,12 +2825,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return falseExpression; } return new OperatorResolveResult(resultType, System.Linq.Expressions.ExpressionType.Conditional, - condition, trueExpression, falseExpression); - } else { + condition, trueExpression, falseExpression); + } + else + { return new ErrorResolveResult(resultType); } } - + bool IsBetterConditionalConversion(Conversion c1, Conversion c2) { // Valid is better than ImplicitConstantExpressionConversion is better than invalid @@ -2489,43 +2842,48 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return true; return !c2.IsValid; } - + bool HasType(ResolveResult r) { return r.Type.Kind != TypeKind.None && r.Type.Kind != TypeKind.Null; } #endregion - + #region ResolvePrimitive public ResolveResult ResolvePrimitive(object value) { - if (value == null) { + if (value == null) + { return new ResolveResult(SpecialType.NullType); - } else { + } + else + { TypeCode typeCode = Type.GetTypeCode(value.GetType()); IType type = compilation.FindType(typeCode); return new ConstantResolveResult(type, value); } } #endregion - + #region ResolveDefaultValue public ResolveResult ResolveDefaultValue(IType type) { return new ConstantResolveResult(type, GetDefaultValue(type)); } - + public static object GetDefaultValue(IType type) { ITypeDefinition typeDef = type.GetDefinition(); if (typeDef == null) return null; - if (typeDef.Kind == TypeKind.Enum) { + if (typeDef.Kind == TypeKind.Enum) + { typeDef = typeDef.EnumUnderlyingType.GetDefinition(); if (typeDef == null) return null; } - switch (typeDef.KnownTypeCode) { + switch (typeDef.KnownTypeCode) + { case KnownTypeCode.Boolean: return false; case KnownTypeCode.Char: @@ -2557,7 +2915,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region ResolveArrayCreation /// /// Resolves an array creation. @@ -2578,7 +2936,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public ArrayCreateResolveResult ResolveArrayCreation(IType elementType, int[] sizeArguments, ResolveResult[] initializerElements = null) { ResolveResult[] sizeArgResults = new ResolveResult[sizeArguments.Length]; - for (int i = 0; i < sizeArguments.Length; i++) { + for (int i = 0; i < sizeArguments.Length; i++) + { if (sizeArguments[i] < 0) sizeArgResults[i] = ErrorResolveResult.UnknownError; else @@ -2586,7 +2945,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } return ResolveArrayCreation(elementType, sizeArgResults, initializerElements); } - + /// /// Resolves an array creation. /// @@ -2608,34 +2967,38 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver int dimensions = sizeArguments.Length; if (dimensions == 0) throw new ArgumentException("sizeArguments.Length must not be 0"); - if (elementType == null) { + if (elementType == null) + { TypeInference typeInference = new TypeInference(compilation, conversions); elementType = typeInference.GetBestCommonType(initializerElements, out _); } IType arrayType = new ArrayType(compilation, elementType, dimensions); - + AdjustArrayAccessArguments(sizeArguments); - - if (initializerElements != null) { - for (int i = 0; i < initializerElements.Length; i++) { + + if (initializerElements != null) + { + for (int i = 0; i < initializerElements.Length; i++) + { initializerElements[i] = Convert(initializerElements[i], elementType); } } return new ArrayCreateResolveResult(arrayType, sizeArguments, initializerElements); } #endregion - + public ResolveResult ResolveTypeOf(IType referencedType) { return new TypeOfResolveResult(compilation.FindType(KnownTypeCode.Type), referencedType); } - + #region ResolveAssignment public ResolveResult ResolveAssignment(AssignmentOperatorType op, ResolveResult lhs, ResolveResult rhs) { var linqOp = AssignmentExpression.GetLinqNodeType(op, this.CheckForOverflow); var bop = AssignmentExpression.GetCorrespondingBinaryOperator(op); - if (bop == null) { + if (bop == null) + { return new OperatorResolveResult(lhs.Type, linqOp, lhs, this.Convert(rhs, lhs.Type)); } ResolveResult bopResult = ResolveBinaryOperator(bop.Value, lhs, rhs); @@ -2643,7 +3006,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (opResult == null || opResult.Operands.Count != 2) return bopResult; return new OperatorResolveResult(lhs.Type, linqOp, opResult.UserDefinedOperatorMethod, opResult.IsLiftedOperator, - new [] { lhs, opResult.Operands[1] }); + new[] { lhs, opResult.Operands[1] }); } #endregion } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CastResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CastResolveResult.cs index ef8f68d4d..9ed3987a1 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CastResolveResult.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CastResolveResult.cs @@ -48,12 +48,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // * CastTests.ExplicitConversion_In_Assignment // * FindReferencesTest.FindReferencesForOpImplicitInAssignment_ExplicitCast // * CS0029InvalidConversionIssueTests.ExplicitConversionFromUnknownType - + public CastResolveResult(ConversionResolveResult rr) : base(rr.Type, rr.Input, rr.Conversion, rr.CheckForOverflow) { } - + public CastResolveResult(IType targetType, ResolveResult input, Conversion conversion, bool checkForOverflow) : base(targetType, input, conversion, checkForOverflow) { diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/DynamicInvocationResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/DynamicInvocationResolveResult.cs index c9bc53cf4..caf46c8ff 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/DynamicInvocationResolveResult.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/DynamicInvocationResolveResult.cs @@ -18,13 +18,15 @@ using System.Collections.Generic; using System.Globalization; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.CSharp.Resolver { - public enum DynamicInvocationType { + public enum DynamicInvocationType + { /// /// The invocation is a normal invocation ( 'a(b)' ). /// @@ -59,7 +61,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// /// Arguments for the call. Named arguments will be instances of . /// - public readonly IList Arguments; + public readonly IList Arguments; /// /// Gets the list of initializer statements that are appplied to the result of this invocation. @@ -70,10 +72,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// public readonly IList InitializerStatements; - public DynamicInvocationResolveResult(ResolveResult target, DynamicInvocationType invocationType, IList arguments, IList initializerStatements = null) : base(SpecialType.Dynamic) { - this.Target = target; - this.InvocationType = invocationType; - this.Arguments = arguments ?? EmptyList.Instance; + public DynamicInvocationResolveResult(ResolveResult target, DynamicInvocationType invocationType, IList arguments, IList initializerStatements = null) : base(SpecialType.Dynamic) + { + this.Target = target; + this.InvocationType = invocationType; + this.Arguments = arguments ?? EmptyList.Instance; this.InitializerStatements = initializerStatements ?? EmptyList.Instance; } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/DynamicMemberResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/DynamicMemberResolveResult.cs index 72e6e3213..67cfeb468 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/DynamicMemberResolveResult.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/DynamicMemberResolveResult.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Globalization; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; @@ -38,7 +39,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// public readonly string Member; - public DynamicMemberResolveResult(ResolveResult target, string member) : base(SpecialType.Dynamic) { + public DynamicMemberResolveResult(ResolveResult target, string member) : base(SpecialType.Dynamic) + { this.Target = target; this.Member = member; } @@ -48,7 +50,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return string.Format(CultureInfo.InvariantCulture, "[Dynamic member '{0}']", Member); } - public override IEnumerable GetChildResults() { + public override IEnumerable GetChildResults() + { return new[] { Target }; } } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/LambdaResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/LambdaResolveResult.cs index 740af770f..700695271 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/LambdaResolveResult.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/LambdaResolveResult.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; @@ -33,30 +34,30 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver protected LambdaResolveResult() : base(SpecialType.NoType) { } - + /// /// 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 /// @@ -65,19 +66,19 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// Use the property to retrieve the actual return type as determined by the target delegate type. /// public abstract IType GetInferredReturnType(IType[] parameterTypes); - + /// /// Gets the list of parameters. /// public abstract IReadOnlyList Parameters { get; } - + /// /// Gets the return type of the lambda. /// /// If the lambda is async, the return type includes Task<T> /// public abstract IType ReturnType { get; } - + /// /// Gets whether the lambda body is valid for the given parameter types and return type. /// @@ -86,16 +87,16 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// otherwise returns . /// public abstract Conversion IsValid(IType[] parameterTypes, IType returnType, CSharpConversions conversions); - + /// /// Gets the resolve result for the lambda body. /// Returns a resolve result for 'void' for statement lambdas. /// public abstract ResolveResult Body { get; } - + public override IEnumerable GetChildResults() { - return new [] { this.Body }; + return new[] { this.Body }; } } @@ -148,24 +149,33 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public override Conversion IsValid(IType[] parameterTypes, IType returnType, CSharpConversions conversions) { // Anonymous method expressions without parameter lists are applicable to any parameter list. - if (HasParameterList) { + if (HasParameterList) + { if (this.Parameters.Count != parameterTypes.Length) return Conversion.None; - for (int i = 0; i < parameterTypes.Length; ++i) { - if (!conversions.IdentityConversion(parameterTypes[i], this.Parameters[i].Type)) { - if (IsImplicitlyTyped) { + for (int i = 0; i < parameterTypes.Length; ++i) + { + if (!conversions.IdentityConversion(parameterTypes[i], this.Parameters[i].Type)) + { + if (IsImplicitlyTyped) + { // it's possible that different parameter types also lead to a valid conversion return LambdaConversion.Instance; - } else { + } + else + { return Conversion.None; } } } } if (conversions.IdentityConversion(this.ReturnType, returnType) - || conversions.ImplicitConversion(this.InferredReturnType, returnType).IsValid) { + || conversions.ImplicitConversion(this.InferredReturnType, returnType).IsValid) + { return LambdaConversion.Instance; - } else { + } + else + { return Conversion.None; } } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs b/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs index e8884a0e0..049c6b953 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/Log.cs @@ -39,7 +39,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { Debug.WriteLine(text); } - + #if __MonoCS__ [Conditional("MCS_DEBUG")] #else @@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { Debug.WriteLine(format, args); } - + #if __MonoCS__ [Conditional("MCS_DEBUG")] #else @@ -57,19 +57,23 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver #endif internal static void WriteCollection(string text, IEnumerable lines) { - #if DEBUG +#if DEBUG T[] arr = lines.ToArray(); - if (arr.Length == 0) { + if (arr.Length == 0) + { Debug.WriteLine(text + ""); - } else { + } + else + { Debug.WriteLine(text + (arr[0] != null ? arr[0].ToString() : "")); - for (int i = 1; i < arr.Length; i++) { + for (int i = 1; i < arr.Length; i++) + { Debug.WriteLine(new string(' ', text.Length) + (arr[i] != null ? arr[i].ToString() : "")); } } - #endif +#endif } - + #if __MonoCS__ [Conditional("MCS_DEBUG")] #else @@ -79,7 +83,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { Debug.Indent(); } - + #if __MonoCS__ [Conditional("MCS_DEBUG")] #else diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/MemberLookup.cs b/ICSharpCode.Decompiler/CSharp/Resolver/MemberLookup.cs index 95c05ff6d..f1b2e570b 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/MemberLookup.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/MemberLookup.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; @@ -45,18 +46,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return returnType.Kind == TypeKind.Dynamic || returnType.Kind == TypeKind.Delegate; } #endregion - + readonly ITypeDefinition currentTypeDefinition; readonly IModule currentModule; readonly bool isInEnumMemberInitializer; - + public MemberLookup(ITypeDefinition currentTypeDefinition, IModule currentModule, bool isInEnumMemberInitializer = false) { this.currentTypeDefinition = currentTypeDefinition; this.currentModule = currentModule; this.isInEnumMemberInitializer = isInEnumMemberInitializer; } - + #region IsAccessible /// /// Gets whether access to protected instance members of the target expression is possible. @@ -65,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { return targetResolveResult is ThisResolveResult || IsProtectedAccessAllowed(targetResolveResult.Type); } - + /// /// Gets whether access to protected instance members of the target type is possible. /// @@ -80,13 +81,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver ITypeDefinition typeDef = targetType.GetDefinition(); if (typeDef == null) return false; - for (ITypeDefinition c = currentTypeDefinition; c != null; c = c.DeclaringTypeDefinition) { + for (ITypeDefinition c = currentTypeDefinition; c != null; c = c.DeclaringTypeDefinition) + { if (typeDef.IsDerivedFrom(c)) return true; } return false; } - + /// /// Gets whether is accessible in the current class. /// @@ -101,12 +103,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (entity == null) throw new ArgumentNullException(nameof(entity)); // C# 4.0 spec, §3.5.2 Accessiblity domains - switch (entity.Accessibility) { + 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) - for (var t = currentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) { + for (var t = currentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) + { if (t.Equals(entity.DeclaringTypeDefinition)) return true; } @@ -125,23 +129,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new Exception("Invalid value for Accessibility"); } } - + bool IsInternalAccessible(IModule module) { return module != null && currentModule != null && module.InternalsVisibleTo(currentModule); } - + bool IsProtectedAccessible(bool allowProtectedAccess, IEntity entity) { // For static members and type definitions, we do not require the qualifying reference // to be derived from the current class (allowProtectedAccess). if (entity.IsStatic || entity.SymbolKind == SymbolKind.TypeDefinition) allowProtectedAccess = true; - - for (var t = currentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) { + + for (var t = currentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) + { if (t.Equals(entity.DeclaringTypeDefinition)) 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 if (allowProtectedAccess && t.IsDerivedFrom(entity.DeclaringTypeDefinition)) @@ -150,7 +155,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return false; } #endregion - + #region GetAccessibleMembers /// /// Retrieves all members that are accessible and not hidden (by being overridden or shadowed). @@ -160,13 +165,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { if (targetResolveResult == null) throw new ArgumentNullException(nameof(targetResolveResult)); - + bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter; bool allowProtectedAccess = IsProtectedAccessAllowed(targetResolveResult); - + // maps the member name to the list of lookup groups var lookupGroupDict = new Dictionary>(); - + // 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 @@ -174,57 +179,69 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // 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()) { - + foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes()) + { + List entities = new List(); entities.AddRange(type.GetMembers(options: GetMemberOptions.IgnoreInheritedMembers)); - if (!targetIsTypeParameter) { + if (!targetIsTypeParameter) + { var nestedTypes = type.GetNestedTypes(options: GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions); // GetDefinition() might return null if some IType has a strange implementation of GetNestedTypes. entities.AddRange(nestedTypes.Select(t => t.GetDefinition()).Where(td => td != null)); } - - foreach (var entityGroup in entities.GroupBy(e => e.Name)) { - + + foreach (var entityGroup in entities.GroupBy(e => e.Name)) + { + List lookupGroups = new List(); if (!lookupGroupDict.TryGetValue(entityGroup.Key, out lookupGroups)) lookupGroupDict.Add(entityGroup.Key, lookupGroups = new List()); - + List newNestedTypes = null; List newMethods = null; IMember newNonMethod = null; - + IEnumerable typeBaseTypes = null; - - if (!targetIsTypeParameter) { + + if (!targetIsTypeParameter) + { AddNestedTypes(type, entityGroup.OfType(), 0, lookupGroups, ref typeBaseTypes, ref newNestedTypes); } AddMembers(type, entityGroup.OfType(), allowProtectedAccess, lookupGroups, false, ref typeBaseTypes, ref newMethods, ref newNonMethod); - + if (newNestedTypes != null || newMethods != null || newNonMethod != null) lookupGroups.Add(new LookupGroup(type, newNestedTypes, newMethods, newNonMethod)); } } - - foreach (List lookupGroups in lookupGroupDict.Values) { + + foreach (List lookupGroups in lookupGroupDict.Values) + { // Remove interface members hidden by class members. - if (targetIsTypeParameter) { + if (targetIsTypeParameter) + { // This can happen only with type parameters. RemoveInterfaceMembersHiddenByClassMembers(lookupGroups); } - + // Now report the results: - foreach (LookupGroup lookupGroup in lookupGroups) { - if (!lookupGroup.MethodsAreHidden) { - foreach (IMethod method in lookupGroup.Methods) { + foreach (LookupGroup lookupGroup in lookupGroups) + { + if (!lookupGroup.MethodsAreHidden) + { + foreach (IMethod method in lookupGroup.Methods) + { yield return method; } } - if (!lookupGroup.NonMethodIsHidden) { + if (!lookupGroup.NonMethodIsHidden) + { yield return lookupGroup.NonMethod; } - if (lookupGroup.NestedTypes != null) { - foreach (IType type in lookupGroup.NestedTypes) { + if (lookupGroup.NestedTypes != null) + { + foreach (IType type in lookupGroup.NestedTypes) + { ITypeDefinition typeDef = type.GetDefinition(); if (typeDef != null) yield return typeDef; @@ -234,24 +251,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #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; @@ -261,7 +278,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver this.MethodsAreHidden = (methods == null || methods.Count == 0); this.NonMethodIsHidden = (nonMethod == null); } - + public bool AllHidden { get { if (NestedTypes != null && NestedTypes.Count > 0) @@ -271,7 +288,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region LookupType public ResolveResult LookupType(IType declaringType, string name, IReadOnlyList typeArguments, bool parameterizeResultType = true) { @@ -281,53 +298,59 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new ArgumentNullException(nameof(name)); if (typeArguments == null) throw new ArgumentNullException(nameof(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()) { + if (declaringType.Kind != TypeKind.TypeParameter) + { + foreach (IType type in declaringType.GetNonInterfaceBaseTypes()) + { List newNestedTypes = null; IEnumerable typeBaseTypes = null; - + IEnumerable nestedTypes; - if (parameterizeResultType) { + if (parameterizeResultType) + { nestedTypes = type.GetNestedTypes(typeArguments, filter, GetMemberOptions.IgnoreInheritedMembers); - } else { + } + else + { nestedTypes = type.GetNestedTypes(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) { + + 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. @@ -340,20 +363,20 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new ArgumentNullException(nameof(name)); if (typeArguments == null) throw new ArgumentNullException(nameof(typeArguments)); - + bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter; - + bool allowProtectedAccess = IsProtectedAccessAllowed(targetResolveResult); - Predicate nestedTypeFilter = delegate(ITypeDefinition entity) { + Predicate nestedTypeFilter = delegate (ITypeDefinition entity) { return entity.Name == name && IsAccessible(entity, allowProtectedAccess); }; - Predicate memberFilter = delegate(IMember entity) { + Predicate memberFilter = delegate (IMember entity) { // NOTE: Atm destructors can be looked up with 'Finalize' return entity.SymbolKind != SymbolKind.Indexer && - entity.SymbolKind != SymbolKind.Operator && - entity.Name == name; + entity.SymbolKind != SymbolKind.Operator && + entity.Name == name; }; - + List lookupGroups = new List(); // This loop will handle base types before derived types. // The loop performs three jobs: @@ -362,50 +385,56 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // 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()) { - + foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes()) + { + List newNestedTypes = null; List newMethods = null; IMember newNonMethod = null; - + IEnumerable typeBaseTypes = null; - - if (!isInvocation && !targetIsTypeParameter) { + + 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, nestedTypeFilter, GetMemberOptions.IgnoreInheritedMembers); AddNestedTypes(type, nestedTypes, typeArguments.Count, lookupGroups, ref typeBaseTypes, ref newNestedTypes); } - + IEnumerable members; - if (typeArguments.Count == 0) { + 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(memberFilter, GetMemberOptions.IgnoreInheritedMembers); if (isInvocation) members = members.Where(m => IsInvocable(m)); - } else { + } + else + { // No need to check for isInvocation/isInvocable here: // we only fetch methods members = type.GetMethods(typeArguments, memberFilter, GetMemberOptions.IgnoreInheritedMembers); } AddMembers(type, members, allowProtectedAccess, 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) { + 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. @@ -414,42 +443,45 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { if (targetResolveResult == null) throw new ArgumentNullException(nameof(targetResolveResult)); - + IType targetType = targetResolveResult.Type; bool allowProtectedAccess = IsProtectedAccessAllowed(targetResolveResult); Predicate filter = p => p.IsIndexer && !p.IsExplicitInterfaceImplementation; - + List lookupGroups = new List(); - foreach (IType type in targetType.GetNonInterfaceBaseTypes()) { + foreach (IType type in targetType.GetNonInterfaceBaseTypes()) + { List newMethods = null; IMember newNonMethod = null; - + IEnumerable typeBaseTypes = null; - + var members = type.GetProperties(filter, GetMemberOptions.IgnoreInheritedMembers); AddMembers(type, members, allowProtectedAccess, 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) { + 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++) { + 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. @@ -461,27 +493,30 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// 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) + List lookupGroups, + ref IEnumerable typeBaseTypes, + ref List newNestedTypes) { - foreach (IType nestedType in nestedTypes) { + 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) { + foreach (var lookupGroup in lookupGroups) + { if (lookupGroup.AllHidden) continue; // everything is already hidden if (typeBaseTypes == null) typeBaseTypes = type.GetNonInterfaceBaseTypes(); - - if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { + + 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(); @@ -489,7 +524,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region AddMembers /// /// Adds members to 'newMethods'/'newNonMethod'. @@ -505,45 +540,55 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// The target list for methods (created on demand). /// The target variable for non-method members. void AddMembers(IType type, IEnumerable members, - bool allowProtectedAccess, - List lookupGroups, - bool treatAllParameterizedMembersAsMethods, - ref IEnumerable typeBaseTypes, ref List newMethods, ref IMember newNonMethod) + bool allowProtectedAccess, + List lookupGroups, + bool treatAllParameterizedMembersAsMethods, + ref IEnumerable typeBaseTypes, ref List newMethods, ref IMember newNonMethod) { - foreach (IMember member in members) { + foreach (IMember member in members) + { if (!IsAccessible(member, allowProtectedAccess)) continue; - + IParameterizedMember method; if (treatAllParameterizedMembersAsMethods) method = member as IParameterizedMember; else method = member as IMethod; - + bool replacedVirtualMemberWithOverride = false; - if (member.IsOverride) { + 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--) { + for (int i = lookupGroups.Count - 1; i >= 0 && !replacedVirtualMemberWithOverride; i--) + { if (typeBaseTypes == null) typeBaseTypes = type.GetNonInterfaceBaseTypes(); - + var lookupGroup = lookupGroups[i]; - if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { - if (method != null && !lookupGroup.MethodsAreHidden) { + if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) + { + if (method != null && !lookupGroup.MethodsAreHidden) + { // Find the matching method, and replace it with the override - for (int j = 0; j < lookupGroup.Methods.Count; j++) { - if (SignatureComparer.Ordinal.Equals(method, lookupGroup.Methods[j])) { + for (int j = 0; j < lookupGroup.Methods.Count; j++) + { + if (SignatureComparer.Ordinal.Equals(method, lookupGroup.Methods[j])) + { lookupGroup.Methods[j] = method; replacedVirtualMemberWithOverride = true; break; } } - } else { + } + else + { // If the member type matches, replace it with the override - if (lookupGroup.NonMethod != null && lookupGroup.NonMethod.SymbolKind == member.SymbolKind) { + if (lookupGroup.NonMethod != null && lookupGroup.NonMethod.SymbolKind == member.SymbolKind) + { lookupGroup.NonMethod = member; replacedVirtualMemberWithOverride = true; break; @@ -554,63 +599,80 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } // If the member wasn't an override, or if we didn't find any matching virtual method, // proceed to add the member. - if (!replacedVirtualMemberWithOverride) { + if (!replacedVirtualMemberWithOverride) + { // Make the member hide other members: - foreach (var lookupGroup in lookupGroups) { + foreach (var lookupGroup in lookupGroups) + { if (lookupGroup.AllHidden) continue; // everything is already hidden if (typeBaseTypes == null) typeBaseTypes = type.GetNonInterfaceBaseTypes(); - - if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { + + 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) + if (method == null) + { // !(member is IMethod) lookupGroup.MethodsAreHidden = true; } } } - + // Add the new member - if (method != null) { + if (method != null) + { if (newMethods == null) newMethods = new List(); newMethods.Add(method); - } else { + } + else + { newNonMethod = member; } } } } #endregion - + #region RemoveInterfaceMembersHiddenByClassMembers void RemoveInterfaceMembersHiddenByClassMembers(List lookupGroups) { - foreach (var classLookupGroup in 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) { + if (hasNestedTypes || !classLookupGroup.NonMethodIsHidden) + { // Hide all members from interface types - foreach (var interfaceLookupGroup in lookupGroups) { - if (IsInterfaceOrSystemObject(interfaceLookupGroup.DeclaringType)) { + foreach (var interfaceLookupGroup in lookupGroups) + { + if (IsInterfaceOrSystemObject(interfaceLookupGroup.DeclaringType)) + { interfaceLookupGroup.NestedTypes = null; interfaceLookupGroup.NonMethodIsHidden = true; interfaceLookupGroup.MethodsAreHidden = true; } } - } else if (!classLookupGroup.MethodsAreHidden) { - foreach (var classMethod in classLookupGroup.Methods) { + } + else if (!classLookupGroup.MethodsAreHidden) + { + foreach (var 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)) { + foreach (var interfaceLookupGroup in lookupGroups) + { + if (IsInterfaceOrSystemObject(interfaceLookupGroup.DeclaringType)) + { interfaceLookupGroup.NestedTypes = null; interfaceLookupGroup.NonMethodIsHidden = true; - if (interfaceLookupGroup.Methods != null && !interfaceLookupGroup.MethodsAreHidden) { + 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( @@ -622,7 +684,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } } - + static bool IsInterfaceOrSystemObject(IType type) { // return true if type is an interface or System.Object @@ -632,55 +694,67 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return d != null && d.KnownTypeCode == KnownTypeCode.Object; } #endregion - + #region CreateResult ResolveResult CreateResult(ResolveResult targetResolveResult, List lookupGroups, string name, IReadOnlyList typeArguments) { // Remove all hidden groups lookupGroups.RemoveAll(g => g.AllHidden); - - if (lookupGroups.Count == 0) { + + 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 (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) { + foreach (var lookupGroup in lookupGroups) + { + if (!lookupGroup.MethodsAreHidden && lookupGroup.Methods.Count > 0) + { var methodListWithDeclType = new MethodListWithDeclaringType(lookupGroup.DeclaringType); - foreach (var method in lookupGroup.Methods) { + 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 != 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 (resultGroup.NonMethod.IsStatic && targetResolveResult is ThisResolveResult) { + + if (resultGroup.NonMethod.IsStatic && targetResolveResult is ThisResolveResult) + { targetResolveResult = new TypeResolveResult(targetResolveResult.Type); } - - if (lookupGroups.Count > 1) { + + if (lookupGroups.Count > 1) + { return new AmbiguousMemberResolveResult(targetResolveResult, resultGroup.NonMethod); - } else { - if (isInEnumMemberInitializer) { + } + else + { + if (isInEnumMemberInitializer) + { IField field = resultGroup.NonMethod as IField; - if (field != null && field.DeclaringTypeDefinition != null && field.DeclaringTypeDefinition.Kind == TypeKind.Enum) { + if (field != null && field.DeclaringTypeDefinition != null && field.DeclaringTypeDefinition.Kind == TypeKind.Enum) + { return new MemberResolveResult( targetResolveResult, field, field.DeclaringTypeDefinition.EnumUnderlyingType, diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/MethodGroupResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/MethodGroupResolveResult.cs index 3f4454ad3..8951cb596 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/MethodGroupResolveResult.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/MethodGroupResolveResult.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -32,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public class MethodListWithDeclaringType : List { readonly IType declaringType; - + /// /// The declaring type. /// @@ -55,19 +56,19 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver 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. /// A method reference used to create a delegate is resolved to a MethodGroupResolveResult. @@ -80,8 +81,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver readonly IReadOnlyList typeArguments; readonly ResolveResult targetResult; readonly string methodName; - - public MethodGroupResolveResult(ResolveResult targetResult, string methodName, + + public MethodGroupResolveResult(ResolveResult targetResult, string methodName, IReadOnlyList methods, IReadOnlyList typeArguments) : base(SpecialType.NoType) { @@ -92,28 +93,28 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver 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 != null ? targetResult.Type : SpecialType.UnknownType; } } - + /// /// 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. @@ -121,7 +122,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public IEnumerable Methods { get { return methodLists.SelectMany(m => m.Cast()); } } - + /// /// Gets the methods that were found, grouped by their declaring type. /// This list does not include extension methods. @@ -130,23 +131,23 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public IEnumerable MethodsGroupedByDeclaringType { get { return methodLists; } } - + /// /// Gets the type arguments that were explicitly provided. /// public IReadOnlyList 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; - + // the resolver is used to fetch extension methods on demand internal CSharpResolver resolver; - + /// /// Gets all candidate extension methods. /// Note: this includes candidates that are not eligible due to an inapplicable @@ -164,11 +165,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// public IEnumerable> GetExtensionMethods() { - if (resolver != null) { + if (resolver != null) + { Debug.Assert(extensionMethods == null); - try { + try + { extensionMethods = resolver.GetExtensionMethods(methodName, typeArguments); - } finally { + } + finally + { resolver = null; } } @@ -196,13 +201,19 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public IEnumerable> GetEligibleExtensionMethods(bool substituteInferredTypes) { var result = new List>(); - foreach (var methodGroup in GetExtensionMethods()) { + foreach (var methodGroup in GetExtensionMethods()) + { var outputGroup = new List(); - foreach (var method in methodGroup) { - if (CSharpResolver.IsEligibleExtensionMethod(this.TargetType, method, true, out IType[] inferredTypes)) { - if (substituteInferredTypes && inferredTypes != null) { + foreach (var method in methodGroup) + { + if (CSharpResolver.IsEligibleExtensionMethod(this.TargetType, method, true, out IType[] inferredTypes)) + { + if (substituteInferredTypes && inferredTypes != null) + { outputGroup.Add(method.Specialize(new TypeParameterSubstitution(null, inferredTypes))); - } else { + } + else + { outputGroup.Add(method); } } @@ -212,41 +223,44 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } return result; } - + public override string ToString() { return string.Format("[{0} with {1} method(s)]", GetType().Name, this.Methods.Count()); } - + public OverloadResolution PerformOverloadResolution(ICompilation compilation, ResolveResult[] arguments, string[] argumentNames = null, - bool allowExtensionMethods = true, - bool allowExpandingParams = true, - bool allowOptionalParameters = true, - bool checkForOverflow = false, CSharpConversions conversions = null) + bool allowExtensionMethods = true, + bool allowExpandingParams = true, + bool allowOptionalParameters = true, + bool checkForOverflow = false, CSharpConversions conversions = null) { Log.WriteLine("Performing overload resolution for " + this); Log.WriteCollection(" Arguments: ", arguments); - + var typeArgumentArray = this.TypeArguments.ToArray(); OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, typeArgumentArray, conversions); or.AllowExpandingParams = allowExpandingParams; or.AllowOptionalParameters = allowOptionalParameters; or.CheckForOverflow = checkForOverflow; - + or.AddMethodLists(methodLists); - - if (allowExtensionMethods && !or.FoundApplicableCandidate) { + + if (allowExtensionMethods && !or.FoundApplicableCandidate) + { // No applicable match found, so let's try extension methods. - + var extensionMethods = this.GetExtensionMethods(); - - if (extensionMethods.Any()) { + + if (extensionMethods.Any()) + { 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) { + if (argumentNames != null) + { extArgumentNames = new string[argumentNames.Length + 1]; argumentNames.CopyTo(extArgumentNames, 1); } @@ -255,9 +269,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver extOr.AllowOptionalParameters = allowOptionalParameters; extOr.IsExtensionMethodInvocation = true; extOr.CheckForOverflow = checkForOverflow; - - foreach (var g in extensionMethods) { - foreach (var method in g) { + + foreach (var g in extensionMethods) + { + foreach (var method in g) + { Log.Indent(); OverloadResolutionErrors errors = extOr.AddCandidate(method); Log.Unindent(); @@ -268,7 +284,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } // 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) { + 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; @@ -278,7 +295,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Log.WriteLine("Overload resolution finished, best candidate is {0}.", or.GetBestCandidateWithSubstitutedTypeArguments()); return or; } - + public override IEnumerable GetChildResults() { if (targetResult != null) diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs b/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs index fedc71ebd..e35f05b70 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/OverloadResolution.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -85,9 +86,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public int ArgumentsPassedToParamsArray { get { int count = 0; - if (IsExpandedForm) { + if (IsExpandedForm) + { int paramsParameterIndex = this.Parameters.Count - 1; - foreach (int parameterIndex in ArgumentToParameterMap) { + foreach (int parameterIndex in ArgumentToParameterMap) + { if (parameterIndex == paramsParameterIndex) count++; } @@ -106,7 +109,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // We'll re-substitute them as part of RunTypeInference(). this.Parameters = memberDefinition.Parameters; IMethod methodDefinition = memberDefinition as IMethod; - if (methodDefinition != null && methodDefinition.TypeParameters.Count > 0) { + if (methodDefinition != null && methodDefinition.TypeParameters.Count > 0) + { this.TypeParameters = methodDefinition.TypeParameters; } this.ParameterTypes = new IType[this.Parameters.Count]; @@ -222,7 +226,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Candidate c = new Candidate(member, false); c.AddError(additionalErrors); - if (CalculateCandidate(c)) { + if (CalculateCandidate(c)) + { //candidates.Add(c); } @@ -232,7 +237,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Candidate expandedCandidate = new Candidate(member, true); expandedCandidate.AddError(additionalErrors); // consider expanded form only if it isn't obviously wrong - if (CalculateCandidate(expandedCandidate)) { + if (CalculateCandidate(expandedCandidate)) + { //candidates.Add(expandedCandidate); if (expandedCandidate.ErrorCount < c.ErrorCount) @@ -259,17 +265,22 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver bool ResolveParameterTypes(Candidate candidate, bool useSpecializedParameters) { - for (int i = 0; i < candidate.Parameters.Count; i++) { + for (int i = 0; i < candidate.Parameters.Count; i++) + { IType type; - if (useSpecializedParameters) { + if (useSpecializedParameters) + { // Use the parameter type of the specialized non-generic method or indexer Debug.Assert(!candidate.IsGenericMethod); type = candidate.Member.Parameters[i].Type; - } else { + } + else + { // Use the type of the original formal parameter type = candidate.Parameters[i].Type; } - if (candidate.IsExpandedForm && i == candidate.Parameters.Count - 1) { + if (candidate.IsExpandedForm && i == candidate.Parameters.Count - 1) + { ArrayType arrayType = type as ArrayType; if (arrayType != null && arrayType.Dimensions == 1) type = arrayType.ElementType; @@ -300,8 +311,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver isHiddenByDerivedType = new bool[methodLists.Count]; else isHiddenByDerivedType = null; - for (int i = methodLists.Count - 1; i >= 0; i--) { - if (isHiddenByDerivedType != null && isHiddenByDerivedType[i]) { + 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; } @@ -309,7 +322,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver MethodListWithDeclaringType methodList = methodLists[i]; bool foundApplicableCandidateInCurrentList = false; - for (int j = 0; j < methodList.Count; j++) { + for (int j = 0; j < methodList.Count; j++) + { IParameterizedMember method = methodList[j]; Log.Indent(); OverloadResolutionErrors errors = AddCandidate(method); @@ -319,9 +333,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver foundApplicableCandidateInCurrentList |= IsApplicable(errors); } - if (foundApplicableCandidateInCurrentList && i > 0) { - foreach (IType baseType in methodList.DeclaringType.GetAllBaseTypes()) { - for (int j = 0; j < i; j++) { + if (foundApplicableCandidateInCurrentList && i > 0) + { + foreach (IType baseType in methodList.DeclaringType.GetAllBaseTypes()) + { + for (int j = 0; j < i; j++) + { if (!isHiddenByDerivedType[j] && baseType.Equals(methodLists[j].DeclaringType)) isHiddenByDerivedType[j] = true; } @@ -333,14 +350,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver [Conditional("DEBUG")] internal void LogCandidateAddingResult(string text, IParameterizedMember method, OverloadResolutionErrors errors) { - #if DEBUG +#if DEBUG Log.WriteLine(string.Format("{0} {1} = {2}{3}", text, method, errors == OverloadResolutionErrors.None ? "Success" : errors.ToString(), this.BestCandidate == method ? " (best candidate so far)" : this.BestCandidateAmbiguousWith == method ? " (ambiguous)" : "" )); - #endif +#endif } #endregion @@ -353,30 +370,43 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver bool hasPositionalArgument = false; // go backwards, so that hasPositionalArgument tells us whether there // are non-trailing named arguments - for (int i = arguments.Length - 1; i >= 0; i--) { + for (int i = arguments.Length - 1; i >= 0; i--) + { candidate.ArgumentToParameterMap[i] = -1; - if (argumentNames[i] == null || hasPositionalArgument) { + if (argumentNames[i] == null || hasPositionalArgument) + { hasPositionalArgument = true; // positional argument or non-trailing named argument - if (i < candidate.ParameterTypes.Length) { + if (i < candidate.ParameterTypes.Length) + { candidate.ArgumentToParameterMap[i] = i; - if (argumentNames[i] != null && argumentNames[i] != candidate.Parameters[i].Name) { + if (argumentNames[i] != null && argumentNames[i] != candidate.Parameters[i].Name) + { // non-trailing named argument must match name candidate.AddError(OverloadResolutionErrors.NoParameterFoundForNamedArgument); } - } else if (candidate.IsExpandedForm) { + } + else if (candidate.IsExpandedForm) + { candidate.ArgumentToParameterMap[i] = candidate.ParameterTypes.Length - 1; - if (argumentNames[i] != null) { + if (argumentNames[i] != null) + { // can't use non-trailing named argument here candidate.AddError(OverloadResolutionErrors.NoParameterFoundForNamedArgument); } - } else { + } + else + { candidate.AddError(OverloadResolutionErrors.TooManyPositionalArguments); } - } else { + } + else + { // (trailing) named argument - for (int j = 0; j < candidate.Parameters.Count; j++) { - if (argumentNames[i] == candidate.Parameters[j].Name) { + for (int j = 0; j < candidate.Parameters.Count; j++) + { + if (argumentNames[i] == candidate.Parameters[j].Name) + { candidate.ArgumentToParameterMap[i] = j; } } @@ -390,8 +420,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver #region RunTypeInference void RunTypeInference(Candidate candidate) { - if (candidate.TypeParameters == null) { - if (explicitlyGivenTypeArguments != null) { + if (candidate.TypeParameters == null) + { + if (explicitlyGivenTypeArguments != null) + { // method does not expect type arguments, but was given some candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); } @@ -401,27 +433,37 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } ParameterizedType parameterizedDeclaringType = candidate.Member.DeclaringType as ParameterizedType; IReadOnlyList classTypeArguments; - if (parameterizedDeclaringType != null) { + if (parameterizedDeclaringType != null) + { classTypeArguments = parameterizedDeclaringType.TypeArguments; - } else { + } + else + { classTypeArguments = null; } // The method is generic: - if (explicitlyGivenTypeArguments != null) { - if (explicitlyGivenTypeArguments.Length == candidate.TypeParameters.Count) { + if (explicitlyGivenTypeArguments != null) + { + if (explicitlyGivenTypeArguments.Length == candidate.TypeParameters.Count) + { candidate.InferredTypes = explicitlyGivenTypeArguments; - } else { + } + else + { candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); // wrong number of type arguments given, so truncate the list or pad with UnknownType candidate.InferredTypes = new IType[candidate.TypeParameters.Count]; - for (int i = 0; i < candidate.InferredTypes.Length; i++) { + for (int i = 0; i < candidate.InferredTypes.Length; i++) + { if (i < explicitlyGivenTypeArguments.Length) candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i]; else candidate.InferredTypes[i] = SpecialType.UnknownType; } } - } else { + } + else + { TypeInference ti = new TypeInference(compilation, conversions); IType[] parameterTypes = candidate.ArgumentToParameterMap .SelectReadOnlyArray(parameterIndex => parameterIndex >= 0 ? candidate.ParameterTypes[parameterIndex] : SpecialType.UnknownType); @@ -432,7 +474,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } // Now substitute in the formal parameters: var substitution = new ConstraintValidatingSubstitution(classTypeArguments, candidate.InferredTypes, this); - for (int i = 0; i < candidate.ParameterTypes.Length; i++) { + for (int i = 0; i < candidate.ParameterTypes.Length; i++) + { candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution); } if (!substitution.ConstraintsValid) @@ -453,15 +496,19 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public override IType VisitParameterizedType(ParameterizedType type) { IType newType = base.VisitParameterizedType(type); - if (newType != type && ConstraintsValid) { + if (newType != type && ConstraintsValid) + { // something was changed, so we need to validate the constraints ParameterizedType newParameterizedType = newType as ParameterizedType; - if (newParameterizedType != null) { + if (newParameterizedType != null) + { // C# 4.0 spec: §4.4.4 Satisfying constraints var typeParameters = newParameterizedType.TypeParameters; var substitution = newParameterizedType.GetSubstitution(); - for (int i = 0; i < typeParameters.Count; i++) { - if (!ValidateConstraints(typeParameters[i], newParameterizedType.GetTypeArgument(i), substitution, conversions)) { + for (int i = 0; i < typeParameters.Count; i++) + { + if (!ValidateConstraints(typeParameters[i], newParameterizedType.GetTypeArgument(i), substitution, conversions)) + { ConstraintsValid = false; break; } @@ -483,7 +530,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (candidate.TypeParameters == null || candidate.TypeParameters.Count == 0) return OverloadResolutionErrors.None; // the method isn't generic var substitution = GetSubstitution(candidate); - for (int i = 0; i < candidate.TypeParameters.Count; i++) { + for (int i = 0; i < candidate.TypeParameters.Count; i++) + { if (!ValidateConstraints(candidate.TypeParameters[i], substitution.MethodTypeArguments[i], substitution)) return OverloadResolutionErrors.MethodConstraintsNotSatisfied; } @@ -510,21 +558,25 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver internal static bool ValidateConstraints(ITypeParameter typeParameter, IType typeArgument, TypeVisitor substitution, CSharpConversions conversions) { - switch (typeArgument.Kind) { // void, null, and pointers cannot be used as type arguments + switch (typeArgument.Kind) + { // void, null, and pointers cannot be used as type arguments case TypeKind.Void: case TypeKind.Null: case TypeKind.Pointer: return false; } - if (typeParameter.HasReferenceTypeConstraint) { + if (typeParameter.HasReferenceTypeConstraint) + { if (typeArgument.IsReferenceType != true) return false; } - if (typeParameter.HasValueTypeConstraint) { + if (typeParameter.HasValueTypeConstraint) + { if (!NullableType.IsNonNullableValueType(typeArgument)) return false; } - if (typeParameter.HasDefaultConstructorConstraint) { + if (typeParameter.HasDefaultConstructorConstraint) + { ITypeDefinition def = typeArgument.GetDefinition(); if (def != null && def.IsAbstract) return false; @@ -535,7 +587,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (!ctors.Any()) return false; } - foreach (IType constraintType in typeParameter.DirectBaseTypes) { + foreach (IType constraintType in typeParameter.DirectBaseTypes) + { IType c = constraintType; if (substitution != null) c = c.AcceptVisitor(substitution); @@ -563,48 +616,61 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // Test whether parameters were mapped the correct number of arguments: int[] argumentCountPerParameter = new int[candidate.ParameterTypes.Length]; - foreach (int parameterIndex in candidate.ArgumentToParameterMap) { + foreach (int parameterIndex in candidate.ArgumentToParameterMap) + { if (parameterIndex >= 0) argumentCountPerParameter[parameterIndex]++; } - for (int i = 0; i < argumentCountPerParameter.Length; i++) { + for (int i = 0; i < argumentCountPerParameter.Length; i++) + { if (candidate.IsExpandedForm && i == argumentCountPerParameter.Length - 1) continue; // any number of arguments is fine for the params-array - if (argumentCountPerParameter[i] == 0) { + if (argumentCountPerParameter[i] == 0) + { if (this.AllowOptionalParameters && candidate.Parameters[i].IsOptional) candidate.HasUnmappedOptionalParameters = true; else candidate.AddError(OverloadResolutionErrors.MissingArgumentForRequiredParameter); - } else if (argumentCountPerParameter[i] > 1) { + } + else if (argumentCountPerParameter[i] > 1) + { candidate.AddError(OverloadResolutionErrors.MultipleArgumentsForSingleParameter); } } candidate.ArgumentConversions = new Conversion[arguments.Length]; // Test whether argument passing mode matches the parameter passing mode - for (int i = 0; i < arguments.Length; i++) { + for (int i = 0; i < arguments.Length; i++) + { int parameterIndex = candidate.ArgumentToParameterMap[i]; - if (parameterIndex < 0) { + if (parameterIndex < 0) + { candidate.ArgumentConversions[i] = Conversion.None; continue; } ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult; - if (brrr != null) { + if (brrr != null) + { if (brrr.ReferenceKind != candidate.Parameters[parameterIndex].ReferenceKind) candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); - } else { + } + else + { if (candidate.Parameters[parameterIndex].ReferenceKind != ReferenceKind.None) candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); } IType parameterType = candidate.ParameterTypes[parameterIndex]; Conversion c = conversions.ImplicitConversion(arguments[i], parameterType); candidate.ArgumentConversions[i] = c; - if (IsExtensionMethodInvocation && parameterIndex == 0) { + 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 { + } + else + { if ((!c.IsValid && !c.IsUserDefined && !c.IsMethodGroupConversion) && parameterType.Kind != TypeKind.Unknown) candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch); } @@ -628,17 +694,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver bool c1IsBetter = false; bool c2IsBetter = false; bool parameterTypesEqual = true; - for (int i = 0; i < arguments.Length; i++) { + for (int i = 0; i < arguments.Length; i++) + { int p1 = c1.ArgumentToParameterMap[i]; int p2 = c2.ArgumentToParameterMap[i]; - if (p1 >= 0 && p2 < 0) { + if (p1 >= 0 && p2 < 0) + { c1IsBetter = true; - } else if (p1 < 0 && p2 >= 0) { + } + else if (p1 < 0 && p2 >= 0) + { c2IsBetter = true; - } else if (p1 >= 0 && p2 >= 0) { + } + else if (p1 >= 0 && p2 >= 0) + { if (!conversions.IdentityConversion(c1.ParameterTypes[p1], c2.ParameterTypes[p2])) parameterTypesEqual = false; - switch (conversions.BetterConversion(arguments[i], c1.ParameterTypes[p1], c2.ParameterTypes[p2])) { + switch (conversions.BetterConversion(arguments[i], c1.ParameterTypes[p1], c2.ParameterTypes[p2])) + { case 1: c1IsBetter = true; break; @@ -654,10 +727,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return 2; // prefer members with less errors (part of heuristic that produces a best candidate even if none is applicable) - if (c1.ErrorCount < c2.ErrorCount) return 1; - if (c1.ErrorCount > c2.ErrorCount) return 2; + if (c1.ErrorCount < c2.ErrorCount) + return 1; + if (c1.ErrorCount > c2.ErrorCount) + return 2; - if (!c1IsBetter && !c2IsBetter && parameterTypesEqual) { + if (!c1IsBetter && !c2IsBetter && parameterTypesEqual) + { // we need the tie-breaking rules // non-generic methods are better @@ -674,8 +750,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // prefer the member with less arguments mapped to the params-array int r = c1.ArgumentsPassedToParamsArray.CompareTo(c2.ArgumentsPassedToParamsArray); - if (r < 0) return 1; - else if (r > 0) return 2; + if (r < 0) + return 1; + else if (r > 0) + return 2; // prefer the member where no default values need to be substituted if (!c1.HasUnmappedOptionalParameters && c2.HasUnmappedOptionalParameters) @@ -703,8 +781,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { // prefer the member with more formal parmeters (in case both have different number of optional parameters) int r = c1.Parameters.Count.CompareTo(c2.Parameters.Count); - if (r > 0) return 1; - else if (r < 0) return 2; + if (r > 0) + return 1; + else if (r < 0) + return 2; return MoreSpecificFormalParameters(c1.Parameters.Select(p => p.Type), c2.Parameters.Select(p => p.Type)); } @@ -713,8 +793,10 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { bool c1IsBetter = false; bool c2IsBetter = false; - foreach (var pair in t1.Zip(t2, (a, b) => new { Item1 = a, Item2 = b })) { - switch (MoreSpecificFormalParameter(pair.Item1, pair.Item2)) { + foreach (var pair in t1.Zip(t2, (a, b) => new { Item1 = a, Item2 = b })) + { + switch (MoreSpecificFormalParameter(pair.Item1, pair.Item2)) + { case 1: c1IsBetter = true; break; @@ -739,14 +821,16 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver ParameterizedType p1 = t1 as ParameterizedType; ParameterizedType p2 = t2 as ParameterizedType; - if (p1 != null && p2 != null && p1.TypeParameterCount == p2.TypeParameterCount) { + if (p1 != null && p2 != null && p1.TypeParameterCount == p2.TypeParameterCount) + { int r = MoreSpecificFormalParameters(p1.TypeArguments, p2.TypeArguments); if (r > 0) return r; } TypeWithElementType tew1 = t1 as TypeWithElementType; TypeWithElementType tew2 = t2 as TypeWithElementType; - if (tew1 != null && tew2 != null) { + if (tew1 != null && tew2 != null) + { return MoreSpecificFormalParameter(tew1.ElementType, tew2.ElementType); } return 0; @@ -756,11 +840,15 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver #region ConsiderIfNewCandidateIsBest void ConsiderIfNewCandidateIsBest(Candidate candidate) { - if (bestCandidate == null) { + if (bestCandidate == null) + { bestCandidate = candidate; bestCandidateWasValidated = false; - } else { - switch (BetterFunctionMember(candidate, bestCandidate)) { + } + else + { + switch (BetterFunctionMember(candidate, bestCandidate)) + { case 0: // Overwrite 'bestCandidateAmbiguousWith' so that API users can // detect the set of all ambiguous methods if they look at @@ -791,7 +879,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver get { if (bestCandidate == null) return OverloadResolutionErrors.None; - if (!bestCandidateWasValidated) { + if (!bestCandidateWasValidated) + { bestCandidateValidationResult = ValidateMethodConstraints(bestCandidate); bestCandidateWasValidated = true; } @@ -885,27 +974,37 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { var conversions = this.ArgumentConversions; ResolveResult[] args = new ResolveResult[arguments.Length]; - for (int i = 0; i < args.Length; i++) { + for (int i = 0; i < args.Length; i++) + { var argument = arguments[i]; if (this.IsExtensionMethodInvocation && i == 0 && targetResolveResult != null) argument = targetResolveResult; int parameterIndex = bestCandidate.ArgumentToParameterMap[i]; - if (parameterIndex >= 0 && conversions[i] != Conversion.IdentityConversion) { + if (parameterIndex >= 0 && conversions[i] != Conversion.IdentityConversion) + { // Wrap argument in ConversionResolveResult IType parameterType = bestCandidate.ParameterTypes[parameterIndex]; - if (parameterType.Kind != TypeKind.Unknown) { - if (arguments[i].IsCompileTimeConstant && conversions[i].IsValid && !conversions[i].IsUserDefined) { + if (parameterType.Kind != TypeKind.Unknown) + { + if (arguments[i].IsCompileTimeConstant && conversions[i].IsValid && !conversions[i].IsUserDefined) + { argument = new CSharpResolver(compilation).WithCheckForOverflow(CheckForOverflow).ResolveCast(parameterType, argument); - } else { + } + else + { argument = new ConversionResolveResult(parameterType, argument, conversions[i], CheckForOverflow); } } } - if (bestCandidateForNamedArguments != null && argumentNames[i] != null) { + if (bestCandidateForNamedArguments != null && argumentNames[i] != null) + { // Wrap argument in NamedArgumentResolveResult - if (parameterIndex >= 0) { + if (parameterIndex >= 0) + { argument = new NamedArgumentResolveResult(bestCandidateForNamedArguments.Parameters[parameterIndex], argument, bestCandidateForNamedArguments); - } else { + } + else + { argument = new NamedArgumentResolveResult(argumentNames[i], argument); } } @@ -919,9 +1018,12 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (bestCandidate == null) return null; IMethod method = bestCandidate.Member as IMethod; - if (method != null && method.TypeParameters.Count > 0) { + if (method != null && method.TypeParameters.Count > 0) + { return ((IMethod)method.MemberDefinition).Specialize(GetSubstitution(bestCandidate)); - } else { + } + else + { return bestCandidate.Member; } } diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/TypeInference.cs b/ICSharpCode.Decompiler/CSharp/Resolver/TypeInference.cs index 1f912464f..28afb46a5 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/TypeInference.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/TypeInference.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -43,7 +44,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver /// ImprovedReturnAllResults } - + /// /// Implements C# 4.0 Type Inference (§7.5.2). /// @@ -52,11 +53,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver readonly ICompilation compilation; readonly CSharpConversions conversions; TypeInferenceAlgorithm algorithm = TypeInferenceAlgorithm.CSharp4; - + // determines the maximum generic nesting level; necessary to avoid infinite recursion in 'Improved' mode. const int maxNestingLevel = 5; int nestingLevel; - + #region Constructor public TypeInference(ICompilation compilation) { @@ -65,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver this.compilation = compilation; this.conversions = CSharpConversions.Get(compilation); } - + internal TypeInference(ICompilation compilation, CSharpConversions conversions) { Debug.Assert(compilation != null); @@ -74,7 +75,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver this.conversions = conversions; } #endregion - + #region Properties /// /// Gets/Sets the type inference algorithm used. @@ -83,7 +84,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver get { return algorithm; } set { algorithm = value; } } - + TypeInference CreateNestedInstance() { TypeInference c = new TypeInference(compilation, conversions); @@ -92,13 +93,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return c; } #endregion - + TP[] typeParameters; IType[] parameterTypes; ResolveResult[] arguments; bool[,] dependencyMatrix; IReadOnlyList classTypeArguments; - + #region InferTypeArguments (main function) /// /// Performs type inference. @@ -120,9 +121,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new ArgumentNullException(nameof(arguments)); if (parameterTypes == null) throw new ArgumentNullException(nameof(parameterTypes)); - try { + try + { this.typeParameters = new TP[typeParameters.Count]; - for (int i = 0; i < this.typeParameters.Length; i++) { + 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 != SymbolKind.Method) @@ -131,7 +134,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } this.parameterTypes = new IType[Math.Min(arguments.Count, parameterTypes.Count)]; this.arguments = new ResolveResult[this.parameterTypes.Length]; - for (int i = 0; i < this.parameterTypes.Length; i++) { + for (int i = 0; i < this.parameterTypes.Length; i++) + { if (arguments[i] == null || parameterTypes[i] == null) throw new ArgumentNullException(); this.arguments[i] = arguments[i]; @@ -140,22 +144,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver this.classTypeArguments = classTypeArguments; Log.WriteLine("Type Inference"); Log.WriteLine(" Signature: M<" + string.Join(", ", this.typeParameters) + ">" - + "(" + string.Join(", ", this.parameterTypes) + ")"); + + "(" + 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 ?? SpecialType.UnknownType)) + ">"); + "M<" + string.Join(", ", this.typeParameters.Select(tp => tp.FixedTo ?? SpecialType.UnknownType)) + ">"); return this.typeParameters.Select(tp => tp.FixedTo ?? SpecialType.UnknownType).ToArray(); - } finally { + } + finally + { Reset(); } } - + void Reset() { // clean up so that memory used by the operation can be garbage collected as soon as possible @@ -165,7 +171,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver this.dependencyMatrix = null; this.classTypeArguments = null; } - + /// /// Infers type arguments for the occurring in the /// so that the resulting type (after substition) satisfies the given bounds. @@ -181,20 +187,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver if (upperBounds == null) throw new ArgumentNullException(nameof(upperBounds)); this.typeParameters = new TP[typeParameters.Count]; - for (int i = 0; i < this.typeParameters.Length; i++) { + for (int i = 0; i < this.typeParameters.Length; i++) + { if (i != typeParameters[i].Index) throw new ArgumentException("Type parameter has wrong index"); this.typeParameters[i] = new TP(typeParameters[i]); } - foreach (IType b in lowerBounds) { + foreach (IType b in lowerBounds) + { MakeLowerBoundInference(b, targetType); } - foreach (IType b in upperBounds) { + foreach (IType b in upperBounds) + { MakeUpperBoundInference(b, targetType); } IType[] result = new IType[this.typeParameters.Length]; success = true; - for (int i = 0; i < result.Length; i++) { + for (int i = 0; i < result.Length; i++) + { success &= Fix(this.typeParameters[i]); result[i] = this.typeParameters[i].FixedTo ?? SpecialType.UnknownType; } @@ -202,7 +212,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return result; } #endregion - + sealed class TP { public readonly HashSet LowerBounds = new HashSet(); @@ -211,22 +221,22 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver public bool MultipleDifferentExactBounds; public readonly ITypeParameter TypeParameter; public IType FixedTo; - + public bool IsFixed { get { return FixedTo != null; } } - + public bool HasBounds { get { return LowerBounds.Count > 0 || UpperBounds.Count > 0 || ExactBound != null; } } - + public TP(ITypeParameter typeParameter) { if (typeParameter == null) throw new ArgumentNullException(nameof(typeParameter)); this.TypeParameter = typeParameter; } - + public void AddExactBound(IType type) { // Exact bounds need to stored separately, not just as Lower+Upper bounds, @@ -236,24 +246,24 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver else if (!ExactBound.Equals(type)) MultipleDifferentExactBounds = true; } - + public override string ToString() { return TypeParameter.Name; } } - + sealed class OccursInVisitor : TypeVisitor { readonly TP[] tp; public readonly bool[] Occurs; - + public OccursInVisitor(TypeInference typeInference) { this.tp = typeInference.typeParameters; this.Occurs = new bool[tp.Length]; } - + public override IType VisitTypeParameter(ITypeParameter type) { int index = type.Index; @@ -262,64 +272,79 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return base.VisitTypeParameter(type); } } - + #region Inference Phases void PhaseOne() { // C# 4.0 spec: §7.5.2.1 The first phase Log.WriteLine("Phase One"); - for (int i = 0; i < arguments.Length; i++) { + for (int i = 0; i < arguments.Length; i++) + { ResolveResult Ei = arguments[i]; IType Ti = parameterTypes[i]; - + LambdaResolveResult lrr = Ei as LambdaResolveResult; - if (lrr != null) { + if (lrr != null) + { MakeExplicitParameterTypeInference(lrr, Ti); } - if (lrr != null || Ei is MethodGroupResolveResult) { + if (lrr != null || Ei is MethodGroupResolveResult) + { // this is not in the spec??? - if (OutputTypeContainsUnfixed(Ei, Ti) && !InputTypesContainsUnfixed(Ei, Ti)) { + if (OutputTypeContainsUnfixed(Ei, Ti) && !InputTypesContainsUnfixed(Ei, Ti)) + { MakeOutputTypeInference(Ei, Ti); } } - - if (IsValidType(Ei.Type)) { - if (Ti is ByReferenceType) { + + if (IsValidType(Ei.Type)) + { + if (Ti is ByReferenceType) + { MakeExactInference(Ei.Type, Ti); - } else { + } + else + { MakeLowerBoundInference(Ei.Type, Ti); } } } } - + static bool IsValidType(IType type) { return type.Kind != TypeKind.Unknown && type.Kind != TypeKind.Null && type.Kind != TypeKind.None; } - + bool PhaseTwo() { // C# 4.0 spec: §7.5.2.2 The second phase 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) => !Xj.IsFixed && DependsOn(Xi, Xj))) { + foreach (TP Xi in typeParameters) + { + if (Xi.IsFixed == false) + { + 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) { + 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) { + foreach (TP Xi in typeParameters) + { // Xi has a non­empty set of bounds - if (!Xi.IsFixed && Xi.HasBounds) { + if (!Xi.IsFixed && Xi.HasBounds) + { // There is at least one type variable Xj that depends on Xi - if (typeParameters.Any((TP Xj) => DependsOn(Xj, Xi))) { + if (typeParameters.Any((TP Xj) => DependsOn(Xj, Xi))) + { typeParametersToFix.Add(Xi); } } @@ -327,28 +352,36 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } // now fix 'em bool errorDuringFix = false; - foreach (TP tp in typeParametersToFix) { + foreach (TP tp in typeParametersToFix) + { if (!Fix(tp)) errorDuringFix = true; } if (errorDuringFix) return false; bool unfixedTypeVariablesExist = typeParameters.Any((TP X) => X.IsFixed == false); - if (typeParametersToFix.Count == 0 && unfixedTypeVariablesExist) { + 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) { + } + else if (!unfixedTypeVariablesExist) + { // Otherwise, if no further unfixed type variables exist, type inference succeeds. return true; - } else { + } + else + { // Otherwise, for all arguments ei with corresponding parameter type Ti - for (int i = 0; i < arguments.Length; i++) { + for (int i = 0; i < arguments.Length; i++) + { ResolveResult Ei = arguments[i]; IType Ti = parameterTypes[i]; // where the output types (§7.4.2.4) contain unfixed type variables Xj // but the input types (§7.4.2.3) do not - if (OutputTypeContainsUnfixed(Ei, Ti) && !InputTypesContainsUnfixed(Ei, Ti)) { + if (OutputTypeContainsUnfixed(Ei, Ti) && !InputTypesContainsUnfixed(Ei, Ti)) + { // an output type inference (§7.4.2.6) is made for ei with type Ti. Log.WriteLine("MakeOutputTypeInference for argument #" + i); MakeOutputTypeInference(Ei, Ti); @@ -359,17 +392,20 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region Input Types / Output Types (§7.5.2.3 + §7.5.2.4) IType[] InputTypes(ResolveResult e, IType t) { // C# 4.0 spec: §7.5.2.3 Input types LambdaResolveResult lrr = e as LambdaResolveResult; - if (lrr != null && lrr.IsImplicitlyTyped || e is MethodGroupResolveResult) { + if (lrr != null && lrr.IsImplicitlyTyped || e is MethodGroupResolveResult) + { IMethod m = GetDelegateOrExpressionTreeSignature(t); - if (m != null) { + if (m != null) + { IType[] inputTypes = new IType[m.Parameters.Count]; - for (int i = 0; i < inputTypes.Length; i++) { + for (int i = 0; i < inputTypes.Length; i++) + { inputTypes[i] = m.Parameters[i].Type; } return inputTypes; @@ -377,81 +413,94 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } return Empty.Array; } - + IType[] OutputTypes(ResolveResult e, IType t) { // C# 4.0 spec: §7.5.2.4 Output types LambdaResolveResult lrr = e as LambdaResolveResult; - if (lrr != null || e is MethodGroupResolveResult) { + if (lrr != null || e is MethodGroupResolveResult) + { IMethod m = GetDelegateOrExpressionTreeSignature(t); - if (m != null) { + if (m != null) + { return new[] { m.ReturnType }; } } return Empty.Array; } - + static IMethod GetDelegateOrExpressionTreeSignature(IType t) { if (t.TypeParameterCount == 1 && t.Name == "Expression" - && t.Namespace == "System.Linq.Expressions") + && t.Namespace == "System.Linq.Expressions") { t = t.TypeArguments[0]; } return t.GetDelegateInvokeMethod(); } - + bool InputTypesContainsUnfixed(ResolveResult argument, IType parameterType) { return AnyTypeContainsUnfixedParameter(InputTypes(argument, parameterType)); } - + bool OutputTypeContainsUnfixed(ResolveResult argument, IType parameterType) { return AnyTypeContainsUnfixedParameter(OutputTypes(argument, parameterType)); } - + bool AnyTypeContainsUnfixedParameter(IEnumerable types) { OccursInVisitor o = new OccursInVisitor(this); - foreach (var type in types) { + foreach (var type in types) + { type.AcceptVisitor(o); } - for (int i = 0; i < typeParameters.Length; i++) { + for (int i = 0; i < typeParameters.Length; i++) + { if (!typeParameters[i].IsFixed && o.Occurs[i]) return true; } return false; } #endregion - + #region DependsOn (§7.5.2.5) // C# 4.0 spec: §7.5.2.5 Dependance - + void CalculateDependencyMatrix() { int n = typeParameters.Length; dependencyMatrix = new bool[n, n]; - for (int k = 0; k < arguments.Length; k++) { + for (int k = 0; k < arguments.Length; k++) + { OccursInVisitor input = new OccursInVisitor(this); OccursInVisitor output = new OccursInVisitor(this); - foreach (var type in InputTypes(arguments[k], parameterTypes[k])) { + foreach (var type in InputTypes(arguments[k], parameterTypes[k])) + { type.AcceptVisitor(input); } - foreach (var type in OutputTypes(arguments[k], parameterTypes[k])) { + foreach (var type in OutputTypes(arguments[k], parameterTypes[k])) + { type.AcceptVisitor(output); } - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { dependencyMatrix[i, j] |= input.Occurs[j] && output.Occurs[i]; } } } // calculate transitive closure using Warshall's algorithm: - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - if (dependencyMatrix[i, j]) { - for (int k = 0; k < n; k++) { + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + if (dependencyMatrix[i, j]) + { + for (int k = 0; k < n; k++) + { if (dependencyMatrix[j, k]) dependencyMatrix[i, k] = true; } @@ -459,7 +508,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } } - + bool DependsOn(TP x, TP y) { if (dependencyMatrix == null) @@ -468,7 +517,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return dependencyMatrix[x.TypeParameter.Index, y.TypeParameter.Index]; } #endregion - + #region MakeOutputTypeInference (§7.5.2.6) void MakeOutputTypeInference(ResolveResult e, IType t) { @@ -476,21 +525,27 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // 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. LambdaResolveResult lrr = e as LambdaResolveResult; - if (lrr != null) { + if (lrr != null) + { IMethod m = GetDelegateOrExpressionTreeSignature(t); - if (m != null) { + if (m != null) + { IType inferredReturnType; - if (lrr.IsImplicitlyTyped) { + 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++) { + for (int i = 0; i < inferredParameterTypes.Length; i++) + { IType parameterType = m.Parameters[i].Type; inferredParameterTypes[i] = parameterType.AcceptVisitor(substitution); } inferredReturnType = lrr.GetInferredReturnType(inferredParameterTypes); - } else { + } + else + { inferredReturnType = lrr.GetInferredReturnType(null); } MakeLowerBoundInference(inferredReturnType, m.ReturnType); @@ -502,25 +557,32 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // 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) { + if (mgrr != null) + { IMethod m = GetDelegateOrExpressionTreeSignature(t); - if (m != null) { + if (m != null) + { ResolveResult[] args = new ResolveResult[m.Parameters.Count]; TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs(); - for (int i = 0; i < args.Length; i++) { + for (int i = 0; i < args.Length; i++) + { IParameter param = m.Parameters[i]; IType parameterType = param.Type.AcceptVisitor(substitution); - if ((param.ReferenceKind != ReferenceKind.None) && parameterType.Kind == TypeKind.ByReference) { + if ((param.ReferenceKind != ReferenceKind.None) && parameterType.Kind == TypeKind.ByReference) + { parameterType = ((ByReferenceType)parameterType).ElementType; args[i] = new ByReferenceResolveResult(parameterType, param.ReferenceKind); - } else { + } + else + { args[i] = new ResolveResult(parameterType); } } var or = mgrr.PerformOverloadResolution(compilation, - args, - allowExpandingParams: false, allowOptionalParameters: false); - if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null) { + args, + allowExpandingParams: false, allowOptionalParameters: false); + if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null) + { IType returnType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType; MakeLowerBoundInference(returnType, m.ReturnType); } @@ -528,21 +590,23 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return; } // Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T. - if (IsValidType(e.Type)) { + if (IsValidType(e.Type)) + { MakeLowerBoundInference(e.Type, t); } } - + TypeParameterSubstitution GetSubstitutionForFixedTPs() { IType[] fixedTypes = new IType[typeParameters.Length]; - for (int i = 0; i < fixedTypes.Length; i++) { + for (int i = 0; i < fixedTypes.Length; i++) + { fixedTypes[i] = typeParameters[i].FixedTo ?? SpecialType.UnknownType; } return new TypeParameterSubstitution(classTypeArguments, fixedTypes); } #endregion - + #region MakeExplicitParameterTypeInference (§7.5.2.7) void MakeExplicitParameterTypeInference(LambdaResolveResult e, IType t) { @@ -553,12 +617,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m == null) return; - for (int i = 0; i < e.Parameters.Count && i < m.Parameters.Count; i++) { + for (int i = 0; i < e.Parameters.Count && i < m.Parameters.Count; i++) + { MakeExactInference(e.Parameters[i].Type, m.Parameters[i].Type); } } #endregion - + #region MakeExactInference (§7.5.2.8) /// /// Make exact inference from U to V. @@ -568,14 +633,16 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { Log.WriteLine("MakeExactInference from " + U + " to " + V); - if (U.Nullability == V.Nullability) { + if (U.Nullability == V.Nullability) + { U = U.WithoutNullability(); V = V.WithoutNullability(); } // 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) { + if (tp != null && tp.IsFixed == false) + { Log.WriteLine(" Add exact bound '" + U + "' to " + tp); tp.AddExactBound(U); return; @@ -583,14 +650,16 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver // Handle by reference types: ByReferenceType brU = U as ByReferenceType; ByReferenceType brV = V as ByReferenceType; - if (brU != null && brV != null) { + if (brU != null && brV != null) + { MakeExactInference(brU.ElementType, brV.ElementType); return; } // Handle array types: ArrayType arrU = U as ArrayType; ArrayType arrV = V as ArrayType; - if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) { + if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) + { MakeExactInference(arrU.ElementType, arrV.ElementType); return; } @@ -598,23 +667,26 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver ParameterizedType pU = U.TupleUnderlyingTypeOrSelf() as ParameterizedType; ParameterizedType pV = V.TupleUnderlyingTypeOrSelf() as ParameterizedType; if (pU != null && pV != null - && object.Equals(pU.GenericType, pV.GenericType) - && pU.TypeParameterCount == pV.TypeParameterCount) + && object.Equals(pU.GenericType, pV.GenericType) + && pU.TypeParameterCount == pV.TypeParameterCount) { Log.Indent(); - for (int i = 0; i < pU.TypeParameterCount; i++) { + for (int i = 0; i < pU.TypeParameterCount; i++) + { MakeExactInference(pU.GetTypeArgument(i), pV.GetTypeArgument(i)); } Log.Unindent(); } } - + TP GetTPForType(IType v) { - if (v is NullabilityAnnotatedTypeParameter natp) { + if (v is NullabilityAnnotatedTypeParameter natp) + { v = natp.OriginalTypeParameter; } - if (v is ITypeParameter p) { + if (v is ITypeParameter p) + { int index = p.Index; if (index < typeParameters.Length && typeParameters[index].TypeParameter == p) return typeParameters[index]; @@ -622,7 +694,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return null; } #endregion - + #region MakeLowerBoundInference (§7.5.2.9) /// /// Make lower bound inference from U to V. @@ -631,27 +703,31 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver void MakeLowerBoundInference(IType U, IType V) { Log.WriteLine(" MakeLowerBoundInference from " + U + " to " + V); - if (U.Nullability == V.Nullability) { + if (U.Nullability == V.Nullability) + { U = U.WithoutNullability(); V = V.WithoutNullability(); } // 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) { + if (tp != null && tp.IsFixed == false) + { Log.WriteLine(" Add lower bound '" + U + "' to " + tp); tp.LowerBounds.Add(U); return; } // Handle nullable covariance: - if (NullableType.IsNullable(U) && NullableType.IsNullable(V)) { + if (NullableType.IsNullable(U) && NullableType.IsNullable(V)) + { MakeLowerBoundInference(NullableType.GetUnderlyingType(U), NullableType.GetUnderlyingType(V)); return; } // Handle by reference types: ByReferenceType brU = U as ByReferenceType; ByReferenceType brV = V as ByReferenceType; - if (brU != null && brV != null) { + if (brU != null && brV != null) + { MakeExactInference(brU.ElementType, brV.ElementType); return; } @@ -659,19 +735,25 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver ArrayType arrU = U as ArrayType; ArrayType arrV = V as ArrayType; ParameterizedType pV = V.TupleUnderlyingTypeOrSelf() as ParameterizedType; - if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) { + if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) + { MakeLowerBoundInference(arrU.ElementType, arrV.ElementType); return; - } else if (arrU != null && IsGenericInterfaceImplementedByArray(pV) && arrU.Dimensions == 1) { + } + else if (arrU != null && IsGenericInterfaceImplementedByArray(pV) && arrU.Dimensions == 1) + { MakeLowerBoundInference(arrU.ElementType, pV.GetTypeArgument(0)); return; } // Handle parameterized types: - if (pV != null) { + if (pV != null) + { ParameterizedType uniqueBaseType = null; - foreach (IType baseU in U.GetAllBaseTypes()) { + foreach (IType baseU in U.GetAllBaseTypes()) + { ParameterizedType pU = baseU.TupleUnderlyingTypeOrSelf() as ParameterizedType; - if (pU != null && object.Equals(pU.GenericType, pV.GenericType) && pU.TypeParameterCount == pV.TypeParameterCount) { + if (pU != null && object.Equals(pU.GenericType, pV.GenericType) && pU.TypeParameterCount == pV.TypeParameterCount) + { if (uniqueBaseType == null) uniqueBaseType = pU; else @@ -679,14 +761,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } Log.Indent(); - if (uniqueBaseType != null) { - for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { + if (uniqueBaseType != null) + { + for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) + { IType Ui = uniqueBaseType.GetTypeArgument(i); IType Vi = pV.GetTypeArgument(i); - if (Ui.IsReferenceType == true) { + if (Ui.IsReferenceType == true) + { // look for variance ITypeParameter Xi = pV.TypeParameters[i]; - switch (Xi.Variance) { + switch (Xi.Variance) + { case VarianceModifier.Covariant: MakeLowerBoundInference(Ui, Vi); break; @@ -697,7 +783,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver MakeExactInference(Ui, Vi); break; } - } else { + } + else + { // not known to be a reference type MakeExactInference(Ui, Vi); } @@ -706,12 +794,13 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Log.Unindent(); } } - + static bool IsGenericInterfaceImplementedByArray(ParameterizedType rt) { if (rt == null || rt.TypeParameterCount != 1) return false; - switch (rt.GetDefinition()?.KnownTypeCode) { + switch (rt.GetDefinition()?.KnownTypeCode) + { case KnownTypeCode.IEnumerableOfT: case KnownTypeCode.ICollectionOfT: case KnownTypeCode.IListOfT: @@ -723,7 +812,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region MakeUpperBoundInference (§7.5.2.10) /// /// Make upper bound inference from U to V. @@ -732,36 +821,44 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver void MakeUpperBoundInference(IType U, IType V) { Log.WriteLine(" MakeUpperBoundInference from " + U + " to " + V); - if (U.Nullability == V.Nullability) { + if (U.Nullability == V.Nullability) + { U = U.WithoutNullability(); V = V.WithoutNullability(); } // 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) { + if (tp != null && tp.IsFixed == false) + { Log.WriteLine(" Add upper bound '" + U + "' to " + tp); tp.UpperBounds.Add(U); return; } - + // Handle array types: ArrayType arrU = U as ArrayType; ArrayType arrV = V as ArrayType; ParameterizedType pU = U.TupleUnderlyingTypeOrSelf() as ParameterizedType; - if (arrV != null && arrU != null && arrU.Dimensions == arrV.Dimensions) { + if (arrV != null && arrU != null && arrU.Dimensions == arrV.Dimensions) + { MakeUpperBoundInference(arrU.ElementType, arrV.ElementType); return; - } else if (arrV != null && IsGenericInterfaceImplementedByArray(pU) && arrV.Dimensions == 1) { + } + else if (arrV != null && IsGenericInterfaceImplementedByArray(pU) && arrV.Dimensions == 1) + { MakeUpperBoundInference(pU.GetTypeArgument(0), arrV.ElementType); return; } // Handle parameterized types: - if (pU != null) { + if (pU != null) + { ParameterizedType uniqueBaseType = null; - foreach (IType baseV in V.GetAllBaseTypes()) { + foreach (IType baseV in V.GetAllBaseTypes()) + { ParameterizedType pV = baseV.TupleUnderlyingTypeOrSelf() as ParameterizedType; - if (pV != null && object.Equals(pU.GenericType, pV.GenericType) && pU.TypeParameterCount == pV.TypeParameterCount) { + if (pV != null && object.Equals(pU.GenericType, pV.GenericType) && pU.TypeParameterCount == pV.TypeParameterCount) + { if (uniqueBaseType == null) uniqueBaseType = pV; else @@ -769,14 +866,18 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } Log.Indent(); - if (uniqueBaseType != null) { - for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { + if (uniqueBaseType != null) + { + for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) + { IType Ui = pU.GetTypeArgument(i); IType Vi = uniqueBaseType.GetTypeArgument(i); - if (Ui.IsReferenceType == true) { + if (Ui.IsReferenceType == true) + { // look for variance ITypeParameter Xi = pU.TypeParameters[i]; - switch (Xi.Variance) { + switch (Xi.Variance) + { case VarianceModifier.Covariant: MakeUpperBoundInference(Ui, Vi); break; @@ -787,7 +888,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver MakeExactInference(Ui, Vi); break; } - } else { + } + else + { // not known to be a reference type MakeExactInference(Ui, Vi); } @@ -797,13 +900,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } #endregion - + #region Fixing (§7.5.2.11) bool Fix(TP tp) { Log.WriteLine(" Trying to fix " + tp); Debug.Assert(!tp.IsFixed); - if (tp.ExactBound != null) { + if (tp.ExactBound != null) + { // the exact bound will always be the result tp.FixedTo = tp.ExactBound; // check validity @@ -815,18 +919,21 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver Log.Indent(); var types = CreateNestedInstance().FindTypesInBounds(tp.LowerBounds.ToArray(), tp.UpperBounds.ToArray()); Log.Unindent(); - if (algorithm == TypeInferenceAlgorithm.ImprovedReturnAllResults) { + if (algorithm == TypeInferenceAlgorithm.ImprovedReturnAllResults) + { tp.FixedTo = IntersectionType.Create(types); Log.WriteLine(" T was fixed " + (types.Count >= 1 ? "successfully" : "(with errors)") + " to " + tp.FixedTo); return types.Count >= 1; - } else { + } + else + { tp.FixedTo = GetFirstTypePreferNonInterfaces(types); Log.WriteLine(" T was fixed " + (types.Count == 1 ? "successfully" : "(with errors)") + " to " + tp.FixedTo); return types.Count == 1; } } #endregion - + #region Finding the best common type of a set of expresssions /// /// Gets the best common type (C# 4.0 spec: §7.5.2.14) of a set of expressions. @@ -835,25 +942,30 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver { if (expressions == null) throw new ArgumentNullException(nameof(expressions)); - if (expressions.Count == 1) { + if (expressions.Count == 1) + { success = IsValidType(expressions[0].Type); return expressions[0].Type; } Log.WriteCollection("GetBestCommonType() for ", expressions); - try { + try + { ITypeParameter tp = DummyTypeParameter.GetMethodTypeParameter(0); this.typeParameters = new TP[1] { new TP(tp) }; - foreach (ResolveResult r in expressions) { + foreach (ResolveResult r in expressions) + { MakeOutputTypeInference(r, tp); } success = Fix(typeParameters[0]); return typeParameters[0].FixedTo ?? SpecialType.UnknownType; - } finally { + } + finally + { Reset(); } } #endregion - + #region FindTypeInBounds /// /// Finds a type that satisfies the given lower and upper bounds. @@ -864,23 +976,26 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver throw new ArgumentNullException(nameof(lowerBounds)); if (upperBounds == null) throw new ArgumentNullException(nameof(upperBounds)); - + var result = FindTypesInBounds(lowerBounds, upperBounds); - - if (algorithm == TypeInferenceAlgorithm.ImprovedReturnAllResults) { + + if (algorithm == TypeInferenceAlgorithm.ImprovedReturnAllResults) + { return IntersectionType.Create(result); - } else { + } + else + { // return any of the candidates (prefer non-interfaces) return GetFirstTypePreferNonInterfaces(result); } } - + static IType GetFirstTypePreferNonInterfaces(IReadOnlyList result) { return result.FirstOrDefault(c => c.Kind != TypeKind.Interface) ?? result.FirstOrDefault() ?? SpecialType.UnknownType; } - + IReadOnlyList FindTypesInBounds(IReadOnlyList lowerBounds, IReadOnlyList upperBounds) { // If there's only a single type; return that single type. @@ -891,11 +1006,11 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return lowerBounds; if (nestingLevel > maxNestingLevel) return EmptyList.Instance; - + // Finds a type X so that "LB <: X <: UB" 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) .Where(c => lowerBounds.All(b => conversions.ImplicitConversion(b, c).IsValid)) @@ -903,7 +1018,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver .ToList(); // evaluate the query only once Log.WriteCollection("FindTypesInBound, Candidates=", candidateTypes); - + // According to the C# specification, we need to pick the most specific // of the candidate types. (the type which has conversions to all others) // However, csc actually seems to choose the least specific. @@ -920,36 +1035,46 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return candidateTypes; } candidateTypes.Clear(); - + // Now try the improved algorithm Log.Indent(); List candidateTypeDefinitions; - if (lowerBounds.Count > 0) { + if (lowerBounds.Count > 0) + { // Find candidates by using the lower bounds: var hashSet = new HashSet(lowerBounds[0].GetAllBaseTypeDefinitions()); - for (int i = 1; i < lowerBounds.Count; i++) { + for (int i = 1; i < lowerBounds.Count; i++) + { hashSet.IntersectWith(lowerBounds[i].GetAllBaseTypeDefinitions()); } candidateTypeDefinitions = hashSet.ToList(); - } else { + } + else + { // Find candidates by looking at all classes in the project: candidateTypeDefinitions = compilation.GetAllTypeDefinitions().ToList(); } - + // Now filter out candidates that violate the upper bounds: - foreach (IType ub in upperBounds) { + foreach (IType ub in upperBounds) + { ITypeDefinition ubDef = ub.GetDefinition(); - if (ubDef != null) { + if (ubDef != null) + { candidateTypeDefinitions.RemoveAll(c => !c.IsDerivedFrom(ubDef)); } } - - foreach (ITypeDefinition candidateDef in candidateTypeDefinitions) { + + foreach (ITypeDefinition candidateDef in candidateTypeDefinitions) + { // determine the type parameters for the candidate: IType candidate; - if (candidateDef.TypeParameterCount == 0) { + if (candidateDef.TypeParameterCount == 0) + { candidate = candidateDef; - } else { + } + else + { Log.WriteLine("Inferring arguments for candidate type definition: " + candidateDef); bool success; IType[] result = InferTypeArgumentsFromBounds( @@ -957,30 +1082,38 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver new ParameterizedType(candidateDef, candidateDef.TypeParameters), lowerBounds, upperBounds, out success); - if (success) { + if (success) + { candidate = new ParameterizedType(candidateDef, result); - } else { + } + else + { Log.WriteLine("Inference failed; ignoring candidate"); continue; } } Log.WriteLine("Candidate type: " + candidate); - - if (upperBounds.Count == 0) { + + if (upperBounds.Count == 0) + { // if there were only lower bounds, we aim for the most specific candidate: - + // if this candidate isn't made redundant by an existing, more specific candidate: - if (!candidateTypes.Any(c => c.GetDefinition().IsDerivedFrom(candidateDef))) { + if (!candidateTypes.Any(c => c.GetDefinition().IsDerivedFrom(candidateDef))) + { // remove all existing candidates made redundant by this candidate: candidateTypes.RemoveAll(c => candidateDef.IsDerivedFrom(c.GetDefinition())); // add new candidate candidateTypes.Add(candidate); } - } else { + } + else + { // if there were upper bounds, we aim for the least specific candidate: - + // if this candidate isn't made redundant by an existing, less specific candidate: - if (!candidateTypes.Any(c => candidateDef.IsDerivedFrom(c.GetDefinition()))) { + if (!candidateTypes.Any(c => candidateDef.IsDerivedFrom(c.GetDefinition()))) + { // remove all existing candidates made redundant by this candidate: candidateTypes.RemoveAll(c => c.GetDefinition().IsDerivedFrom(candidateDef)); // add new candidate diff --git a/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs b/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs index 072424663..44515dc0f 100644 --- a/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.IL; @@ -87,7 +88,7 @@ namespace ICSharpCode.Decompiler.CSharp readonly List<(ILFunction, DebugInfo.SequencePoint)> sequencePoints = new List<(ILFunction, DebugInfo.SequencePoint)>(); readonly HashSet mappedInstructions = new HashSet(); - + // Stack holding information for outer statements. readonly Stack outerStates = new Stack(); @@ -96,7 +97,8 @@ namespace ICSharpCode.Decompiler.CSharp void VisitAsSequencePoint(AstNode node) { - if (node.IsNull) return; + if (node.IsNull) + return; StartSequencePoint(node); node.AcceptVisitor(this); EndSequencePoint(node.StartLocation, node.EndLocation); @@ -111,17 +113,21 @@ namespace ICSharpCode.Decompiler.CSharp public override void VisitBlockStatement(BlockStatement blockStatement) { ILInstruction blockContainer = blockStatement.Annotations.OfType().FirstOrDefault(); - if (blockContainer != null) { + if (blockContainer != null) + { StartSequencePoint(blockStatement.LBraceToken); int intervalStart; - if (blockContainer.Parent is TryCatchHandler handler && !handler.ExceptionSpecifierILRange.IsEmpty) { + if (blockContainer.Parent is TryCatchHandler handler && !handler.ExceptionSpecifierILRange.IsEmpty) + { // if this block container is part of a TryCatchHandler, do not steal the exception-specifier IL range intervalStart = handler.ExceptionSpecifierILRange.End; - } else { + } + else + { intervalStart = blockContainer.StartILOffset; } // The end will be set to the first sequence point candidate location before the first statement of the function when the seqeunce point is adjusted - int intervalEnd = intervalStart + 1; + int intervalEnd = intervalStart + 1; Interval interval = new Interval(intervalStart, intervalEnd); List intervals = new List(); @@ -130,16 +136,19 @@ namespace ICSharpCode.Decompiler.CSharp current.Function = blockContainer.Ancestors.OfType().FirstOrDefault(); EndSequencePoint(blockStatement.LBraceToken.StartLocation, blockStatement.LBraceToken.EndLocation); } - else { + else + { // Ideally, we'd be able to address this case. Blocks that are not the top-level function block have no ILInstruction annotations. It isn't clear to me how to determine the il range. // For now, do not add the opening brace sequence in this case. } - foreach (var stmt in blockStatement.Statements) { + foreach (var stmt in blockStatement.Statements) + { VisitAsSequencePoint(stmt); } var implicitReturn = blockStatement.Annotation(); - if (implicitReturn != null) { + if (implicitReturn != null) + { StartSequencePoint(blockStatement.RBraceToken); AddToSequencePoint(implicitReturn.Leave); EndSequencePoint(blockStatement.RBraceToken.StartLocation, blockStatement.RBraceToken.EndLocation); @@ -149,21 +158,24 @@ namespace ICSharpCode.Decompiler.CSharp public override void VisitForStatement(ForStatement forStatement) { // Every element of a for-statement is its own sequence point. - foreach (var init in forStatement.Initializers) { + foreach (var init in forStatement.Initializers) + { VisitAsSequencePoint(init); } VisitAsSequencePoint(forStatement.Condition); - foreach (var inc in forStatement.Iterators) { + foreach (var inc in forStatement.Iterators) + { VisitAsSequencePoint(inc); } VisitAsSequencePoint(forStatement.EmbeddedStatement); } - + public override void VisitSwitchStatement(SwitchStatement switchStatement) { StartSequencePoint(switchStatement); switchStatement.Expression.AcceptVisitor(this); - foreach (var section in switchStatement.SwitchSections) { + foreach (var section in switchStatement.SwitchSections) + { // note: sections will not contribute to the current sequence point section.AcceptVisitor(this); } @@ -176,7 +188,8 @@ namespace ICSharpCode.Decompiler.CSharp public override void VisitSwitchSection(Syntax.SwitchSection switchSection) { // every statement in the switch section is its own sequence point - foreach (var stmt in switchSection.Statements) { + foreach (var stmt in switchSection.Statements) + { VisitAsSequencePoint(stmt); } } @@ -195,10 +208,13 @@ namespace ICSharpCode.Decompiler.CSharp public override void VisitQueryFromClause(QueryFromClause queryFromClause) { - if (queryFromClause.Parent.FirstChild != queryFromClause) { + if (queryFromClause.Parent.FirstChild != queryFromClause) + { AddToSequencePoint(queryFromClause); VisitAsSequencePoint(queryFromClause.Expression); - } else { + } + else + { base.VisitQueryFromClause(queryFromClause); } } @@ -253,7 +269,8 @@ namespace ICSharpCode.Decompiler.CSharp public override void VisitForeachStatement(ForeachStatement foreachStatement) { var foreachInfo = foreachStatement.Annotation(); - if (foreachInfo == null) { + if (foreachInfo == null) + { base.VisitForeachStatement(foreachStatement); return; } @@ -266,11 +283,11 @@ namespace ICSharpCode.Decompiler.CSharp StartSequencePoint(foreachStatement); AddToSequencePoint(foreachInfo.MoveNextCall); EndSequencePoint(foreachStatement.InToken.StartLocation, foreachStatement.InToken.EndLocation); - + StartSequencePoint(foreachStatement); AddToSequencePoint(foreachInfo.GetCurrentCall); EndSequencePoint(foreachStatement.VariableType.StartLocation, foreachStatement.VariableDesignation.EndLocation); - + VisitAsSequencePoint(foreachStatement.EmbeddedStatement); } @@ -313,7 +330,8 @@ namespace ICSharpCode.Decompiler.CSharp public override void VisitFixedStatement(FixedStatement fixedStatement) { - foreach (var v in fixedStatement.Variables) { + foreach (var v in fixedStatement.Variables) + { VisitAsSequencePoint(v); } VisitAsSequencePoint(fixedStatement.EmbeddedStatement); @@ -322,7 +340,8 @@ namespace ICSharpCode.Decompiler.CSharp public override void VisitTryCatchStatement(TryCatchStatement tryCatchStatement) { VisitAsSequencePoint(tryCatchStatement.TryBlock); - foreach (var c in tryCatchStatement.CatchClauses) { + foreach (var c in tryCatchStatement.CatchClauses) + { VisitAsSequencePoint(c); } VisitAsSequencePoint(tryCatchStatement.FinallyBlock); @@ -330,15 +349,19 @@ namespace ICSharpCode.Decompiler.CSharp public override void VisitCatchClause(CatchClause catchClause) { - if (catchClause.Condition.IsNull) { + if (catchClause.Condition.IsNull) + { var tryCatchHandler = catchClause.Annotation(); - if (tryCatchHandler != null && !tryCatchHandler.ExceptionSpecifierILRange.IsEmpty) { + if (tryCatchHandler != null && !tryCatchHandler.ExceptionSpecifierILRange.IsEmpty) + { StartSequencePoint(catchClause.CatchToken); var function = tryCatchHandler.Ancestors.OfType().FirstOrDefault(); AddToSequencePointRaw(function, new[] { tryCatchHandler.ExceptionSpecifierILRange }); EndSequencePoint(catchClause.CatchToken.StartLocation, catchClause.RParToken.IsNull ? catchClause.CatchToken.EndLocation : catchClause.RParToken.EndLocation); } - } else { + } + else + { StartSequencePoint(catchClause.WhenToken); AddToSequencePoint(catchClause.Condition); EndSequencePoint(catchClause.WhenToken.StartLocation, catchClause.CondRParToken.EndLocation); @@ -359,7 +382,8 @@ namespace ICSharpCode.Decompiler.CSharp { Debug.Assert(!startLocation.IsEmpty, "missing startLocation"); Debug.Assert(!endLocation.IsEmpty, "missing endLocation"); - if (current.Intervals.Count > 0 && current.Function != null) { + if (current.Intervals.Count > 0 && current.Function != null) + { // use LongSet to deduplicate and merge the intervals var longSet = new LongSet(current.Intervals.Select(i => new LongInterval(i.Start, i.End))); Debug.Assert(!longSet.IsEmpty); @@ -388,19 +412,22 @@ namespace ICSharpCode.Decompiler.CSharp /// void AddToSequencePoint(AstNode node) { - foreach (var inst in node.Annotations.OfType()) { + foreach (var inst in node.Annotations.OfType()) + { AddToSequencePoint(inst); } } void AddToSequencePoint(ILInstruction inst) { - if (!mappedInstructions.Add(inst)) { + if (!mappedInstructions.Add(inst)) + { // inst was already used by a nested sequence point within this sequence point return; } // Add the IL range associated with this instruction to the current sequence point. - if (HasUsableILRange(inst) && current.Intervals != null) { + if (HasUsableILRange(inst) && current.Intervals != null) + { current.Intervals.AddRange(inst.ILRanges); var function = inst.Parent.Ancestors.OfType().FirstOrDefault(); Debug.Assert(current.Function == null || current.Function == function); @@ -413,7 +440,8 @@ namespace ICSharpCode.Decompiler.CSharp // Also add the child IL instructions, unless they were already processed by // another C# expression. - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { AddToSequencePoint(child); } } @@ -431,27 +459,36 @@ namespace ICSharpCode.Decompiler.CSharp internal Dictionary> GetSequencePoints() { var dict = new Dictionary>(); - foreach (var (function, sequencePoint) in this.sequencePoints) { - if (!dict.TryGetValue(function, out var list)) { + foreach (var (function, sequencePoint) in this.sequencePoints) + { + if (!dict.TryGetValue(function, out var list)) + { dict.Add(function, list = new List()); } list.Add(sequencePoint); } - foreach (var (function, list) in dict.ToList()) { + foreach (var (function, list) in dict.ToList()) + { // For each function, sort sequence points and fix overlaps var newList = new List(); int pos = 0; IOrderedEnumerable currFunctionSequencePoints = list.OrderBy(sp => sp.Offset).ThenBy(sp => sp.EndOffset); - foreach (DebugInfo.SequencePoint sequencePoint in currFunctionSequencePoints) { - if (sequencePoint.Offset < pos) { + foreach (DebugInfo.SequencePoint sequencePoint in currFunctionSequencePoints) + { + if (sequencePoint.Offset < pos) + { // overlapping sequence point? // delete previous sequence points that are after sequencePoint.Offset - while (newList.Count > 0 && newList.Last().EndOffset > sequencePoint.Offset) { + while (newList.Count > 0 && newList.Last().EndOffset > sequencePoint.Offset) + { var last = newList.Last(); - if (last.Offset >= sequencePoint.Offset) { + if (last.Offset >= sequencePoint.Offset) + { newList.RemoveAt(newList.Count - 1); - } else { + } + else + { last.EndOffset = sequencePoint.Offset; newList[newList.Count - 1] = last; } @@ -462,7 +499,8 @@ namespace ICSharpCode.Decompiler.CSharp pos = sequencePoint.EndOffset; } // Add a hidden sequence point to account for the epilog of the function - if (pos < function.CodeSize) { + if (pos < function.CodeSize) + { var hidden = new DebugInfo.SequencePoint(); hidden.Offset = pos; hidden.EndOffset = function.CodeSize; @@ -474,7 +512,8 @@ namespace ICSharpCode.Decompiler.CSharp List sequencePointCandidates = function.SequencePointCandidates; int currSPCandidateIndex = 0; - for (int i = 0; i < newList.Count - 1; i++) { + for (int i = 0; i < newList.Count - 1; i++) + { DebugInfo.SequencePoint currSequencePoint = newList[i]; DebugInfo.SequencePoint nextSequencePoint = newList[i + 1]; @@ -483,33 +522,38 @@ namespace ICSharpCode.Decompiler.CSharp // point is not required as it is 0 for the first sequence point and is moved during the last // iteration for all others. while (currSPCandidateIndex < sequencePointCandidates.Count && - sequencePointCandidates[currSPCandidateIndex] < currSequencePoint.EndOffset) { + sequencePointCandidates[currSPCandidateIndex] < currSequencePoint.EndOffset) + { currSPCandidateIndex++; } - if (currSPCandidateIndex < sequencePointCandidates.Count && sequencePointCandidates[currSPCandidateIndex] <= nextSequencePoint.Offset) { + if (currSPCandidateIndex < sequencePointCandidates.Count && sequencePointCandidates[currSPCandidateIndex] <= nextSequencePoint.Offset) + { currSequencePoint.EndOffset = sequencePointCandidates[currSPCandidateIndex]; } // Adjust the start offset of the next sequence point to the closest previous sequence point candidate // but do not create an overlapping sequence point. while (currSPCandidateIndex < sequencePointCandidates.Count && - sequencePointCandidates[currSPCandidateIndex] < nextSequencePoint.Offset) { + sequencePointCandidates[currSPCandidateIndex] < nextSequencePoint.Offset) + { currSPCandidateIndex++; } - if (currSPCandidateIndex < sequencePointCandidates.Count && sequencePointCandidates[currSPCandidateIndex - 1] >= currSequencePoint.EndOffset) { + if (currSPCandidateIndex < sequencePointCandidates.Count && sequencePointCandidates[currSPCandidateIndex - 1] >= currSequencePoint.EndOffset) + { nextSequencePoint.Offset = sequencePointCandidates[currSPCandidateIndex - 1]; currSPCandidateIndex--; } // Fill in any gaps with a hidden sequence point - if (currSequencePoint.EndOffset != nextSequencePoint.Offset) { + if (currSequencePoint.EndOffset != nextSequencePoint.Offset) + { SequencePoint newSP = new SequencePoint() { Offset = currSequencePoint.EndOffset, EndOffset = nextSequencePoint.Offset }; newSP.SetHidden(); newList.Insert(++i, newSP); } } dict[function] = newList; - } + } return dict; } diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index 83ad50217..294c58930 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -16,18 +16,19 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System.Diagnostics; -using ICSharpCode.Decompiler.IL; +using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; +using System.Threading; + using ICSharpCode.Decompiler.CSharp.Syntax; +using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; +using ICSharpCode.Decompiler.IL; +using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; -using System; -using System.Threading; -using ICSharpCode.Decompiler.IL.Transforms; -using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; namespace ICSharpCode.Decompiler.CSharp { @@ -97,7 +98,8 @@ namespace ICSharpCode.Decompiler.CSharp { var expr = exprBuilder.Translate(inst); // strip top-level ref on ref re-assignment - if (expr.Expression is DirectionExpression dirExpr) { + if (expr.Expression is DirectionExpression dirExpr) + { expr = expr.UnwrapChild(dirExpr.Expression); } return new ExpressionStatement(expr).WithILInstruction(inst); @@ -106,7 +108,8 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedStatement VisitNop(Nop inst) { var stmt = new EmptyStatement(); - if (inst.Comment != null) { + if (inst.Comment != null) + { stmt.AddChild(new Comment(inst.Comment), Roles.Comment); } return stmt.WithILInstruction(inst); @@ -126,26 +129,39 @@ namespace ICSharpCode.Decompiler.CSharp // unpack nullable type, if necessary: // we need to do this in all cases, because there are nullable bools and enum types as well. type = NullableType.GetUnderlyingType(type); - if (type.IsKnownType(KnownTypeCode.Boolean)) { + if (type.IsKnownType(KnownTypeCode.Boolean)) + { value = i != 0; - } else if (type.IsKnownType(KnownTypeCode.String) && map != null) { + } + else if (type.IsKnownType(KnownTypeCode.String) && map != null) + { var keys = map.Where(entry => entry.Value == i).Select(entry => entry.Key); foreach (var key in keys) yield return new ConstantResolveResult(type, key); yield break; - } else if (type.Kind == TypeKind.Enum) { + } + else if (type.Kind == TypeKind.Enum) + { var enumType = type.GetDefinition().EnumUnderlyingType; TypeCode typeCode = ReflectionHelper.GetTypeCode(enumType); - if (typeCode != TypeCode.Empty) { + if (typeCode != TypeCode.Empty) + { value = CSharpPrimitiveCast.Cast(typeCode, i, false); - } else { + } + else + { value = i; } - } else { + } + else + { TypeCode typeCode = ReflectionHelper.GetTypeCode(type); - if (typeCode != TypeCode.Empty) { + if (typeCode != TypeCode.Empty) + { value = CSharpPrimitiveCast.Cast(typeCode, i, false); - } else { + } + else + { value = i; } } @@ -165,9 +181,12 @@ namespace ICSharpCode.Decompiler.CSharp caseLabelMapping = new Dictionary(); TranslatedExpression value; - if (inst.Value is StringToInt strToInt) { + if (inst.Value is StringToInt strToInt) + { value = exprBuilder.Translate(strToInt.Argument); - } else { + } + else + { strToInt = null; value = exprBuilder.Translate(inst.Value); } @@ -177,26 +196,34 @@ namespace ICSharpCode.Decompiler.CSharp var stmt = new SwitchStatement() { Expression = value }; Dictionary translationDictionary = new Dictionary(); // initialize C# switch sections. - foreach (var section in inst.Sections) { + foreach (var section in inst.Sections) + { // This is used in the block-label mapping. ConstantResolveResult firstValueResolveResult; var astSection = new Syntax.SwitchSection(); // Create case labels: - if (section == defaultSection) { + if (section == defaultSection) + { astSection.CaseLabels.Add(new CaseLabel()); firstValueResolveResult = null; - } else { + } + else + { var values = section.Labels.Values.SelectMany(i => CreateTypedCaseLabel(i, value.Type, strToInt?.Map)).ToArray(); - if (section.HasNullLabel) { + if (section.HasNullLabel) + { astSection.CaseLabels.Add(new CaseLabel(new NullReferenceExpression())); firstValueResolveResult = new ConstantResolveResult(SpecialType.NullType, null); - } else { + } + else + { Debug.Assert(values.Length > 0); firstValueResolveResult = values[0]; } astSection.CaseLabels.AddRange(values.Select(label => new CaseLabel(exprBuilder.ConvertConstantValue(label, allowImplicitConversion: true)))); } - switch (section.Body) { + switch (section.Body) + { case Branch br: // we can only inline the block, if all branches are in the switchContainer. if (br.TargetContainer == switchContainer && switchContainer.Descendants.OfType().Where(b => b.TargetBlock == br.TargetBlock).All(b => BlockContainer.FindClosestSwitchContainer(b) == switchContainer)) @@ -208,9 +235,11 @@ namespace ICSharpCode.Decompiler.CSharp translationDictionary.Add(section, astSection); stmt.SwitchSections.Add(astSection); } - foreach (var section in inst.Sections) { + foreach (var section in inst.Sections) + { var astSection = translationDictionary[section]; - switch (section.Body) { + switch (section.Body) + { case Branch br: // we can only inline the block, if all branches are in the switchContainer. if (br.TargetContainer == switchContainer && switchContainer.Descendants.OfType().Where(b => b.TargetBlock == br.TargetBlock).All(b => BlockContainer.FindClosestSwitchContainer(b) == switchContainer)) @@ -219,7 +248,8 @@ namespace ICSharpCode.Decompiler.CSharp ConvertSwitchSectionBody(astSection, section.Body); break; case Leave leave: - if (astSection.CaseLabels.Count == 1 && astSection.CaseLabels.First().Expression.IsNull && leave.TargetContainer == switchContainer) { + if (astSection.CaseLabels.Count == 1 && astSection.CaseLabels.First().Expression.IsNull && leave.TargetContainer == switchContainer) + { stmt.SwitchSections.Remove(astSection); break; } @@ -229,24 +259,32 @@ namespace ICSharpCode.Decompiler.CSharp break; } } - if (switchContainer != null && stmt.SwitchSections.Count > 0) { + if (switchContainer != null && stmt.SwitchSections.Count > 0) + { // Translate any remaining blocks: var lastSectionStatements = stmt.SwitchSections.Last().Statements; - foreach (var block in switchContainer.Blocks.Skip(1)) { - if (caseLabelMapping.ContainsKey(block)) continue; + foreach (var block in switchContainer.Blocks.Skip(1)) + { + if (caseLabelMapping.ContainsKey(block)) + continue; lastSectionStatements.Add(new LabelStatement { Label = block.Label }); - foreach (var nestedInst in block.Instructions) { + foreach (var nestedInst in block.Instructions) + { var nestedStmt = Convert(nestedInst); - if (nestedStmt is BlockStatement b) { + if (nestedStmt is BlockStatement b) + { foreach (var nested in b.Statements) lastSectionStatements.Add(nested.Detach()); - } else { + } + else + { lastSectionStatements.Add(nestedStmt); } } Debug.Assert(block.FinalInstruction.OpCode == OpCode.Nop); } - if (endContainerLabels.TryGetValue(switchContainer, out string label)) { + if (endContainerLabels.TryGetValue(switchContainer, out string label)) + { lastSectionStatements.Add(new LabelStatement { Label = label }); lastSectionStatements.Add(new BreakStatement()); } @@ -261,12 +299,16 @@ namespace ICSharpCode.Decompiler.CSharp { var body = Convert(bodyInst); astSection.Statements.Add(body); - if (!bodyInst.HasFlag(InstructionFlags.EndPointUnreachable)) { + if (!bodyInst.HasFlag(InstructionFlags.EndPointUnreachable)) + { // we need to insert 'break;' BlockStatement block = body as BlockStatement; - if (block != null) { + if (block != null) + { block.Add(new BreakStatement()); - } else { + } + else + { astSection.Statements.Add(new BreakStatement()); } } @@ -281,11 +323,13 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedStatement VisitBranch(Branch inst) { - if (inst.TargetBlock == continueTarget) { + if (inst.TargetBlock == continueTarget) + { continueCount++; return new ContinueStatement().WithILInstruction(inst); } - if (caseLabelMapping != null && caseLabelMapping.TryGetValue(inst.TargetBlock, out var label)) { + if (caseLabelMapping != null && caseLabelMapping.TryGetValue(inst.TargetBlock, out var label)) + { if (label == null) return new GotoDefaultStatement().WithILInstruction(inst); return new GotoCaseStatement() { LabelExpression = exprBuilder.ConvertConstantValue(label, allowImplicitConversion: true) } @@ -303,17 +347,21 @@ namespace ICSharpCode.Decompiler.CSharp { if (inst.TargetContainer == breakTarget) return new BreakStatement().WithILInstruction(inst); - if (inst.TargetContainer == currentReturnContainer) { + if (inst.TargetContainer == currentReturnContainer) + { if (currentIsIterator) return new YieldBreakStatement().WithILInstruction(inst); - else if (!inst.Value.MatchNop()) { + else if (!inst.Value.MatchNop()) + { var expr = exprBuilder.Translate(inst.Value, typeHint: currentResultType) .ConvertTo(currentResultType, exprBuilder, allowImplicitConversion: true); return new ReturnStatement(expr).WithILInstruction(inst); - } else + } + else return new ReturnStatement().WithILInstruction(inst); } - if (!endContainerLabels.TryGetValue(inst.TargetContainer, out string label)) { + if (!endContainerLabels.TryGetValue(inst.TargetContainer, out string label)) + { label = "end_" + inst.TargetLabel; endContainerLabels.Add(inst.TargetContainer, label); } @@ -355,16 +403,21 @@ namespace ICSharpCode.Decompiler.CSharp { var tryCatch = new TryCatchStatement(); tryCatch.TryBlock = ConvertAsBlock(inst.TryBlock); - foreach (var handler in inst.Handlers) { + foreach (var handler in inst.Handlers) + { var catchClause = new CatchClause(); catchClause.AddAnnotation(handler); var v = handler.Variable; - if (v != null) { + if (v != null) + { catchClause.AddAnnotation(new ILVariableResolveResult(v, v.Type)); - if (v.StoreCount > 1 || v.LoadCount > 0 || v.AddressCount > 0) { + if (v.StoreCount > 1 || v.LoadCount > 0 || v.AddressCount > 0) + { catchClause.VariableName = v.Name; catchClause.Type = exprBuilder.ConvertType(v.Type); - } else if (!v.Type.IsKnownType(KnownTypeCode.Object)) { + } + else if (!v.Type.IsKnownType(KnownTypeCode.Object)) + { catchClause.Type = exprBuilder.ConvertType(v.Type); } } @@ -425,16 +478,20 @@ namespace ICSharpCode.Decompiler.CSharp KnownTypeCode knownTypeCode; IType disposeType; string disposeTypeMethodName; - if (inst.IsAsync) { + if (inst.IsAsync) + { knownTypeCode = KnownTypeCode.IAsyncDisposable; disposeType = exprBuilder.compilation.FindType(KnownTypeCode.IAsyncDisposable); disposeTypeMethodName = "DisposeAsync"; - } else { + } + else + { knownTypeCode = KnownTypeCode.IDisposable; disposeType = exprBuilder.compilation.FindType(KnownTypeCode.IDisposable); disposeTypeMethodName = "Dispose"; } - if (!IsValidInCSharp(inst, knownTypeCode)) { + if (!IsValidInCSharp(inst, knownTypeCode)) + { Debug.Assert(var.Kind == VariableKind.UsingLocal); var.Kind = VariableKind.Local; var disposeVariable = currentFunction.RegisterVariable( @@ -442,7 +499,8 @@ namespace ICSharpCode.Decompiler.CSharp AssignVariableNames.GenerateVariableName(currentFunction, disposeType) ); Expression disposeInvocation = new InvocationExpression(new MemberReferenceExpression(exprBuilder.ConvertVariable(disposeVariable).Expression, disposeTypeMethodName)); - if (inst.IsAsync) { + if (inst.IsAsync) + { disposeInvocation = new UnaryOperatorExpression { Expression = disposeInvocation, Operator = UnaryOperatorType.Await }; } return new BlockStatement { @@ -458,8 +516,11 @@ namespace ICSharpCode.Decompiler.CSharp } }, }.WithILInstruction(inst); - } else { - if (var.LoadCount > 0 || var.AddressCount > 0) { + } + else + { + if (var.LoadCount > 0 || var.AddressCount > 0) + { var type = settings.AnonymousTypes && var.Type.ContainsAnonymousType() ? new SimpleType("var") : exprBuilder.ConvertType(var.Type); var vds = new VariableDeclarationStatement(type, var.Name, resource); vds.Variables.Single().AddAnnotation(new ILVariableResolveResult(var, var.Type)); @@ -484,7 +545,8 @@ namespace ICSharpCode.Decompiler.CSharp Statement TransformToForeach(UsingInstruction inst, Expression resource) { - if (!settings.ForEachStatement) { + if (!settings.ForEachStatement) + { return null; } // Check if the using resource matches the GetEnumerator pattern. @@ -524,9 +586,12 @@ namespace ICSharpCode.Decompiler.CSharp var collectionExpr = m.Get("collection").Single(); // Special case: foreach (var item in this) is decompiled as foreach (var item in base) // but a base reference is not valid in this context. - if (collectionExpr is BaseReferenceExpression) { + if (collectionExpr is BaseReferenceExpression) + { collectionExpr = new ThisReferenceExpression().CopyAnnotationsFrom(collectionExpr); - } else if (IsDynamicCastToIEnumerable(collectionExpr, out var dynamicExpr)) { + } + else if (IsDynamicCastToIEnumerable(collectionExpr, out var dynamicExpr)) + { collectionExpr = dynamicExpr.Detach(); } // Handle explicit casts: @@ -535,7 +600,8 @@ namespace ICSharpCode.Decompiler.CSharp var type = singleGetter.Method.ReturnType; ILInstruction instToReplace = singleGetter; bool useVar = false; - switch (instToReplace.Parent) { + switch (instToReplace.Parent) + { case CastClass cc: type = cc.Type; instToReplace = cc; @@ -545,10 +611,12 @@ namespace ICSharpCode.Decompiler.CSharp instToReplace = ua; break; default: - if (TupleType.IsTupleCompatible(type, out _)) { + if (TupleType.IsTupleCompatible(type, out _)) + { // foreach with get_Current returning a tuple type, let's check which type "var" would infer: var foreachRR = exprBuilder.resolver.ResolveForeach(collectionExpr.GetResolveResult()); - if (EqualErasedType(type, foreachRR.ElementType)) { + if (EqualErasedType(type, foreachRR.ElementType)) + { type = foreachRR.ElementType; useVar = true; } @@ -559,7 +627,8 @@ namespace ICSharpCode.Decompiler.CSharp VariableDesignation designation = null; // Handle the required foreach-variable transformation: - switch (transformation) { + switch (transformation) + { case RequiredGetCurrentTransformation.UseExistingVariable: if (foreachVariable.Type.Kind != TypeKind.Dynamic) foreachVariable.Type = type; @@ -593,7 +662,8 @@ namespace ICSharpCode.Decompiler.CSharp break; } - if (designation == null) { + if (designation == null) + { designation = new SingleVariableDesignation { Identifier = foreachVariable.Name }; // Add the variable annotation for highlighting designation.AddAnnotation(new ILVariableResolveResult(foreachVariable, foreachVariable.Type)); @@ -605,7 +675,8 @@ namespace ICSharpCode.Decompiler.CSharp // Remove the first statement, as it is the foreachVariable = enumerator.Current; statement. Statement firstStatement = foreachBody.Statements.First(); - if (firstStatement is LabelStatement) { + if (firstStatement is LabelStatement) + { // skip the entry-point label, if any firstStatement = firstStatement.GetNextStatement(); } @@ -626,7 +697,8 @@ namespace ICSharpCode.Decompiler.CSharp foreachStmt.AddAnnotation(new ForeachAnnotation(inst.ResourceExpression, conditionInst, singleGetter)); foreachStmt.CopyAnnotationsFrom(whileLoop); // If there was an optional return statement, return it as well. - if (optionalReturnAfterLoop != null) { + if (optionalReturnAfterLoop != null) + { return new BlockStatement { Statements = { foreachStmt, @@ -647,21 +719,28 @@ namespace ICSharpCode.Decompiler.CSharp VariableDesignation ConstructDesignation(MatchInstruction matchInstruction) { var designations = new ParenthesizedVariableDesignation(); - foreach (var subPattern in matchInstruction.SubPatterns.Cast()) { - if (subPattern.IsVar) { + foreach (var subPattern in matchInstruction.SubPatterns.Cast()) + { + if (subPattern.IsVar) + { var designation = new SingleVariableDesignation(); - if (subPattern.HasDesignator) { + if (subPattern.HasDesignator) + { ILVariable v = ((StLoc)assignments[assignmentPos]).Variable; if (isForeach) v.Kind = VariableKind.ForeachLocal; designation.Identifier = v.Name; designation.AddAnnotation(new ILVariableResolveResult(v)); assignmentPos++; - } else { + } + else + { designation.Identifier = "_"; } designations.VariableDesignations.Add(designation); - } else { + } + else + { designations.VariableDesignations.Add(ConstructDesignation(subPattern)); } } @@ -676,7 +755,8 @@ namespace ICSharpCode.Decompiler.CSharp private bool IsDynamicCastToIEnumerable(Expression expr, out Expression dynamicExpr) { - if (!(expr is CastExpression cast)) { + if (!(expr is CastExpression cast)) + { dynamicExpr = null; return false; } @@ -712,7 +792,8 @@ namespace ICSharpCode.Decompiler.CSharp return nestedContainer; // If the leave is a return, we can move the return out of the using-block and put it after the loop // (but only if the value doesn't have side-effects) - if (leave.IsLeavingFunction && SemanticHelper.IsPure(leave.Value.Flags)) { + if (leave.IsLeavingFunction && SemanticHelper.IsPure(leave.Value.Flags)) + { optionalReturnInst = leave; return nestedContainer; } @@ -807,16 +888,19 @@ namespace ICSharpCode.Decompiler.CSharp while (inst.Parent is UnboxAny || inst.Parent is CastClass) inst = inst.Parent; // One variable was found. - if (inst.Parent is StLoc stloc && (stloc.Variable.Kind == VariableKind.Local || stloc.Variable.Kind == VariableKind.StackSlot)) { + if (inst.Parent is StLoc stloc && (stloc.Variable.Kind == VariableKind.Local || stloc.Variable.Kind == VariableKind.StackSlot)) + { // Must be a plain assignment expression and variable must only be used in 'body' + only assigned once. - if (stloc.Parent == loopBody && VariableIsOnlyUsedInBlock(stloc, usingContainer, loopContainer)) { + if (stloc.Parent == loopBody && VariableIsOnlyUsedInBlock(stloc, usingContainer, loopContainer)) + { foreachVariable = stloc.Variable; return RequiredGetCurrentTransformation.UseExistingVariable; } } // In optimized Roslyn code it can happen that the foreach variable is referenced via addressof // We only do this unwrapping if where dealing with a custom struct type. - if (CurrentIsStructSetterTarget(inst, singleGetter)) { + if (CurrentIsStructSetterTarget(inst, singleGetter)) + { return RequiredGetCurrentTransformation.IntroduceNewVariableAndLocalCopy; } // No suitable variable was found: we need a new one. @@ -834,7 +918,8 @@ namespace ICSharpCode.Decompiler.CSharp if (!NormalizeTypeVisitor.TypeErasure.EquivalentTypes(operandType, expectedType)) return false; var usedVariables = new HashSet(ILVariableEqualityComparer.Instance); - foreach (var item in deconstruction.Assignments.Instructions) { + foreach (var item in deconstruction.Assignments.Instructions) + { if (!item.MatchStLoc(out var v, out var value)) return false; expectedType = ((LdLoc)value).Variable.Type; @@ -877,7 +962,8 @@ namespace ICSharpCode.Decompiler.CSharp if (ILInlining.IsUsedAsThisPointerInCall(la) && !IsTargetOfSetterCall(la, la.Variable.Type)) return true; var current = la.Parent; - while (current is LdFlda next) { + while (current is LdFlda next) + { current = next.Parent; } return current is LdObj; @@ -900,13 +986,15 @@ namespace ICSharpCode.Decompiler.CSharp return false; if (targetType.IsReferenceType ?? false) return false; - switch (inst.Parent.OpCode) { + switch (inst.Parent.OpCode) + { case OpCode.Call: case OpCode.CallVirt: var targetMethod = ((CallInstruction)inst.Parent).Method; if (!targetMethod.IsAccessor || targetMethod.IsStatic) return false; - switch (targetMethod.AccessorOwner) { + switch (targetMethod.AccessorOwner) + { case IProperty p: return targetMethod.AccessorKind == System.Reflection.MethodSemanticsAttributes.Setter; default: @@ -929,23 +1017,34 @@ namespace ICSharpCode.Decompiler.CSharp var fixedStmt = new FixedStatement(); fixedStmt.Type = exprBuilder.ConvertType(inst.Variable.Type); Expression initExpr; - if (inst.Init is GetPinnableReference gpr) { - if (gpr.Method != null) { + if (inst.Init is GetPinnableReference gpr) + { + if (gpr.Method != null) + { IType expectedType = gpr.Method.IsStatic ? gpr.Method.Parameters[0].Type : gpr.Method.DeclaringType; initExpr = exprBuilder.Translate(gpr.Argument, typeHint: expectedType).ConvertTo(expectedType, exprBuilder); - } else { + } + else + { initExpr = exprBuilder.Translate(gpr.Argument); } - } else { + } + else + { IType refType = inst.Variable.Type; - if (refType is PointerType pointerType) { + if (refType is PointerType pointerType) + { refType = new ByReferenceType(pointerType.ElementType); } initExpr = exprBuilder.Translate(inst.Init, typeHint: refType).ConvertTo(refType, exprBuilder); - if (initExpr is DirectionExpression dirExpr) { - if (dirExpr.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.Dereference) { + if (initExpr is DirectionExpression dirExpr) + { + if (dirExpr.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.Dereference) + { initExpr = uoe.Expression.Detach(); - } else { + } + else + { initExpr = new UnaryOperatorExpression(UnaryOperatorType.AddressOf, dirExpr.Expression.Detach()) .WithRR(new ResolveResult(inst.Variable.Type)); } @@ -962,7 +1061,8 @@ namespace ICSharpCode.Decompiler.CSharp return Default(block); // Block without container BlockStatement blockStatement = new BlockStatement(); - foreach (var inst in block.Instructions) { + foreach (var inst in block.Instructions) + { blockStatement.Add(Convert(inst)); } if (block.FinalInstruction.OpCode != OpCode.Nop) @@ -972,7 +1072,8 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedStatement VisitBlockContainer(BlockContainer container) { - if (container.Kind != ContainerKind.Normal && container.EntryPoint.IncomingEdgeCount > 1) { + if (container.Kind != ContainerKind.Normal && container.EntryPoint.IncomingEdgeCount > 1) + { var oldContinueTarget = continueTarget; var oldContinueCount = continueCount; var oldBreakTarget = breakTarget; @@ -982,9 +1083,13 @@ namespace ICSharpCode.Decompiler.CSharp continueCount = oldContinueCount; breakTarget = oldBreakTarget; return loop.WithILInstruction(container); - } else if (container.EntryPoint.Instructions.Count == 1 && container.EntryPoint.Instructions[0] is SwitchInstruction switchInst) { + } + else if (container.EntryPoint.Instructions.Count == 1 && container.EntryPoint.Instructions[0] is SwitchInstruction switchInst) + { return TranslateSwitch(container, switchInst).WithILInstruction(container); - } else { + } + else + { var blockStmt = ConvertBlockContainer(container, false); return blockStmt.WithILInstruction(container); } @@ -997,13 +1102,15 @@ namespace ICSharpCode.Decompiler.CSharp BlockStatement blockStatement; continueCount = 0; breakTarget = container; - switch (container.Kind) { + switch (container.Kind) + { case ContainerKind.Loop: continueTarget = container.EntryPoint; blockStatement = ConvertBlockContainer(container, true); Debug.Assert(continueCount < container.EntryPoint.IncomingEdgeCount); Debug.Assert(blockStatement.Statements.First() is LabelStatement); - if (container.EntryPoint.IncomingEdgeCount == continueCount + 1) { + if (container.EntryPoint.IncomingEdgeCount == continueCount + 1) + { // Remove the entrypoint label if all jumps to the label were replaced with 'continue;' statements blockStatement.Statements.First().Remove(); } @@ -1021,7 +1128,8 @@ namespace ICSharpCode.Decompiler.CSharp blockStatement.Add(new BreakStatement()); blockStatement = ConvertBlockContainer(blockStatement, container, container.Blocks.Skip(1).Except(new[] { loopBody }), true); Debug.Assert(continueCount < container.EntryPoint.IncomingEdgeCount); - if (continueCount + 1 < container.EntryPoint.IncomingEdgeCount) { + if (continueCount + 1 < container.EntryPoint.IncomingEdgeCount) + { // There's an incoming edge to the entry point (=while condition) that wasn't represented as "continue;" // -> emit a real label // We'll also remove any "continue;" in front of the label, as it's redundant. @@ -1039,20 +1147,23 @@ namespace ICSharpCode.Decompiler.CSharp if (!container.MatchConditionBlock(continueTarget, out condition, out _)) throw new NotSupportedException("Invalid condition block in do-while loop."); blockStatement = ConvertBlockContainer(new BlockStatement(), container, container.Blocks.SkipLast(1), true); - if (container.EntryPoint.IncomingEdgeCount == 2) { + if (container.EntryPoint.IncomingEdgeCount == 2) + { // Remove the entry-point label, if there are only two jumps to the entry-point: // from outside the loop and from the condition-block. blockStatement.Statements.First().Remove(); } if (blockStatement.LastOrDefault() is ContinueStatement continueStmt3) continueStmt3.Remove(); - if (continueTarget.IncomingEdgeCount > continueCount) { + if (continueTarget.IncomingEdgeCount > continueCount) + { // if there are branches to the condition block, that were not converted // to continue statements, we have to introduce an extra label. blockStatement.Add(new LabelStatement { Label = continueTarget.Label }); } DeclareLocalFunctions(currentFunction, container, blockStatement); - if (blockStatement.Statements.Count == 0) { + if (blockStatement.Statements.Count == 0) + { return new WhileStatement { Condition = exprBuilder.TranslateCondition(condition), EmbeddedStatement = blockStatement @@ -1078,7 +1189,8 @@ namespace ICSharpCode.Decompiler.CSharp }; if (blockStatement.LastOrDefault() is ContinueStatement continueStmt4) continueStmt4.Remove(); - for (int i = 0; i < continueTarget.Instructions.Count - 1; i++) { + for (int i = 0; i < continueTarget.Instructions.Count - 1; i++) + { forStmt.Iterators.Add(Convert(continueTarget.Instructions[i])); } if (continueTarget.IncomingEdgeCount > continueCount) @@ -1099,7 +1211,8 @@ namespace ICSharpCode.Decompiler.CSharp void DeclareLocalFunctions(ILFunction currentFunction, BlockContainer container, BlockStatement blockStatement) { - foreach (var localFunction in currentFunction.LocalFunctions.OrderBy(f => f.Name)) { + foreach (var localFunction in currentFunction.LocalFunctions.OrderBy(f => f.Name)) + { if (localFunction.DeclarationScope != container) continue; blockStatement.Add(TranslateFunction(localFunction)); @@ -1113,7 +1226,8 @@ namespace ICSharpCode.Decompiler.CSharp method.Body = nestedBuilder.ConvertAsBlock(function.Body); Comment prev = null; - foreach (string warning in function.Warnings) { + foreach (string warning in function.Warnings) + { method.Body.InsertChildAfter(prev, prev = new Comment(warning), Roles.Comment); } @@ -1128,35 +1242,46 @@ namespace ICSharpCode.Decompiler.CSharp BlockStatement ConvertBlockContainer(BlockStatement blockStatement, BlockContainer container, IEnumerable blocks, bool isLoop) { - foreach (var block in blocks) { - if (block.IncomingEdgeCount > 1 || block != container.EntryPoint) { + foreach (var block in blocks) + { + if (block.IncomingEdgeCount > 1 || block != container.EntryPoint) + { // If there are any incoming branches to this block, add a label: blockStatement.Add(new LabelStatement { Label = block.Label }); } - foreach (var inst in block.Instructions) { - if (!isLoop && inst is Leave leave && IsFinalLeave(leave)) { + foreach (var inst in block.Instructions) + { + if (!isLoop && inst is Leave leave && IsFinalLeave(leave)) + { // skip the final 'leave' instruction and just fall out of the BlockStatement blockStatement.AddAnnotation(new ImplicitReturnAnnotation(leave)); continue; } var stmt = Convert(inst); - if (stmt is BlockStatement b) { + if (stmt is BlockStatement b) + { foreach (var nested in b.Statements) blockStatement.Add(nested.Detach()); - } else { + } + else + { blockStatement.Add(stmt); } } - if (block.FinalInstruction.OpCode != OpCode.Nop) { + if (block.FinalInstruction.OpCode != OpCode.Nop) + { blockStatement.Add(Convert(block.FinalInstruction)); } } - if (endContainerLabels.TryGetValue(container, out string label)) { - if (isLoop && !(blockStatement.LastOrDefault() is ContinueStatement)) { + if (endContainerLabels.TryGetValue(container, out string label)) + { + if (isLoop && !(blockStatement.LastOrDefault() is ContinueStatement)) + { blockStatement.Add(new ContinueStatement()); } blockStatement.Add(new LabelStatement { Label = label }); - if (isLoop) { + if (isLoop) + { blockStatement.Add(new BreakStatement()); } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs b/ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs index 1d0e9e685..91a05b3e2 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs @@ -29,6 +29,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; + using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.TypeSystem; @@ -154,7 +155,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public void Freeze() { - if (!IsFrozen) { + if (!IsFrozen) + { for (AstNode child = firstChild; child != null; child = child.nextSibling) child.Freeze(); flags |= frozenBit; @@ -247,7 +249,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public IEnumerable Children { get { AstNode next; - for (AstNode cur = firstChild; cur != null; cur = next) { + for (AstNode cur = firstChild; cur != null; cur = next) + { Debug.Assert(cur.parent == this); // Remember next before yielding cur. // This allows removing/replacing nodes while iterating through the list. @@ -262,7 +265,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public IEnumerable Ancestors { get { - for (AstNode cur = parent; cur != null; cur = cur.parent) { + for (AstNode cur = parent; cur != null; cur = cur.parent) + { yield return cur; } } @@ -273,7 +277,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public IEnumerable AncestorsAndSelf { get { - for (AstNode cur = this; cur != null; cur = cur.parent) { + for (AstNode cur = this; cur != null; cur = cur.parent) + { yield return cur; } } @@ -306,7 +311,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax IEnumerable GetDescendantsImpl(bool includeSelf, Func descendIntoChildren = null) { - if (includeSelf) { + if (includeSelf) + { yield return this; if (descendIntoChildren != null && !descendIntoChildren(this)) yield break; @@ -315,7 +321,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax Stack nextStack = new Stack(); nextStack.Push(null); AstNode pos = firstChild; - while (pos != null) { + while (pos != null) + { // Remember next before yielding pos. // This allows removing/replacing nodes while iterating through the list. if (pos.nextSibling != null) @@ -337,7 +344,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (role == null) throw new ArgumentNullException(nameof(role)); uint roleIndex = role.Index; - for (var cur = firstChild; cur != null; cur = cur.nextSibling) { + for (var cur = firstChild; cur != null; cur = cur.nextSibling) + { if ((cur.flags & roleIndexMask) == roleIndex) return (T)cur; } @@ -405,9 +413,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { child.parent = this; child.SetRole(role); - if (firstChild == null) { + if (firstChild == null) + { lastChild = firstChild = child; - } else { + } + else + { lastChild.nextSibling = child; child.prevSibling = lastChild; lastChild = child; @@ -418,7 +429,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { if (role == null) throw new ArgumentNullException(nameof(role)); - if (nextSibling == null || nextSibling.IsNull) { + if (nextSibling == null || nextSibling.IsNull) + { AddChild(child, role); return; } @@ -444,10 +456,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax child.nextSibling = nextSibling; child.prevSibling = nextSibling.prevSibling; - if (nextSibling.prevSibling != null) { + if (nextSibling.prevSibling != null) + { Debug.Assert(nextSibling.prevSibling.nextSibling == nextSibling); nextSibling.prevSibling.nextSibling = child; - } else { + } + else + { Debug.Assert(firstChild == nextSibling); firstChild = child; } @@ -464,19 +479,26 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public void Remove() { - if (parent != null) { + if (parent != null) + { ThrowIfFrozen(); - if (prevSibling != null) { + if (prevSibling != null) + { Debug.Assert(prevSibling.nextSibling == this); prevSibling.nextSibling = nextSibling; - } else { + } + else + { Debug.Assert(parent.firstChild == this); parent.firstChild = nextSibling; } - if (nextSibling != null) { + if (nextSibling != null) + { Debug.Assert(nextSibling.prevSibling == this); nextSibling.prevSibling = prevSibling; - } else { + } + else + { Debug.Assert(parent.lastChild == this); parent.lastChild = prevSibling; } @@ -491,28 +513,35 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public void ReplaceWith(AstNode newNode) { - if (newNode == null || newNode.IsNull) { + if (newNode == null || newNode.IsNull) + { Remove(); return; } if (newNode == this) return; // nothing to do... - if (parent == null) { + if (parent == null) + { throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); } ThrowIfFrozen(); // Because this method doesn't statically check the new node's type with the role, // we perform a runtime test: - if (!this.Role.IsValid(newNode)) { + if (!this.Role.IsValid(newNode)) + { throw new ArgumentException(string.Format("The new node '{0}' is not valid in the role {1}", newNode.GetType().Name, this.Role.ToString()), nameof(newNode)); } - if (newNode.parent != null) { + if (newNode.parent != null) + { // newNode is used within this tree? - if (newNode.Ancestors.Contains(this)) { + if (newNode.Ancestors.Contains(this)) + { // e.g. "parenthesizedExpr.ReplaceWith(parenthesizedExpr.Expression);" // enable automatic removal newNode.Remove(); - } else { + } + else + { throw new ArgumentException("Node is already used in another tree.", nameof(newNode)); } } @@ -524,17 +553,23 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax newNode.prevSibling = prevSibling; newNode.nextSibling = nextSibling; - if (prevSibling != null) { + if (prevSibling != null) + { Debug.Assert(prevSibling.nextSibling == this); prevSibling.nextSibling = newNode; - } else { + } + else + { Debug.Assert(parent.firstChild == this); parent.firstChild = newNode; } - if (nextSibling != null) { + if (nextSibling != null) + { Debug.Assert(nextSibling.prevSibling == this); nextSibling.prevSibling = newNode; - } else { + } + else + { Debug.Assert(parent.lastChild == this); parent.lastChild = newNode; } @@ -547,7 +582,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { if (replaceFunction == null) throw new ArgumentNullException(nameof(replaceFunction)); - if (parent == null) { + if (parent == null) + { throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); } AstNode oldParent = parent; @@ -557,10 +593,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax AstNode replacement = replaceFunction(this); if (oldSuccessor != null && oldSuccessor.parent != oldParent) throw new InvalidOperationException("replace function changed nextSibling of node being replaced?"); - if (!(replacement == null || replacement.IsNull)) { + if (!(replacement == null || replacement.IsNull)) + { if (replacement.parent != null) throw new InvalidOperationException("replace function must return the root of a tree"); - if (!oldRole.IsValid(replacement)) { + if (!oldRole.IsValid(replacement)) + { throw new InvalidOperationException(string.Format("The new node '{0}' is not valid in the role {1}", replacement.GetType().Name, oldRole.ToString())); } @@ -588,7 +626,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax copy.flags &= ~frozenBit; // unfreeze the copy // Then perform a deep copy: - for (AstNode cur = firstChild; cur != null; cur = cur.nextSibling) { + for (AstNode cur = firstChild; cur != null; cur = cur.nextSibling) + { copy.AddChildUnsafe(cur.Clone(), cur.Role); } @@ -687,7 +726,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public AstNode GetCSharpNodeBefore(AstNode node) { var n = node.PrevSibling; - while (n != null) { + while (n != null) + { if (n.Role != Roles.Comment) return n; n = n.GetPrevNode(); @@ -741,15 +781,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { AstNode result = null; AstNode node = this; - while (node.LastChild != null) { + while (node.LastChild != null) + { var child = node.LastChild; while (child != null && child.StartLocation > location) child = child.prevSibling; - if (child != null && location < child.EndLocation) { + if (child != null && location < child.EndLocation) + { if (pred == null || pred(child)) result = child; node = child; - } else { + } + else + { // found no better child node - therefore the parent is the right one. break; } @@ -776,15 +820,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { T result = null; AstNode node = this; - while (node.LastChild != null) { + while (node.LastChild != null) + { var child = node.LastChild; while (child != null && child.StartLocation > location) child = child.prevSibling; - if (child != null && location < child.EndLocation) { + if (child != null && location < child.EndLocation) + { if (child is T) result = (T)child; node = child; - } else { + } + else + { // found no better child node - therefore the parent is the right one. break; } @@ -814,15 +862,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { AstNode result = null; AstNode node = this; - while (node.LastChild != null) { + while (node.LastChild != null) + { var child = node.LastChild; while (child != null && child.StartLocation > location) child = child.prevSibling; - if (child != null && location <= child.EndLocation) { + if (child != null && location <= child.EndLocation) + { if (pred == null || pred(child)) result = child; node = child; - } else { + } + else + { // found no better child node - therefore the parent is the right one. break; } @@ -849,15 +901,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { T result = null; AstNode node = this; - while (node.LastChild != null) { + while (node.LastChild != null) + { var child = node.LastChild; while (child != null && child.StartLocation > location) child = child.prevSibling; - if (child != null && location <= child.EndLocation) { + if (child != null && location <= child.EndLocation) + { if (child is T) result = (T)child; node = child; - } else { + } + else + { // found no better child node - therefore the parent is the right one. break; } @@ -872,7 +928,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public AstNode GetNodeContaining(TextLocation startLocation, TextLocation endLocation) { - for (AstNode child = firstChild; child != null; child = child.nextSibling) { + for (AstNode child = firstChild; child != null; child = child.nextSibling) + { if (child.StartLocation <= startLocation && endLocation <= child.EndLocation) return child.GetNodeContaining(startLocation, endLocation); } @@ -893,17 +950,24 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public IEnumerable GetNodesBetween(TextLocation start, TextLocation end) { AstNode node = this; - while (node != null) { + while (node != null) + { AstNode next; - if (start <= node.StartLocation && node.EndLocation <= end) { + if (start <= node.StartLocation && node.EndLocation <= end) + { // Remember next before yielding node. // This allows iteration to continue when the caller removes/replaces the node. next = node.GetNextNode(); yield return node; - } else { - if (node.EndLocation <= start) { + } + else + { + if (node.EndLocation <= start) + { next = node.GetNextNode(); - } else { + } + else + { next = node.FirstChild; } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs b/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs index 1a72042ee..e61079c71 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs @@ -21,6 +21,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -33,7 +34,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { readonly AstNode node; readonly Role role; - + public AstNodeCollection(AstNode node, Role role) { if (node == null) @@ -43,43 +44,46 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.node = node; this.role = role; } - + public int Count { get { int count = 0; uint roleIndex = role.Index; - for (AstNode cur = node.FirstChild; cur != null; cur = cur.NextSibling) { + for (AstNode cur = node.FirstChild; cur != null; cur = cur.NextSibling) + { if (cur.RoleIndex == roleIndex) count++; } return count; } } - + public void Add(T element) { node.AddChild(element, role); } - + public void AddRange(IEnumerable nodes) { // Evaluate 'nodes' first, since it might change when we add the new children // Example: collection.AddRange(collection); - if (nodes != null) { + if (nodes != null) + { foreach (T node in nodes.ToList()) Add(node); } } - + public void AddRange(T[] nodes) { // Fast overload for arrays - we don't need to create a copy - if (nodes != null) { + if (nodes != null) + { foreach (T node in nodes) Add(node); } } - + public void ReplaceWith(IEnumerable nodes) { // Evaluate 'nodes' first, since it might change when we call Clear() @@ -87,43 +91,48 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (nodes != null) nodes = nodes.ToList(); Clear(); - if (nodes != null) { + if (nodes != null) + { foreach (T node in nodes) Add(node); } } - + public void MoveTo(ICollection targetCollection) { if (targetCollection == null) throw new ArgumentNullException(nameof(targetCollection)); - foreach (T node in this) { + foreach (T node in this) + { node.Remove(); targetCollection.Add(node); } } - + public bool Contains(T element) { return element != null && element.Parent == node && element.RoleIndex == role.Index; } - + public bool Remove(T element) { - if (Contains(element)) { + if (Contains(element)) + { element.Remove(); return true; - } else { + } + else + { return false; } } - + public void CopyTo(T[] array, int arrayIndex) { foreach (T item in this) array[arrayIndex++] = item; } - + public void Clear() { foreach (T item in this) @@ -135,7 +144,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax foreach (T item in this) yield return item.Detach(); } - + /// /// Returns the first element for which the predicate returns true, /// or the null node (AstNode with IsNull=true) if no such object is found. @@ -147,7 +156,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return item; return role.NullObject; } - + /// /// Returns the last element for which the predicate returns true, /// or the null node (AstNode with IsNull=true) if no such object is found. @@ -160,16 +169,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax result = item; return result; } - + bool ICollection.IsReadOnly { get { return false; } } - + public IEnumerator GetEnumerator() { uint roleIndex = role.Index; AstNode next; - for (AstNode cur = node.FirstChild; cur != null; cur = next) { + for (AstNode cur = node.FirstChild; cur != null; cur = next) + { Debug.Assert(cur.Parent == node); // Remember next before yielding cur. // This allows removing/replacing nodes while iterating through the list. @@ -178,18 +188,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax yield return (T)cur; } } - + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } - + #region Equals and GetHashCode implementation public override int GetHashCode() { return node.GetHashCode() ^ role.GetHashCode(); } - + public override bool Equals(object obj) { AstNodeCollection other = obj as AstNodeCollection; @@ -198,22 +208,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return this.node == other.node && this.role == other.role; } #endregion - + internal bool DoMatch(AstNodeCollection other, Match match) { return Pattern.DoMatchCollection(role, node.FirstChild, other.node.FirstChild, match); } - + public void InsertAfter(T existingItem, T newItem) { node.InsertChildAfter(existingItem, newItem, role); } - + public void InsertBefore(T existingItem, T newItem) { node.InsertChildBefore(existingItem, newItem, role); } - + /// /// Applies the to all nodes in this collection. /// @@ -221,7 +231,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { uint roleIndex = role.Index; AstNode next; - for (AstNode cur = node.FirstChild; cur != null; cur = next) { + for (AstNode cur = node.FirstChild; cur != null; cur = next) + { Debug.Assert(cur.Parent == node); // Remember next before yielding cur. // This allows removing/replacing nodes while iterating through the list. diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/AstType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/AstType.cs index 66dd7d4d2..a8b8da53a 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/AstType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/AstType.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.TypeSystem; @@ -30,8 +31,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public abstract class AstType : AstNode { #region Null - public new static readonly AstType Null = new NullAstType (); - + public new static readonly AstType Null = new NullAstType(); + sealed class NullAstType : AstType { public override bool IsNull { @@ -39,94 +40,94 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } - + public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider) { return SpecialType.UnknownType; } } #endregion - + #region PatternPlaceholder public static implicit operator AstType(PatternMatching.Pattern pattern) { return pattern != null ? new PatternPlaceholder(pattern) : null; } - + sealed class PatternPlaceholder : AstType, INode { readonly PatternMatching.Pattern child; - + public PatternPlaceholder(PatternMatching.Pattern child) { this.child = child; } - + public override NodeType NodeType { get { return NodeType.Pattern; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitPatternPlaceholder (this, child); + visitor.VisitPatternPlaceholder(this, child); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitPatternPlaceholder (this, child); + return visitor.VisitPatternPlaceholder(this, child); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitPatternPlaceholder (this, child, data); + return visitor.VisitPatternPlaceholder(this, child, data); } - + public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider) { throw new NotSupportedException(); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return child.DoMatch(other, match); } - + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) { return child.DoMatchCollection(role, pos, match, backtrackingInfo); } } #endregion - + public override NodeType NodeType { get { return NodeType.TypeReference; } } - + public new AstType Clone() { return (AstType)base.Clone(); } - + /// /// Gets whether this type is a SimpleType "var". /// @@ -135,7 +136,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax SimpleType st = this as SimpleType; return st != null && st.Identifier == "var" && st.TypeArguments.Count == 0; } - + /// /// Create an ITypeReference for this AstType. /// Uses the context (ancestors of this node) to determine the correct . @@ -151,7 +152,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return ToTypeReference(GetNameLookupMode(), interningProvider); } - + /// /// Create an ITypeReference for this AstType. /// @@ -163,7 +164,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// (on CSharpTypeResolveContext only) is used. /// public abstract ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null); - + /// /// Gets the name lookup mode from the context (looking at the ancestors of this ). /// @@ -172,10 +173,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax AstType outermostType = this; while (outermostType.Parent is AstType) outermostType = (AstType)outermostType.Parent; - - if (outermostType.Parent is UsingDeclaration || outermostType.Parent is UsingAliasDeclaration) { + + if (outermostType.Parent is UsingDeclaration || outermostType.Parent is UsingAliasDeclaration) + { return NameLookupMode.TypeInUsingDeclaration; - } else if (outermostType.Role == Roles.BaseType) { + } + else if (outermostType.Role == Roles.BaseType) + { // Use BaseTypeReference for a type's base type, and for a constraint on a type. // Do not use it for a constraint on a method. if (outermostType.Parent is TypeDeclaration || (outermostType.Parent is Constraint && outermostType.Parent.Parent is TypeDeclaration)) @@ -183,7 +187,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } return NameLookupMode.Type; } - + /// /// Creates a pointer type from this type by nesting it in a . /// If this type already is a pointer type, this method just increases the PointerRank of the existing pointer type. @@ -192,7 +196,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return new ComposedType { BaseType = this }.MakePointerType(); } - + /// /// Creates an array type from this type by nesting it in a . /// If this type already is an array type, the additional rank is prepended to the existing array specifier list. @@ -202,7 +206,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return new ComposedType { BaseType = this }.MakeArrayType(rank); } - + /// /// Creates a nullable type from this type by nesting it in a . /// @@ -218,7 +222,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return new ComposedType { BaseType = this, HasRefSpecifier = true }; } - + /// /// Builds an expression that can be used to access a static member on this type. /// @@ -228,7 +232,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax memberType.TypeArguments.AddRange(typeArguments); return memberType; } - + /// /// Builds an expression that can be used to access a static member on this type. /// @@ -238,7 +242,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax memberType.TypeArguments.AddRange(typeArguments); return memberType; } - + /// /// Creates a simple AstType from a dotted name. /// Does not support generics, arrays, etc. - just simple dotted names, @@ -248,7 +252,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { string[] parts = dottedName.Split('.'); AstType type = new SimpleType(parts[0]); - for (int i = 1; i < parts.Length; i++) { + for (int i = 1; i < parts.Length; i++) + { type = new MemberType(type, parts[i]); } return type; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/CSharpModifierToken.cs b/ICSharpCode.Decompiler/CSharp/Syntax/CSharpModifierToken.cs index 00c4482b1..b81a7d76b 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/CSharpModifierToken.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/CSharpModifierToken.cs @@ -26,6 +26,7 @@ using System; using System.Collections.Immutable; + using ICSharpCode.Decompiler.CSharp.OutputVisitor; namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -33,32 +34,32 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class CSharpModifierToken : CSharpTokenNode { Modifiers modifier; - + public Modifiers Modifier { get { return modifier; } - set { + set { ThrowIfFrozen(); - this.modifier = value; + this.modifier = value; } } public override TextLocation EndLocation { get { - return new TextLocation (StartLocation.Line, StartLocation.Column + GetModifierLength (Modifier)); + return new TextLocation(StartLocation.Line, StartLocation.Column + GetModifierLength(Modifier)); } } public override string ToString(CSharpFormattingOptions formattingOptions) { - return GetModifierName (Modifier); + return GetModifierName(Modifier); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { CSharpModifierToken o = other as CSharpModifierToken; return o != null && this.modifier == o.modifier; } - + // Not worth using a dictionary for such few elements. // This table is sorted in the order that modifiers should be output when generating code. public static ImmutableArray AllModifiers { get; } = ImmutableArray.Create( @@ -72,15 +73,16 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax Modifiers.Async, Modifiers.Any ); - - public CSharpModifierToken (TextLocation location, Modifiers modifier) : base (location, null) + + public CSharpModifierToken(TextLocation location, Modifiers modifier) : base(location, null) { this.Modifier = modifier; } - + public static string GetModifierName(Modifiers modifier) { - switch (modifier) { + switch (modifier) + { case Modifiers.Private: return "private"; case Modifiers.Internal: @@ -127,7 +129,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public static int GetModifierLength(Modifiers modifier) { - switch (modifier) { + switch (modifier) + { case Modifiers.Private: return "private".Length; case Modifiers.Internal: @@ -171,10 +174,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax throw new NotSupportedException("Invalid value for Modifiers"); } } - + public static Modifiers GetModifierValue(string modifier) { - switch (modifier) { + switch (modifier) + { case "private": return Modifiers.Private; case "internal": diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/CSharpTokenNode.cs b/ICSharpCode.Decompiler/CSharp/Syntax/CSharpTokenNode.cs index 5e18c5d3f..5cd2a5d02 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/CSharpTokenNode.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/CSharpTokenNode.cs @@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class CSharpTokenNode : AstNode { - public static new readonly CSharpTokenNode Null = new NullCSharpTokenNode (); + public static new readonly CSharpTokenNode Null = new NullCSharpTokenNode(); class NullCSharpTokenNode : CSharpTokenNode { public override bool IsNull { @@ -44,38 +44,38 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public NullCSharpTokenNode () : base (TextLocation.Empty, null) + + public NullCSharpTokenNode() : base(TextLocation.Empty, null) { } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } } - + public override NodeType NodeType { get { return NodeType.Token; } } - + TextLocation startLocation; public override TextLocation StartLocation { get { @@ -85,17 +85,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax int TokenLength { get { - return TokenRole.TokenLengths [(int)(this.flags >> AstNodeFlagsUsedBits)]; + return TokenRole.TokenLengths[(int)(this.flags >> AstNodeFlagsUsedBits)]; } } - + public override TextLocation EndLocation { get { - return new TextLocation (StartLocation.Line, StartLocation.Column + TokenLength); + return new TextLocation(StartLocation.Line, StartLocation.Column + TokenLength); } } - public CSharpTokenNode (TextLocation location, TokenRole role) + public CSharpTokenNode(TextLocation location, TokenRole role) { this.startLocation = location; if (role != null) @@ -104,24 +104,24 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public override string ToString(CSharpFormattingOptions formattingOptions) { - return TokenRole.Tokens [(int)(this.flags >> AstNodeFlagsUsedBits)]; + return TokenRole.Tokens[(int)(this.flags >> AstNodeFlagsUsedBits)]; } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitCSharpTokenNode (this); + visitor.VisitCSharpTokenNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitCSharpTokenNode (this); + return visitor.VisitCSharpTokenNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitCSharpTokenNode (this, data); + return visitor.VisitCSharpTokenNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { CSharpTokenNode o = other as CSharpTokenNode; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/CSharpUtil.cs b/ICSharpCode.Decompiler/CSharp/Syntax/CSharpUtil.cs index 0cb4555cd..07b5402ae 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/CSharpUtil.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/CSharpUtil.cs @@ -39,33 +39,42 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return InvertConditionInternal(condition); } - + static Expression InvertConditionInternal(Expression condition) { - if (condition is ParenthesizedExpression) { + if (condition is ParenthesizedExpression) + { return new ParenthesizedExpression(InvertCondition(((ParenthesizedExpression)condition).Expression)); } - - if (condition is UnaryOperatorExpression) { + + if (condition is UnaryOperatorExpression) + { var uOp = (UnaryOperatorExpression)condition; - if (uOp.Operator == UnaryOperatorType.Not) { + if (uOp.Operator == UnaryOperatorType.Not) + { if (!(uOp.Parent is Expression)) return GetInnerMostExpression(uOp.Expression).Clone(); return uOp.Expression.Clone(); } return new UnaryOperatorExpression(UnaryOperatorType.Not, uOp.Clone()); } - - if (condition is BinaryOperatorExpression) { + + if (condition is BinaryOperatorExpression) + { var bOp = (BinaryOperatorExpression)condition; - if ((bOp.Operator == BinaryOperatorType.ConditionalAnd) || (bOp.Operator == BinaryOperatorType.ConditionalOr)) { + if ((bOp.Operator == BinaryOperatorType.ConditionalAnd) || (bOp.Operator == BinaryOperatorType.ConditionalOr)) + { return new BinaryOperatorExpression(InvertCondition(bOp.Left), NegateConditionOperator(bOp.Operator), InvertCondition(bOp.Right)); - } else if ((bOp.Operator == BinaryOperatorType.Equality) || (bOp.Operator == BinaryOperatorType.InEquality) || (bOp.Operator == BinaryOperatorType.GreaterThan) - || (bOp.Operator == BinaryOperatorType.GreaterThanOrEqual) || (bOp.Operator == BinaryOperatorType.LessThan) || - (bOp.Operator == BinaryOperatorType.LessThanOrEqual)) { + } + else if ((bOp.Operator == BinaryOperatorType.Equality) || (bOp.Operator == BinaryOperatorType.InEquality) || (bOp.Operator == BinaryOperatorType.GreaterThan) + || (bOp.Operator == BinaryOperatorType.GreaterThanOrEqual) || (bOp.Operator == BinaryOperatorType.LessThan) || + (bOp.Operator == BinaryOperatorType.LessThanOrEqual)) + { return new BinaryOperatorExpression(bOp.Left.Clone(), NegateRelationalOperator(bOp.Operator), bOp.Right.Clone()); - } else { + } + else + { var negatedOp = NegateRelationalOperator(bOp.Operator); if (negatedOp == BinaryOperatorType.Any) return new UnaryOperatorExpression(UnaryOperatorType.Not, new ParenthesizedExpression(condition.Clone())); @@ -74,18 +83,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return bOp; } } - if (condition is ConditionalExpression) { + if (condition is ConditionalExpression) + { var cEx = condition.Clone() as ConditionalExpression; cEx.Condition = InvertCondition(cEx.Condition); return cEx; } - if (condition is PrimitiveExpression) { + if (condition is PrimitiveExpression) + { var pex = condition as PrimitiveExpression; - if (pex.Value is bool) { - return new PrimitiveExpression(!((bool)pex.Value)); + if (pex.Value is bool) + { + return new PrimitiveExpression(!((bool)pex.Value)); } } - + return new UnaryOperatorExpression(UnaryOperatorType.Not, AddParensForUnaryExpressionIfRequired(condition.Clone())); } @@ -96,12 +108,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax internal static Expression AddParensForUnaryExpressionIfRequired(Expression expression) { if ((expression is BinaryOperatorExpression) || - (expression is AssignmentExpression) || - (expression is CastExpression) || - (expression is AsExpression) || - (expression is IsExpression) || - (expression is LambdaExpression) || - (expression is ConditionalExpression)) { + (expression is AssignmentExpression) || + (expression is CastExpression) || + (expression is AsExpression) || + (expression is IsExpression) || + (expression is LambdaExpression) || + (expression is ConditionalExpression)) + { return new ParenthesizedExpression(expression); } @@ -116,7 +129,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public static BinaryOperatorType NegateRelationalOperator(BinaryOperatorType op) { - switch (op) { + switch (op) + { case BinaryOperatorType.GreaterThan: return BinaryOperatorType.LessThanOrEqual; case BinaryOperatorType.GreaterThanOrEqual: @@ -153,7 +167,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public static BinaryOperatorType NegateConditionOperator(BinaryOperatorType op) { - switch (op) { + switch (op) + { case BinaryOperatorType.ConditionalOr: return BinaryOperatorType.ConditionalAnd; case BinaryOperatorType.ConditionalAnd: diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs index 79363dc99..05532d89e 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs @@ -27,6 +27,7 @@ using System; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.TypeSystem; @@ -77,7 +78,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } } - + public bool HasNullableSpecifier { get { return !GetChildByRole(NullableRole).IsNull; @@ -98,7 +99,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return GetChildByRole(NullableRole); } } - + public int PointerRank { get { return GetChildrenByRole(PointerRole).Count; @@ -107,40 +108,42 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (value < 0) throw new ArgumentOutOfRangeException(); int d = this.PointerRank; - while (d > value) { + while (d > value) + { GetChildByRole(PointerRole).Remove(); d--; } - while (d < value) { + while (d < value) + { InsertChildBefore(GetChildByRole(PointerRole), new CSharpTokenNode(TextLocation.Empty, PointerRole), PointerRole); d++; } } } - + public AstNodeCollection ArraySpecifiers { - get { return GetChildrenByRole (ArraySpecifierRole); } + get { return GetChildrenByRole(ArraySpecifierRole); } } public AstNodeCollection PointerTokens { - get { return GetChildrenByRole (PointerRole); } + get { return GetChildrenByRole(PointerRole); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitComposedType (this); + visitor.VisitComposedType(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitComposedType (this); + return visitor.VisitComposedType(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitComposedType (this, data); + return visitor.VisitComposedType(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ComposedType o = other as ComposedType; @@ -164,24 +167,28 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (this.HasNullableSpecifier) b.Append('?'); b.Append('*', this.PointerRank); - foreach (var arraySpecifier in this.ArraySpecifiers) { + foreach (var arraySpecifier in this.ArraySpecifiers) + { b.Append('['); b.Append(',', arraySpecifier.Dimensions - 1); b.Append(']'); } return b.ToString(); } - + public override AstType MakePointerType() { - if (ArraySpecifiers.Any()) { + if (ArraySpecifiers.Any()) + { return base.MakePointerType(); - } else { + } + else + { this.PointerRank++; return this; } } - + public override AstType MakeArrayType(int dimensions) { InsertChildBefore(this.ArraySpecifiers.FirstOrDefault(), new ArraySpecifier(dimensions), ArraySpecifierRole); @@ -199,23 +206,27 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (interningProvider == null) interningProvider = InterningProvider.Dummy; ITypeReference t = this.BaseType.ToTypeReference(lookupMode, interningProvider); - if (this.HasNullableSpecifier) { + if (this.HasNullableSpecifier) + { t = interningProvider.Intern(NullableType.Create(t)); } int pointerRank = this.PointerRank; - for (int i = 0; i < pointerRank; i++) { + for (int i = 0; i < pointerRank; i++) + { t = interningProvider.Intern(new PointerTypeReference(t)); } - foreach (var a in this.ArraySpecifiers.Reverse()) { + foreach (var a in this.ArraySpecifiers.Reverse()) + { t = interningProvider.Intern(new ArrayTypeReference(t, a.Dimensions)); } - if (this.HasRefSpecifier) { + if (this.HasRefSpecifier) + { t = interningProvider.Intern(new ByReferenceTypeReference(t)); } return t; } } - + /// /// [,,,] /// @@ -226,54 +237,56 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return NodeType.Unknown; } } - + public ArraySpecifier() { } - + public ArraySpecifier(int dimensions) { this.Dimensions = dimensions; } - + public CSharpTokenNode LBracketToken { - get { return GetChildByRole (Roles.LBracket); } + get { return GetChildByRole(Roles.LBracket); } } - + public int Dimensions { get { return 1 + GetChildrenByRole(Roles.Comma).Count; } set { int d = this.Dimensions; - while (d > value) { + while (d > value) + { GetChildByRole(Roles.Comma).Remove(); d--; } - while (d < value) { + while (d < value) + { InsertChildBefore(GetChildByRole(Roles.Comma), new CSharpTokenNode(TextLocation.Empty, Roles.Comma), Roles.Comma); d++; } } } - + public CSharpTokenNode RBracketToken { - get { return GetChildByRole (Roles.RBracket); } + get { return GetChildByRole(Roles.RBracket); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitArraySpecifier (this); + visitor.VisitArraySpecifier(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitArraySpecifier (this); + return visitor.VisitArraySpecifier(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitArraySpecifier(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ArraySpecifier o = other as ArraySpecifier; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs b/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs index 610fabbe3..75909133d 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs @@ -32,17 +32,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public abstract class DepthFirstAstVisitor : IAstVisitor { - protected virtual void VisitChildren (AstNode node) + protected virtual void VisitChildren(AstNode node) { AstNode next; - for (var child = node.FirstChild; child != null; child = next) { + for (var child = node.FirstChild; child != null; child = next) + { // Store next to allow the loop to continue // if the visitor removes/replaces child. next = child.NextSibling; - child.AcceptVisitor (this); + child.AcceptVisitor(this); } } - + public virtual void VisitNullNode(AstNode nullNode) { // Should we call VisitChildren here? @@ -50,55 +51,55 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax // Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes; // so changing this might break VisitChildren() overrides that expect the node to be part of the AST. } - - public virtual void VisitSyntaxTree (SyntaxTree syntaxTree) + + public virtual void VisitSyntaxTree(SyntaxTree syntaxTree) { - VisitChildren (syntaxTree); + VisitChildren(syntaxTree); } - + public virtual void VisitComment(Comment comment) { VisitChildren(comment); } - public virtual void VisitDocumentationReference (DocumentationReference documentationReference) + public virtual void VisitDocumentationReference(DocumentationReference documentationReference) { - VisitChildren (documentationReference); + VisitChildren(documentationReference); } - - public virtual void VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective) + + public virtual void VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective) { - VisitChildren (preProcessorDirective); + VisitChildren(preProcessorDirective); } - public virtual void VisitIdentifier (Identifier identifier) + public virtual void VisitIdentifier(Identifier identifier) { - VisitChildren (identifier); + VisitChildren(identifier); } - - public virtual void VisitCSharpTokenNode (CSharpTokenNode token) + + public virtual void VisitCSharpTokenNode(CSharpTokenNode token) { - VisitChildren (token); + VisitChildren(token); } - - public virtual void VisitPrimitiveType (PrimitiveType primitiveType) + + public virtual void VisitPrimitiveType(PrimitiveType primitiveType) { - VisitChildren (primitiveType); + VisitChildren(primitiveType); } - - public virtual void VisitComposedType (ComposedType composedType) + + public virtual void VisitComposedType(ComposedType composedType) { - VisitChildren (composedType); + VisitChildren(composedType); } - + public virtual void VisitSimpleType(SimpleType simpleType) { - VisitChildren (simpleType); + VisitChildren(simpleType); } - + public virtual void VisitMemberType(MemberType memberType) { - VisitChildren (memberType); + VisitChildren(memberType); } public virtual void VisitTupleType(TupleAstType tupleType) @@ -108,7 +109,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public virtual void VisitTupleTypeElement(TupleTypeElement tupleTypeElement) { - VisitChildren (tupleTypeElement); + VisitChildren(tupleTypeElement); } public virtual void VisitFunctionPointerType(FunctionPointerType functionPointerType) @@ -116,234 +117,234 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax VisitChildren(functionPointerType); } - public virtual void VisitAttribute (Attribute attribute) + public virtual void VisitAttribute(Attribute attribute) { - VisitChildren (attribute); + VisitChildren(attribute); } - - public virtual void VisitAttributeSection (AttributeSection attributeSection) + + public virtual void VisitAttributeSection(AttributeSection attributeSection) { - VisitChildren (attributeSection); + VisitChildren(attributeSection); } - - public virtual void VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration) + + public virtual void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration) { - VisitChildren (delegateDeclaration); + VisitChildren(delegateDeclaration); } - - public virtual void VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration) + + public virtual void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) { - VisitChildren (namespaceDeclaration); + VisitChildren(namespaceDeclaration); } - - public virtual void VisitTypeDeclaration (TypeDeclaration typeDeclaration) + + public virtual void VisitTypeDeclaration(TypeDeclaration typeDeclaration) { - VisitChildren (typeDeclaration); + VisitChildren(typeDeclaration); } - - public virtual void VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration) + + public virtual void VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration) { - VisitChildren (typeParameterDeclaration); + VisitChildren(typeParameterDeclaration); } - - public virtual void VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration) + + public virtual void VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration) { - VisitChildren (enumMemberDeclaration); + VisitChildren(enumMemberDeclaration); } - - public virtual void VisitUsingDeclaration (UsingDeclaration usingDeclaration) + + public virtual void VisitUsingDeclaration(UsingDeclaration usingDeclaration) { - VisitChildren (usingDeclaration); + VisitChildren(usingDeclaration); } - - public virtual void VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration) + + public virtual void VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration) { - VisitChildren (usingDeclaration); + VisitChildren(usingDeclaration); } - + public virtual void VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration) { - VisitChildren (externAliasDeclaration); + VisitChildren(externAliasDeclaration); } - - public virtual void VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration) + + public virtual void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) { - VisitChildren (constructorDeclaration); + VisitChildren(constructorDeclaration); } - - public virtual void VisitConstructorInitializer (ConstructorInitializer constructorInitializer) + + public virtual void VisitConstructorInitializer(ConstructorInitializer constructorInitializer) { - VisitChildren (constructorInitializer); + VisitChildren(constructorInitializer); } - - public virtual void VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration) + + public virtual void VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration) { - VisitChildren (destructorDeclaration); + VisitChildren(destructorDeclaration); } - - public virtual void VisitEventDeclaration (EventDeclaration eventDeclaration) + + public virtual void VisitEventDeclaration(EventDeclaration eventDeclaration) { - VisitChildren (eventDeclaration); + VisitChildren(eventDeclaration); } - - public virtual void VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration) + + public virtual void VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration) { - VisitChildren (eventDeclaration); + VisitChildren(eventDeclaration); } - - public virtual void VisitFieldDeclaration (FieldDeclaration fieldDeclaration) + + public virtual void VisitFieldDeclaration(FieldDeclaration fieldDeclaration) { - VisitChildren (fieldDeclaration); + VisitChildren(fieldDeclaration); } - - public virtual void VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration) + + public virtual void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration) { - VisitChildren (fixedFieldDeclaration); + VisitChildren(fixedFieldDeclaration); } - - public virtual void VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer) + + public virtual void VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer) { - VisitChildren (fixedVariableInitializer); + VisitChildren(fixedVariableInitializer); } - - public virtual void VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration) + + public virtual void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration) { - VisitChildren (indexerDeclaration); + VisitChildren(indexerDeclaration); } - - public virtual void VisitMethodDeclaration (MethodDeclaration methodDeclaration) + + public virtual void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { - VisitChildren (methodDeclaration); + VisitChildren(methodDeclaration); } - - public virtual void VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration) + + public virtual void VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration) { - VisitChildren (operatorDeclaration); + VisitChildren(operatorDeclaration); } - - public virtual void VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration) + + public virtual void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) { - VisitChildren (propertyDeclaration); + VisitChildren(propertyDeclaration); } - - public virtual void VisitAccessor (Accessor accessor) + + public virtual void VisitAccessor(Accessor accessor) { - VisitChildren (accessor); + VisitChildren(accessor); } - - public virtual void VisitVariableInitializer (VariableInitializer variableInitializer) + + public virtual void VisitVariableInitializer(VariableInitializer variableInitializer) { - VisitChildren (variableInitializer); + VisitChildren(variableInitializer); } - - public virtual void VisitParameterDeclaration (ParameterDeclaration parameterDeclaration) + + public virtual void VisitParameterDeclaration(ParameterDeclaration parameterDeclaration) { - VisitChildren (parameterDeclaration); + VisitChildren(parameterDeclaration); } - - public virtual void VisitConstraint (Constraint constraint) + + public virtual void VisitConstraint(Constraint constraint) { - VisitChildren (constraint); + VisitChildren(constraint); } - - public virtual void VisitBlockStatement (BlockStatement blockStatement) + + public virtual void VisitBlockStatement(BlockStatement blockStatement) { - VisitChildren (blockStatement); + VisitChildren(blockStatement); } - - public virtual void VisitExpressionStatement (ExpressionStatement expressionStatement) + + public virtual void VisitExpressionStatement(ExpressionStatement expressionStatement) { - VisitChildren (expressionStatement); + VisitChildren(expressionStatement); } - - public virtual void VisitBreakStatement (BreakStatement breakStatement) + + public virtual void VisitBreakStatement(BreakStatement breakStatement) { - VisitChildren (breakStatement); + VisitChildren(breakStatement); } - - public virtual void VisitCheckedStatement (CheckedStatement checkedStatement) + + public virtual void VisitCheckedStatement(CheckedStatement checkedStatement) { - VisitChildren (checkedStatement); + VisitChildren(checkedStatement); } - - public virtual void VisitContinueStatement (ContinueStatement continueStatement) + + public virtual void VisitContinueStatement(ContinueStatement continueStatement) { - VisitChildren (continueStatement); + VisitChildren(continueStatement); } - - public virtual void VisitDoWhileStatement (DoWhileStatement doWhileStatement) + + public virtual void VisitDoWhileStatement(DoWhileStatement doWhileStatement) { - VisitChildren (doWhileStatement); + VisitChildren(doWhileStatement); } - - public virtual void VisitEmptyStatement (EmptyStatement emptyStatement) + + public virtual void VisitEmptyStatement(EmptyStatement emptyStatement) { - VisitChildren (emptyStatement); + VisitChildren(emptyStatement); } - - public virtual void VisitFixedStatement (FixedStatement fixedStatement) + + public virtual void VisitFixedStatement(FixedStatement fixedStatement) { - VisitChildren (fixedStatement); + VisitChildren(fixedStatement); } - - public virtual void VisitForeachStatement (ForeachStatement foreachStatement) + + public virtual void VisitForeachStatement(ForeachStatement foreachStatement) { - VisitChildren (foreachStatement); + VisitChildren(foreachStatement); } - - public virtual void VisitForStatement (ForStatement forStatement) + + public virtual void VisitForStatement(ForStatement forStatement) { - VisitChildren (forStatement); + VisitChildren(forStatement); } - - public virtual void VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement) + + public virtual void VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement) { - VisitChildren (gotoCaseStatement); + VisitChildren(gotoCaseStatement); } - - public virtual void VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement) + + public virtual void VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement) { - VisitChildren (gotoDefaultStatement); + VisitChildren(gotoDefaultStatement); } - - public virtual void VisitGotoStatement (GotoStatement gotoStatement) + + public virtual void VisitGotoStatement(GotoStatement gotoStatement) { - VisitChildren (gotoStatement); + VisitChildren(gotoStatement); } - - public virtual void VisitIfElseStatement (IfElseStatement ifElseStatement) + + public virtual void VisitIfElseStatement(IfElseStatement ifElseStatement) { - VisitChildren (ifElseStatement); + VisitChildren(ifElseStatement); } - - public virtual void VisitLabelStatement (LabelStatement labelStatement) + + public virtual void VisitLabelStatement(LabelStatement labelStatement) { - VisitChildren (labelStatement); + VisitChildren(labelStatement); } - - public virtual void VisitLockStatement (LockStatement lockStatement) + + public virtual void VisitLockStatement(LockStatement lockStatement) { - VisitChildren (lockStatement); + VisitChildren(lockStatement); } - - public virtual void VisitReturnStatement (ReturnStatement returnStatement) + + public virtual void VisitReturnStatement(ReturnStatement returnStatement) { - VisitChildren (returnStatement); + VisitChildren(returnStatement); } - - public virtual void VisitSwitchStatement (SwitchStatement switchStatement) + + public virtual void VisitSwitchStatement(SwitchStatement switchStatement) { - VisitChildren (switchStatement); + VisitChildren(switchStatement); } - - public virtual void VisitSwitchSection (SwitchSection switchSection) + + public virtual void VisitSwitchSection(SwitchSection switchSection) { - VisitChildren (switchSection); + VisitChildren(switchSection); } - - public virtual void VisitCaseLabel (CaseLabel caseLabel) + + public virtual void VisitCaseLabel(CaseLabel caseLabel) { - VisitChildren (caseLabel); + VisitChildren(caseLabel); } public virtual void VisitSwitchExpression(SwitchExpression switchExpression) @@ -356,39 +357,39 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax VisitChildren(switchExpressionSection); } - public virtual void VisitThrowStatement (ThrowStatement throwStatement) + public virtual void VisitThrowStatement(ThrowStatement throwStatement) { - VisitChildren (throwStatement); + VisitChildren(throwStatement); } - - public virtual void VisitTryCatchStatement (TryCatchStatement tryCatchStatement) + + public virtual void VisitTryCatchStatement(TryCatchStatement tryCatchStatement) { - VisitChildren (tryCatchStatement); + VisitChildren(tryCatchStatement); } - - public virtual void VisitCatchClause (CatchClause catchClause) + + public virtual void VisitCatchClause(CatchClause catchClause) { - VisitChildren (catchClause); + VisitChildren(catchClause); } - - public virtual void VisitUncheckedStatement (UncheckedStatement uncheckedStatement) + + public virtual void VisitUncheckedStatement(UncheckedStatement uncheckedStatement) { - VisitChildren (uncheckedStatement); + VisitChildren(uncheckedStatement); } - - public virtual void VisitUnsafeStatement (UnsafeStatement unsafeStatement) + + public virtual void VisitUnsafeStatement(UnsafeStatement unsafeStatement) { - VisitChildren (unsafeStatement); + VisitChildren(unsafeStatement); } - - public virtual void VisitUsingStatement (UsingStatement usingStatement) + + public virtual void VisitUsingStatement(UsingStatement usingStatement) { - VisitChildren (usingStatement); + VisitChildren(usingStatement); } - - public virtual void VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement) + + public virtual void VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement) { - VisitChildren (variableDeclarationStatement); + VisitChildren(variableDeclarationStatement); } public virtual void VisitLocalFunctionDeclarationStatement(LocalFunctionDeclarationStatement localFunctionDeclarationStatement) @@ -396,69 +397,69 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax VisitChildren(localFunctionDeclarationStatement); } - public virtual void VisitWhileStatement (WhileStatement whileStatement) + public virtual void VisitWhileStatement(WhileStatement whileStatement) { - VisitChildren (whileStatement); + VisitChildren(whileStatement); } - - public virtual void VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement) + + public virtual void VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement) { - VisitChildren (yieldBreakStatement); + VisitChildren(yieldBreakStatement); } - - public virtual void VisitYieldReturnStatement (YieldReturnStatement yieldReturnStatement) + + public virtual void VisitYieldReturnStatement(YieldReturnStatement yieldReturnStatement) { - VisitChildren (yieldReturnStatement); + VisitChildren(yieldReturnStatement); } - - public virtual void VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression) + + public virtual void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression) { - VisitChildren (anonymousMethodExpression); + VisitChildren(anonymousMethodExpression); } - - public virtual void VisitLambdaExpression (LambdaExpression lambdaExpression) + + public virtual void VisitLambdaExpression(LambdaExpression lambdaExpression) { - VisitChildren (lambdaExpression); + VisitChildren(lambdaExpression); } - - public virtual void VisitAssignmentExpression (AssignmentExpression assignmentExpression) + + public virtual void VisitAssignmentExpression(AssignmentExpression assignmentExpression) { - VisitChildren (assignmentExpression); + VisitChildren(assignmentExpression); } - - public virtual void VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression) + + public virtual void VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression) { - VisitChildren (baseReferenceExpression); + VisitChildren(baseReferenceExpression); } - - public virtual void VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression) + + public virtual void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { - VisitChildren (binaryOperatorExpression); + VisitChildren(binaryOperatorExpression); } - - public virtual void VisitCastExpression (CastExpression castExpression) + + public virtual void VisitCastExpression(CastExpression castExpression) { - VisitChildren (castExpression); + VisitChildren(castExpression); } - - public virtual void VisitCheckedExpression (CheckedExpression checkedExpression) + + public virtual void VisitCheckedExpression(CheckedExpression checkedExpression) { - VisitChildren (checkedExpression); + VisitChildren(checkedExpression); } - - public virtual void VisitConditionalExpression (ConditionalExpression conditionalExpression) + + public virtual void VisitConditionalExpression(ConditionalExpression conditionalExpression) { - VisitChildren (conditionalExpression); + VisitChildren(conditionalExpression); } - - public virtual void VisitIdentifierExpression (IdentifierExpression identifierExpression) + + public virtual void VisitIdentifierExpression(IdentifierExpression identifierExpression) { - VisitChildren (identifierExpression); + VisitChildren(identifierExpression); } - - public virtual void VisitIndexerExpression (IndexerExpression indexerExpression) + + public virtual void VisitIndexerExpression(IndexerExpression indexerExpression) { - VisitChildren (indexerExpression); + VisitChildren(indexerExpression); } public virtual void VisitInterpolatedStringExpression(InterpolatedStringExpression interpolatedStringExpression) @@ -476,29 +477,29 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax VisitChildren(interpolatedStringText); } - public virtual void VisitInvocationExpression (InvocationExpression invocationExpression) + public virtual void VisitInvocationExpression(InvocationExpression invocationExpression) { - VisitChildren (invocationExpression); + VisitChildren(invocationExpression); } - - public virtual void VisitDirectionExpression (DirectionExpression directionExpression) + + public virtual void VisitDirectionExpression(DirectionExpression directionExpression) { - VisitChildren (directionExpression); + VisitChildren(directionExpression); } - - public virtual void VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression) + + public virtual void VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) { - VisitChildren (memberReferenceExpression); + VisitChildren(memberReferenceExpression); } - - public virtual void VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression) + + public virtual void VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression) { - VisitChildren (nullReferenceExpression); + VisitChildren(nullReferenceExpression); } - - public virtual void VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression) + + public virtual void VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression) { - VisitChildren (objectCreateExpression); + VisitChildren(objectCreateExpression); } public virtual void VisitDeclarationExpression(DeclarationExpression declarationExpression) @@ -513,162 +514,162 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public virtual void VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression) { - VisitChildren (anonymousTypeCreateExpression); + VisitChildren(anonymousTypeCreateExpression); } - - public virtual void VisitArrayCreateExpression (ArrayCreateExpression arrayCreateExpression) + + public virtual void VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression) { - VisitChildren (arrayCreateExpression); + VisitChildren(arrayCreateExpression); } - - public virtual void VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression) + + public virtual void VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression) { - VisitChildren (parenthesizedExpression); + VisitChildren(parenthesizedExpression); } - - public virtual void VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression) + + public virtual void VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression) { - VisitChildren (pointerReferenceExpression); + VisitChildren(pointerReferenceExpression); } - + public virtual void VisitPrimitiveExpression(PrimitiveExpression primitiveExpression) { - VisitChildren (primitiveExpression); + VisitChildren(primitiveExpression); } - - public virtual void VisitSizeOfExpression (SizeOfExpression sizeOfExpression) + + public virtual void VisitSizeOfExpression(SizeOfExpression sizeOfExpression) { - VisitChildren (sizeOfExpression); + VisitChildren(sizeOfExpression); } - - public virtual void VisitStackAllocExpression (StackAllocExpression stackAllocExpression) + + public virtual void VisitStackAllocExpression(StackAllocExpression stackAllocExpression) { - VisitChildren (stackAllocExpression); + VisitChildren(stackAllocExpression); } - + public virtual void VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression) { - VisitChildren (thisReferenceExpression); + VisitChildren(thisReferenceExpression); } - public virtual void VisitThrowExpression (ThrowExpression throwExpression) + public virtual void VisitThrowExpression(ThrowExpression throwExpression) { - VisitChildren (throwExpression); + VisitChildren(throwExpression); } public virtual void VisitTupleExpression(TupleExpression tupleExpression) { - VisitChildren (tupleExpression); + VisitChildren(tupleExpression); } - public virtual void VisitTypeOfExpression (TypeOfExpression typeOfExpression) + public virtual void VisitTypeOfExpression(TypeOfExpression typeOfExpression) { - VisitChildren (typeOfExpression); + VisitChildren(typeOfExpression); } - + public virtual void VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression) { - VisitChildren (typeReferenceExpression); + VisitChildren(typeReferenceExpression); } - - public virtual void VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression) + + public virtual void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression) { - VisitChildren (unaryOperatorExpression); + VisitChildren(unaryOperatorExpression); } - - public virtual void VisitUncheckedExpression (UncheckedExpression uncheckedExpression) + + public virtual void VisitUncheckedExpression(UncheckedExpression uncheckedExpression) { - VisitChildren (uncheckedExpression); + VisitChildren(uncheckedExpression); } - + public virtual void VisitQueryExpression(QueryExpression queryExpression) { - VisitChildren (queryExpression); + VisitChildren(queryExpression); } - + public virtual void VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause) { - VisitChildren (queryContinuationClause); + VisitChildren(queryContinuationClause); } - + public virtual void VisitQueryFromClause(QueryFromClause queryFromClause) { - VisitChildren (queryFromClause); + VisitChildren(queryFromClause); } - + public virtual void VisitQueryLetClause(QueryLetClause queryLetClause) { - VisitChildren (queryLetClause); + VisitChildren(queryLetClause); } - + public virtual void VisitQueryWhereClause(QueryWhereClause queryWhereClause) { - VisitChildren (queryWhereClause); + VisitChildren(queryWhereClause); } - + public virtual void VisitQueryJoinClause(QueryJoinClause queryJoinClause) { - VisitChildren (queryJoinClause); + VisitChildren(queryJoinClause); } - + public virtual void VisitQueryOrderClause(QueryOrderClause queryOrderClause) { - VisitChildren (queryOrderClause); + VisitChildren(queryOrderClause); } - + public virtual void VisitQueryOrdering(QueryOrdering queryOrdering) { - VisitChildren (queryOrdering); + VisitChildren(queryOrdering); } - + public virtual void VisitQuerySelectClause(QuerySelectClause querySelectClause) { - VisitChildren (querySelectClause); + VisitChildren(querySelectClause); } - + public virtual void VisitQueryGroupClause(QueryGroupClause queryGroupClause) { - VisitChildren (queryGroupClause); + VisitChildren(queryGroupClause); } - - public virtual void VisitAsExpression (AsExpression asExpression) + + public virtual void VisitAsExpression(AsExpression asExpression) { - VisitChildren (asExpression); + VisitChildren(asExpression); } - - public virtual void VisitIsExpression (IsExpression isExpression) + + public virtual void VisitIsExpression(IsExpression isExpression) { - VisitChildren (isExpression); + VisitChildren(isExpression); } - - public virtual void VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression) + + public virtual void VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression) { - VisitChildren (defaultValueExpression); + VisitChildren(defaultValueExpression); } - - public virtual void VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression) + + public virtual void VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression) { - VisitChildren (undocumentedExpression); + VisitChildren(undocumentedExpression); } - - public virtual void VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression) + + public virtual void VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression) { - VisitChildren (arrayInitializerExpression); + VisitChildren(arrayInitializerExpression); } - - public virtual void VisitArraySpecifier (ArraySpecifier arraySpecifier) + + public virtual void VisitArraySpecifier(ArraySpecifier arraySpecifier) { - VisitChildren (arraySpecifier); + VisitChildren(arraySpecifier); } - - public virtual void VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression) + + public virtual void VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression) { - VisitChildren (namedArgumentExpression); + VisitChildren(namedArgumentExpression); } - - public virtual void VisitNamedExpression (NamedExpression namedExpression) + + public virtual void VisitNamedExpression(NamedExpression namedExpression) { - VisitChildren (namedExpression); + VisitChildren(namedExpression); } public virtual void VisitSingleVariableDesignation(SingleVariableDesignation singleVariableDesignation) @@ -688,329 +689,330 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public virtual void VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern) { - VisitChildren (placeholder); + VisitChildren(placeholder); } } - + /// /// AST visitor with a default implementation that visits all node depth-first. /// public abstract class DepthFirstAstVisitor : IAstVisitor { - protected virtual T VisitChildren (AstNode node) + protected virtual T VisitChildren(AstNode node) { AstNode next; - for (var child = node.FirstChild; child != null; child = next) { + for (var child = node.FirstChild; child != null; child = next) + { // Store next to allow the loop to continue // if the visitor removes/replaces child. next = child.NextSibling; - child.AcceptVisitor (this); + child.AcceptVisitor(this); } - return default (T); + return default(T); } - + public virtual T VisitNullNode(AstNode nullNode) { // Should we call VisitChildren here? // We usually want to ignore null nodes. // Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes; // so changing this might break VisitChildren() overrides that expect the node to be part of the AST. - return default (T); + return default(T); } - - public virtual T VisitSyntaxTree (SyntaxTree unit) + + public virtual T VisitSyntaxTree(SyntaxTree unit) { - return VisitChildren (unit); + return VisitChildren(unit); } - - public virtual T VisitComment (Comment comment) + + public virtual T VisitComment(Comment comment) { - return VisitChildren (comment); + return VisitChildren(comment); } - - public virtual T VisitDocumentationReference (DocumentationReference documentationReference) + + public virtual T VisitDocumentationReference(DocumentationReference documentationReference) { - return VisitChildren (documentationReference); + return VisitChildren(documentationReference); } - - public virtual T VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective) + + public virtual T VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective) { - return VisitChildren (preProcessorDirective); + return VisitChildren(preProcessorDirective); } - public virtual T VisitIdentifier (Identifier identifier) + public virtual T VisitIdentifier(Identifier identifier) { - return VisitChildren (identifier); + return VisitChildren(identifier); } - - public virtual T VisitCSharpTokenNode (CSharpTokenNode token) + + public virtual T VisitCSharpTokenNode(CSharpTokenNode token) { - return VisitChildren (token); + return VisitChildren(token); } - - public virtual T VisitPrimitiveType (PrimitiveType primitiveType) + + public virtual T VisitPrimitiveType(PrimitiveType primitiveType) { - return VisitChildren (primitiveType); + return VisitChildren(primitiveType); } - - public virtual T VisitComposedType (ComposedType composedType) + + public virtual T VisitComposedType(ComposedType composedType) { - return VisitChildren (composedType); + return VisitChildren(composedType); } - + public virtual T VisitSimpleType(SimpleType simpleType) { - return VisitChildren (simpleType); + return VisitChildren(simpleType); } - + public virtual T VisitMemberType(MemberType memberType) { - return VisitChildren (memberType); + return VisitChildren(memberType); } public virtual T VisitTupleType(TupleAstType tupleType) { - return VisitChildren (tupleType); + return VisitChildren(tupleType); } public virtual T VisitTupleTypeElement(TupleTypeElement tupleTypeElement) { - return VisitChildren (tupleTypeElement); + return VisitChildren(tupleTypeElement); } public virtual T VisitFunctionPointerType(FunctionPointerType functionPointerType) { - return VisitChildren (functionPointerType); + return VisitChildren(functionPointerType); } - public virtual T VisitAttribute (Attribute attribute) + public virtual T VisitAttribute(Attribute attribute) { - return VisitChildren (attribute); + return VisitChildren(attribute); } - - public virtual T VisitAttributeSection (AttributeSection attributeSection) + + public virtual T VisitAttributeSection(AttributeSection attributeSection) { - return VisitChildren (attributeSection); + return VisitChildren(attributeSection); } - - public virtual T VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration) + + public virtual T VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration) { - return VisitChildren (delegateDeclaration); + return VisitChildren(delegateDeclaration); } - - public virtual T VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration) + + public virtual T VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) { - return VisitChildren (namespaceDeclaration); + return VisitChildren(namespaceDeclaration); } - - public virtual T VisitTypeDeclaration (TypeDeclaration typeDeclaration) + + public virtual T VisitTypeDeclaration(TypeDeclaration typeDeclaration) { - return VisitChildren (typeDeclaration); + return VisitChildren(typeDeclaration); } - - public virtual T VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration) + + public virtual T VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration) { - return VisitChildren (typeParameterDeclaration); + return VisitChildren(typeParameterDeclaration); } - - public virtual T VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration) + + public virtual T VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration) { - return VisitChildren (enumMemberDeclaration); + return VisitChildren(enumMemberDeclaration); } - - public virtual T VisitUsingDeclaration (UsingDeclaration usingDeclaration) + + public virtual T VisitUsingDeclaration(UsingDeclaration usingDeclaration) { - return VisitChildren (usingDeclaration); + return VisitChildren(usingDeclaration); } - - public virtual T VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration) + + public virtual T VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration) { - return VisitChildren (usingDeclaration); + return VisitChildren(usingDeclaration); } - + public virtual T VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration) { - return VisitChildren (externAliasDeclaration); + return VisitChildren(externAliasDeclaration); } - - public virtual T VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration) + + public virtual T VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) { - return VisitChildren (constructorDeclaration); + return VisitChildren(constructorDeclaration); } - - public virtual T VisitConstructorInitializer (ConstructorInitializer constructorInitializer) + + public virtual T VisitConstructorInitializer(ConstructorInitializer constructorInitializer) { - return VisitChildren (constructorInitializer); + return VisitChildren(constructorInitializer); } - - public virtual T VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration) + + public virtual T VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration) { - return VisitChildren (destructorDeclaration); + return VisitChildren(destructorDeclaration); } - - public virtual T VisitEventDeclaration (EventDeclaration eventDeclaration) + + public virtual T VisitEventDeclaration(EventDeclaration eventDeclaration) { - return VisitChildren (eventDeclaration); + return VisitChildren(eventDeclaration); } - - public virtual T VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration) + + public virtual T VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration) { - return VisitChildren (eventDeclaration); + return VisitChildren(eventDeclaration); } - - public virtual T VisitFieldDeclaration (FieldDeclaration fieldDeclaration) + + public virtual T VisitFieldDeclaration(FieldDeclaration fieldDeclaration) { - return VisitChildren (fieldDeclaration); + return VisitChildren(fieldDeclaration); } - - public virtual T VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration) + + public virtual T VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration) { - return VisitChildren (fixedFieldDeclaration); + return VisitChildren(fixedFieldDeclaration); } - - public virtual T VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer) + + public virtual T VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer) { - return VisitChildren (fixedVariableInitializer); + return VisitChildren(fixedVariableInitializer); } - - public virtual T VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration) + + public virtual T VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration) { - return VisitChildren (indexerDeclaration); + return VisitChildren(indexerDeclaration); } - - public virtual T VisitMethodDeclaration (MethodDeclaration methodDeclaration) + + public virtual T VisitMethodDeclaration(MethodDeclaration methodDeclaration) { - return VisitChildren (methodDeclaration); + return VisitChildren(methodDeclaration); } - - public virtual T VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration) + + public virtual T VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration) { - return VisitChildren (operatorDeclaration); + return VisitChildren(operatorDeclaration); } - - public virtual T VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration) + + public virtual T VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) { - return VisitChildren (propertyDeclaration); + return VisitChildren(propertyDeclaration); } - - public virtual T VisitAccessor (Accessor accessor) + + public virtual T VisitAccessor(Accessor accessor) { - return VisitChildren (accessor); + return VisitChildren(accessor); } - - public virtual T VisitVariableInitializer (VariableInitializer variableInitializer) + + public virtual T VisitVariableInitializer(VariableInitializer variableInitializer) { - return VisitChildren (variableInitializer); + return VisitChildren(variableInitializer); } - - public virtual T VisitParameterDeclaration (ParameterDeclaration parameterDeclaration) + + public virtual T VisitParameterDeclaration(ParameterDeclaration parameterDeclaration) { - return VisitChildren (parameterDeclaration); + return VisitChildren(parameterDeclaration); } - - public virtual T VisitConstraint (Constraint constraint) + + public virtual T VisitConstraint(Constraint constraint) { - return VisitChildren (constraint); + return VisitChildren(constraint); } - - public virtual T VisitBlockStatement (BlockStatement blockStatement) + + public virtual T VisitBlockStatement(BlockStatement blockStatement) { - return VisitChildren (blockStatement); + return VisitChildren(blockStatement); } - - public virtual T VisitExpressionStatement (ExpressionStatement expressionStatement) + + public virtual T VisitExpressionStatement(ExpressionStatement expressionStatement) { - return VisitChildren (expressionStatement); + return VisitChildren(expressionStatement); } - - public virtual T VisitBreakStatement (BreakStatement breakStatement) + + public virtual T VisitBreakStatement(BreakStatement breakStatement) { - return VisitChildren (breakStatement); + return VisitChildren(breakStatement); } - - public virtual T VisitCheckedStatement (CheckedStatement checkedStatement) + + public virtual T VisitCheckedStatement(CheckedStatement checkedStatement) { - return VisitChildren (checkedStatement); + return VisitChildren(checkedStatement); } - - public virtual T VisitContinueStatement (ContinueStatement continueStatement) + + public virtual T VisitContinueStatement(ContinueStatement continueStatement) { - return VisitChildren (continueStatement); + return VisitChildren(continueStatement); } - - public virtual T VisitDoWhileStatement (DoWhileStatement doWhileStatement) + + public virtual T VisitDoWhileStatement(DoWhileStatement doWhileStatement) { - return VisitChildren (doWhileStatement); + return VisitChildren(doWhileStatement); } - - public virtual T VisitEmptyStatement (EmptyStatement emptyStatement) + + public virtual T VisitEmptyStatement(EmptyStatement emptyStatement) { - return VisitChildren (emptyStatement); + return VisitChildren(emptyStatement); } - - public virtual T VisitFixedStatement (FixedStatement fixedStatement) + + public virtual T VisitFixedStatement(FixedStatement fixedStatement) { - return VisitChildren (fixedStatement); + return VisitChildren(fixedStatement); } - - public virtual T VisitForeachStatement (ForeachStatement foreachStatement) + + public virtual T VisitForeachStatement(ForeachStatement foreachStatement) { - return VisitChildren (foreachStatement); + return VisitChildren(foreachStatement); } - - public virtual T VisitForStatement (ForStatement forStatement) + + public virtual T VisitForStatement(ForStatement forStatement) { - return VisitChildren (forStatement); + return VisitChildren(forStatement); } - - public virtual T VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement) + + public virtual T VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement) { - return VisitChildren (gotoCaseStatement); + return VisitChildren(gotoCaseStatement); } - - public virtual T VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement) + + public virtual T VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement) { - return VisitChildren (gotoDefaultStatement); + return VisitChildren(gotoDefaultStatement); } - - public virtual T VisitGotoStatement (GotoStatement gotoStatement) + + public virtual T VisitGotoStatement(GotoStatement gotoStatement) { - return VisitChildren (gotoStatement); + return VisitChildren(gotoStatement); } - - public virtual T VisitIfElseStatement (IfElseStatement ifElseStatement) + + public virtual T VisitIfElseStatement(IfElseStatement ifElseStatement) { - return VisitChildren (ifElseStatement); + return VisitChildren(ifElseStatement); } - - public virtual T VisitLabelStatement (LabelStatement labelStatement) + + public virtual T VisitLabelStatement(LabelStatement labelStatement) { - return VisitChildren (labelStatement); + return VisitChildren(labelStatement); } - - public virtual T VisitLockStatement (LockStatement lockStatement) + + public virtual T VisitLockStatement(LockStatement lockStatement) { - return VisitChildren (lockStatement); + return VisitChildren(lockStatement); } - - public virtual T VisitReturnStatement (ReturnStatement returnStatement) + + public virtual T VisitReturnStatement(ReturnStatement returnStatement) { - return VisitChildren (returnStatement); + return VisitChildren(returnStatement); } - - public virtual T VisitSwitchStatement (SwitchStatement switchStatement) + + public virtual T VisitSwitchStatement(SwitchStatement switchStatement) { - return VisitChildren (switchStatement); + return VisitChildren(switchStatement); } - - public virtual T VisitSwitchSection (SwitchSection switchSection) + + public virtual T VisitSwitchSection(SwitchSection switchSection) { - return VisitChildren (switchSection); + return VisitChildren(switchSection); } - - public virtual T VisitCaseLabel (CaseLabel caseLabel) + + public virtual T VisitCaseLabel(CaseLabel caseLabel) { - return VisitChildren (caseLabel); + return VisitChildren(caseLabel); } public virtual T VisitSwitchExpression(SwitchExpression switchExpression) @@ -1023,39 +1025,39 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return VisitChildren(switchExpressionSection); } - public virtual T VisitThrowStatement (ThrowStatement throwStatement) + public virtual T VisitThrowStatement(ThrowStatement throwStatement) { - return VisitChildren (throwStatement); + return VisitChildren(throwStatement); } - - public virtual T VisitTryCatchStatement (TryCatchStatement tryCatchStatement) + + public virtual T VisitTryCatchStatement(TryCatchStatement tryCatchStatement) { - return VisitChildren (tryCatchStatement); + return VisitChildren(tryCatchStatement); } - - public virtual T VisitCatchClause (CatchClause catchClause) + + public virtual T VisitCatchClause(CatchClause catchClause) { - return VisitChildren (catchClause); + return VisitChildren(catchClause); } - - public virtual T VisitUncheckedStatement (UncheckedStatement uncheckedStatement) + + public virtual T VisitUncheckedStatement(UncheckedStatement uncheckedStatement) { - return VisitChildren (uncheckedStatement); + return VisitChildren(uncheckedStatement); } - - public virtual T VisitUnsafeStatement (UnsafeStatement unsafeStatement) + + public virtual T VisitUnsafeStatement(UnsafeStatement unsafeStatement) { - return VisitChildren (unsafeStatement); + return VisitChildren(unsafeStatement); } - - public virtual T VisitUsingStatement (UsingStatement usingStatement) + + public virtual T VisitUsingStatement(UsingStatement usingStatement) { - return VisitChildren (usingStatement); + return VisitChildren(usingStatement); } - - public virtual T VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement) + + public virtual T VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement) { - return VisitChildren (variableDeclarationStatement); + return VisitChildren(variableDeclarationStatement); } public virtual T VisitLocalFunctionDeclarationStatement(LocalFunctionDeclarationStatement localFunctionDeclarationStatement) @@ -1063,69 +1065,69 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return VisitChildren(localFunctionDeclarationStatement); } - public virtual T VisitWhileStatement (WhileStatement whileStatement) + public virtual T VisitWhileStatement(WhileStatement whileStatement) { - return VisitChildren (whileStatement); + return VisitChildren(whileStatement); } - - public virtual T VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement) + + public virtual T VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement) { - return VisitChildren (yieldBreakStatement); + return VisitChildren(yieldBreakStatement); } - - public virtual T VisitYieldReturnStatement (YieldReturnStatement yieldReturnStatement) + + public virtual T VisitYieldReturnStatement(YieldReturnStatement yieldReturnStatement) { - return VisitChildren (yieldReturnStatement); + return VisitChildren(yieldReturnStatement); } - - public virtual T VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression) + + public virtual T VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression) { - return VisitChildren (anonymousMethodExpression); + return VisitChildren(anonymousMethodExpression); } - - public virtual T VisitLambdaExpression (LambdaExpression lambdaExpression) + + public virtual T VisitLambdaExpression(LambdaExpression lambdaExpression) { - return VisitChildren (lambdaExpression); + return VisitChildren(lambdaExpression); } - - public virtual T VisitAssignmentExpression (AssignmentExpression assignmentExpression) + + public virtual T VisitAssignmentExpression(AssignmentExpression assignmentExpression) { - return VisitChildren (assignmentExpression); + return VisitChildren(assignmentExpression); } - - public virtual T VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression) + + public virtual T VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression) { - return VisitChildren (baseReferenceExpression); + return VisitChildren(baseReferenceExpression); } - - public virtual T VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression) + + public virtual T VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { - return VisitChildren (binaryOperatorExpression); + return VisitChildren(binaryOperatorExpression); } - - public virtual T VisitCastExpression (CastExpression castExpression) + + public virtual T VisitCastExpression(CastExpression castExpression) { - return VisitChildren (castExpression); + return VisitChildren(castExpression); } - - public virtual T VisitCheckedExpression (CheckedExpression checkedExpression) + + public virtual T VisitCheckedExpression(CheckedExpression checkedExpression) { - return VisitChildren (checkedExpression); + return VisitChildren(checkedExpression); } - - public virtual T VisitConditionalExpression (ConditionalExpression conditionalExpression) + + public virtual T VisitConditionalExpression(ConditionalExpression conditionalExpression) { - return VisitChildren (conditionalExpression); + return VisitChildren(conditionalExpression); } - - public virtual T VisitIdentifierExpression (IdentifierExpression identifierExpression) + + public virtual T VisitIdentifierExpression(IdentifierExpression identifierExpression) { - return VisitChildren (identifierExpression); + return VisitChildren(identifierExpression); } - - public virtual T VisitIndexerExpression (IndexerExpression indexerExpression) + + public virtual T VisitIndexerExpression(IndexerExpression indexerExpression) { - return VisitChildren (indexerExpression); + return VisitChildren(indexerExpression); } public virtual T VisitInterpolatedStringExpression(InterpolatedStringExpression interpolatedStringExpression) @@ -1143,29 +1145,29 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return VisitChildren(interpolatedStringText); } - public virtual T VisitInvocationExpression (InvocationExpression invocationExpression) + public virtual T VisitInvocationExpression(InvocationExpression invocationExpression) { - return VisitChildren (invocationExpression); + return VisitChildren(invocationExpression); } - - public virtual T VisitDirectionExpression (DirectionExpression directionExpression) + + public virtual T VisitDirectionExpression(DirectionExpression directionExpression) { - return VisitChildren (directionExpression); + return VisitChildren(directionExpression); } - - public virtual T VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression) + + public virtual T VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) { - return VisitChildren (memberReferenceExpression); + return VisitChildren(memberReferenceExpression); } - - public virtual T VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression) + + public virtual T VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression) { - return VisitChildren (nullReferenceExpression); + return VisitChildren(nullReferenceExpression); } - - public virtual T VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression) + + public virtual T VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression) { - return VisitChildren (objectCreateExpression); + return VisitChildren(objectCreateExpression); } public virtual T VisitDeclarationExpression(DeclarationExpression declarationExpression) @@ -1180,162 +1182,162 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public virtual T VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression) { - return VisitChildren (anonymousTypeCreateExpression); + return VisitChildren(anonymousTypeCreateExpression); } - - public virtual T VisitArrayCreateExpression (ArrayCreateExpression arrayCreateExpression) + + public virtual T VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression) { - return VisitChildren (arrayCreateExpression); + return VisitChildren(arrayCreateExpression); } - - public virtual T VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression) + + public virtual T VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression) { - return VisitChildren (parenthesizedExpression); + return VisitChildren(parenthesizedExpression); } - - public virtual T VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression) + + public virtual T VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression) { - return VisitChildren (pointerReferenceExpression); + return VisitChildren(pointerReferenceExpression); } - + public virtual T VisitPrimitiveExpression(PrimitiveExpression primitiveExpression) { - return VisitChildren (primitiveExpression); + return VisitChildren(primitiveExpression); } - - public virtual T VisitSizeOfExpression (SizeOfExpression sizeOfExpression) + + public virtual T VisitSizeOfExpression(SizeOfExpression sizeOfExpression) { - return VisitChildren (sizeOfExpression); + return VisitChildren(sizeOfExpression); } - - public virtual T VisitStackAllocExpression (StackAllocExpression stackAllocExpression) + + public virtual T VisitStackAllocExpression(StackAllocExpression stackAllocExpression) { - return VisitChildren (stackAllocExpression); + return VisitChildren(stackAllocExpression); } - + public virtual T VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression) { - return VisitChildren (thisReferenceExpression); + return VisitChildren(thisReferenceExpression); } - public virtual T VisitThrowExpression (ThrowExpression throwExpression) + public virtual T VisitThrowExpression(ThrowExpression throwExpression) { - return VisitChildren (throwExpression); + return VisitChildren(throwExpression); } - public virtual T VisitTupleExpression (TupleExpression tupleExpression) + public virtual T VisitTupleExpression(TupleExpression tupleExpression) { - return VisitChildren (tupleExpression); + return VisitChildren(tupleExpression); } - public virtual T VisitTypeOfExpression (TypeOfExpression typeOfExpression) + public virtual T VisitTypeOfExpression(TypeOfExpression typeOfExpression) { - return VisitChildren (typeOfExpression); + return VisitChildren(typeOfExpression); } - + public virtual T VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression) { - return VisitChildren (typeReferenceExpression); + return VisitChildren(typeReferenceExpression); } - - public virtual T VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression) + + public virtual T VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression) { - return VisitChildren (unaryOperatorExpression); + return VisitChildren(unaryOperatorExpression); } - - public virtual T VisitUncheckedExpression (UncheckedExpression uncheckedExpression) + + public virtual T VisitUncheckedExpression(UncheckedExpression uncheckedExpression) { - return VisitChildren (uncheckedExpression); + return VisitChildren(uncheckedExpression); } - + public virtual T VisitQueryExpression(QueryExpression queryExpression) { - return VisitChildren (queryExpression); + return VisitChildren(queryExpression); } - + public virtual T VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause) { - return VisitChildren (queryContinuationClause); + return VisitChildren(queryContinuationClause); } - + public virtual T VisitQueryFromClause(QueryFromClause queryFromClause) { - return VisitChildren (queryFromClause); + return VisitChildren(queryFromClause); } - + public virtual T VisitQueryLetClause(QueryLetClause queryLetClause) { - return VisitChildren (queryLetClause); + return VisitChildren(queryLetClause); } - + public virtual T VisitQueryWhereClause(QueryWhereClause queryWhereClause) { - return VisitChildren (queryWhereClause); + return VisitChildren(queryWhereClause); } - + public virtual T VisitQueryJoinClause(QueryJoinClause queryJoinClause) { - return VisitChildren (queryJoinClause); + return VisitChildren(queryJoinClause); } - + public virtual T VisitQueryOrderClause(QueryOrderClause queryOrderClause) { - return VisitChildren (queryOrderClause); + return VisitChildren(queryOrderClause); } - + public virtual T VisitQueryOrdering(QueryOrdering queryOrdering) { - return VisitChildren (queryOrdering); + return VisitChildren(queryOrdering); } - + public virtual T VisitQuerySelectClause(QuerySelectClause querySelectClause) { - return VisitChildren (querySelectClause); + return VisitChildren(querySelectClause); } - + public virtual T VisitQueryGroupClause(QueryGroupClause queryGroupClause) { - return VisitChildren (queryGroupClause); + return VisitChildren(queryGroupClause); } - - public virtual T VisitAsExpression (AsExpression asExpression) + + public virtual T VisitAsExpression(AsExpression asExpression) { - return VisitChildren (asExpression); + return VisitChildren(asExpression); } - - public virtual T VisitIsExpression (IsExpression isExpression) + + public virtual T VisitIsExpression(IsExpression isExpression) { - return VisitChildren (isExpression); + return VisitChildren(isExpression); } - - public virtual T VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression) + + public virtual T VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression) { - return VisitChildren (defaultValueExpression); + return VisitChildren(defaultValueExpression); } - - public virtual T VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression) + + public virtual T VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression) { - return VisitChildren (undocumentedExpression); + return VisitChildren(undocumentedExpression); } - - public virtual T VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression) + + public virtual T VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression) { - return VisitChildren (arrayInitializerExpression); + return VisitChildren(arrayInitializerExpression); } - - public virtual T VisitArraySpecifier (ArraySpecifier arraySpecifier) + + public virtual T VisitArraySpecifier(ArraySpecifier arraySpecifier) { - return VisitChildren (arraySpecifier); + return VisitChildren(arraySpecifier); } - - public virtual T VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression) + + public virtual T VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression) { - return VisitChildren (namedArgumentExpression); + return VisitChildren(namedArgumentExpression); } - - public virtual T VisitNamedExpression (NamedExpression namedExpression) + + public virtual T VisitNamedExpression(NamedExpression namedExpression) { - return VisitChildren (namedExpression); + return VisitChildren(namedExpression); } public virtual T VisitSingleVariableDesignation(SingleVariableDesignation singleVariableDesignation) @@ -1355,329 +1357,330 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public virtual T VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern) { - return VisitChildren (placeholder); + return VisitChildren(placeholder); } } - + /// /// AST visitor with a default implementation that visits all node depth-first. /// public abstract class DepthFirstAstVisitor : IAstVisitor { - protected virtual S VisitChildren (AstNode node, T data) + protected virtual S VisitChildren(AstNode node, T data) { AstNode next; - for (var child = node.FirstChild; child != null; child = next) { + for (var child = node.FirstChild; child != null; child = next) + { // Store next to allow the loop to continue // if the visitor removes/replaces child. next = child.NextSibling; - child.AcceptVisitor (this, data); + child.AcceptVisitor(this, data); } - return default (S); + return default(S); } - + public virtual S VisitNullNode(AstNode nullNode, T data) { // Should we call VisitChildren here? // We usually want to ignore null nodes. // Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes; // so changing this might break VisitChildren() overrides that expect the node to be part of the AST. - return default (S); + return default(S); } - - public virtual S VisitSyntaxTree (SyntaxTree unit, T data) + + public virtual S VisitSyntaxTree(SyntaxTree unit, T data) { - return VisitChildren (unit, data); + return VisitChildren(unit, data); } - - public virtual S VisitComment (Comment comment, T data) + + public virtual S VisitComment(Comment comment, T data) { - return VisitChildren (comment, data); + return VisitChildren(comment, data); } - - public virtual S VisitDocumentationReference (DocumentationReference documentationReference, T data) + + public virtual S VisitDocumentationReference(DocumentationReference documentationReference, T data) { - return VisitChildren (documentationReference, data); + return VisitChildren(documentationReference, data); } - - public virtual S VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective, T data) + + public virtual S VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective, T data) { - return VisitChildren (preProcessorDirective, data); + return VisitChildren(preProcessorDirective, data); } - public virtual S VisitIdentifier (Identifier identifier, T data) + public virtual S VisitIdentifier(Identifier identifier, T data) { - return VisitChildren (identifier, data); + return VisitChildren(identifier, data); } - - public virtual S VisitCSharpTokenNode (CSharpTokenNode token, T data) + + public virtual S VisitCSharpTokenNode(CSharpTokenNode token, T data) { - return VisitChildren (token, data); + return VisitChildren(token, data); } - - public virtual S VisitPrimitiveType (PrimitiveType primitiveType, T data) + + public virtual S VisitPrimitiveType(PrimitiveType primitiveType, T data) { - return VisitChildren (primitiveType, data); + return VisitChildren(primitiveType, data); } - - public virtual S VisitComposedType (ComposedType composedType, T data) + + public virtual S VisitComposedType(ComposedType composedType, T data) { - return VisitChildren (composedType, data); + return VisitChildren(composedType, data); } - + public virtual S VisitSimpleType(SimpleType simpleType, T data) { - return VisitChildren (simpleType, data); + return VisitChildren(simpleType, data); } - + public virtual S VisitMemberType(MemberType memberType, T data) { - return VisitChildren (memberType, data); + return VisitChildren(memberType, data); } public virtual S VisitTupleType(TupleAstType tupleType, T data) { - return VisitChildren (tupleType, data); + return VisitChildren(tupleType, data); } public virtual S VisitTupleTypeElement(TupleTypeElement tupleTypeElement, T data) { - return VisitChildren (tupleTypeElement, data); + return VisitChildren(tupleTypeElement, data); } public virtual S VisitFunctionPointerType(FunctionPointerType functionPointerType, T data) { - return VisitChildren (functionPointerType, data); + return VisitChildren(functionPointerType, data); } - public virtual S VisitAttribute (Attribute attribute, T data) + public virtual S VisitAttribute(Attribute attribute, T data) { - return VisitChildren (attribute, data); + return VisitChildren(attribute, data); } - - public virtual S VisitAttributeSection (AttributeSection attributeSection, T data) + + public virtual S VisitAttributeSection(AttributeSection attributeSection, T data) { - return VisitChildren (attributeSection, data); + return VisitChildren(attributeSection, data); } - - public virtual S VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, T data) + + public virtual S VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, T data) { - return VisitChildren (delegateDeclaration, data); + return VisitChildren(delegateDeclaration, data); } - - public virtual S VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, T data) + + public virtual S VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, T data) { - return VisitChildren (namespaceDeclaration, data); + return VisitChildren(namespaceDeclaration, data); } - - public virtual S VisitTypeDeclaration (TypeDeclaration typeDeclaration, T data) + + public virtual S VisitTypeDeclaration(TypeDeclaration typeDeclaration, T data) { - return VisitChildren (typeDeclaration, data); + return VisitChildren(typeDeclaration, data); } - - public virtual S VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration, T data) + + public virtual S VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, T data) { - return VisitChildren (typeParameterDeclaration, data); + return VisitChildren(typeParameterDeclaration, data); } - - public virtual S VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, T data) + + public virtual S VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, T data) { - return VisitChildren (enumMemberDeclaration, data); + return VisitChildren(enumMemberDeclaration, data); } - - public virtual S VisitUsingDeclaration (UsingDeclaration usingDeclaration, T data) + + public virtual S VisitUsingDeclaration(UsingDeclaration usingDeclaration, T data) { - return VisitChildren (usingDeclaration, data); + return VisitChildren(usingDeclaration, data); } - - public virtual S VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration, T data) + + public virtual S VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, T data) { - return VisitChildren (usingDeclaration, data); + return VisitChildren(usingDeclaration, data); } - + public virtual S VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, T data) { - return VisitChildren (externAliasDeclaration, data); + return VisitChildren(externAliasDeclaration, data); } - - public virtual S VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, T data) + + public virtual S VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, T data) { - return VisitChildren (constructorDeclaration, data); + return VisitChildren(constructorDeclaration, data); } - - public virtual S VisitConstructorInitializer (ConstructorInitializer constructorInitializer, T data) + + public virtual S VisitConstructorInitializer(ConstructorInitializer constructorInitializer, T data) { - return VisitChildren (constructorInitializer, data); + return VisitChildren(constructorInitializer, data); } - - public virtual S VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, T data) + + public virtual S VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, T data) { - return VisitChildren (destructorDeclaration, data); + return VisitChildren(destructorDeclaration, data); } - - public virtual S VisitEventDeclaration (EventDeclaration eventDeclaration, T data) + + public virtual S VisitEventDeclaration(EventDeclaration eventDeclaration, T data) { - return VisitChildren (eventDeclaration, data); + return VisitChildren(eventDeclaration, data); } - - public virtual S VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration, T data) + + public virtual S VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, T data) { - return VisitChildren (eventDeclaration, data); + return VisitChildren(eventDeclaration, data); } - - public virtual S VisitFieldDeclaration (FieldDeclaration fieldDeclaration, T data) + + public virtual S VisitFieldDeclaration(FieldDeclaration fieldDeclaration, T data) { - return VisitChildren (fieldDeclaration, data); + return VisitChildren(fieldDeclaration, data); } - - public virtual S VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, T data) + + public virtual S VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, T data) { - return VisitChildren (fixedFieldDeclaration, data); + return VisitChildren(fixedFieldDeclaration, data); } - - public virtual S VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer, T data) + + public virtual S VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, T data) { - return VisitChildren (fixedVariableInitializer, data); + return VisitChildren(fixedVariableInitializer, data); } - - public virtual S VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, T data) + + public virtual S VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, T data) { - return VisitChildren (indexerDeclaration, data); + return VisitChildren(indexerDeclaration, data); } - - public virtual S VisitMethodDeclaration (MethodDeclaration methodDeclaration, T data) + + public virtual S VisitMethodDeclaration(MethodDeclaration methodDeclaration, T data) { - return VisitChildren (methodDeclaration, data); + return VisitChildren(methodDeclaration, data); } - - public virtual S VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, T data) + + public virtual S VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, T data) { - return VisitChildren (operatorDeclaration, data); + return VisitChildren(operatorDeclaration, data); } - - public virtual S VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, T data) + + public virtual S VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, T data) { - return VisitChildren (propertyDeclaration, data); + return VisitChildren(propertyDeclaration, data); } - - public virtual S VisitAccessor (Accessor accessor, T data) + + public virtual S VisitAccessor(Accessor accessor, T data) { - return VisitChildren (accessor, data); + return VisitChildren(accessor, data); } - - public virtual S VisitVariableInitializer (VariableInitializer variableInitializer, T data) + + public virtual S VisitVariableInitializer(VariableInitializer variableInitializer, T data) { - return VisitChildren (variableInitializer, data); + return VisitChildren(variableInitializer, data); } - - public virtual S VisitParameterDeclaration (ParameterDeclaration parameterDeclaration, T data) + + public virtual S VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, T data) { - return VisitChildren (parameterDeclaration, data); + return VisitChildren(parameterDeclaration, data); } - - public virtual S VisitConstraint (Constraint constraint, T data) + + public virtual S VisitConstraint(Constraint constraint, T data) { - return VisitChildren (constraint, data); + return VisitChildren(constraint, data); } - - public virtual S VisitBlockStatement (BlockStatement blockStatement, T data) + + public virtual S VisitBlockStatement(BlockStatement blockStatement, T data) { - return VisitChildren (blockStatement, data); + return VisitChildren(blockStatement, data); } - - public virtual S VisitExpressionStatement (ExpressionStatement expressionStatement, T data) + + public virtual S VisitExpressionStatement(ExpressionStatement expressionStatement, T data) { - return VisitChildren (expressionStatement, data); + return VisitChildren(expressionStatement, data); } - - public virtual S VisitBreakStatement (BreakStatement breakStatement, T data) + + public virtual S VisitBreakStatement(BreakStatement breakStatement, T data) { - return VisitChildren (breakStatement, data); + return VisitChildren(breakStatement, data); } - - public virtual S VisitCheckedStatement (CheckedStatement checkedStatement, T data) + + public virtual S VisitCheckedStatement(CheckedStatement checkedStatement, T data) { - return VisitChildren (checkedStatement, data); + return VisitChildren(checkedStatement, data); } - - public virtual S VisitContinueStatement (ContinueStatement continueStatement, T data) + + public virtual S VisitContinueStatement(ContinueStatement continueStatement, T data) { - return VisitChildren (continueStatement, data); + return VisitChildren(continueStatement, data); } - - public virtual S VisitDoWhileStatement (DoWhileStatement doWhileStatement, T data) + + public virtual S VisitDoWhileStatement(DoWhileStatement doWhileStatement, T data) { - return VisitChildren (doWhileStatement, data); + return VisitChildren(doWhileStatement, data); } - - public virtual S VisitEmptyStatement (EmptyStatement emptyStatement, T data) + + public virtual S VisitEmptyStatement(EmptyStatement emptyStatement, T data) { - return VisitChildren (emptyStatement, data); + return VisitChildren(emptyStatement, data); } - - public virtual S VisitFixedStatement (FixedStatement fixedStatement, T data) + + public virtual S VisitFixedStatement(FixedStatement fixedStatement, T data) { - return VisitChildren (fixedStatement, data); + return VisitChildren(fixedStatement, data); } - - public virtual S VisitForeachStatement (ForeachStatement foreachStatement, T data) + + public virtual S VisitForeachStatement(ForeachStatement foreachStatement, T data) { - return VisitChildren (foreachStatement, data); + return VisitChildren(foreachStatement, data); } - - public virtual S VisitForStatement (ForStatement forStatement, T data) + + public virtual S VisitForStatement(ForStatement forStatement, T data) { - return VisitChildren (forStatement, data); + return VisitChildren(forStatement, data); } - - public virtual S VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement, T data) + + public virtual S VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement, T data) { - return VisitChildren (gotoCaseStatement, data); + return VisitChildren(gotoCaseStatement, data); } - - public virtual S VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement, T data) + + public virtual S VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement, T data) { - return VisitChildren (gotoDefaultStatement, data); + return VisitChildren(gotoDefaultStatement, data); } - - public virtual S VisitGotoStatement (GotoStatement gotoStatement, T data) + + public virtual S VisitGotoStatement(GotoStatement gotoStatement, T data) { - return VisitChildren (gotoStatement, data); + return VisitChildren(gotoStatement, data); } - - public virtual S VisitIfElseStatement (IfElseStatement ifElseStatement, T data) + + public virtual S VisitIfElseStatement(IfElseStatement ifElseStatement, T data) { - return VisitChildren (ifElseStatement, data); + return VisitChildren(ifElseStatement, data); } - - public virtual S VisitLabelStatement (LabelStatement labelStatement, T data) + + public virtual S VisitLabelStatement(LabelStatement labelStatement, T data) { - return VisitChildren (labelStatement, data); + return VisitChildren(labelStatement, data); } - - public virtual S VisitLockStatement (LockStatement lockStatement, T data) + + public virtual S VisitLockStatement(LockStatement lockStatement, T data) { - return VisitChildren (lockStatement, data); + return VisitChildren(lockStatement, data); } - - public virtual S VisitReturnStatement (ReturnStatement returnStatement, T data) + + public virtual S VisitReturnStatement(ReturnStatement returnStatement, T data) { - return VisitChildren (returnStatement, data); + return VisitChildren(returnStatement, data); } - - public virtual S VisitSwitchStatement (SwitchStatement switchStatement, T data) + + public virtual S VisitSwitchStatement(SwitchStatement switchStatement, T data) { - return VisitChildren (switchStatement, data); + return VisitChildren(switchStatement, data); } - - public virtual S VisitSwitchSection (SwitchSection switchSection, T data) + + public virtual S VisitSwitchSection(SwitchSection switchSection, T data) { - return VisitChildren (switchSection, data); + return VisitChildren(switchSection, data); } - - public virtual S VisitCaseLabel (CaseLabel caseLabel, T data) + + public virtual S VisitCaseLabel(CaseLabel caseLabel, T data) { - return VisitChildren (caseLabel, data); + return VisitChildren(caseLabel, data); } public virtual S VisitSwitchExpression(SwitchExpression switchExpression, T data) @@ -1690,39 +1693,39 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return VisitChildren(switchExpressionSection, data); } - public virtual S VisitThrowStatement (ThrowStatement throwStatement, T data) + public virtual S VisitThrowStatement(ThrowStatement throwStatement, T data) { - return VisitChildren (throwStatement, data); + return VisitChildren(throwStatement, data); } - - public virtual S VisitTryCatchStatement (TryCatchStatement tryCatchStatement, T data) + + public virtual S VisitTryCatchStatement(TryCatchStatement tryCatchStatement, T data) { - return VisitChildren (tryCatchStatement, data); + return VisitChildren(tryCatchStatement, data); } - - public virtual S VisitCatchClause (CatchClause catchClause, T data) + + public virtual S VisitCatchClause(CatchClause catchClause, T data) { - return VisitChildren (catchClause, data); + return VisitChildren(catchClause, data); } - - public virtual S VisitUncheckedStatement (UncheckedStatement uncheckedStatement, T data) + + public virtual S VisitUncheckedStatement(UncheckedStatement uncheckedStatement, T data) { - return VisitChildren (uncheckedStatement, data); + return VisitChildren(uncheckedStatement, data); } - - public virtual S VisitUnsafeStatement (UnsafeStatement unsafeStatement, T data) + + public virtual S VisitUnsafeStatement(UnsafeStatement unsafeStatement, T data) { - return VisitChildren (unsafeStatement, data); + return VisitChildren(unsafeStatement, data); } - - public virtual S VisitUsingStatement (UsingStatement usingStatement, T data) + + public virtual S VisitUsingStatement(UsingStatement usingStatement, T data) { - return VisitChildren (usingStatement, data); + return VisitChildren(usingStatement, data); } - - public virtual S VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, T data) + + public virtual S VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, T data) { - return VisitChildren (variableDeclarationStatement, data); + return VisitChildren(variableDeclarationStatement, data); } public virtual S VisitLocalFunctionDeclarationStatement(LocalFunctionDeclarationStatement localFunctionDeclarationStatement, T data) @@ -1730,69 +1733,69 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return VisitChildren(localFunctionDeclarationStatement, data); } - public virtual S VisitWhileStatement (WhileStatement whileStatement, T data) + public virtual S VisitWhileStatement(WhileStatement whileStatement, T data) { - return VisitChildren (whileStatement, data); + return VisitChildren(whileStatement, data); } - - public virtual S VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement, T data) + + public virtual S VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, T data) { - return VisitChildren (yieldBreakStatement, data); + return VisitChildren(yieldBreakStatement, data); } - - public virtual S VisitYieldReturnStatement (YieldReturnStatement yieldReturnStatement, T data) + + public virtual S VisitYieldReturnStatement(YieldReturnStatement yieldReturnStatement, T data) { - return VisitChildren (yieldReturnStatement, data); + return VisitChildren(yieldReturnStatement, data); } - - public virtual S VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression, T data) + + public virtual S VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, T data) { - return VisitChildren (anonymousMethodExpression, data); + return VisitChildren(anonymousMethodExpression, data); } - - public virtual S VisitLambdaExpression (LambdaExpression lambdaExpression, T data) + + public virtual S VisitLambdaExpression(LambdaExpression lambdaExpression, T data) { - return VisitChildren (lambdaExpression, data); + return VisitChildren(lambdaExpression, data); } - - public virtual S VisitAssignmentExpression (AssignmentExpression assignmentExpression, T data) + + public virtual S VisitAssignmentExpression(AssignmentExpression assignmentExpression, T data) { - return VisitChildren (assignmentExpression, data); + return VisitChildren(assignmentExpression, data); } - - public virtual S VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression, T data) + + public virtual S VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, T data) { - return VisitChildren (baseReferenceExpression, data); + return VisitChildren(baseReferenceExpression, data); } - - public virtual S VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, T data) + + public virtual S VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, T data) { - return VisitChildren (binaryOperatorExpression, data); + return VisitChildren(binaryOperatorExpression, data); } - - public virtual S VisitCastExpression (CastExpression castExpression, T data) + + public virtual S VisitCastExpression(CastExpression castExpression, T data) { - return VisitChildren (castExpression, data); + return VisitChildren(castExpression, data); } - - public virtual S VisitCheckedExpression (CheckedExpression checkedExpression, T data) + + public virtual S VisitCheckedExpression(CheckedExpression checkedExpression, T data) { - return VisitChildren (checkedExpression, data); + return VisitChildren(checkedExpression, data); } - - public virtual S VisitConditionalExpression (ConditionalExpression conditionalExpression, T data) + + public virtual S VisitConditionalExpression(ConditionalExpression conditionalExpression, T data) { - return VisitChildren (conditionalExpression, data); + return VisitChildren(conditionalExpression, data); } - - public virtual S VisitIdentifierExpression (IdentifierExpression identifierExpression, T data) + + public virtual S VisitIdentifierExpression(IdentifierExpression identifierExpression, T data) { - return VisitChildren (identifierExpression, data); + return VisitChildren(identifierExpression, data); } - - public virtual S VisitIndexerExpression (IndexerExpression indexerExpression, T data) + + public virtual S VisitIndexerExpression(IndexerExpression indexerExpression, T data) { - return VisitChildren (indexerExpression, data); + return VisitChildren(indexerExpression, data); } public virtual S VisitInterpolatedStringExpression(InterpolatedStringExpression interpolatedStringExpression, T data) @@ -1810,29 +1813,29 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return VisitChildren(interpolatedStringText, data); } - public virtual S VisitInvocationExpression (InvocationExpression invocationExpression, T data) + public virtual S VisitInvocationExpression(InvocationExpression invocationExpression, T data) { - return VisitChildren (invocationExpression, data); + return VisitChildren(invocationExpression, data); } - - public virtual S VisitDirectionExpression (DirectionExpression directionExpression, T data) + + public virtual S VisitDirectionExpression(DirectionExpression directionExpression, T data) { - return VisitChildren (directionExpression, data); + return VisitChildren(directionExpression, data); } - - public virtual S VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression, T data) + + public virtual S VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, T data) { - return VisitChildren (memberReferenceExpression, data); + return VisitChildren(memberReferenceExpression, data); } - - public virtual S VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression, T data) + + public virtual S VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, T data) { - return VisitChildren (nullReferenceExpression, data); + return VisitChildren(nullReferenceExpression, data); } - - public virtual S VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, T data) + + public virtual S VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, T data) { - return VisitChildren (objectCreateExpression, data); + return VisitChildren(objectCreateExpression, data); } public virtual S VisitDeclarationExpression(DeclarationExpression declarationExpression, T data) @@ -1847,162 +1850,162 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public virtual S VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, T data) { - return VisitChildren (anonymousTypeCreateExpression, data); + return VisitChildren(anonymousTypeCreateExpression, data); } - - public virtual S VisitArrayCreateExpression (ArrayCreateExpression arrayCreateExpression, T data) + + public virtual S VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, T data) { - return VisitChildren (arrayCreateExpression, data); + return VisitChildren(arrayCreateExpression, data); } - - public virtual S VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, T data) + + public virtual S VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, T data) { - return VisitChildren (parenthesizedExpression, data); + return VisitChildren(parenthesizedExpression, data); } - - public virtual S VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression, T data) + + public virtual S VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, T data) { - return VisitChildren (pointerReferenceExpression, data); + return VisitChildren(pointerReferenceExpression, data); } - + public virtual S VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, T data) { - return VisitChildren (primitiveExpression, data); + return VisitChildren(primitiveExpression, data); } - - public virtual S VisitSizeOfExpression (SizeOfExpression sizeOfExpression, T data) + + public virtual S VisitSizeOfExpression(SizeOfExpression sizeOfExpression, T data) { - return VisitChildren (sizeOfExpression, data); + return VisitChildren(sizeOfExpression, data); } - - public virtual S VisitStackAllocExpression (StackAllocExpression stackAllocExpression, T data) + + public virtual S VisitStackAllocExpression(StackAllocExpression stackAllocExpression, T data) { - return VisitChildren (stackAllocExpression, data); + return VisitChildren(stackAllocExpression, data); } - + public virtual S VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, T data) { - return VisitChildren (thisReferenceExpression, data); + return VisitChildren(thisReferenceExpression, data); } - public virtual S VisitThrowExpression (ThrowExpression throwExpression, T data) + public virtual S VisitThrowExpression(ThrowExpression throwExpression, T data) { - return VisitChildren (throwExpression, data); + return VisitChildren(throwExpression, data); } - public virtual S VisitTupleExpression (TupleExpression tupleExpression, T data) + public virtual S VisitTupleExpression(TupleExpression tupleExpression, T data) { - return VisitChildren (tupleExpression, data); + return VisitChildren(tupleExpression, data); } - public virtual S VisitTypeOfExpression (TypeOfExpression typeOfExpression, T data) + public virtual S VisitTypeOfExpression(TypeOfExpression typeOfExpression, T data) { - return VisitChildren (typeOfExpression, data); + return VisitChildren(typeOfExpression, data); } - + public virtual S VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, T data) { - return VisitChildren (typeReferenceExpression, data); + return VisitChildren(typeReferenceExpression, data); } - - public virtual S VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression, T data) + + public virtual S VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, T data) { - return VisitChildren (unaryOperatorExpression, data); + return VisitChildren(unaryOperatorExpression, data); } - - public virtual S VisitUncheckedExpression (UncheckedExpression uncheckedExpression, T data) + + public virtual S VisitUncheckedExpression(UncheckedExpression uncheckedExpression, T data) { - return VisitChildren (uncheckedExpression, data); + return VisitChildren(uncheckedExpression, data); } - + public virtual S VisitQueryExpression(QueryExpression queryExpression, T data) { - return VisitChildren (queryExpression, data); + return VisitChildren(queryExpression, data); } - + public virtual S VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, T data) { - return VisitChildren (queryContinuationClause, data); + return VisitChildren(queryContinuationClause, data); } - + public virtual S VisitQueryFromClause(QueryFromClause queryFromClause, T data) { - return VisitChildren (queryFromClause, data); + return VisitChildren(queryFromClause, data); } - + public virtual S VisitQueryLetClause(QueryLetClause queryLetClause, T data) { - return VisitChildren (queryLetClause, data); + return VisitChildren(queryLetClause, data); } - + public virtual S VisitQueryWhereClause(QueryWhereClause queryWhereClause, T data) { - return VisitChildren (queryWhereClause, data); + return VisitChildren(queryWhereClause, data); } - + public virtual S VisitQueryJoinClause(QueryJoinClause queryJoinClause, T data) { - return VisitChildren (queryJoinClause, data); + return VisitChildren(queryJoinClause, data); } - + public virtual S VisitQueryOrderClause(QueryOrderClause queryOrderClause, T data) { - return VisitChildren (queryOrderClause, data); + return VisitChildren(queryOrderClause, data); } - + public virtual S VisitQueryOrdering(QueryOrdering queryOrdering, T data) { - return VisitChildren (queryOrdering, data); + return VisitChildren(queryOrdering, data); } - + public virtual S VisitQuerySelectClause(QuerySelectClause querySelectClause, T data) { - return VisitChildren (querySelectClause, data); + return VisitChildren(querySelectClause, data); } - + public virtual S VisitQueryGroupClause(QueryGroupClause queryGroupClause, T data) { - return VisitChildren (queryGroupClause, data); + return VisitChildren(queryGroupClause, data); } - - public virtual S VisitAsExpression (AsExpression asExpression, T data) + + public virtual S VisitAsExpression(AsExpression asExpression, T data) { - return VisitChildren (asExpression, data); + return VisitChildren(asExpression, data); } - - public virtual S VisitIsExpression (IsExpression isExpression, T data) + + public virtual S VisitIsExpression(IsExpression isExpression, T data) { - return VisitChildren (isExpression, data); + return VisitChildren(isExpression, data); } - - public virtual S VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression, T data) + + public virtual S VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, T data) { - return VisitChildren (defaultValueExpression, data); + return VisitChildren(defaultValueExpression, data); } - - public virtual S VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression, T data) + + public virtual S VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression, T data) { - return VisitChildren (undocumentedExpression, data); + return VisitChildren(undocumentedExpression, data); } - - public virtual S VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, T data) + + public virtual S VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, T data) { - return VisitChildren (arrayInitializerExpression, data); + return VisitChildren(arrayInitializerExpression, data); } - - public virtual S VisitArraySpecifier (ArraySpecifier arraySpecifier, T data) + + public virtual S VisitArraySpecifier(ArraySpecifier arraySpecifier, T data) { - return VisitChildren (arraySpecifier, data); + return VisitChildren(arraySpecifier, data); } - - public virtual S VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression, T data) + + public virtual S VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, T data) { - return VisitChildren (namedArgumentExpression, data); + return VisitChildren(namedArgumentExpression, data); } - - public virtual S VisitNamedExpression (NamedExpression namedExpression, T data) + + public virtual S VisitNamedExpression(NamedExpression namedExpression, T data) { - return VisitChildren (namedExpression, data); + return VisitChildren(namedExpression, data); } public virtual S VisitSingleVariableDesignation(SingleVariableDesignation singleVariableDesignation, T data) @@ -2022,7 +2025,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public virtual S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern, T data) { - return VisitChildren (placeholder, data); + return VisitChildren(placeholder, data); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs b/ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs index 85a2b4319..893f015fc 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs @@ -27,11 +27,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public static readonly Role DeclaringTypeRole = new Role("DeclaringType", AstType.Null); public static readonly Role ConversionOperatorReturnTypeRole = new Role("ConversionOperatorReturnType", AstType.Null); - + SymbolKind symbolKind; OperatorType operatorType; bool hasParameterList; - + /// /// Gets/Sets the entity type. /// Possible values are: @@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax symbolKind = value; } } - + /// /// Gets/Sets the operator type. /// This property is only used when SymbolKind==Operator. @@ -59,7 +59,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax operatorType = value; } } - + /// /// Gets/Sets whether a parameter list was provided. /// @@ -70,11 +70,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax hasParameterList = value; } } - + public override NodeType NodeType { get { return NodeType.Unknown; } } - + /// /// Gets/Sets the declaring type. /// @@ -82,7 +82,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get { return GetChildByRole(DeclaringTypeRole); } set { SetChildByRole(DeclaringTypeRole, value); } } - + /// /// Gets/sets the member name. /// This property is only used when SymbolKind==None. @@ -91,7 +91,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get { return GetChildByRole(Roles.Identifier).Name; } set { SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + /// /// Gets/Sets the return type of conversion operators. /// This property is only used when SymbolKind==Operator and OperatorType is explicit or implicit. @@ -100,28 +100,32 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get { return GetChildByRole(ConversionOperatorReturnTypeRole); } set { SetChildByRole(ConversionOperatorReturnTypeRole, value); } } - + public AstNodeCollection TypeArguments { - get { return GetChildrenByRole (Roles.TypeArgument); } + get { return GetChildrenByRole(Roles.TypeArgument); } } - + public AstNodeCollection Parameters { - get { return GetChildrenByRole (Roles.Parameter); } + get { return GetChildrenByRole(Roles.Parameter); } } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { DocumentationReference o = other as DocumentationReference; if (!(o != null && this.SymbolKind == o.SymbolKind && this.HasParameterList == o.HasParameterList)) return false; - if (this.SymbolKind == SymbolKind.Operator) { + if (this.SymbolKind == SymbolKind.Operator) + { if (this.OperatorType != o.OperatorType) return false; - if (this.OperatorType == OperatorType.Implicit || this.OperatorType == OperatorType.Explicit) { + if (this.OperatorType == OperatorType.Implicit || this.OperatorType == OperatorType.Explicit) + { if (!this.ConversionOperatorReturnType.DoMatch(o.ConversionOperatorReturnType, match)) return false; } - } else if (this.SymbolKind == SymbolKind.None) { + } + else if (this.SymbolKind == SymbolKind.None) + { if (!MatchString(this.MemberName, o.MemberName)) return false; if (!this.TypeArguments.DoMatch(o.TypeArguments, match)) @@ -129,20 +133,20 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } return this.Parameters.DoMatch(o.Parameters, match); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitDocumentationReference (this); + visitor.VisitDocumentationReference(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitDocumentationReference (this); + return visitor.VisitDocumentationReference(this); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitDocumentationReference (this, data); + return visitor.VisitDocumentationReference(this, data); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousMethodExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousMethodExpression.cs index 683f56860..633073b36 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousMethodExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousMethodExpression.cs @@ -34,79 +34,81 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class AnonymousMethodExpression : Expression { - public readonly static TokenRole DelegateKeywordRole = new TokenRole ("delegate"); + public readonly static TokenRole DelegateKeywordRole = new TokenRole("delegate"); public readonly static TokenRole AsyncModifierRole = LambdaExpression.AsyncModifierRole; - + bool isAsync; - + public bool IsAsync { get { return isAsync; } set { ThrowIfFrozen(); isAsync = value; } } - + // used to tell the difference between delegate {} and delegate () {} bool hasParameterList; - + public bool HasParameterList { get { return hasParameterList || Parameters.Any(); } set { ThrowIfFrozen(); hasParameterList = value; } } - + public CSharpTokenNode DelegateToken { - get { return GetChildByRole (DelegateKeywordRole); } + get { return GetChildByRole(DelegateKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstNodeCollection Parameters { - get { return GetChildrenByRole (Roles.Parameter); } + get { return GetChildrenByRole(Roles.Parameter); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public BlockStatement Body { - get { return GetChildByRole (Roles.Body); } - set { SetChildByRole (Roles.Body, value); } + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } } - - public AnonymousMethodExpression () + + public AnonymousMethodExpression() { } - - public AnonymousMethodExpression (BlockStatement body, IEnumerable parameters = null) + + public AnonymousMethodExpression(BlockStatement body, IEnumerable parameters = null) { - if (parameters != null) { + if (parameters != null) + { hasParameterList = true; - foreach (var parameter in parameters) { - AddChild (parameter, Roles.Parameter); + foreach (var parameter in parameters) + { + AddChild(parameter, Roles.Parameter); } } - AddChild (body, Roles.Body); + AddChild(body, Roles.Body); } - - public AnonymousMethodExpression (BlockStatement body, params ParameterDeclaration[] parameters) : this (body, (IEnumerable)parameters) + + public AnonymousMethodExpression(BlockStatement body, params ParameterDeclaration[] parameters) : this(body, (IEnumerable)parameters) { } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitAnonymousMethodExpression (this); + visitor.VisitAnonymousMethodExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitAnonymousMethodExpression (this); + return visitor.VisitAnonymousMethodExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitAnonymousMethodExpression (this, data); + return visitor.VisitAnonymousMethodExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { AnonymousMethodExpression o = other as AnonymousMethodExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousTypeCreateExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousTypeCreateExpression.cs index 2bf075aa2..e74e2e1af 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousTypeCreateExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousTypeCreateExpression.cs @@ -32,54 +32,55 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class AnonymousTypeCreateExpression : Expression { - public readonly static TokenRole NewKeywordRole = new TokenRole ("new"); - + public readonly static TokenRole NewKeywordRole = new TokenRole("new"); + public CSharpTokenNode NewToken { - get { return GetChildByRole (NewKeywordRole); } + get { return GetChildByRole(NewKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstNodeCollection Initializers { - get { return GetChildrenByRole (Roles.Expression); } + get { return GetChildrenByRole(Roles.Expression); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - - public AnonymousTypeCreateExpression () + + public AnonymousTypeCreateExpression() { } - - public AnonymousTypeCreateExpression (IEnumerable initializers) + + public AnonymousTypeCreateExpression(IEnumerable initializers) { - foreach (var ini in initializers) { - AddChild (ini, Roles.Expression); + foreach (var ini in initializers) + { + AddChild(ini, Roles.Expression); } } - - public AnonymousTypeCreateExpression (params Expression[] initializer) : this ((IEnumerable)initializer) + + public AnonymousTypeCreateExpression(params Expression[] initializer) : this((IEnumerable)initializer) { } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitAnonymousTypeCreateExpression (this); + visitor.VisitAnonymousTypeCreateExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitAnonymousTypeCreateExpression (this); + return visitor.VisitAnonymousTypeCreateExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitAnonymousTypeCreateExpression (this, data); + return visitor.VisitAnonymousTypeCreateExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { var o = other as AnonymousTypeCreateExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs index e29726ddf..eaad6ff6b 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs @@ -24,23 +24,23 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class ArrayCreateExpression : Expression { - public readonly static TokenRole NewKeywordRole = new TokenRole ("new"); + public readonly static TokenRole NewKeywordRole = new TokenRole("new"); public readonly static Role AdditionalArraySpecifierRole = new Role("AdditionalArraySpecifier"); public readonly static Role InitializerRole = new Role("Initializer", ArrayInitializerExpression.Null); - + public CSharpTokenNode NewToken { - get { return GetChildByRole (NewKeywordRole); } + get { return GetChildByRole(NewKeywordRole); } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } } - + public AstNodeCollection Arguments { - get { return GetChildrenByRole (Roles.Argument); } + get { return GetChildrenByRole(Roles.Argument); } } - + /// /// Gets additional array ranks (those without size info). /// Empty for "new int[5,1]"; will contain a single element for "new int[5][]". @@ -48,27 +48,27 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public AstNodeCollection AdditionalArraySpecifiers { get { return GetChildrenByRole(AdditionalArraySpecifierRole); } } - + public ArrayInitializerExpression Initializer { - get { return GetChildByRole (InitializerRole); } - set { SetChildByRole (InitializerRole, value); } + get { return GetChildByRole(InitializerRole); } + set { SetChildByRole(InitializerRole, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitArrayCreateExpression (this); + visitor.VisitArrayCreateExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitArrayCreateExpression (this); + return visitor.VisitArrayCreateExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitArrayCreateExpression (this, data); + return visitor.VisitArrayCreateExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ArrayCreateExpression o = other as ArrayCreateExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayInitializerExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayInitializerExpression.cs index 1332ee227..f9ce09152 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayInitializerExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayInitializerExpression.cs @@ -48,20 +48,20 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax 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 (); - + public new static readonly ArrayInitializerExpression Null = new NullArrayInitializerExpression(); + sealed class NullArrayInitializerExpression : ArrayInitializerExpression { public override bool IsNull { @@ -69,63 +69,63 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } } #endregion - + public CSharpTokenNode LBraceToken { - get { return GetChildByRole (Roles.LBrace); } + get { return GetChildByRole(Roles.LBrace); } } - + public AstNodeCollection Elements { get { return GetChildrenByRole(Roles.Expression); } } - + public CSharpTokenNode RBraceToken { - get { return GetChildByRole (Roles.RBrace); } + get { return GetChildByRole(Roles.RBrace); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitArrayInitializerExpression (this); + visitor.VisitArrayInitializerExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitArrayInitializerExpression (this); + return visitor.VisitArrayInitializerExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitArrayInitializerExpression (this, 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); } - public static ArrayInitializerExpression CreateSingleElementInitializer () + public static ArrayInitializerExpression CreateSingleElementInitializer() { return new SingleArrayInitializerExpression(); } @@ -139,34 +139,34 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - + } - + #region PatternPlaceholder public static implicit operator ArrayInitializerExpression(PatternMatching.Pattern pattern) { return pattern != null ? new PatternPlaceholder(pattern) : null; } - + sealed class PatternPlaceholder : ArrayInitializerExpression, PatternMatching.INode { readonly PatternMatching.Pattern child; - + public PatternPlaceholder(PatternMatching.Pattern child) { this.child = child; } - + public override NodeType NodeType { get { return NodeType.Pattern; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitPatternPlaceholder(this, child); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitPatternPlaceholder(this, child); } @@ -175,12 +175,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return visitor.VisitPatternPlaceholder(this, child, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return child.DoMatch(other, match); } - + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) { return child.DoMatchCollection(role, pos, match, backtrackingInfo); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AsExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AsExpression.cs index ed66ce7fe..b01fd4f86 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AsExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AsExpression.cs @@ -32,47 +32,47 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class AsExpression : Expression { - public readonly static TokenRole AsKeywordRole = new TokenRole ("as"); - + public readonly static TokenRole AsKeywordRole = new TokenRole("as"); + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } + get { return GetChildByRole(Roles.Expression); } set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode AsToken { - get { return GetChildByRole (AsKeywordRole); } + get { return GetChildByRole(AsKeywordRole); } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } + get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } } - - public AsExpression () + + public AsExpression() { } - - public AsExpression (Expression expression, AstType type) + + public AsExpression(Expression expression, AstType type) { - AddChild (expression, Roles.Expression); - AddChild (type, Roles.Type); + AddChild(expression, Roles.Expression); + AddChild(type, Roles.Type); } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitAsExpression (this); + visitor.VisitAsExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitAsExpression (this); + return visitor.VisitAsExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitAsExpression (this, data); + return visitor.VisitAsExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { AsExpression o = other as AsExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs index da02b77e7..acd1038a8 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs @@ -25,8 +25,8 @@ // THE SOFTWARE. using System; -using System.Linq.Expressions; using System.Collections.Generic; +using System.Linq.Expressions; namespace ICSharpCode.Decompiler.CSharp.Syntax { @@ -38,80 +38,81 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax // reuse roles from BinaryOperatorExpression public readonly static Role LeftRole = BinaryOperatorExpression.LeftRole; public readonly static Role RightRole = BinaryOperatorExpression.RightRole; - - public readonly static TokenRole AssignRole = new TokenRole ("="); - public readonly static TokenRole AddRole = new TokenRole ("+="); - public readonly static TokenRole SubtractRole = new TokenRole ("-="); - public readonly static TokenRole MultiplyRole = new TokenRole ("*="); - public readonly static TokenRole DivideRole = new TokenRole ("/="); - public readonly static TokenRole ModulusRole = new TokenRole ("%="); - public readonly static TokenRole ShiftLeftRole = new TokenRole ("<<="); - public readonly static TokenRole ShiftRightRole = new TokenRole (">>="); - public readonly static TokenRole BitwiseAndRole = new TokenRole ("&="); - public readonly static TokenRole BitwiseOrRole = new TokenRole ("|="); - public readonly static TokenRole ExclusiveOrRole = new TokenRole ("^="); - + + public readonly static TokenRole AssignRole = new TokenRole("="); + public readonly static TokenRole AddRole = new TokenRole("+="); + public readonly static TokenRole SubtractRole = new TokenRole("-="); + public readonly static TokenRole MultiplyRole = new TokenRole("*="); + public readonly static TokenRole DivideRole = new TokenRole("/="); + public readonly static TokenRole ModulusRole = new TokenRole("%="); + public readonly static TokenRole ShiftLeftRole = new TokenRole("<<="); + public readonly static TokenRole ShiftRightRole = new TokenRole(">>="); + public readonly static TokenRole BitwiseAndRole = new TokenRole("&="); + public readonly static TokenRole BitwiseOrRole = new TokenRole("|="); + public readonly static TokenRole ExclusiveOrRole = new TokenRole("^="); + public AssignmentExpression() { } - + public AssignmentExpression(Expression left, Expression right) { this.Left = left; this.Right = right; } - + public AssignmentExpression(Expression left, AssignmentOperatorType op, Expression right) { this.Left = left; this.Operator = op; this.Right = right; } - + public AssignmentOperatorType Operator { get; set; } - + public Expression Left { - get { return GetChildByRole (LeftRole); } + get { return GetChildByRole(LeftRole); } set { SetChildByRole(LeftRole, value); } } - + public CSharpTokenNode OperatorToken { - get { return GetChildByRole (GetOperatorRole(Operator)); } + get { return GetChildByRole(GetOperatorRole(Operator)); } } - + public Expression Right { - get { return GetChildByRole (RightRole); } + get { return GetChildByRole(RightRole); } set { SetChildByRole(RightRole, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitAssignmentExpression (this); + visitor.VisitAssignmentExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitAssignmentExpression (this); + return visitor.VisitAssignmentExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitAssignmentExpression (this, data); + return visitor.VisitAssignmentExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { AssignmentExpression o = other as AssignmentExpression; return o != null && (this.Operator == AssignmentOperatorType.Any || this.Operator == o.Operator) && this.Left.DoMatch(o.Left, match) && this.Right.DoMatch(o.Right, match); } - + public static TokenRole GetOperatorRole(AssignmentOperatorType op) { - switch (op) { + switch (op) + { case AssignmentOperatorType.Assign: return AssignRole; case AssignmentOperatorType.Add: @@ -138,14 +139,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax throw new NotSupportedException("Invalid value for AssignmentOperatorType"); } } - + /// /// Gets the binary operator for the specified compound assignment operator. /// Returns null if 'op' is not a compound assignment. /// public static BinaryOperatorType? GetCorrespondingBinaryOperator(AssignmentOperatorType op) { - switch (op) { + switch (op) + { case AssignmentOperatorType.Assign: return null; case AssignmentOperatorType.Add: @@ -172,10 +174,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax throw new NotSupportedException("Invalid value for AssignmentOperatorType"); } } - + public static ExpressionType GetLinqNodeType(AssignmentOperatorType op, bool checkForOverflow) { - switch (op) { + switch (op) + { case AssignmentOperatorType.Assign: return ExpressionType.Assign; case AssignmentOperatorType.Add: @@ -205,7 +208,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public static AssignmentOperatorType? GetAssignmentOperatorTypeFromExpressionType(ExpressionType expressionType) { - switch (expressionType) { + switch (expressionType) + { case ExpressionType.AddAssign: case ExpressionType.AddAssignChecked: return AssignmentOperatorType.Add; @@ -234,12 +238,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } } - + public enum AssignmentOperatorType { /// left = right Assign, - + /// left += right Add, /// left -= right @@ -255,14 +259,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ShiftLeft, /// left >>= right ShiftRight, - + /// left &= right BitwiseAnd, /// left |= right BitwiseOr, /// left ^= right ExclusiveOr, - + /// Any operator (for pattern matching) Any } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BaseReferenceExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BaseReferenceExpression.cs index 8e99ec074..5084d0e04 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BaseReferenceExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BaseReferenceExpression.cs @@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get; set; } - + public override TextLocation StartLocation { get { return Location; @@ -44,25 +44,25 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } public override TextLocation EndLocation { get { - return new TextLocation (Location.Line, Location.Column + "base".Length); + return new TextLocation(Location.Line, Location.Column + "base".Length); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitBaseReferenceExpression (this); + visitor.VisitBaseReferenceExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitBaseReferenceExpression (this); + return visitor.VisitBaseReferenceExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitBaseReferenceExpression (this, data); + return visitor.VisitBaseReferenceExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { BaseReferenceExpression o = other as BaseReferenceExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs index b6358f56a..579d92e53 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs @@ -25,8 +25,8 @@ // THE SOFTWARE. using System; -using System.Linq.Expressions; using System.Collections.Generic; +using System.Linq.Expressions; namespace ICSharpCode.Decompiler.CSharp.Syntax { @@ -35,85 +35,86 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class BinaryOperatorExpression : Expression { - public readonly static TokenRole BitwiseAndRole = new TokenRole ("&"); - public readonly static TokenRole BitwiseOrRole = new TokenRole ("|"); - public readonly static TokenRole ConditionalAndRole = new TokenRole ("&&"); - public readonly static TokenRole ConditionalOrRole = new TokenRole ("||"); - public readonly static TokenRole ExclusiveOrRole = new TokenRole ("^"); - public readonly static TokenRole GreaterThanRole = new TokenRole (">"); - public readonly static TokenRole GreaterThanOrEqualRole = new TokenRole (">="); - public readonly static TokenRole EqualityRole = new TokenRole ("=="); - public readonly static TokenRole InEqualityRole = new TokenRole ("!="); - public readonly static TokenRole LessThanRole = new TokenRole ("<"); - public readonly static TokenRole LessThanOrEqualRole = new TokenRole ("<="); - public readonly static TokenRole AddRole = new TokenRole ("+"); - public readonly static TokenRole SubtractRole = new TokenRole ("-"); - public readonly static TokenRole MultiplyRole = new TokenRole ("*"); - public readonly static TokenRole DivideRole = new TokenRole ("/"); - public readonly static TokenRole ModulusRole = new TokenRole ("%"); - public readonly static TokenRole ShiftLeftRole = new TokenRole ("<<"); - public readonly static TokenRole ShiftRightRole = new TokenRole (">>"); - public readonly static TokenRole NullCoalescingRole = new TokenRole ("??"); - public readonly static TokenRole RangeRole = new TokenRole (".."); - + public readonly static TokenRole BitwiseAndRole = new TokenRole("&"); + public readonly static TokenRole BitwiseOrRole = new TokenRole("|"); + public readonly static TokenRole ConditionalAndRole = new TokenRole("&&"); + public readonly static TokenRole ConditionalOrRole = new TokenRole("||"); + public readonly static TokenRole ExclusiveOrRole = new TokenRole("^"); + public readonly static TokenRole GreaterThanRole = new TokenRole(">"); + public readonly static TokenRole GreaterThanOrEqualRole = new TokenRole(">="); + public readonly static TokenRole EqualityRole = new TokenRole("=="); + public readonly static TokenRole InEqualityRole = new TokenRole("!="); + public readonly static TokenRole LessThanRole = new TokenRole("<"); + public readonly static TokenRole LessThanOrEqualRole = new TokenRole("<="); + public readonly static TokenRole AddRole = new TokenRole("+"); + public readonly static TokenRole SubtractRole = new TokenRole("-"); + public readonly static TokenRole MultiplyRole = new TokenRole("*"); + public readonly static TokenRole DivideRole = new TokenRole("/"); + public readonly static TokenRole ModulusRole = new TokenRole("%"); + public readonly static TokenRole ShiftLeftRole = new TokenRole("<<"); + public readonly static TokenRole ShiftRightRole = new TokenRole(">>"); + public readonly static TokenRole NullCoalescingRole = new TokenRole("??"); + public readonly static TokenRole RangeRole = new TokenRole(".."); + public readonly static Role LeftRole = new Role("Left", Expression.Null); public readonly static Role RightRole = new Role("Right", Expression.Null); - + public BinaryOperatorExpression() { } - + public BinaryOperatorExpression(Expression left, BinaryOperatorType op, Expression right) { this.Left = left; this.Operator = op; this.Right = right; } - + public BinaryOperatorType Operator { get; set; } - + public Expression Left { - get { return GetChildByRole (LeftRole); } + get { return GetChildByRole(LeftRole); } set { SetChildByRole(LeftRole, value); } } - + public CSharpTokenNode OperatorToken { - get { return GetChildByRole (GetOperatorRole (Operator)); } + get { return GetChildByRole(GetOperatorRole(Operator)); } } - + public Expression Right { - get { return GetChildByRole (RightRole); } - set { SetChildByRole (RightRole, value); } + get { return GetChildByRole(RightRole); } + set { SetChildByRole(RightRole, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitBinaryOperatorExpression (this); + visitor.VisitBinaryOperatorExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitBinaryOperatorExpression (this); + return visitor.VisitBinaryOperatorExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitBinaryOperatorExpression (this, data); + return visitor.VisitBinaryOperatorExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { BinaryOperatorExpression o = other as BinaryOperatorExpression; return o != null && (this.Operator == BinaryOperatorType.Any || this.Operator == o.Operator) && this.Left.DoMatch(o.Left, match) && this.Right.DoMatch(o.Right, match); } - - public static TokenRole GetOperatorRole (BinaryOperatorType op) + + public static TokenRole GetOperatorRole(BinaryOperatorType op) { - switch (op) { + switch (op) + { case BinaryOperatorType.BitwiseAnd: return BitwiseAndRole; case BinaryOperatorType.BitwiseOr: @@ -158,10 +159,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax throw new NotSupportedException("Invalid value for BinaryOperatorType"); } } - + public static ExpressionType GetLinqNodeType(BinaryOperatorType op, bool checkForOverflow) { - switch (op) { + switch (op) + { case BinaryOperatorType.BitwiseAnd: return ExpressionType.And; case BinaryOperatorType.BitwiseOr: @@ -207,14 +209,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } } - + 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='||' @@ -229,7 +231,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ConditionalOr, /// left ^ right ExclusiveOr, - + /// left > right GreaterThan, /// left >= right @@ -242,7 +244,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax LessThan, /// left <= right LessThanOrEqual, - + /// left + right Add, /// left - right @@ -253,12 +255,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax Divide, /// left % right Modulus, - + /// left << right ShiftLeft, /// left >> right ShiftRight, - + /// left ?? right NullCoalescing, /// left .. right diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CastExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CastExpression.cs index 7fa21e4ca..f3bd22ec2 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CastExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CastExpression.cs @@ -33,48 +33,48 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class CastExpression : Expression { public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - - public CastExpression () + + public CastExpression() { } - public CastExpression (AstType castToType, Expression expression) + public CastExpression(AstType castToType, Expression expression) { - AddChild (castToType, Roles.Type); - AddChild (expression, Roles.Expression); + AddChild(castToType, Roles.Type); + AddChild(expression, Roles.Expression); } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitCastExpression (this); + visitor.VisitCastExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitCastExpression (this); + return visitor.VisitCastExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitCastExpression (this, data); + return visitor.VisitCastExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { CastExpression o = other as CastExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CheckedExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CheckedExpression.cs index 64dde7ba2..baff6c51a 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CheckedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CheckedExpression.cs @@ -32,49 +32,49 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class CheckedExpression : Expression { - public readonly static TokenRole CheckedKeywordRole = new TokenRole ("checked"); - + public readonly static TokenRole CheckedKeywordRole = new TokenRole("checked"); + public CSharpTokenNode CheckedToken { - get { return GetChildByRole (CheckedKeywordRole); } + get { return GetChildByRole(CheckedKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } + get { return GetChildByRole(Roles.Expression); } set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - - public CheckedExpression () + + public CheckedExpression() { } - - public CheckedExpression (Expression expression) + + public CheckedExpression(Expression expression) { - AddChild (expression, Roles.Expression); + AddChild(expression, Roles.Expression); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitCheckedExpression (this); + visitor.VisitCheckedExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitCheckedExpression (this); + return visitor.VisitCheckedExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitCheckedExpression (this, data); + return visitor.VisitCheckedExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { CheckedExpression o = other as CheckedExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ConditionalExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ConditionalExpression.cs index 098aa8d4f..a1576e5cc 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ConditionalExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ConditionalExpression.cs @@ -37,56 +37,56 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public readonly static Role TrueRole = new Role("True", Expression.Null); public readonly static TokenRole ColonRole = Roles.Colon; public readonly static Role FalseRole = new Role("False", Expression.Null); - + public Expression Condition { get { return GetChildByRole(ConditionRole); } set { SetChildByRole(ConditionRole, value); } } - + public CSharpTokenNode QuestionMarkToken { - get { return GetChildByRole (QuestionMarkRole); } + get { return GetChildByRole(QuestionMarkRole); } } - + public Expression TrueExpression { get { return GetChildByRole(TrueRole); } set { SetChildByRole(TrueRole, value); } } - + public CSharpTokenNode ColonToken { - get { return GetChildByRole (ColonRole); } + get { return GetChildByRole(ColonRole); } } - + public Expression FalseExpression { get { return GetChildByRole(FalseRole); } set { SetChildByRole(FalseRole, value); } } - - public ConditionalExpression () + + public ConditionalExpression() { } - - public ConditionalExpression (Expression condition, Expression trueExpression, Expression falseExpression) + + public ConditionalExpression(Expression condition, Expression trueExpression, Expression falseExpression) { - AddChild (condition, ConditionRole); - AddChild (trueExpression, TrueRole); - AddChild (falseExpression, FalseRole); + AddChild(condition, ConditionRole); + AddChild(trueExpression, TrueRole); + AddChild(falseExpression, FalseRole); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitConditionalExpression (this); + visitor.VisitConditionalExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitConditionalExpression (this); + return visitor.VisitConditionalExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitConditionalExpression (this, data); + return visitor.VisitConditionalExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ConditionalExpression o = other as ConditionalExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DefaultValueExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DefaultValueExpression.cs index 93e33d4a6..372325a40 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DefaultValueExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DefaultValueExpression.cs @@ -32,49 +32,49 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class DefaultValueExpression : Expression { - public readonly static TokenRole DefaultKeywordRole = new TokenRole ("default"); + public readonly static TokenRole DefaultKeywordRole = new TokenRole("default"); public CSharpTokenNode DefaultToken { - get { return GetChildByRole (DefaultKeywordRole); } + get { return GetChildByRole(DefaultKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } + get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - - public DefaultValueExpression () + + public DefaultValueExpression() { } - - public DefaultValueExpression (AstType type) + + public DefaultValueExpression(AstType type) { - AddChild (type, Roles.Type); + AddChild(type, Roles.Type); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitDefaultValueExpression (this); + visitor.VisitDefaultValueExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitDefaultValueExpression (this); + return visitor.VisitDefaultValueExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitDefaultValueExpression (this, data); + return visitor.VisitDefaultValueExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { DefaultValueExpression o = other as DefaultValueExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DirectionExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DirectionExpression.cs index 4af225c1f..e92115530 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DirectionExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DirectionExpression.cs @@ -34,13 +34,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax Ref, In } - + /// /// ref Expression /// public class DirectionExpression : Expression { - public readonly static TokenRole RefKeywordRole = new TokenRole ("ref"); + public readonly static TokenRole RefKeywordRole = new TokenRole("ref"); public readonly static TokenRole OutKeywordRole = new TokenRole("out"); public readonly static TokenRole InKeywordRole = new TokenRole("in"); @@ -48,10 +48,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get; set; } - + public CSharpTokenNode FieldDirectionToken { get { - switch (FieldDirection) { + switch (FieldDirection) + { case FieldDirection.Ref: return GetChildByRole(RefKeywordRole); case FieldDirection.In: @@ -61,37 +62,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - - public DirectionExpression () + + public DirectionExpression() { } - - public DirectionExpression (FieldDirection direction, Expression expression) + + public DirectionExpression(FieldDirection direction, Expression expression) { this.FieldDirection = direction; - AddChild (expression, Roles.Expression); + AddChild(expression, Roles.Expression); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitDirectionExpression (this); + visitor.VisitDirectionExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitDirectionExpression (this); + return visitor.VisitDirectionExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitDirectionExpression (this, data); + return visitor.VisitDirectionExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { DirectionExpression o = other as DirectionExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ErrorExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ErrorExpression.cs index 713e71166..89f9fcfdd 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ErrorExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ErrorExpression.cs @@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return Location; } } - + public override TextLocation EndLocation { get { return Location; @@ -48,31 +48,31 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax private set; } - public ErrorExpression () + public ErrorExpression() { } - public ErrorExpression (string error) + public ErrorExpression(string error) { AddChild(new Comment(error, CommentType.MultiLine), Roles.Comment); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitErrorNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitErrorNode(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitErrorNode(this, data); } - protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { var o = other as ErrorExpression; return o != null; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/Expression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/Expression.cs index 4089fd7f8..c5d73352e 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/Expression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/Expression.cs @@ -31,8 +31,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public abstract class Expression : AstNode { #region Null - public new static readonly Expression Null = new NullExpression (); - + public new static readonly Expression Null = new NullExpression(); + sealed class NullExpression : Expression { public override bool IsNull { @@ -40,81 +40,81 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } } #endregion - + #region PatternPlaceholder public static implicit operator Expression(PatternMatching.Pattern pattern) { return pattern != null ? new PatternPlaceholder(pattern) : null; } - + sealed class PatternPlaceholder : Expression, PatternMatching.INode { readonly PatternMatching.Pattern child; - + public PatternPlaceholder(PatternMatching.Pattern child) { this.child = child; } - + public override NodeType NodeType { get { return NodeType.Pattern; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitPatternPlaceholder(this, child); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitPatternPlaceholder(this, child); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitPatternPlaceholder(this, child, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return child.DoMatch(other, match); } - + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) { return child.DoMatchCollection(role, pos, match, backtrackingInfo); } } #endregion - + public override NodeType NodeType { get { return NodeType.Expression; } } - + public new Expression Clone() { return (Expression)base.Clone(); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IdentifierExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IdentifierExpression.cs index 0c5839886..76fc8c2a5 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IdentifierExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IdentifierExpression.cs @@ -31,54 +31,54 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public IdentifierExpression() { } - + public IdentifierExpression(string identifier) { this.Identifier = identifier; } - + public IdentifierExpression(string identifier, TextLocation location) { - SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create (identifier, location)); + SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create(identifier, location)); } - + public string Identifier { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create(value)); } } public Identifier IdentifierToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } public AstNodeCollection TypeArguments { - get { return GetChildrenByRole (Roles.TypeArgument); } + get { return GetChildrenByRole(Roles.TypeArgument); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitIdentifierExpression (this); + visitor.VisitIdentifierExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitIdentifierExpression (this); + return visitor.VisitIdentifierExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitIdentifierExpression (this, data); + return visitor.VisitIdentifierExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { IdentifierExpression o = other as IdentifierExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IndexerExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IndexerExpression.cs index e800ac993..e688b2a74 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IndexerExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IndexerExpression.cs @@ -34,55 +34,57 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class IndexerExpression : Expression { public Expression Target { - get { return GetChildByRole (Roles.TargetExpression); } + get { return GetChildByRole(Roles.TargetExpression); } set { SetChildByRole(Roles.TargetExpression, value); } } - + public CSharpTokenNode LBracketToken { - get { return GetChildByRole (Roles.LBracket); } + get { return GetChildByRole(Roles.LBracket); } } - + public AstNodeCollection Arguments { get { return GetChildrenByRole(Roles.Argument); } } - + public CSharpTokenNode RBracketToken { - get { return GetChildByRole (Roles.RBracket); } + get { return GetChildByRole(Roles.RBracket); } } - - public IndexerExpression () + + public IndexerExpression() { } - - public IndexerExpression (Expression target, IEnumerable arguments) + + public IndexerExpression(Expression target, IEnumerable arguments) { - AddChild (target, Roles.TargetExpression); - if (arguments != null) { - foreach (var arg in arguments) { - AddChild (arg, Roles.Argument); + AddChild(target, Roles.TargetExpression); + if (arguments != null) + { + foreach (var arg in arguments) + { + AddChild(arg, Roles.Argument); } } } - - public IndexerExpression (Expression target, params Expression[] arguments) : this (target, (IEnumerable)arguments) + + public IndexerExpression(Expression target, params Expression[] arguments) : this(target, (IEnumerable)arguments) { } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitIndexerExpression (this); + visitor.VisitIndexerExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitIndexerExpression (this); + return visitor.VisitIndexerExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitIndexerExpression (this, data); + return visitor.VisitIndexerExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { IndexerExpression o = other as IndexerExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InterpolatedStringExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InterpolatedStringExpression.cs index 4da978a63..9f7c6ab47 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InterpolatedStringExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InterpolatedStringExpression.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; + using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; namespace ICSharpCode.Decompiler.CSharp.Syntax diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InvocationExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InvocationExpression.cs index c2d11fcb3..3ed91cefc 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InvocationExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InvocationExpression.cs @@ -34,55 +34,57 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class InvocationExpression : Expression { public Expression Target { - get { return GetChildByRole (Roles.TargetExpression); } + get { return GetChildByRole(Roles.TargetExpression); } set { SetChildByRole(Roles.TargetExpression, value); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstNodeCollection Arguments { get { return GetChildrenByRole(Roles.Argument); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitInvocationExpression (this); + visitor.VisitInvocationExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitInvocationExpression (this); + return visitor.VisitInvocationExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitInvocationExpression (this, data); + return visitor.VisitInvocationExpression(this, data); } - - public InvocationExpression () + + public InvocationExpression() { } - - public InvocationExpression (Expression target, IEnumerable arguments) + + public InvocationExpression(Expression target, IEnumerable arguments) { - AddChild (target, Roles.TargetExpression); - if (arguments != null) { - foreach (var arg in arguments) { - AddChild (arg, Roles.Argument); + 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) + + 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; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IsExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IsExpression.cs index 8a65eaee8..fa1bea0bc 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IsExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IsExpression.cs @@ -32,17 +32,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class IsExpression : Expression { - public readonly static TokenRole IsKeywordRole = new TokenRole ("is"); - + public readonly static TokenRole IsKeywordRole = new TokenRole("is"); + public Expression Expression { get { return GetChildByRole(Roles.Expression); } set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode IsToken { - get { return GetChildByRole (IsKeywordRole); } + get { return GetChildByRole(IsKeywordRole); } } - + public AstType Type { get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } @@ -52,28 +52,28 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { } - public IsExpression (Expression expression, AstType type) + public IsExpression(Expression expression, AstType type) { - AddChild (expression, Roles.Expression); - AddChild (type, Roles.Type); + AddChild(expression, Roles.Expression); + AddChild(type, Roles.Type); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitIsExpression (this); + visitor.VisitIsExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitIsExpression (this); + return visitor.VisitIsExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitIsExpression (this, data); + return visitor.VisitIsExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { IsExpression o = other as IsExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/LambdaExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/LambdaExpression.cs index 30ed76fa1..c3829d882 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/LambdaExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/LambdaExpression.cs @@ -31,52 +31,52 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class LambdaExpression : Expression { - public readonly static TokenRole AsyncModifierRole = new TokenRole ("async"); + public readonly static TokenRole AsyncModifierRole = new TokenRole("async"); public static readonly Role BodyRole = new Role("Body", AstNode.Null); - + bool isAsync; - + public bool IsAsync { get { return isAsync; } set { ThrowIfFrozen(); isAsync = value; } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } public AstNodeCollection Parameters { - get { return GetChildrenByRole (Roles.Parameter); } + get { return GetChildrenByRole(Roles.Parameter); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } public CSharpTokenNode ArrowToken { - get { return GetChildByRole (Roles.Arrow); } + get { return GetChildByRole(Roles.Arrow); } } - + public AstNode Body { - get { return GetChildByRole (BodyRole); } - set { SetChildByRole (BodyRole, value); } + get { return GetChildByRole(BodyRole); } + set { SetChildByRole(BodyRole, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitLambdaExpression (this); + visitor.VisitLambdaExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitLambdaExpression (this); + return visitor.VisitLambdaExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitLambdaExpression (this, data); + return visitor.VisitLambdaExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { LambdaExpression o = other as LambdaExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/MemberReferenceExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/MemberReferenceExpression.cs index d3085736a..fcda03b54 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/MemberReferenceExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/MemberReferenceExpression.cs @@ -43,73 +43,75 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } public CSharpTokenNode DotToken { - get { return GetChildByRole (Roles.Dot); } + get { return GetChildByRole(Roles.Dot); } } - + public string MemberName { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier MemberNameToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } - + public CSharpTokenNode LChevronToken { - get { return GetChildByRole (Roles.LChevron); } + get { return GetChildByRole(Roles.LChevron); } } - + public AstNodeCollection TypeArguments { - get { return GetChildrenByRole (Roles.TypeArgument); } + get { return GetChildrenByRole(Roles.TypeArgument); } } - + public CSharpTokenNode RChevronToken { - get { return GetChildByRole (Roles.RChevron); } + get { return GetChildByRole(Roles.RChevron); } } - - public MemberReferenceExpression () + + public MemberReferenceExpression() { } - - public MemberReferenceExpression (Expression target, string memberName, IEnumerable arguments = null) + + public MemberReferenceExpression(Expression target, string memberName, IEnumerable arguments = null) { - AddChild (target, Roles.TargetExpression); + AddChild(target, Roles.TargetExpression); MemberName = memberName; - if (arguments != null) { - foreach (var arg in arguments) { - AddChild (arg, Roles.TypeArgument); + if (arguments != null) + { + foreach (var arg in arguments) + { + AddChild(arg, Roles.TypeArgument); } } } - - public MemberReferenceExpression (Expression target, string memberName, params AstType[] arguments) : this (target, memberName, (IEnumerable)arguments) + + public MemberReferenceExpression(Expression target, string memberName, params AstType[] arguments) : this(target, memberName, (IEnumerable)arguments) { } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitMemberReferenceExpression (this); + visitor.VisitMemberReferenceExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitMemberReferenceExpression (this); + return visitor.VisitMemberReferenceExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitMemberReferenceExpression (this, data); + return visitor.VisitMemberReferenceExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { MemberReferenceExpression o = other as MemberReferenceExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NamedArgumentExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NamedArgumentExpression.cs index a15e4d774..5f3fb3627 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NamedArgumentExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NamedArgumentExpression.cs @@ -28,55 +28,55 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public NamedArgumentExpression() { } - + public NamedArgumentExpression(string name, Expression expression) { this.Name = name; this.Expression = expression; } - + public string Name { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier NameToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { SetChildByRole(Roles.Identifier, value); } } - + public CSharpTokenNode ColonToken { - get { return GetChildByRole (Roles.Colon); } + get { return GetChildByRole(Roles.Colon); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitNamedArgumentExpression (this); + visitor.VisitNamedArgumentExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitNamedArgumentExpression (this); + return visitor.VisitNamedArgumentExpression(this); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNamedArgumentExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { NamedArgumentExpression o = other as NamedArgumentExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NamedExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NamedExpression.cs index 25eec4caa..d8fe23df8 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NamedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NamedExpression.cs @@ -37,55 +37,55 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public NamedExpression() { } - - public NamedExpression (string name, Expression expression) + + public NamedExpression(string name, Expression expression) { this.Name = name; this.Expression = expression; } - + public string Name { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier NameToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { SetChildByRole(Roles.Identifier, value); } } - + public CSharpTokenNode AssignToken { - get { return GetChildByRole (Roles.Assign); } + get { return GetChildByRole(Roles.Assign); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitNamedExpression (this); + visitor.VisitNamedExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitNamedExpression (this); + return visitor.VisitNamedExpression(this); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNamedExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { var o = other as NamedExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NullReferenceExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NullReferenceExpression.cs index ae3db7e80..ee67fb20f 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NullReferenceExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NullReferenceExpression.cs @@ -38,43 +38,43 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return location; } } - + internal void SetStartLocation(TextLocation value) { ThrowIfFrozen(); this.location = value; } - + public override TextLocation EndLocation { get { - return new TextLocation (location.Line, location.Column + "null".Length); + return new TextLocation(location.Line, location.Column + "null".Length); } } - - public NullReferenceExpression () + + public NullReferenceExpression() { } - - public NullReferenceExpression (TextLocation location) + + public NullReferenceExpression(TextLocation location) { this.location = location; } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitNullReferenceExpression (this); + visitor.VisitNullReferenceExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitNullReferenceExpression (this); + return visitor.VisitNullReferenceExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitNullReferenceExpression (this, data); + return visitor.VisitNullReferenceExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { NullReferenceExpression o = other as NullReferenceExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ObjectCreateExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ObjectCreateExpression.cs index 8ffb1fdf5..f559f6a89 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ObjectCreateExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ObjectCreateExpression.cs @@ -33,68 +33,70 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class ObjectCreateExpression : Expression { - public readonly static TokenRole NewKeywordRole = new TokenRole ("new"); + public readonly static TokenRole NewKeywordRole = new TokenRole("new"); public readonly static Role InitializerRole = ArrayCreateExpression.InitializerRole; - + public CSharpTokenNode NewToken { - get { return GetChildByRole (NewKeywordRole); } + get { return GetChildByRole(NewKeywordRole); } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstNodeCollection Arguments { - get { return GetChildrenByRole (Roles.Argument); } + get { return GetChildrenByRole(Roles.Argument); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public ArrayInitializerExpression Initializer { - get { return GetChildByRole (InitializerRole); } - set { SetChildByRole (InitializerRole, value); } + get { return GetChildByRole(InitializerRole); } + set { SetChildByRole(InitializerRole, value); } } - - public ObjectCreateExpression () + + public ObjectCreateExpression() { } - - public ObjectCreateExpression (AstType type, IEnumerable arguments = null) + + public ObjectCreateExpression(AstType type, IEnumerable arguments = null) { - AddChild (type, Roles.Type); - if (arguments != null) { - foreach (var arg in arguments) { - AddChild (arg, Roles.Argument); + AddChild(type, Roles.Type); + if (arguments != null) + { + foreach (var arg in arguments) + { + AddChild(arg, Roles.Argument); } } } - - public ObjectCreateExpression (AstType type, params Expression[] arguments) : this (type, (IEnumerable)arguments) + + public ObjectCreateExpression(AstType type, params Expression[] arguments) : this(type, (IEnumerable)arguments) { } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitObjectCreateExpression (this); + visitor.VisitObjectCreateExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitObjectCreateExpression (this); + return visitor.VisitObjectCreateExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitObjectCreateExpression (this, data); + return visitor.VisitObjectCreateExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ObjectCreateExpression o = other as ObjectCreateExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ParenthesizedExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ParenthesizedExpression.cs index 1619fb619..b662ab3d4 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ParenthesizedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ParenthesizedExpression.cs @@ -33,48 +33,48 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class ParenthesizedExpression : Expression { public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public ParenthesizedExpression() { } - + public ParenthesizedExpression(Expression expr) { Expression = expr; } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitParenthesizedExpression (this); + visitor.VisitParenthesizedExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitParenthesizedExpression (this); + return visitor.VisitParenthesizedExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitParenthesizedExpression (this, data); + return visitor.VisitParenthesizedExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ParenthesizedExpression o = other as ParenthesizedExpression; return o != null && this.Expression.DoMatch(o.Expression, match); } - + /// /// Gets whether the expression acts like a parenthesized expression, /// i.e. whether information about the expected type (for lambda type inference) flows @@ -85,7 +85,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return expression is ParenthesizedExpression || expression is CheckedExpression || expression is UncheckedExpression; } - + /// /// Unpacks the given expression if it is a ParenthesizedExpression, CheckedExpression or UncheckedExpression. /// diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PointerReferenceExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PointerReferenceExpression.cs index 83d19b9cd..d678cdaf8 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PointerReferenceExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PointerReferenceExpression.cs @@ -32,54 +32,54 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class PointerReferenceExpression : Expression { - public readonly static TokenRole ArrowRole = new TokenRole ("->"); - + public readonly static TokenRole ArrowRole = new TokenRole("->"); + public Expression Target { - get { return GetChildByRole (Roles.TargetExpression); } + get { return GetChildByRole(Roles.TargetExpression); } set { SetChildByRole(Roles.TargetExpression, value); } } - + public CSharpTokenNode ArrowToken { - get { return GetChildByRole (ArrowRole); } + get { return GetChildByRole(ArrowRole); } } - + public string MemberName { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier MemberNameToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } - + public AstNodeCollection TypeArguments { - get { return GetChildrenByRole (Roles.TypeArgument); } + get { return GetChildrenByRole(Roles.TypeArgument); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitPointerReferenceExpression (this); + visitor.VisitPointerReferenceExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitPointerReferenceExpression (this); + return visitor.VisitPointerReferenceExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitPointerReferenceExpression (this, data); + return visitor.VisitPointerReferenceExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { PointerReferenceExpression o = other as PointerReferenceExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PrimitiveExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PrimitiveExpression.cs index eb45b4278..1e2138338 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PrimitiveExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PrimitiveExpression.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -49,19 +50,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class PrimitiveExpression : Expression { public static readonly object AnyValue = new object(); - + TextLocation startLocation; TextLocation endLocation; - public override TextLocation StartLocation => startLocation; - public override TextLocation EndLocation => endLocation; - + public override TextLocation StartLocation => startLocation; + public override TextLocation EndLocation => endLocation; + internal void SetLocation(TextLocation startLocation, TextLocation endLocation) { ThrowIfFrozen(); this.startLocation = startLocation; this.endLocation = endLocation; } - + object value; LiteralFormat format; @@ -72,70 +73,75 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.value = value; } } - + public LiteralFormat Format { - get { return format;} + get { return format; } set { ThrowIfFrozen(); format = value; } } - public PrimitiveExpression (object value) + public PrimitiveExpression(object value) { this.Value = value; } - - public PrimitiveExpression (object value, LiteralFormat format) + + public PrimitiveExpression(object value, LiteralFormat format) { this.Value = value; this.format = format; } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitPrimitiveExpression (this); + visitor.VisitPrimitiveExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitPrimitiveExpression (this); + return visitor.VisitPrimitiveExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitPrimitiveExpression (this, data); + return visitor.VisitPrimitiveExpression(this, data); } unsafe static TextLocation AdvanceLocation(TextLocation startLocation, string str) { int line = startLocation.Line; - int col = startLocation.Column; - fixed (char* start = str) { + int col = startLocation.Column; + fixed (char* start = str) + { char* p = start; char* endPtr = start + str.Length; - while (p < endPtr) { + while (p < endPtr) + { var nl = NewLine.GetDelimiterLength(*p, () => { char* nextp = p + 1; if (nextp < endPtr) return *nextp; return '\0'; }); - if (nl > 0) { + if (nl > 0) + { line++; col = 1; if (nl == 2) p++; - } else { + } + else + { col++; } p++; } } - return new TextLocation (line, col); + return new TextLocation(line, col); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { PrimitiveExpression o = other as PrimitiveExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs index c8f599100..6b91ec02f 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs @@ -23,10 +23,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class QueryExpression : Expression { public static readonly Role ClauseRole = new Role("Clause"); - + #region Null - public new static readonly QueryExpression Null = new NullQueryExpression (); - + public new static readonly QueryExpression Null = new NullQueryExpression(); + sealed class NullQueryExpression : QueryExpression { public override bool IsNull { @@ -34,62 +34,62 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } } #endregion - + public AstNodeCollection Clauses { get { return GetChildrenByRole(ClauseRole); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitQueryExpression (this); + visitor.VisitQueryExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitQueryExpression (this); + return visitor.VisitQueryExpression(this); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitQueryExpression (this, data); + return visitor.VisitQueryExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QueryExpression o = other as QueryExpression; return o != null && !o.IsNull && this.Clauses.DoMatch(o.Clauses, match); } } - + public abstract class QueryClause : AstNode { public override NodeType NodeType { get { return NodeType.QueryClause; } } } - + /// /// Represents a query continuation. /// "(from .. select ..) into Identifier" or "(from .. group .. by ..) into Identifier" @@ -111,103 +111,103 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class QueryContinuationClause : QueryClause { public static readonly Role PrecedingQueryRole = new Role("PrecedingQuery", QueryExpression.Null); - public static readonly TokenRole IntoKeywordRole = new TokenRole ("into"); - + public static readonly TokenRole IntoKeywordRole = new TokenRole("into"); + public QueryExpression PrecedingQuery { get { return GetChildByRole(PrecedingQueryRole); } set { SetChildByRole(PrecedingQueryRole, value); } } - + public CSharpTokenNode IntoKeyword { - get { return GetChildByRole (IntoKeywordRole); } + get { return GetChildByRole(IntoKeywordRole); } } public string Identifier { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create(value)); } } - + public Identifier IdentifierToken { - get { return GetChildByRole (Roles.Identifier); } + get { return GetChildByRole(Roles.Identifier); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitQueryContinuationClause (this); + visitor.VisitQueryContinuationClause(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitQueryContinuationClause (this); + return visitor.VisitQueryContinuationClause(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitQueryContinuationClause (this, data); + return visitor.VisitQueryContinuationClause(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QueryContinuationClause o = other as QueryContinuationClause; return o != null && MatchString(this.Identifier, o.Identifier) && this.PrecedingQuery.DoMatch(o.PrecedingQuery, match); } } - + public class QueryFromClause : QueryClause { - public static readonly TokenRole FromKeywordRole = new TokenRole ("from"); - public static readonly TokenRole InKeywordRole = new TokenRole ("in"); - + public static readonly TokenRole FromKeywordRole = new TokenRole("from"); + public static readonly TokenRole InKeywordRole = new TokenRole("in"); + public CSharpTokenNode FromKeyword { - get { return GetChildByRole (FromKeywordRole); } + get { return GetChildByRole(FromKeywordRole); } } public AstType Type { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } } - + public string Identifier { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create(value)); } } - + public Identifier IdentifierToken { get { return GetChildByRole(Roles.Identifier); } } - + public CSharpTokenNode InKeyword { - get { return GetChildByRole (InKeywordRole); } + get { return GetChildByRole(InKeywordRole); } } public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitQueryFromClause (this); + visitor.VisitQueryFromClause(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitQueryFromClause (this); + return visitor.VisitQueryFromClause(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitQueryFromClause (this, data); + return visitor.VisitQueryFromClause(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QueryFromClause o = other as QueryFromClause; @@ -215,197 +215,197 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax && this.Expression.DoMatch(o.Expression, match); } } - + public class QueryLetClause : QueryClause { - public readonly static TokenRole LetKeywordRole = new TokenRole ("let"); - + public readonly static TokenRole LetKeywordRole = new TokenRole("let"); + public CSharpTokenNode LetKeyword { get { return GetChildByRole(LetKeywordRole); } } - + public string Identifier { get { return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create(value)); } } - + public Identifier IdentifierToken { get { return GetChildByRole(Roles.Identifier); } } - + public CSharpTokenNode AssignToken { get { return GetChildByRole(Roles.Assign); } } - + public Expression Expression { get { return GetChildByRole(Roles.Expression); } set { SetChildByRole(Roles.Expression, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitQueryLetClause (this); + visitor.VisitQueryLetClause(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitQueryLetClause (this); + return visitor.VisitQueryLetClause(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitQueryLetClause (this, data); + return visitor.VisitQueryLetClause(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QueryLetClause o = other as QueryLetClause; return o != null && MatchString(this.Identifier, o.Identifier) && this.Expression.DoMatch(o.Expression, match); } } - - + + public class QueryWhereClause : QueryClause { - public readonly static TokenRole WhereKeywordRole = new TokenRole ("where"); + public readonly static TokenRole WhereKeywordRole = new TokenRole("where"); public CSharpTokenNode WhereKeyword { - get { return GetChildByRole (WhereKeywordRole); } + get { return GetChildByRole(WhereKeywordRole); } } - + public Expression Condition { - get { return GetChildByRole (Roles.Condition); } - set { SetChildByRole (Roles.Condition, value); } + get { return GetChildByRole(Roles.Condition); } + set { SetChildByRole(Roles.Condition, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitQueryWhereClause (this); + visitor.VisitQueryWhereClause(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitQueryWhereClause (this); + return visitor.VisitQueryWhereClause(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitQueryWhereClause (this, data); + return visitor.VisitQueryWhereClause(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QueryWhereClause o = other as QueryWhereClause; return o != null && this.Condition.DoMatch(o.Condition, match); } } - + /// /// Represents a join or group join clause. /// public class QueryJoinClause : QueryClause { - public static readonly TokenRole JoinKeywordRole = new TokenRole ("join"); + public static readonly TokenRole JoinKeywordRole = new TokenRole("join"); public static readonly Role TypeRole = Roles.Type; public static readonly Role JoinIdentifierRole = Roles.Identifier; - public static readonly TokenRole InKeywordRole = new TokenRole ("in"); + public static readonly TokenRole InKeywordRole = new TokenRole("in"); public static readonly Role InExpressionRole = Roles.Expression; - public static readonly TokenRole OnKeywordRole = new TokenRole ("on"); + public static readonly TokenRole OnKeywordRole = new TokenRole("on"); public static readonly Role OnExpressionRole = new Role("OnExpression", Expression.Null); - public static readonly TokenRole EqualsKeywordRole = new TokenRole ("equals"); + public static readonly TokenRole EqualsKeywordRole = new TokenRole("equals"); public static readonly Role EqualsExpressionRole = new Role("EqualsExpression", Expression.Null); - public static readonly TokenRole IntoKeywordRole = new TokenRole ("into"); + public static readonly TokenRole IntoKeywordRole = new TokenRole("into"); public static readonly Role IntoIdentifierRole = new Role("IntoIdentifier", Identifier.Null); - + public bool IsGroupJoin { get { return !string.IsNullOrEmpty(this.IntoIdentifier); } } - + public CSharpTokenNode JoinKeyword { - get { return GetChildByRole (JoinKeywordRole); } + get { return GetChildByRole(JoinKeywordRole); } } - + public AstType Type { - get { return GetChildByRole (TypeRole); } - set { SetChildByRole (TypeRole, value); } + get { return GetChildByRole(TypeRole); } + set { SetChildByRole(TypeRole, value); } } - + public string JoinIdentifier { get { return GetChildByRole(JoinIdentifierRole).Name; } set { - SetChildByRole(JoinIdentifierRole, Identifier.Create (value)); + SetChildByRole(JoinIdentifierRole, Identifier.Create(value)); } } - + public Identifier JoinIdentifierToken { get { return GetChildByRole(JoinIdentifierRole); } } - + public CSharpTokenNode InKeyword { - get { return GetChildByRole (InKeywordRole); } + get { return GetChildByRole(InKeywordRole); } } - + public Expression InExpression { - get { return GetChildByRole (InExpressionRole); } - set { SetChildByRole (InExpressionRole, value); } + get { return GetChildByRole(InExpressionRole); } + set { SetChildByRole(InExpressionRole, value); } } - + public CSharpTokenNode OnKeyword { - get { return GetChildByRole (OnKeywordRole); } + get { return GetChildByRole(OnKeywordRole); } } - + public Expression OnExpression { - get { return GetChildByRole (OnExpressionRole); } - set { SetChildByRole (OnExpressionRole, value); } + get { return GetChildByRole(OnExpressionRole); } + set { SetChildByRole(OnExpressionRole, value); } } - + public CSharpTokenNode EqualsKeyword { - get { return GetChildByRole (EqualsKeywordRole); } + get { return GetChildByRole(EqualsKeywordRole); } } - + public Expression EqualsExpression { - get { return GetChildByRole (EqualsExpressionRole); } - set { SetChildByRole (EqualsExpressionRole, value); } + get { return GetChildByRole(EqualsExpressionRole); } + set { SetChildByRole(EqualsExpressionRole, value); } } - + public CSharpTokenNode IntoKeyword { - get { return GetChildByRole (IntoKeywordRole); } + get { return GetChildByRole(IntoKeywordRole); } } - + public string IntoIdentifier { get { - return GetChildByRole (IntoIdentifierRole).Name; + return GetChildByRole(IntoIdentifierRole).Name; } set { - SetChildByRole(IntoIdentifierRole, Identifier.Create (value)); + SetChildByRole(IntoIdentifierRole, Identifier.Create(value)); } } - + public Identifier IntoIdentifierToken { get { return GetChildByRole(IntoIdentifierRole); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitQueryJoinClause (this); + visitor.VisitQueryJoinClause(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitQueryJoinClause (this); + return visitor.VisitQueryJoinClause(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitQueryJoinClause (this, data); + return visitor.VisitQueryJoinClause(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QueryJoinClause o = other as QueryJoinClause; @@ -416,169 +416,169 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax && MatchString(this.IntoIdentifier, o.IntoIdentifier); } } - + public class QueryOrderClause : QueryClause { - public static readonly TokenRole OrderbyKeywordRole = new TokenRole ("orderby"); + public static readonly TokenRole OrderbyKeywordRole = new TokenRole("orderby"); public static readonly Role OrderingRole = new Role("Ordering"); - + public CSharpTokenNode OrderbyToken { - get { return GetChildByRole (OrderbyKeywordRole); } + get { return GetChildByRole(OrderbyKeywordRole); } } - + public AstNodeCollection Orderings { - get { return GetChildrenByRole (OrderingRole); } + get { return GetChildrenByRole(OrderingRole); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitQueryOrderClause (this); + visitor.VisitQueryOrderClause(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitQueryOrderClause (this); + return visitor.VisitQueryOrderClause(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitQueryOrderClause (this, data); + return visitor.VisitQueryOrderClause(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QueryOrderClause o = other as QueryOrderClause; return o != null && this.Orderings.DoMatch(o.Orderings, match); } } - + public class QueryOrdering : AstNode { - public readonly static TokenRole AscendingKeywordRole = new TokenRole ("ascending"); - public readonly static TokenRole DescendingKeywordRole = new TokenRole ("descending"); + public readonly static TokenRole AscendingKeywordRole = new TokenRole("ascending"); + public readonly static TokenRole DescendingKeywordRole = new TokenRole("descending"); public override NodeType NodeType { get { return NodeType.Unknown; } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public QueryOrderingDirection Direction { get; set; } - + public CSharpTokenNode DirectionToken { - get { return Direction == QueryOrderingDirection.Ascending ? GetChildByRole (AscendingKeywordRole) : GetChildByRole (DescendingKeywordRole); } + get { return Direction == QueryOrderingDirection.Ascending ? GetChildByRole(AscendingKeywordRole) : GetChildByRole(DescendingKeywordRole); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitQueryOrdering (this); + visitor.VisitQueryOrdering(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitQueryOrdering (this); + return visitor.VisitQueryOrdering(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitQueryOrdering (this, data); + return visitor.VisitQueryOrdering(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QueryOrdering o = other as QueryOrdering; return o != null && this.Direction == o.Direction && this.Expression.DoMatch(o.Expression, match); } } - + public enum QueryOrderingDirection { None, Ascending, Descending } - + public class QuerySelectClause : QueryClause { - public readonly static TokenRole SelectKeywordRole = new TokenRole ("select"); + public readonly static TokenRole SelectKeywordRole = new TokenRole("select"); public CSharpTokenNode SelectKeyword { - get { return GetChildByRole (SelectKeywordRole); } + get { return GetChildByRole(SelectKeywordRole); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitQuerySelectClause (this); + visitor.VisitQuerySelectClause(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitQuerySelectClause (this); + return visitor.VisitQuerySelectClause(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitQuerySelectClause (this, data); + return visitor.VisitQuerySelectClause(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QuerySelectClause o = other as QuerySelectClause; return o != null && this.Expression.DoMatch(o.Expression, match); } } - + public class QueryGroupClause : QueryClause { - public static readonly TokenRole GroupKeywordRole = new TokenRole ("group"); + public static readonly TokenRole GroupKeywordRole = new TokenRole("group"); public static readonly Role ProjectionRole = new Role("Projection", Expression.Null); - public static readonly TokenRole ByKeywordRole = new TokenRole ("by"); + public static readonly TokenRole ByKeywordRole = new TokenRole("by"); public static readonly Role KeyRole = new Role("Key", Expression.Null); - + public CSharpTokenNode GroupKeyword { - get { return GetChildByRole (GroupKeywordRole); } + get { return GetChildByRole(GroupKeywordRole); } } - + public Expression Projection { - get { return GetChildByRole (ProjectionRole); } - set { SetChildByRole (ProjectionRole, value); } + get { return GetChildByRole(ProjectionRole); } + set { SetChildByRole(ProjectionRole, value); } } - + public CSharpTokenNode ByKeyword { - get { return GetChildByRole (ByKeywordRole); } + get { return GetChildByRole(ByKeywordRole); } } - + public Expression Key { - get { return GetChildByRole (KeyRole); } - set { SetChildByRole (KeyRole, value); } + get { return GetChildByRole(KeyRole); } + set { SetChildByRole(KeyRole, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitQueryGroupClause (this); + visitor.VisitQueryGroupClause(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitQueryGroupClause (this); + return visitor.VisitQueryGroupClause(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitQueryGroupClause (this, data); + return visitor.VisitQueryGroupClause(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QueryGroupClause o = other as QueryGroupClause; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SizeOfExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SizeOfExpression.cs index 77746e759..b5daa0a9f 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SizeOfExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SizeOfExpression.cs @@ -32,49 +32,49 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class SizeOfExpression : Expression { - public readonly static TokenRole SizeofKeywordRole = new TokenRole ("sizeof"); - + public readonly static TokenRole SizeofKeywordRole = new TokenRole("sizeof"); + public CSharpTokenNode SizeOfToken { - get { return GetChildByRole (SizeofKeywordRole); } + get { return GetChildByRole(SizeofKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } + get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - - public SizeOfExpression () + + public SizeOfExpression() { } - - public SizeOfExpression (AstType type) + + public SizeOfExpression(AstType type) { - AddChild (type, Roles.Type); + AddChild(type, Roles.Type); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitSizeOfExpression (this); + visitor.VisitSizeOfExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitSizeOfExpression (this); + return visitor.VisitSizeOfExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitSizeOfExpression (this, data); + return visitor.VisitSizeOfExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { SizeOfExpression o = other as SizeOfExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/StackAllocExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/StackAllocExpression.cs index d4c493df2..f3c1c9b85 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/StackAllocExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/StackAllocExpression.cs @@ -32,29 +32,29 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class StackAllocExpression : Expression { - public readonly static TokenRole StackallocKeywordRole = new TokenRole ("stackalloc"); + public readonly static TokenRole StackallocKeywordRole = new TokenRole("stackalloc"); public readonly static Role InitializerRole = new Role("Initializer", ArrayInitializerExpression.Null); public CSharpTokenNode StackAllocToken { - get { return GetChildByRole (StackallocKeywordRole); } + get { return GetChildByRole(StackallocKeywordRole); } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } + get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } } - + public CSharpTokenNode LBracketToken { - get { return GetChildByRole (Roles.LBracket); } + get { return GetChildByRole(Roles.LBracket); } } - + public Expression CountExpression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode RBracketToken { - get { return GetChildByRole (Roles.RBracket); } + get { return GetChildByRole(Roles.RBracket); } } public ArrayInitializerExpression Initializer { @@ -62,21 +62,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax set { SetChildByRole(InitializerRole, value); } } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitStackAllocExpression (this); + visitor.VisitStackAllocExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitStackAllocExpression (this); + return visitor.VisitStackAllocExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitStackAllocExpression (this, data); + return visitor.VisitStackAllocExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { StackAllocExpression o = other as StackAllocExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThisReferenceExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThisReferenceExpression.cs index aa3352cd1..db61e2dad 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThisReferenceExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThisReferenceExpression.cs @@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get; set; } - + public override TextLocation StartLocation { get { return Location; @@ -44,25 +44,25 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } public override TextLocation EndLocation { get { - return new TextLocation (Location.Line, Location.Column + "this".Length); + return new TextLocation(Location.Line, Location.Column + "this".Length); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitThisReferenceExpression (this); + visitor.VisitThisReferenceExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitThisReferenceExpression (this); + return visitor.VisitThisReferenceExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitThisReferenceExpression (this, data); + return visitor.VisitThisReferenceExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ThisReferenceExpression o = other as ThisReferenceExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThrowExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThrowExpression.cs index d346c2e3a..736d2da6d 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThrowExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThrowExpression.cs @@ -24,40 +24,40 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class ThrowExpression : Expression { public static readonly TokenRole ThrowKeywordRole = ThrowStatement.ThrowKeywordRole; - + public CSharpTokenNode ThrowToken { - get { return GetChildByRole (ThrowKeywordRole); } + get { return GetChildByRole(ThrowKeywordRole); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public ThrowExpression() { } - + public ThrowExpression(Expression expression) { - AddChild (expression, Roles.Expression); + AddChild(expression, Roles.Expression); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitThrowExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitThrowExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitThrowExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ThrowExpression o = other as ThrowExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TupleExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TupleExpression.cs index d6f75b93a..143726af4 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TupleExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TupleExpression.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; namespace ICSharpCode.Decompiler.CSharp.Syntax diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeOfExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeOfExpression.cs index 5cce240d3..b6605ab63 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeOfExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeOfExpression.cs @@ -33,49 +33,49 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class TypeOfExpression : Expression { - public readonly static TokenRole TypeofKeywordRole = new TokenRole ("typeof"); - + public readonly static TokenRole TypeofKeywordRole = new TokenRole("typeof"); + public CSharpTokenNode TypeOfToken { - get { return GetChildByRole (TypeofKeywordRole); } + get { return GetChildByRole(TypeofKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } + get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - - public TypeOfExpression () + + public TypeOfExpression() { } - - public TypeOfExpression (AstType type) + + public TypeOfExpression(AstType type) { - AddChild (type, Roles.Type); + AddChild(type, Roles.Type); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitTypeOfExpression (this); + visitor.VisitTypeOfExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitTypeOfExpression (this); + return visitor.VisitTypeOfExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitTypeOfExpression (this, data); + return visitor.VisitTypeOfExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { TypeOfExpression o = other as TypeOfExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeReferenceExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeReferenceExpression.cs index 2ed0b651a..57c8ea9fa 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeReferenceExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeReferenceExpression.cs @@ -29,31 +29,31 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitTypeReferenceExpression (this); + visitor.VisitTypeReferenceExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitTypeReferenceExpression (this); + return visitor.VisitTypeReferenceExpression(this); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitTypeReferenceExpression(this, data); } - - public TypeReferenceExpression () + + public TypeReferenceExpression() { } - - public TypeReferenceExpression (AstType type) + + public TypeReferenceExpression(AstType type) { - AddChild (type, Roles.Type); + AddChild(type, Roles.Type); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { TypeReferenceExpression o = other as TypeReferenceExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UnaryOperatorExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UnaryOperatorExpression.cs index eb29f2d65..af925fc14 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UnaryOperatorExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UnaryOperatorExpression.cs @@ -34,68 +34,69 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class UnaryOperatorExpression : Expression { - public readonly static TokenRole NotRole = new TokenRole ("!"); - public readonly static TokenRole BitNotRole = new TokenRole ("~"); - public readonly static TokenRole MinusRole = new TokenRole ("-"); - public readonly static TokenRole PlusRole = new TokenRole ("+"); - public readonly static TokenRole IncrementRole = new TokenRole ("++"); - public readonly static TokenRole DecrementRole = new TokenRole ("--"); - public readonly static TokenRole DereferenceRole = new TokenRole ("*"); - public readonly static TokenRole AddressOfRole = new TokenRole ("&"); - public readonly static TokenRole AwaitRole = new TokenRole ("await"); - public readonly static TokenRole NullConditionalRole = new TokenRole ("?"); - public readonly static TokenRole SuppressNullableWarningRole = new TokenRole ("!"); - public readonly static TokenRole IndexFromEndRole = new TokenRole ("^"); + public readonly static TokenRole NotRole = new TokenRole("!"); + public readonly static TokenRole BitNotRole = new TokenRole("~"); + public readonly static TokenRole MinusRole = new TokenRole("-"); + public readonly static TokenRole PlusRole = new TokenRole("+"); + public readonly static TokenRole IncrementRole = new TokenRole("++"); + public readonly static TokenRole DecrementRole = new TokenRole("--"); + public readonly static TokenRole DereferenceRole = new TokenRole("*"); + public readonly static TokenRole AddressOfRole = new TokenRole("&"); + public readonly static TokenRole AwaitRole = new TokenRole("await"); + public readonly static TokenRole NullConditionalRole = new TokenRole("?"); + public readonly static TokenRole SuppressNullableWarningRole = new TokenRole("!"); + public readonly static TokenRole IndexFromEndRole = new TokenRole("^"); public UnaryOperatorExpression() { } - + public UnaryOperatorExpression(UnaryOperatorType op, Expression expression) { this.Operator = op; this.Expression = expression; } - + public UnaryOperatorType Operator { get; set; } - + public CSharpTokenNode OperatorToken { - get { return GetChildByRole (GetOperatorRole (Operator)); } + get { return GetChildByRole(GetOperatorRole(Operator)); } } public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitUnaryOperatorExpression (this); + visitor.VisitUnaryOperatorExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitUnaryOperatorExpression (this); + return visitor.VisitUnaryOperatorExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitUnaryOperatorExpression (this, 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 == UnaryOperatorType.Any || this.Operator == o.Operator) && this.Expression.DoMatch(o.Expression, match); } - + public static TokenRole GetOperatorRole(UnaryOperatorType op) { - switch (op) { + switch (op) + { case UnaryOperatorType.Not: return NotRole; case UnaryOperatorType.BitNot: @@ -129,10 +130,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax throw new NotSupportedException("Invalid value for UnaryOperatorType"); } } - + public static ExpressionType GetLinqNodeType(UnaryOperatorType op, bool checkForOverflow) { - switch (op) { + switch (op) + { case UnaryOperatorType.Not: return ExpressionType.Not; case UnaryOperatorType.BitNot: @@ -160,14 +162,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } } - + public enum UnaryOperatorType { /// /// Any unary operator (used in pattern matching) /// Any, - + /// Logical not (!a) Not, /// Bitwise not (~a) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UncheckedExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UncheckedExpression.cs index eef0fd6ba..aa8160127 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UncheckedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UncheckedExpression.cs @@ -32,49 +32,49 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class UncheckedExpression : Expression { - public readonly static TokenRole UncheckedKeywordRole = new TokenRole ("unchecked"); + public readonly static TokenRole UncheckedKeywordRole = new TokenRole("unchecked"); public CSharpTokenNode UncheckedToken { - get { return GetChildByRole (UncheckedKeywordRole); } + get { return GetChildByRole(UncheckedKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } + get { return GetChildByRole(Roles.Expression); } set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - - public UncheckedExpression () + + public UncheckedExpression() { } - - public UncheckedExpression (Expression expression) + + public UncheckedExpression(Expression expression) { - AddChild (expression, Roles.Expression); + AddChild(expression, Roles.Expression); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitUncheckedExpression (this); + visitor.VisitUncheckedExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitUncheckedExpression (this); + return visitor.VisitUncheckedExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitUncheckedExpression (this, data); + return visitor.VisitUncheckedExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { UncheckedExpression o = other as UncheckedExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UndocumentedExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UndocumentedExpression.cs index 647bf3fc7..7de290d8d 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UndocumentedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UndocumentedExpression.cs @@ -35,65 +35,66 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax RefType, // __reftype (expr) MakeRef // __makeref (expr) } - + /// /// Represents undocumented expressions. /// public class UndocumentedExpression : Expression { - public readonly static TokenRole ArglistKeywordRole = new TokenRole ("__arglist"); - public readonly static TokenRole RefvalueKeywordRole = new TokenRole ("__refvalue"); - public readonly static TokenRole ReftypeKeywordRole = new TokenRole ("__reftype"); - public readonly static TokenRole MakerefKeywordRole = new TokenRole ("__makeref"); - + public readonly static TokenRole ArglistKeywordRole = new TokenRole("__arglist"); + public readonly static TokenRole RefvalueKeywordRole = new TokenRole("__refvalue"); + public readonly static TokenRole ReftypeKeywordRole = new TokenRole("__reftype"); + public readonly static TokenRole MakerefKeywordRole = new TokenRole("__makeref"); + public UndocumentedExpressionType UndocumentedExpressionType { get; set; } - + public CSharpTokenNode UndocumentedToken { get { - switch (UndocumentedExpressionType) { - case UndocumentedExpressionType.ArgListAccess: - case UndocumentedExpressionType.ArgList: - return GetChildByRole (ArglistKeywordRole); - case UndocumentedExpressionType.RefValue: - return GetChildByRole (RefvalueKeywordRole); - case UndocumentedExpressionType.RefType: - return GetChildByRole (ReftypeKeywordRole); - case UndocumentedExpressionType.MakeRef: - return GetChildByRole (MakerefKeywordRole); + switch (UndocumentedExpressionType) + { + case UndocumentedExpressionType.ArgListAccess: + case UndocumentedExpressionType.ArgList: + return GetChildByRole(ArglistKeywordRole); + case UndocumentedExpressionType.RefValue: + return GetChildByRole(RefvalueKeywordRole); + case UndocumentedExpressionType.RefType: + return GetChildByRole(ReftypeKeywordRole); + case UndocumentedExpressionType.MakeRef: + return GetChildByRole(MakerefKeywordRole); } return CSharpTokenNode.Null; } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstNodeCollection Arguments { get { return GetChildrenByRole(Roles.Argument); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitUndocumentedExpression (this); + visitor.VisitUndocumentedExpression(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitUndocumentedExpression (this); + return visitor.VisitUndocumentedExpression(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitUndocumentedExpression (this, data); + return visitor.VisitUndocumentedExpression(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { UndocumentedExpression o = other as UndocumentedExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerType.cs index 4352f7ffa..4551dbdee 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerType.cs @@ -26,6 +26,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.IL; @@ -37,37 +38,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public static readonly TokenRole PointerRole = new TokenRole("*"); public static readonly Role CallingConventionRole = new Role("Target", Identifier.Null); - + public string CallingConvention { get { - return GetChildByRole (CallingConventionRole).Name; + return GetChildByRole(CallingConventionRole).Name; } set { - SetChildByRole (CallingConventionRole, Identifier.Create (value)); + SetChildByRole(CallingConventionRole, Identifier.Create(value)); } } public Identifier CallingConventionIdentifier => GetChildByRole(CallingConventionRole); - + public AstNodeCollection TypeArguments { - get { return GetChildrenByRole (Roles.TypeArgument); } + get { return GetChildrenByRole(Roles.TypeArgument); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitFunctionPointerType(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitFunctionPointerType(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitFunctionPointerType(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other is FunctionPointerType o && MatchString(this.CallingConvention, o.CallingConvention) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Attribute.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Attribute.cs index 66dc64211..b07bca2b2 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Attribute.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Attribute.cs @@ -40,20 +40,20 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } public AstType Type { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } } public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } public AstNodeCollection Arguments { - get { return base.GetChildrenByRole (Roles.Argument); } + get { return base.GetChildrenByRole(Roles.Argument); } } public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } // HasArgumentList == false: [Empty] @@ -61,26 +61,26 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get; set; } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitAttribute (this); + visitor.VisitAttribute(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitAttribute (this); + return visitor.VisitAttribute(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitAttribute (this, data); + return visitor.VisitAttribute(this, data); } - - protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { Attribute o = other as Attribute; - return o != null && this.Type.DoMatch (o.Type, match) && this.Arguments.DoMatch (o.Arguments, match); + return o != null && this.Type.DoMatch(o.Type, match) && this.Arguments.DoMatch(o.Arguments, match); } public override string ToString(CSharpFormattingOptions formattingOptions) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/AttributeSection.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/AttributeSection.cs index 5b91b2126..cf8658fe0 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/AttributeSection.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/AttributeSection.cs @@ -37,135 +37,135 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return pattern != null ? new PatternPlaceholder(pattern) : null; } - + sealed class PatternPlaceholder : AttributeSection, PatternMatching.INode { readonly PatternMatching.Pattern child; - + public PatternPlaceholder(PatternMatching.Pattern child) { this.child = child; } - + public override NodeType NodeType { get { return NodeType.Pattern; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitPatternPlaceholder (this, child); + visitor.VisitPatternPlaceholder(this, child); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitPatternPlaceholder (this, child); + return visitor.VisitPatternPlaceholder(this, child); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitPatternPlaceholder(this, child, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return child.DoMatch(other, match); } - + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) { return child.DoMatchCollection(role, pos, match, backtrackingInfo); } } #endregion - + public override NodeType NodeType { get { return NodeType.Unknown; } } - + public CSharpTokenNode LBracketToken { - get { return GetChildByRole (Roles.LBracket); } + get { return GetChildByRole(Roles.LBracket); } } - + public string AttributeTarget { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier AttributeTargetToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } - + public AstNodeCollection Attributes { - get { return base.GetChildrenByRole (Roles.Attribute); } + get { return base.GetChildrenByRole(Roles.Attribute); } } - + public CSharpTokenNode RBracketToken { - get { return GetChildByRole (Roles.RBracket); } + get { return GetChildByRole(Roles.RBracket); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitAttributeSection (this); + visitor.VisitAttributeSection(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitAttributeSection (this); + return visitor.VisitAttributeSection(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitAttributeSection (this, data); + return visitor.VisitAttributeSection(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { AttributeSection o = other as AttributeSection; return o != null && MatchString(this.AttributeTarget, o.AttributeTarget) && this.Attributes.DoMatch(o.Attributes, match); } - + public AttributeSection() { } - + public AttributeSection(Attribute attr) { this.Attributes.Add(attr); } - -// public static string GetAttributeTargetName(AttributeTarget attributeTarget) -// { -// switch (attributeTarget) { -// case AttributeTarget.None: -// return null; -// case AttributeTarget.Assembly: -// return "assembly"; -// case AttributeTarget.Module: -// return "module"; -// case AttributeTarget.Type: -// return "type"; -// case AttributeTarget.Param: -// return "param"; -// case AttributeTarget.Field: -// return "field"; -// case AttributeTarget.Return: -// return "return"; -// case AttributeTarget.Method: -// return "method"; -// default: -// throw new NotSupportedException("Invalid value for AttributeTarget"); -// } -// } + + // public static string GetAttributeTargetName(AttributeTarget attributeTarget) + // { + // switch (attributeTarget) { + // case AttributeTarget.None: + // return null; + // case AttributeTarget.Assembly: + // return "assembly"; + // case AttributeTarget.Module: + // return "module"; + // case AttributeTarget.Type: + // return "type"; + // case AttributeTarget.Param: + // return "param"; + // case AttributeTarget.Field: + // return "field"; + // case AttributeTarget.Return: + // return "return"; + // case AttributeTarget.Method: + // return "method"; + // default: + // throw new NotSupportedException("Invalid value for AttributeTarget"); + // } + // } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Comment.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Comment.cs index b2fc94786..b2a84f0ff 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Comment.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Comment.cs @@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { - public enum CommentType + public enum CommentType { /// /// "//" comment @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// MultiLineDocumentation } - + public class Comment : AstNode { public override NodeType NodeType { @@ -58,14 +58,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return NodeType.Whitespace; } } - + CommentType commentType; - + public CommentType CommentType { get { return commentType; } set { ThrowIfFrozen(); commentType = value; } } - + /// /// Returns true if the is Documentation or MultiLineDocumentation. /// @@ -74,28 +74,28 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return commentType == CommentType.Documentation || commentType == CommentType.MultiLineDocumentation; } } - + bool startsLine; - + public bool StartsLine { get { return startsLine; } set { ThrowIfFrozen(); startsLine = value; } } - + string content; - + public string Content { get { return content; } set { ThrowIfFrozen(); content = value; } } - + TextLocation startLocation; public override TextLocation StartLocation { - get { + get { return startLocation; } } - + TextLocation endLocation; public override TextLocation EndLocation { get { @@ -115,34 +115,34 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.endLocation = value; } - public Comment (string content, CommentType type = CommentType.SingleLine) + public Comment(string content, CommentType type = CommentType.SingleLine) { this.CommentType = type; this.Content = content; } - - public Comment (CommentType commentType, TextLocation startLocation, TextLocation endLocation) + + public Comment(CommentType commentType, TextLocation startLocation, TextLocation endLocation) { this.CommentType = commentType; this.startLocation = startLocation; this.endLocation = endLocation; } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitComment (this); + visitor.VisitComment(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitComment (this); + return visitor.VisitComment(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitComment (this, data); + return visitor.VisitComment(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { Comment o = other as Comment; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Constraint.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Constraint.cs index ec1d707a1..4b0c18618 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Constraint.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Constraint.cs @@ -40,42 +40,43 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } public CSharpTokenNode WhereKeyword { - get { return GetChildByRole (Roles.WhereKeyword); } + get { return GetChildByRole(Roles.WhereKeyword); } } public SimpleType TypeParameter { get { - return GetChildByRole (Roles.ConstraintTypeParameter); + return GetChildByRole(Roles.ConstraintTypeParameter); } set { SetChildByRole(Roles.ConstraintTypeParameter, value); } } - + public AstNodeCollection BaseTypes { get { - return GetChildrenByRole(Roles.BaseType); } + return GetChildrenByRole(Roles.BaseType); + } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitConstraint (this); + visitor.VisitConstraint(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitConstraint (this); + return visitor.VisitConstraint(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitConstraint (this, data); + return visitor.VisitConstraint(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { Constraint o = other as Constraint; - return o != null && this.TypeParameter.DoMatch (o.TypeParameter, match) && this.BaseTypes.DoMatch(o.BaseTypes, match); + return o != null && this.TypeParameter.DoMatch(o.TypeParameter, match) && this.BaseTypes.DoMatch(o.BaseTypes, match); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/DelegateDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/DelegateDeclaration.cs index 0dba88b1d..0d85f5a59 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/DelegateDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/DelegateDeclaration.cs @@ -36,54 +36,54 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public override NodeType NodeType { get { return NodeType.TypeDeclaration; } } - + public override SymbolKind SymbolKind { get { return SymbolKind.TypeDefinition; } } - + public CSharpTokenNode DelegateToken { get { return GetChildByRole(Roles.DelegateKeyword); } } public AstNodeCollection TypeParameters { - get { return GetChildrenByRole (Roles.TypeParameter); } + get { return GetChildrenByRole(Roles.TypeParameter); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstNodeCollection Parameters { - get { return GetChildrenByRole (Roles.Parameter); } + get { return GetChildrenByRole(Roles.Parameter); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public AstNodeCollection Constraints { - get { return GetChildrenByRole (Roles.Constraint); } + get { return GetChildrenByRole(Roles.Constraint); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitDelegateDeclaration (this); + visitor.VisitDelegateDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitDelegateDeclaration (this); + return visitor.VisitDelegateDeclaration(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitDelegateDeclaration (this, data); + return visitor.VisitDelegateDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { DelegateDeclaration o = other as DelegateDeclaration; - return o != null && MatchString(this.Name, o.Name) + return o != null && MatchString(this.Name, o.Name) && this.MatchAttributesAndModifiers(o, match) && this.ReturnType.DoMatch(o.ReturnType, match) && this.TypeParameters.DoMatch(o.TypeParameters, match) && this.Parameters.DoMatch(o.Parameters, match) && this.Constraints.DoMatch(o.Constraints, match); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/ExternAliasDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/ExternAliasDeclaration.cs index b3c6419ba..353e71f2c 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/ExternAliasDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/ExternAliasDeclaration.cs @@ -39,54 +39,54 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } public CSharpTokenNode ExternToken { - get { return GetChildByRole (Roles.ExternKeyword); } + get { return GetChildByRole(Roles.ExternKeyword); } } public CSharpTokenNode AliasToken { - get { return GetChildByRole (Roles.AliasKeyword); } + get { return GetChildByRole(Roles.AliasKeyword); } } public string Name { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier NameToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitExternAliasDeclaration (this); + visitor.VisitExternAliasDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitExternAliasDeclaration (this); + return visitor.VisitExternAliasDeclaration(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitExternAliasDeclaration (this, data); + return visitor.VisitExternAliasDeclaration(this, data); } - protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { var o = other as ExternAliasDeclaration; - return o != null && MatchString (this.Name, o.Name); + return o != null && MatchString(this.Name, o.Name); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/NamespaceDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/NamespaceDeclaration.cs index db676a149..6da1f44ec 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/NamespaceDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/NamespaceDeclaration.cs @@ -23,8 +23,8 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 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; +using System.Collections.Generic; namespace ICSharpCode.Decompiler.CSharp.Syntax { @@ -86,7 +86,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get { var result = new Stack(); AstType type = NamespaceName; - while (type is MemberType) { + while (type is MemberType) + { var mt = (MemberType)type; result.Push(mt.MemberName); type = mt.Target; @@ -153,4 +154,4 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return o != null && MatchString(this.Name, o.Name) && this.Members.DoMatch(o.Members, match); } } -} ; +}; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs index b3de1f90e..87005c003 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs @@ -32,12 +32,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax Invalid = 0, Region = 1, Endregion = 2, - + If = 3, Endif = 4, Elif = 5, Else = 6, - + Define = 7, Undef = 8, Error = 9, @@ -58,23 +58,23 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax set; } - public LinePreprocessorDirective(TextLocation startLocation, TextLocation endLocation) : base (PreProcessorDirectiveType.Line, startLocation, endLocation) + public LinePreprocessorDirective(TextLocation startLocation, TextLocation endLocation) : base(PreProcessorDirectiveType.Line, startLocation, endLocation) { } - public LinePreprocessorDirective(string argument = null) : base (PreProcessorDirectiveType.Line, argument) + public LinePreprocessorDirective(string argument = null) : base(PreProcessorDirectiveType.Line, argument) { } } public class PragmaWarningPreprocessorDirective : PreProcessorDirective { - public static readonly Role WarningRole = new Role ("Warning"); + public static readonly Role WarningRole = new Role("Warning"); - public static readonly TokenRole PragmaKeywordRole = new TokenRole ("#pragma"); - public static readonly TokenRole WarningKeywordRole = new TokenRole ("warning"); - public static readonly TokenRole DisableKeywordRole = new TokenRole ("disable"); - public static readonly TokenRole RestoreKeywordRole = new TokenRole ("restore"); + public static readonly TokenRole PragmaKeywordRole = new TokenRole("#pragma"); + public static readonly TokenRole WarningKeywordRole = new TokenRole("warning"); + public static readonly TokenRole DisableKeywordRole = new TokenRole("disable"); + public static readonly TokenRole RestoreKeywordRole = new TokenRole("restore"); public bool Disable { get { @@ -83,19 +83,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } public CSharpTokenNode PragmaToken { - get { return GetChildByRole (PragmaKeywordRole); } + get { return GetChildByRole(PragmaKeywordRole); } } public CSharpTokenNode WarningToken { - get { return GetChildByRole (WarningKeywordRole); } + get { return GetChildByRole(WarningKeywordRole); } } public CSharpTokenNode DisableToken { - get { return GetChildByRole (DisableKeywordRole); } + get { return GetChildByRole(DisableKeywordRole); } } public CSharpTokenNode RestoreToken { - get { return GetChildByRole (RestoreKeywordRole); } + get { return GetChildByRole(RestoreKeywordRole); } } public AstNodeCollection Warnings { @@ -111,11 +111,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } - public PragmaWarningPreprocessorDirective(TextLocation startLocation, TextLocation endLocation) : base (PreProcessorDirectiveType.Pragma, startLocation, endLocation) + public PragmaWarningPreprocessorDirective(TextLocation startLocation, TextLocation endLocation) : base(PreProcessorDirectiveType.Pragma, startLocation, endLocation) { } - public PragmaWarningPreprocessorDirective(string argument = null) : base (PreProcessorDirectiveType.Pragma, argument) + public PragmaWarningPreprocessorDirective(string argument = null) : base(PreProcessorDirectiveType.Pragma, argument) { } @@ -124,7 +124,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return Warnings.Select(w => (int)w.Value).Any(n => n == pragmaWarning); } } - + public class PreProcessorDirective : AstNode { public override NodeType NodeType { @@ -132,17 +132,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return NodeType.Whitespace; } } - + public PreProcessorDirectiveType Type { get; set; } - + public string Argument { get; set; } - + /// /// For an '#if' directive, specifies whether the condition evaluated to true. /// @@ -150,21 +150,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get; set; } - + TextLocation startLocation; public override TextLocation StartLocation { - get { + get { return startLocation; } } - + TextLocation endLocation; public override TextLocation EndLocation { get { return endLocation; } } - + public PreProcessorDirective(PreProcessorDirectiveType type, TextLocation startLocation, TextLocation endLocation) { this.Type = type; @@ -178,21 +178,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.Argument = argument; } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitPreProcessorDirective (this); + visitor.VisitPreProcessorDirective(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitPreProcessorDirective (this); + return visitor.VisitPreProcessorDirective(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitPreProcessorDirective (this, data); + return visitor.VisitPreProcessorDirective(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { PreProcessorDirective o = other as PreProcessorDirective; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeDeclaration.cs index 78179a43f..cdc68010f 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeDeclaration.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax Interface, Enum } - + /// /// class Name<TypeParameters> : BaseTypes where Constraints; /// @@ -44,16 +44,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public override NodeType NodeType { get { return NodeType.TypeDeclaration; } } - + public override SymbolKind SymbolKind { get { return SymbolKind.TypeDefinition; } } - + ClassType classType; public CSharpTokenNode TypeKeyword { get { - switch (classType) { + switch (classType) + { case ClassType.Class: return GetChildByRole(Roles.ClassKeyword); case ClassType.Struct: @@ -67,7 +68,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } } - + public ClassType ClassType { get { return classType; } set { @@ -77,15 +78,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } public CSharpTokenNode LChevronToken { - get { return GetChildByRole (Roles.LChevron); } + get { return GetChildByRole(Roles.LChevron); } } public AstNodeCollection TypeParameters { - get { return GetChildrenByRole (Roles.TypeParameter); } + get { return GetChildrenByRole(Roles.TypeParameter); } } public CSharpTokenNode RChevronToken { - get { return GetChildByRole (Roles.RChevron); } + get { return GetChildByRole(Roles.RChevron); } } @@ -95,42 +96,42 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return GetChildByRole(Roles.Colon); } } - + public AstNodeCollection BaseTypes { get { return GetChildrenByRole(Roles.BaseType); } } - + public AstNodeCollection Constraints { get { return GetChildrenByRole(Roles.Constraint); } } - + public CSharpTokenNode LBraceToken { - get { return GetChildByRole (Roles.LBrace); } + get { return GetChildByRole(Roles.LBrace); } } public AstNodeCollection Members { - get { return GetChildrenByRole (Roles.TypeMemberRole); } + get { return GetChildrenByRole(Roles.TypeMemberRole); } } - + public CSharpTokenNode RBraceToken { - get { return GetChildByRole (Roles.RBrace); } + get { return GetChildByRole(Roles.RBrace); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitTypeDeclaration (this); + visitor.VisitTypeDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitTypeDeclaration (this); + return visitor.VisitTypeDeclaration(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitTypeDeclaration (this, data); + return visitor.VisitTypeDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { TypeDeclaration o = other as TypeDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeParameterDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeParameterDeclaration.cs index e342d775e..db5c622cf 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeParameterDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeParameterDeclaration.cs @@ -30,27 +30,28 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class TypeParameterDeclaration : AstNode { public static readonly Role AttributeRole = EntityDeclaration.AttributeRole; - public static readonly TokenRole OutVarianceKeywordRole = new TokenRole ("out"); - public static readonly TokenRole InVarianceKeywordRole = new TokenRole ("in"); - + public static readonly TokenRole OutVarianceKeywordRole = new TokenRole("out"); + public static readonly TokenRole InVarianceKeywordRole = new TokenRole("in"); + public override NodeType NodeType { get { return NodeType.Unknown; } } - + public AstNodeCollection Attributes { - get { return GetChildrenByRole (AttributeRole); } + get { return GetChildrenByRole(AttributeRole); } } - + VarianceModifier variance; - + public VarianceModifier Variance { get { return variance; } set { ThrowIfFrozen(); variance = value; } } - + public CSharpTokenNode VarianceToken { get { - switch (Variance) { + switch (Variance) + { case VarianceModifier.Covariant: return GetChildByRole(OutVarianceKeywordRole); case VarianceModifier.Contravariant: @@ -60,49 +61,49 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } } - + public string Name { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier NameToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } - public TypeParameterDeclaration () + public TypeParameterDeclaration() { } - public TypeParameterDeclaration (string name) + public TypeParameterDeclaration(string name) { Name = name; } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitTypeParameterDeclaration (this); + visitor.VisitTypeParameterDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitTypeParameterDeclaration (this); + return visitor.VisitTypeParameterDeclaration(this); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitTypeParameterDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { TypeParameterDeclaration o = other as TypeParameterDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingAliasDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingAliasDeclaration.cs index dbe6beda5..1b3ab140f 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingAliasDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingAliasDeclaration.cs @@ -32,73 +32,73 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class UsingAliasDeclaration : AstNode { - public static readonly TokenRole UsingKeywordRole = new TokenRole ("using"); + public static readonly TokenRole UsingKeywordRole = new TokenRole("using"); public static readonly Role AliasRole = new Role("Alias", Identifier.Null); public static readonly Role ImportRole = UsingDeclaration.ImportRole; - + public override NodeType NodeType { get { return NodeType.Unknown; } } - + public CSharpTokenNode UsingToken { - get { return GetChildByRole (UsingKeywordRole); } + get { return GetChildByRole(UsingKeywordRole); } } - + public string Alias { get { - return GetChildByRole (AliasRole).Name; + return GetChildByRole(AliasRole).Name; } set { - SetChildByRole(AliasRole, Identifier.Create (value)); + SetChildByRole(AliasRole, Identifier.Create(value)); } } - + public CSharpTokenNode AssignToken { - get { return GetChildByRole (Roles.Assign); } + get { return GetChildByRole(Roles.Assign); } } - + public AstType Import { - get { return GetChildByRole (ImportRole); } - set { SetChildByRole (ImportRole, value); } + get { return GetChildByRole(ImportRole); } + set { SetChildByRole(ImportRole, value); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public UsingAliasDeclaration () + + public UsingAliasDeclaration() { } - - public UsingAliasDeclaration (string alias, string nameSpace) + + public UsingAliasDeclaration(string alias, string nameSpace) { - AddChild (Identifier.Create (alias), AliasRole); - AddChild (new SimpleType (nameSpace), ImportRole); + AddChild(Identifier.Create(alias), AliasRole); + AddChild(new SimpleType(nameSpace), ImportRole); } - - public UsingAliasDeclaration (string alias, AstType import) + + public UsingAliasDeclaration(string alias, AstType import) { - AddChild (Identifier.Create (alias), AliasRole); - AddChild (import, ImportRole); + AddChild(Identifier.Create(alias), AliasRole); + AddChild(import, ImportRole); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitUsingAliasDeclaration (this); + visitor.VisitUsingAliasDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitUsingAliasDeclaration (this); + return visitor.VisitUsingAliasDeclaration(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitUsingAliasDeclaration (this, data); + return visitor.VisitUsingAliasDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { UsingAliasDeclaration o = other as UsingAliasDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingDeclaration.cs index e68acc3ee..d7246003c 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingDeclaration.cs @@ -24,8 +24,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System.Text; using System.Collections.Generic; +using System.Text; namespace ICSharpCode.Decompiler.CSharp.Syntax { @@ -34,39 +34,43 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class UsingDeclaration : AstNode { - public static readonly TokenRole UsingKeywordRole = new TokenRole ("using"); + public static readonly TokenRole UsingKeywordRole = new TokenRole("using"); public static readonly Role ImportRole = new Role("Import", AstType.Null); - + public override NodeType NodeType { get { return NodeType.Unknown; } } - + public CSharpTokenNode UsingToken { - get { return GetChildByRole (UsingKeywordRole); } + get { return GetChildByRole(UsingKeywordRole); } } - + public AstType Import { - get { return GetChildByRole (ImportRole); } - set { SetChildByRole (ImportRole, value); } + get { return GetChildByRole(ImportRole); } + set { SetChildByRole(ImportRole, value); } } - + public string Namespace { - get { return ConstructNamespace (Import); } + get { return ConstructNamespace(Import); } } - internal static string ConstructNamespace (AstType type) + internal static string ConstructNamespace(AstType type) { var stack = new Stack(); - while (type is MemberType) { + while (type is MemberType) + { var mt = (MemberType)type; stack.Push(mt.MemberName); type = mt.Target; - if (mt.IsDoubleColon) { + if (mt.IsDoubleColon) + { stack.Push("::"); - } else { - stack.Push("."); + } + else + { + stack.Push("."); } } if (type is SimpleType) @@ -77,40 +81,40 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax result.Append(stack.Pop()); return result.ToString(); } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public UsingDeclaration () + + public UsingDeclaration() { } - - public UsingDeclaration (string nameSpace) + + public UsingDeclaration(string nameSpace) { - AddChild (AstType.Create (nameSpace), ImportRole); + AddChild(AstType.Create(nameSpace), ImportRole); } - - public UsingDeclaration (AstType import) + + public UsingDeclaration(AstType import) { - AddChild (import, ImportRole); + AddChild(import, ImportRole); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitUsingDeclaration (this); + visitor.VisitUsingDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitUsingDeclaration (this); + return visitor.VisitUsingDeclaration(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitUsingDeclaration (this, data); + return visitor.VisitUsingDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { UsingDeclaration o = other as UsingDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/IAnnotatable.cs b/ICSharpCode.Decompiler/CSharp/Syntax/IAnnotatable.cs index e1a6b908c..a82a9d54f 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/IAnnotatable.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/IAnnotatable.cs @@ -117,9 +117,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public object Clone() { - lock (this) { + lock (this) + { AnnotationList copy = new AnnotationList(this.Count); - for (int i = 0; i < this.Count; i++) { + for (int i = 0; i < this.Count; i++) + { object obj = this[i]; ICloneable c = obj as ICloneable; copy.Add(c != null ? c.Clone() : obj); @@ -133,24 +135,30 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { if (annotation == null) throw new ArgumentNullException(nameof(annotation)); - retry: // Retry until successful + retry: // Retry until successful object oldAnnotation = Interlocked.CompareExchange(ref this.annotations, annotation, null); - if (oldAnnotation == null) { + if (oldAnnotation == null) + { return; // we successfully added a single annotation } AnnotationList list = oldAnnotation as AnnotationList; - if (list == null) { + if (list == null) + { // we need to transform the old annotation into a list list = new AnnotationList(4); list.Add(oldAnnotation); list.Add(annotation); - if (Interlocked.CompareExchange(ref this.annotations, list, oldAnnotation) != oldAnnotation) { + if (Interlocked.CompareExchange(ref this.annotations, list, oldAnnotation) != oldAnnotation) + { // the transformation failed (some other thread wrote to this.annotations first) goto retry; } - } else { + } + else + { // once there's a list, use simple locking - lock (list) { + lock (list) + { list.Add(annotation); } } @@ -161,11 +169,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax retry: // Retry until successful object oldAnnotations = this.annotations; AnnotationList list = oldAnnotations as AnnotationList; - if (list != null) { + if (list != null) + { lock (list) list.RemoveAll(obj => obj is T); - } else if (oldAnnotations is T) { - if (Interlocked.CompareExchange(ref this.annotations, null, oldAnnotations) != oldAnnotations) { + } + else if (oldAnnotations is T) + { + if (Interlocked.CompareExchange(ref this.annotations, null, oldAnnotations) != oldAnnotations) + { // Operation failed (some other thread wrote to this.annotations first) goto retry; } @@ -179,11 +191,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax retry: // Retry until successful object oldAnnotations = this.annotations; AnnotationList list = oldAnnotations as AnnotationList; - if (list != null) { + if (list != null) + { lock (list) list.RemoveAll(type.IsInstanceOfType); - } else if (type.IsInstanceOfType(oldAnnotations)) { - if (Interlocked.CompareExchange(ref this.annotations, null, oldAnnotations) != oldAnnotations) { + } + else if (type.IsInstanceOfType(oldAnnotations)) + { + if (Interlocked.CompareExchange(ref this.annotations, null, oldAnnotations) != oldAnnotations) + { // Operation failed (some other thread wrote to this.annotations first) goto retry; } @@ -194,16 +210,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { object annotations = this.annotations; AnnotationList list = annotations as AnnotationList; - if (list != null) { - lock (list) { - foreach (object obj in list) { + if (list != null) + { + lock (list) + { + foreach (object obj in list) + { T t = obj as T; if (t != null) return t; } return null; } - } else { + } + else + { return annotations as T; } } @@ -214,14 +235,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax throw new ArgumentNullException(nameof(type)); object annotations = this.annotations; AnnotationList list = annotations as AnnotationList; - if (list != null) { - lock (list) { - foreach (object obj in list) { + if (list != null) + { + lock (list) + { + foreach (object obj in list) + { if (type.IsInstanceOfType(obj)) return obj; } } - } else { + } + else + { if (type.IsInstanceOfType(annotations)) return annotations; } @@ -235,11 +261,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get { object annotations = this.annotations; AnnotationList list = annotations as AnnotationList; - if (list != null) { - lock (list) { + if (list != null) + { + lock (list) + { return list.ToArray(); } - } else { + } + else + { if (annotations != null) return new object[] { annotations }; else diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs b/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs index 701041316..1e87d6755 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/IAstVisitor.cs @@ -74,7 +74,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax void VisitQueryOrdering(QueryOrdering queryOrdering); void VisitQuerySelectClause(QuerySelectClause querySelectClause); void VisitQueryGroupClause(QueryGroupClause queryGroupClause); - + void VisitAttribute(Attribute attribute); void VisitAttributeSection(AttributeSection attributeSection); void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration); @@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax void VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration); void VisitUsingDeclaration(UsingDeclaration usingDeclaration); void VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration); - + void VisitBlockStatement(BlockStatement blockStatement); void VisitBreakStatement(BreakStatement breakStatement); void VisitCheckedStatement(CheckedStatement checkedStatement); @@ -117,7 +117,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax void VisitWhileStatement(WhileStatement whileStatement); void VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement); void VisitYieldReturnStatement(YieldReturnStatement yieldReturnStatement); - + void VisitAccessor(Accessor accessor); void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration); void VisitConstructorInitializer(ConstructorInitializer constructorInitializer); @@ -134,7 +134,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax void VisitVariableInitializer(VariableInitializer variableInitializer); void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration); void VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer); - + void VisitSyntaxTree(SyntaxTree syntaxTree); void VisitSimpleType(SimpleType simpleType); void VisitMemberType(MemberType memberType); @@ -144,11 +144,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax void VisitComposedType(ComposedType composedType); void VisitArraySpecifier(ArraySpecifier arraySpecifier); void VisitPrimitiveType(PrimitiveType primitiveType); - + void VisitComment(Comment comment); void VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective); void VisitDocumentationReference(DocumentationReference documentationReference); - + void VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration); void VisitConstraint(Constraint constraint); void VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode); @@ -164,7 +164,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax void VisitErrorNode(AstNode errorNode); void VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern); } - + /// /// AST visitor. /// @@ -220,7 +220,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitQueryOrdering(QueryOrdering queryOrdering); S VisitQuerySelectClause(QuerySelectClause querySelectClause); S VisitQueryGroupClause(QueryGroupClause queryGroupClause); - + S VisitAttribute(Attribute attribute); S VisitAttributeSection(AttributeSection attributeSection); S VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration); @@ -229,7 +229,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration); S VisitUsingDeclaration(UsingDeclaration usingDeclaration); S VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration); - + S VisitBlockStatement(BlockStatement blockStatement); S VisitBreakStatement(BreakStatement breakStatement); S VisitCheckedStatement(CheckedStatement checkedStatement); @@ -263,7 +263,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitWhileStatement(WhileStatement whileStatement); S VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement); S VisitYieldReturnStatement(YieldReturnStatement yieldReturnStatement); - + S VisitAccessor(Accessor accessor); S VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration); S VisitConstructorInitializer(ConstructorInitializer constructorInitializer); @@ -280,7 +280,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitVariableInitializer(VariableInitializer variableInitializer); S VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration); S VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer); - + S VisitSyntaxTree(SyntaxTree syntaxTree); S VisitSimpleType(SimpleType simpleType); S VisitMemberType(MemberType memberType); @@ -290,11 +290,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitComposedType(ComposedType composedType); S VisitArraySpecifier(ArraySpecifier arraySpecifier); S VisitPrimitiveType(PrimitiveType primitiveType); - + S VisitComment(Comment comment); S VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective); S VisitDocumentationReference(DocumentationReference documentationReference); - + S VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration); S VisitConstraint(Constraint constraint); S VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode); @@ -310,7 +310,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitErrorNode(AstNode errorNode); S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern); } - + /// /// AST visitor. /// @@ -366,7 +366,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitQueryOrdering(QueryOrdering queryOrdering, T data); S VisitQuerySelectClause(QuerySelectClause querySelectClause, T data); S VisitQueryGroupClause(QueryGroupClause queryGroupClause, T data); - + S VisitAttribute(Attribute attribute, T data); S VisitAttributeSection(AttributeSection attributeSection, T data); S VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, T data); @@ -375,7 +375,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration, T data); S VisitUsingDeclaration(UsingDeclaration usingDeclaration, T data); S VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, T data); - + S VisitBlockStatement(BlockStatement blockStatement, T data); S VisitBreakStatement(BreakStatement breakStatement, T data); S VisitCheckedStatement(CheckedStatement checkedStatement, T data); @@ -409,7 +409,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitWhileStatement(WhileStatement whileStatement, T data); S VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, T data); S VisitYieldReturnStatement(YieldReturnStatement yieldReturnStatement, T data); - + S VisitAccessor(Accessor accessor, T data); S VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, T data); S VisitConstructorInitializer(ConstructorInitializer constructorInitializer, T data); @@ -426,7 +426,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitVariableInitializer(VariableInitializer variableInitializer, T data); S VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, T data); S VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, T data); - + S VisitSyntaxTree(SyntaxTree syntaxTree, T data); S VisitSimpleType(SimpleType simpleType, T data); S VisitMemberType(MemberType memberType, T data); @@ -436,11 +436,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax S VisitComposedType(ComposedType composedType, T data); S VisitArraySpecifier(ArraySpecifier arraySpecifier, T data); S VisitPrimitiveType(PrimitiveType primitiveType, T data); - + S VisitComment(Comment comment, T data); S VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective, T data); S VisitDocumentationReference(DocumentationReference documentationReference, T data); - + S VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, T data); S VisitConstraint(Constraint constraint, T data); S VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, T data); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Identifier.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Identifier.cs index bbadecc74..726c939fb 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Identifier.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Identifier.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public class Identifier : AstNode { - public new static readonly Identifier Null = new NullIdentifier (); + public new static readonly Identifier Null = new NullIdentifier(); sealed class NullIdentifier : Identifier { public override bool IsNull { @@ -38,34 +38,34 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } } - + public override NodeType NodeType { get { return NodeType.Token; } } - + string name; public string Name { get { return this.name; } @@ -76,22 +76,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.name = value; } } - + TextLocation startLocation; public override TextLocation StartLocation { get { return startLocation; } } - + internal void SetStartLocation(TextLocation value) { ThrowIfFrozen(); this.startLocation = value; } - + const uint verbatimBit = 1u << AstNodeFlagsUsedBits; - + public bool IsVerbatim { get { return (flags & verbatimBit) != 0; @@ -104,19 +104,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax flags &= ~verbatimBit; } } - + public override TextLocation EndLocation { get { - return new TextLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length + (IsVerbatim ? 1 : 0)); + return new TextLocation(StartLocation.Line, StartLocation.Column + (Name ?? "").Length + (IsVerbatim ? 1 : 0)); } } - - Identifier () + + Identifier() { this.name = string.Empty; } - - protected Identifier (string name, TextLocation location) + + protected Identifier(string name, TextLocation location) { if (name == null) throw new ArgumentNullException(nameof(name)); @@ -124,46 +124,46 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.startLocation = location; } - public static Identifier Create (string name) + public static Identifier Create(string name) { - return Create (name, TextLocation.Empty); + return Create(name, TextLocation.Empty); } - public static Identifier Create (string name, TextLocation location) + public static Identifier Create(string name, TextLocation location) { if (string.IsNullOrEmpty(name)) return Identifier.Null; if (name[0] == '@') - return new Identifier (name.Substring (1), new TextLocation (location.Line, location.Column + 1)) { IsVerbatim = true }; + return new Identifier(name.Substring(1), new TextLocation(location.Line, location.Column + 1)) { IsVerbatim = true }; else - return new Identifier (name, location); + return new Identifier(name, location); } - - public static Identifier Create (string name, TextLocation location, bool isVerbatim) + + public static Identifier Create(string name, TextLocation location, bool isVerbatim) { - if (string.IsNullOrEmpty (name)) + if (string.IsNullOrEmpty(name)) return Identifier.Null; - + if (isVerbatim) - return new Identifier (name, location) { IsVerbatim = true }; - return new Identifier (name, location); + return new Identifier(name, location) { IsVerbatim = true }; + return new Identifier(name, location); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitIdentifier (this); + visitor.VisitIdentifier(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitIdentifier (this); + return visitor.VisitIdentifier(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitIdentifier (this, data); + return visitor.VisitIdentifier(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { Identifier o = other as Identifier; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/IdentifierExpressionBackreference.cs b/ICSharpCode.Decompiler/CSharp/Syntax/IdentifierExpressionBackreference.cs index 219fda00f..78ee9359d 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/IdentifierExpressionBackreference.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/IdentifierExpressionBackreference.cs @@ -27,18 +27,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class IdentifierExpressionBackreference : PatternMatching.Pattern { readonly string referencedGroupName; - + public string ReferencedGroupName { get { return referencedGroupName; } } - + public IdentifierExpressionBackreference(string referencedGroupName) { if (referencedGroupName == null) throw new ArgumentNullException(nameof(referencedGroupName)); this.referencedGroupName = referencedGroupName; } - + public override bool DoMatch(PatternMatching.INode other, PatternMatching.Match match) { IdentifierExpression ident = other as IdentifierExpression; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs index 26dfa9213..00abace78 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System.Collections.Generic; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.TypeSystem; @@ -34,9 +35,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class MemberType : AstType { public static readonly Role TargetRole = new Role("Target", AstType.Null); - + bool isDoubleColon; - + public bool IsDoubleColon { get { return isDoubleColon; } set { @@ -44,72 +45,73 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax isDoubleColon = value; } } - + public AstType Target { get { return GetChildByRole(TargetRole); } set { SetChildByRole(TargetRole, value); } } - + public string MemberName { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier MemberNameToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } - + public AstNodeCollection TypeArguments { - get { return GetChildrenByRole (Roles.TypeArgument); } + get { return GetChildrenByRole(Roles.TypeArgument); } } - - public MemberType () + + public MemberType() { } - - public MemberType (AstType target, string memberName) + + public MemberType(AstType target, string memberName) { this.Target = target; this.MemberName = memberName; } - - public MemberType (AstType target, string memberName, IEnumerable typeArguments) + + public MemberType(AstType target, string memberName, IEnumerable typeArguments) { this.Target = target; this.MemberName = memberName; - foreach (var arg in typeArguments) { - AddChild (arg, Roles.TypeArgument); + foreach (var arg in typeArguments) + { + AddChild(arg, Roles.TypeArgument); } } - - public MemberType (AstType target, string memberName, params AstType[] typeArguments) : this (target, memberName, (IEnumerable)typeArguments) + + public MemberType(AstType target, string memberName, params AstType[] typeArguments) : this(target, memberName, (IEnumerable)typeArguments) { } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitMemberType (this); + visitor.VisitMemberType(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitMemberType (this); + return visitor.VisitMemberType(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitMemberType (this, data); + return visitor.VisitMemberType(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { MemberType o = other as MemberType; @@ -122,22 +124,29 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { if (interningProvider == null) interningProvider = InterningProvider.Dummy; - + TypeOrNamespaceReference t; - if (this.IsDoubleColon) { + if (this.IsDoubleColon) + { SimpleType st = this.Target as SimpleType; - if (st != null) { + if (st != null) + { t = interningProvider.Intern(new AliasNamespaceReference(interningProvider.Intern(st.Identifier))); - } else { + } + else + { t = null; } - } else { + } + else + { t = this.Target.ToTypeReference(lookupMode, interningProvider) as TypeOrNamespaceReference; } if (t == null) return SpecialType.UnknownType; var typeArguments = new List(); - foreach (var ta in this.TypeArguments) { + foreach (var ta in this.TypeArguments) + { typeArguments.Add(ta.ToTypeReference(lookupMode, interningProvider)); } string memberName = interningProvider.Intern(this.MemberName); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Modifiers.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Modifiers.cs index 150d858e1..98464b09c 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Modifiers.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Modifiers.cs @@ -33,31 +33,31 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [Flags] public enum Modifiers { - None = 0, - - Private = 0x0001, - Internal = 0x0002, + None = 0, + + Private = 0x0001, + Internal = 0x0002, Protected = 0x0004, - Public = 0x0008, - - Abstract = 0x0010, - Virtual = 0x0020, - Sealed = 0x0040, - Static = 0x0080, - Override = 0x0100, - Readonly = 0x0200, - Const = 0x0400, - New = 0x0800, - Partial = 0x1000, - - Extern = 0x2000, - Volatile = 0x4000, - Unsafe = 0x8000, - Async = 0x10000, - Ref = 0x20000, - + Public = 0x0008, + + Abstract = 0x0010, + Virtual = 0x0020, + Sealed = 0x0040, + Static = 0x0080, + Override = 0x0100, + Readonly = 0x0200, + Const = 0x0400, + New = 0x0800, + Partial = 0x1000, + + Extern = 0x2000, + Volatile = 0x4000, + Unsafe = 0x8000, + Async = 0x10000, + Ref = 0x20000, + VisibilityMask = Private | Internal | Protected | Public, - + /// /// Special value used to match any modifiers during pattern matching. /// diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/AnyNode.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/AnyNode.cs index 2488355bb..00b2107e2 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/AnyNode.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/AnyNode.cs @@ -26,16 +26,16 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching public class AnyNode : Pattern { readonly string groupName; - + public string GroupName { get { return groupName; } } - + public AnyNode(string groupName = null) { this.groupName = groupName; } - + public override bool DoMatch(INode other, Match match) { match.Add(this.groupName, other); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/AnyNodeOrNull.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/AnyNodeOrNull.cs index b8fe2ed6d..7ce94c72e 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/AnyNodeOrNull.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/AnyNodeOrNull.cs @@ -46,9 +46,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching public override bool DoMatch(INode other, Match match) { - if (other == null) { + if (other == null) + { match.AddNull(this.groupName); - } else { + } + else + { match.Add(this.groupName, other); } return true; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Backreference.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Backreference.cs index 76ff33aa4..613bd4c2f 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Backreference.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Backreference.cs @@ -27,21 +27,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching public class Backreference : Pattern { readonly string referencedGroupName; - + public string ReferencedGroupName { get { return referencedGroupName; } } - + public Backreference(string referencedGroupName) { if (referencedGroupName == null) throw new ArgumentNullException(nameof(referencedGroupName)); this.referencedGroupName = referencedGroupName; } - + public override bool DoMatch(INode other, Match match) { - var last = match.Get (referencedGroupName).LastOrDefault(); + var last = match.Get(referencedGroupName).LastOrDefault(); if (last == null && other == null) return true; return last.IsMatch(other); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Choice.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Choice.cs index af322cfd3..1cd1b6a22 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Choice.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Choice.cs @@ -28,25 +28,26 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching public class Choice : Pattern, IEnumerable { readonly List alternatives = new List(); - + public void Add(string name, INode alternative) { if (alternative == null) throw new ArgumentNullException(nameof(alternative)); alternatives.Add(new NamedNode(name, alternative)); } - + public void Add(INode alternative) { if (alternative == null) throw new ArgumentNullException(nameof(alternative)); alternatives.Add(alternative); } - + public override bool DoMatch(INode other, Match match) { var checkPoint = match.CheckPoint(); - foreach (INode alt in alternatives) { + foreach (INode alt in alternatives) + { if (alt.DoMatch(other, match)) return true; else @@ -54,12 +55,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching } return false; } - + IEnumerator IEnumerable.GetEnumerator() { return alternatives.GetEnumerator(); } - + IEnumerator IEnumerable.GetEnumerator() { return alternatives.GetEnumerator(); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/INode.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/INode.cs index dc93e371d..d1e3fc6e7 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/INode.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/INode.cs @@ -29,11 +29,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching INode FirstChild { get; } INode NextSibling { get; } bool IsNull { get; } - + bool DoMatch(INode other, Match match); bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo); } - + public static class PatternExtensions { /// @@ -58,7 +58,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching else return default(PatternMatching.Match); } - + public static bool IsMatch(this INode pattern, INode other) { if (pattern == null) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Match.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Match.cs index 3f63b57ff..70a4dbc97 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Match.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Match.cs @@ -26,71 +26,76 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching public struct Match { // TODO: maybe we should add an implicit Match->bool conversion? (implicit operator bool(Match m) { return m != null; }) - + List> results; - + public bool Success { get { return results != null; } } - + internal static Match CreateNew() { Match m; m.results = new List>(); return m; } - + internal int CheckPoint() { return results.Count; } - + internal void RestoreCheckPoint(int checkPoint) { results.RemoveRange(checkPoint, results.Count - checkPoint); } - + public IEnumerable Get(string groupName) { if (results == null) yield break; - foreach (var pair in results) { + foreach (var pair in results) + { if (pair.Key == groupName) yield return pair.Value; } } - + public IEnumerable Get(string groupName) where T : INode { if (results == null) yield break; - foreach (var pair in results) { + foreach (var pair in results) + { if (pair.Key == groupName) yield return (T)pair.Value; } } - + public bool Has(string groupName) { if (results == null) return false; - foreach (var pair in results) { + foreach (var pair in results) + { if (pair.Key == groupName) return true; } return false; } - + public void Add(string groupName, INode node) { - if (groupName != null && node != null) { + if (groupName != null && node != null) + { results.Add(new KeyValuePair(groupName, node)); } } - internal void AddNull (string groupName) + internal void AddNull(string groupName) { - if (groupName != null) { + if (groupName != null) + { results.Add(new KeyValuePair(groupName, null)); } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/NamedNode.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/NamedNode.cs index 95e4f48a4..106ea8ad3 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/NamedNode.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/NamedNode.cs @@ -27,15 +27,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching { readonly string groupName; readonly INode childNode; - + public string GroupName { get { return groupName; } } - + public INode ChildNode { get { return childNode; } } - + public NamedNode(string groupName, INode childNode) { if (childNode == null) @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching this.groupName = groupName; this.childNode = childNode; } - + public override bool DoMatch(INode other, Match match) { match.Add(this.groupName, other); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/OptionalNode.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/OptionalNode.cs index f4f3af44f..f57519ee7 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/OptionalNode.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/OptionalNode.cs @@ -23,28 +23,28 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching public class OptionalNode : Pattern { readonly INode childNode; - + public INode ChildNode { get { return childNode; } } - + public OptionalNode(INode childNode) { if (childNode == null) throw new ArgumentNullException(nameof(childNode)); this.childNode = childNode; } - + public OptionalNode(string groupName, INode childNode) : this(new NamedNode(groupName, childNode)) { } - + public override bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) { backtrackingInfo.backtrackingStack.Push(new PossibleMatch(pos, match.CheckPoint())); return childNode.DoMatch(pos, match); } - + public override bool DoMatch(INode other, Match match) { if (other == null || other.IsNull) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Pattern.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Pattern.cs index d6c57e2ab..f644813f5 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Pattern.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Pattern.cs @@ -30,47 +30,47 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching /// Gets the string that matches any string. /// public static readonly string AnyString = "$any$"; - + public static bool MatchString(string pattern, string text) { return pattern == AnyString || pattern == text; } - + internal struct PossibleMatch { public readonly INode NextOther; // next node after the last matched node public readonly int Checkpoint; // checkpoint - + public PossibleMatch(INode nextOther, int checkpoint) { this.NextOther = nextOther; this.Checkpoint = checkpoint; } } - + bool INode.IsNull { get { return false; } } - + Role INode.Role { get { return null; } } - + INode INode.NextSibling { get { return null; } } - + INode INode.FirstChild { get { return null; } } - + public abstract bool DoMatch(INode other, Match match); - + public virtual bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) { - return DoMatch (pos, match); + return DoMatch(pos, match); } - + public static bool DoMatchCollection(Role role, INode firstPatternChild, INode firstOtherChild, Match match) { BacktrackingInfo backtrackingInfo = new BacktrackingInfo(); @@ -78,25 +78,27 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching Stack stack = backtrackingInfo.backtrackingStack; patternStack.Push(firstPatternChild); stack.Push(new PossibleMatch(firstOtherChild, match.CheckPoint())); - while (stack.Count > 0) { + while (stack.Count > 0) + { INode cur1 = patternStack.Pop(); INode cur2 = stack.Peek().NextOther; match.RestoreCheckPoint(stack.Pop().Checkpoint); bool success = true; - while (cur1 != null && success) { + while (cur1 != null && success) + { while (cur1 != null && cur1.Role != role) cur1 = cur1.NextSibling; while (cur2 != null && cur2.Role != role) cur2 = cur2.NextSibling; if (cur1 == null) break; - + Debug.Assert(stack.Count == patternStack.Count); success = cur1.DoMatchCollection(role, cur2, match, backtrackingInfo); Debug.Assert(stack.Count >= patternStack.Count); while (stack.Count > patternStack.Count) patternStack.Push(cur1.NextSibling); - + cur1 = cur1.NextSibling; if (cur2 != null) cur2 = cur2.NextSibling; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Repeat.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Repeat.cs index 2feaa9966..a99c60be0 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Repeat.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Repeat.cs @@ -27,14 +27,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching public class Repeat : Pattern { readonly INode childNode; - + public int MinCount { get; set; } public int MaxCount { get; set; } - + public INode ChildNode { get { return childNode; } } - + public Repeat(INode childNode) { if (childNode == null) @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching this.MinCount = 0; this.MaxCount = int.MaxValue; } - + public override bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) { var backtrackingStack = backtrackingInfo.backtrackingStack; @@ -51,9 +51,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching int matchCount = 0; if (this.MinCount <= 0) backtrackingStack.Push(new PossibleMatch(pos, match.CheckPoint())); - while (matchCount < this.MaxCount && pos != null && childNode.DoMatch(pos, match)) { + while (matchCount < this.MaxCount && pos != null && childNode.DoMatch(pos, match)) + { matchCount++; - do { + do + { pos = pos.NextSibling; } while (pos != null && pos.Role != role); if (matchCount >= this.MinCount) @@ -61,7 +63,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching } return false; // never do a normal (single-element) match; always make the caller look at the results on the back-tracking stack. } - + public override bool DoMatch(INode other, Match match) { if (other == null || other.IsNull) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PrimitiveType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PrimitiveType.cs index 31e408b54..a6f112542 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PrimitiveType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PrimitiveType.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; + using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.TypeSystem; @@ -36,69 +37,69 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { TextLocation location; string keyword = string.Empty; - + public string Keyword { get { return keyword; } - set { + set { if (value == null) throw new ArgumentNullException(); ThrowIfFrozen(); - keyword = value; + keyword = value; } } - + public KnownTypeCode KnownTypeCode { get { return GetTypeCodeForPrimitiveType(this.Keyword); } } - + public PrimitiveType() { } - + public PrimitiveType(string keyword) { this.Keyword = keyword; } - + public PrimitiveType(string keyword, TextLocation location) { this.Keyword = keyword; this.location = location; } - + public override TextLocation StartLocation { get { return location; } } - + internal void SetStartLocation(TextLocation value) { ThrowIfFrozen(); this.location = value; } - + public override TextLocation EndLocation { get { - return new TextLocation (location.Line, location.Column + keyword.Length); + return new TextLocation(location.Line, location.Column + keyword.Length); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitPrimitiveType (this); + visitor.VisitPrimitiveType(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitPrimitiveType (this); + return visitor.VisitPrimitiveType(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitPrimitiveType (this, data); + return visitor.VisitPrimitiveType(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { PrimitiveType o = other as PrimitiveType; @@ -109,22 +110,26 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return Keyword; } - + public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null) { KnownTypeCode typeCode = GetTypeCodeForPrimitiveType(this.Keyword); - if (typeCode == KnownTypeCode.None) { + if (typeCode == KnownTypeCode.None) + { if (this.Keyword == "__arglist") return SpecialType.ArgList; return new UnknownType(null, this.Keyword); - } else { + } + else + { return KnownTypeReference.Get(typeCode); } } - + public static KnownTypeCode GetTypeCodeForPrimitiveType(string keyword) { - switch (keyword) { + switch (keyword) + { case "string": return KnownTypeCode.String; case "int": diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Role.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Role.cs index 930537b4b..6d9afb8df 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Role.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Role.cs @@ -27,16 +27,16 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public abstract class Role { public const int RoleIndexBits = 9; - + static readonly Role[] roles = new Role[1 << RoleIndexBits]; static int nextRoleIndex = 0; - + readonly uint index; - + public uint Index { get { return index; } } - + // don't allow NRefactory consumers to derive from Role internal Role() { @@ -45,12 +45,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax throw new InvalidOperationException("Too many roles"); roles[this.index] = this; } - + /// /// Gets whether the specified node is valid in this role. /// public abstract bool IsValid(object node); - + /// /// Gets the role with the specified index. /// @@ -59,7 +59,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return roles[index]; } } - + /// /// Represents the role a node plays within its parent. /// All nodes with this role have type T. @@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { readonly string name; // helps with debugging the AST readonly T nullObject; - + /// /// Gets the null object used when there's no node with this role. /// Not every role has a null object; this property returns null for roles without a null object. @@ -80,29 +80,29 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public T NullObject { get { return nullObject; } } - + public override bool IsValid(object node) { return node is T; } - + public Role(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); this.name = name; } - + public Role(string name, T nullObject) { if (name == null) throw new ArgumentNullException(nameof(name)); if (nullObject == null) - throw new ArgumentNullException (nameof(nullObject)); + throw new ArgumentNullException(nameof(nullObject)); this.nullObject = nullObject; this.name = name; } - + public override string ToString() { return name; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs index b45935814..a3f9e69ab 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs @@ -30,22 +30,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public static class Roles { public static readonly Role Root = AstNode.RootRole; - + // some pre defined constants for common roles - public static readonly Role Identifier = new Role ("Identifier", Syntax.Identifier.Null); - public static readonly Role Body = new Role ("Body", BlockStatement.Null); - public static readonly Role Parameter = new Role ("Parameter"); - public static readonly Role Argument = new Role ("Argument", Syntax.Expression.Null); - public static readonly Role Type = new Role ("Type", AstType.Null); - public static readonly Role Expression = new Role ("Expression", Syntax.Expression.Null); - public static readonly Role TargetExpression = new Role ("Target", Syntax.Expression.Null); - public readonly static Role Condition = new Role ("Condition", Syntax.Expression.Null); - public static readonly Role TypeParameter = new Role ("TypeParameter"); - public static readonly Role TypeArgument = new Role ("TypeArgument", AstType.Null); - public readonly static Role Constraint = new Role ("Constraint"); - public static readonly Role Variable = new Role ("Variable", VariableInitializer.Null); - public static readonly Role EmbeddedStatement = new Role ("EmbeddedStatement", Statement.Null); - public readonly static Role TypeMemberRole = new Role ("TypeMember"); + public static readonly Role Identifier = new Role("Identifier", Syntax.Identifier.Null); + public static readonly Role Body = new Role("Body", BlockStatement.Null); + public static readonly Role Parameter = new Role("Parameter"); + public static readonly Role Argument = new Role("Argument", Syntax.Expression.Null); + public static readonly Role Type = new Role("Type", AstType.Null); + public static readonly Role Expression = new Role("Expression", Syntax.Expression.Null); + public static readonly Role TargetExpression = new Role("Target", Syntax.Expression.Null); + public readonly static Role Condition = new Role("Condition", Syntax.Expression.Null); + public static readonly Role TypeParameter = new Role("TypeParameter"); + public static readonly Role TypeArgument = new Role("TypeArgument", AstType.Null); + public readonly static Role Constraint = new Role("Constraint"); + public static readonly Role Variable = new Role("Variable", VariableInitializer.Null); + public static readonly Role EmbeddedStatement = new Role("EmbeddedStatement", Statement.Null); + public readonly static Role TypeMemberRole = new Role("TypeMember"); public static readonly Role VariableDesignationRole = new Role("VariableDesignation", VariableDesignation.Null); @@ -53,40 +53,40 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax // public static readonly TokenRole InKeyword = new TokenRole ("InKeyword", CSharpTokenNode.Null); // some pre defined constants for most used punctuation - public static readonly TokenRole LPar = new TokenRole ("("); - public static readonly TokenRole RPar = new TokenRole (")"); - public static readonly TokenRole LBracket = new TokenRole ("["); - public static readonly TokenRole RBracket = new TokenRole ("]"); - public static readonly TokenRole LBrace = new TokenRole ("{"); - public static readonly TokenRole RBrace = new TokenRole ("}"); - public static readonly TokenRole LChevron = new TokenRole ("<"); - public static readonly TokenRole RChevron = new TokenRole (">"); - public static readonly TokenRole Comma = new TokenRole (","); - public static readonly TokenRole Dot = new TokenRole ("."); - public static readonly TokenRole Semicolon = new TokenRole (";"); - public static readonly TokenRole Assign = new TokenRole ("="); - public static readonly TokenRole Colon = new TokenRole (":"); - public static readonly TokenRole DoubleColon = new TokenRole ("::"); + public static readonly TokenRole LPar = new TokenRole("("); + public static readonly TokenRole RPar = new TokenRole(")"); + public static readonly TokenRole LBracket = new TokenRole("["); + public static readonly TokenRole RBracket = new TokenRole("]"); + public static readonly TokenRole LBrace = new TokenRole("{"); + public static readonly TokenRole RBrace = new TokenRole("}"); + public static readonly TokenRole LChevron = new TokenRole("<"); + public static readonly TokenRole RChevron = new TokenRole(">"); + public static readonly TokenRole Comma = new TokenRole(","); + public static readonly TokenRole Dot = new TokenRole("."); + public static readonly TokenRole Semicolon = new TokenRole(";"); + public static readonly TokenRole Assign = new TokenRole("="); + public static readonly TokenRole Colon = new TokenRole(":"); + public static readonly TokenRole DoubleColon = new TokenRole("::"); public static readonly TokenRole Arrow = new TokenRole("=>"); - public static readonly Role Comment = new Role ("Comment"); - public static readonly Role PreProcessorDirective = new Role ("PreProcessorDirective"); - - public readonly static Role BaseType = new Role ("BaseType", AstType.Null); + public static readonly Role Comment = new Role("Comment"); + public static readonly Role PreProcessorDirective = new Role("PreProcessorDirective"); + + public readonly static Role BaseType = new Role("BaseType", AstType.Null); - public static readonly Role Attribute = new Role ("Attribute"); - public static readonly Role AttributeTargetRole = new Role ("AttributeTarget", CSharpTokenNode.Null); + public static readonly Role Attribute = new Role("Attribute"); + public static readonly Role AttributeTargetRole = new Role("AttributeTarget", CSharpTokenNode.Null); - public readonly static TokenRole WhereKeyword = new TokenRole ("where"); - public readonly static Role ConstraintTypeParameter = new Role ("TypeParameter", SimpleType.Null); - public readonly static TokenRole DelegateKeyword = new TokenRole ("delegate"); - public static readonly TokenRole ExternKeyword = new TokenRole ("extern"); - public static readonly TokenRole AliasKeyword = new TokenRole ("alias"); - public static readonly TokenRole NamespaceKeyword = new TokenRole ("namespace"); + public readonly static TokenRole WhereKeyword = new TokenRole("where"); + public readonly static Role ConstraintTypeParameter = new Role("TypeParameter", SimpleType.Null); + public readonly static TokenRole DelegateKeyword = new TokenRole("delegate"); + public static readonly TokenRole ExternKeyword = new TokenRole("extern"); + public static readonly TokenRole AliasKeyword = new TokenRole("alias"); + public static readonly TokenRole NamespaceKeyword = new TokenRole("namespace"); - public static readonly TokenRole EnumKeyword = new TokenRole ("enum"); - public static readonly TokenRole InterfaceKeyword = new TokenRole ("interface"); - public static readonly TokenRole StructKeyword = new TokenRole ("struct"); - public static readonly TokenRole ClassKeyword = new TokenRole ("class"); + public static readonly TokenRole EnumKeyword = new TokenRole("enum"); + public static readonly TokenRole InterfaceKeyword = new TokenRole("interface"); + public static readonly TokenRole StructKeyword = new TokenRole("struct"); + public static readonly TokenRole ClassKeyword = new TokenRole("class"); } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs index e0798a83a..17a19e345 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System.Collections.Generic; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.TypeSystem; @@ -34,8 +35,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class SimpleType : AstType { #region Null - public new static readonly SimpleType Null = new NullSimpleType (); - + public new static readonly SimpleType Null = new NullSimpleType(); + sealed class NullSimpleType : SimpleType { public override bool IsNull { @@ -43,118 +44,121 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } - + public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider) { return SpecialType.UnknownType; } } #endregion - + public SimpleType() { } - + public SimpleType(string identifier) { this.Identifier = identifier; } - - public SimpleType (Identifier identifier) + + public SimpleType(Identifier identifier) { this.IdentifierToken = identifier; } - + public SimpleType(string identifier, TextLocation location) { - SetChildByRole (Roles.Identifier, Syntax.Identifier.Create (identifier, location)); + SetChildByRole(Roles.Identifier, Syntax.Identifier.Create(identifier, location)); } - - public SimpleType (string identifier, IEnumerable typeArguments) + + public SimpleType(string identifier, IEnumerable typeArguments) { this.Identifier = identifier; - foreach (var arg in typeArguments) { - AddChild (arg, Roles.TypeArgument); + foreach (var arg in typeArguments) + { + AddChild(arg, Roles.TypeArgument); } } - - public SimpleType (string identifier, params AstType[] typeArguments) : this (identifier, (IEnumerable)typeArguments) + + public SimpleType(string identifier, params AstType[] typeArguments) : this(identifier, (IEnumerable)typeArguments) { } - + public string Identifier { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Syntax.Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Syntax.Identifier.Create(value)); } } - + public Identifier IdentifierToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } - + public AstNodeCollection TypeArguments { - get { return GetChildrenByRole (Roles.TypeArgument); } + get { return GetChildrenByRole(Roles.TypeArgument); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitSimpleType (this); + visitor.VisitSimpleType(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitSimpleType (this); + return visitor.VisitSimpleType(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitSimpleType (this, data); + return visitor.VisitSimpleType(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { SimpleType o = other as SimpleType; return o != null && MatchString(this.Identifier, o.Identifier) && this.TypeArguments.DoMatch(o.TypeArguments, match); } - + public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null) { if (interningProvider == null) interningProvider = InterningProvider.Dummy; var typeArguments = new List(); - foreach (var ta in this.TypeArguments) { + foreach (var ta in this.TypeArguments) + { typeArguments.Add(ta.ToTypeReference(lookupMode, interningProvider)); } string identifier = interningProvider.Intern(this.Identifier); - if (typeArguments.Count == 0 && string.IsNullOrEmpty(identifier)) { + if (typeArguments.Count == 0 && string.IsNullOrEmpty(identifier)) + { // empty SimpleType is used for typeof(List<>). return SpecialType.UnboundTypeArgument; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BlockStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BlockStatement.cs index f8c2c67cd..9965c7af9 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BlockStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BlockStatement.cs @@ -34,9 +34,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class BlockStatement : Statement, IEnumerable { public static readonly Role StatementRole = new Role("Statement", Statement.Null); - + #region Null - public static readonly new BlockStatement Null = new NullBlockStatement (); + public static readonly new BlockStatement Null = new NullBlockStatement(); sealed class NullBlockStatement : BlockStatement { public override bool IsNull { @@ -44,108 +44,108 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } } #endregion - + #region PatternPlaceholder public static implicit operator BlockStatement(PatternMatching.Pattern pattern) { return pattern != null ? new PatternPlaceholder(pattern) : null; } - + sealed class PatternPlaceholder : BlockStatement, PatternMatching.INode { readonly PatternMatching.Pattern child; - + public PatternPlaceholder(PatternMatching.Pattern child) { this.child = child; } - + public override NodeType NodeType { get { return NodeType.Pattern; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitPatternPlaceholder(this, child); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitPatternPlaceholder(this, child); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitPatternPlaceholder(this, child, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return child.DoMatch(other, match); } - + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) { return child.DoMatchCollection(role, pos, match, backtrackingInfo); } } #endregion - + public CSharpTokenNode LBraceToken { - get { return GetChildByRole (Roles.LBrace); } + get { return GetChildByRole(Roles.LBrace); } } - + public AstNodeCollection Statements { - get { return GetChildrenByRole (StatementRole); } + get { return GetChildrenByRole(StatementRole); } } - + public CSharpTokenNode RBraceToken { - get { return GetChildByRole (Roles.RBrace); } + get { return GetChildByRole(Roles.RBrace); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitBlockStatement (this); + visitor.VisitBlockStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitBlockStatement (this); + return visitor.VisitBlockStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitBlockStatement (this, data); + return visitor.VisitBlockStatement(this, data); } - + 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); } - + public void Add(Statement statement) { AddChild(statement, StatementRole); @@ -160,7 +160,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return this.Statements.GetEnumerator(); } - + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.Statements.GetEnumerator(); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BreakStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BreakStatement.cs index a1a3a1feb..df8732e81 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BreakStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BreakStatement.cs @@ -32,31 +32,31 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class BreakStatement : Statement { - public static readonly TokenRole BreakKeywordRole = new TokenRole ("break"); - + public static readonly TokenRole BreakKeywordRole = new TokenRole("break"); + public CSharpTokenNode BreakToken { - get { return GetChildByRole (BreakKeywordRole); } + get { return GetChildByRole(BreakKeywordRole); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitBreakStatement (this); + visitor.VisitBreakStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitBreakStatement (this); + return visitor.VisitBreakStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitBreakStatement (this, data); + return visitor.VisitBreakStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { BreakStatement o = other as BreakStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/CheckedStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/CheckedStatement.cs index 89d7ed1aa..c701dcfc5 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/CheckedStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/CheckedStatement.cs @@ -32,41 +32,41 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class CheckedStatement : Statement { - public static readonly TokenRole CheckedKeywordRole = new TokenRole ("checked"); - + public static readonly TokenRole CheckedKeywordRole = new TokenRole("checked"); + public CSharpTokenNode CheckedToken { - get { return GetChildByRole (CheckedKeywordRole); } + get { return GetChildByRole(CheckedKeywordRole); } } - + public BlockStatement Body { - get { return GetChildByRole (Roles.Body); } - set { SetChildByRole (Roles.Body, value); } + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } } - - public CheckedStatement () + + public CheckedStatement() { } - - public CheckedStatement (BlockStatement body) + + public CheckedStatement(BlockStatement body) { - AddChild (body, Roles.Body); + AddChild(body, Roles.Body); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitCheckedStatement (this); + visitor.VisitCheckedStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitCheckedStatement (this); + return visitor.VisitCheckedStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitCheckedStatement (this, data); + return visitor.VisitCheckedStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { CheckedStatement o = other as CheckedStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ContinueStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ContinueStatement.cs index b527bdf1e..a4b8abacf 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ContinueStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ContinueStatement.cs @@ -32,31 +32,31 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class ContinueStatement : Statement { - public static readonly TokenRole ContinueKeywordRole = new TokenRole ("continue"); - + public static readonly TokenRole ContinueKeywordRole = new TokenRole("continue"); + public CSharpTokenNode ContinueToken { - get { return GetChildByRole (ContinueKeywordRole); } + get { return GetChildByRole(ContinueKeywordRole); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitContinueStatement (this); + visitor.VisitContinueStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitContinueStatement (this); + return visitor.VisitContinueStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitContinueStatement (this, data); + return visitor.VisitContinueStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ContinueStatement o = other as ContinueStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/DoWhileStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/DoWhileStatement.cs index bc25ec3f2..ce05ff6b6 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/DoWhileStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/DoWhileStatement.cs @@ -32,54 +32,54 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class DoWhileStatement : Statement { - public static readonly TokenRole DoKeywordRole = new TokenRole ("do"); - public static readonly TokenRole WhileKeywordRole = new TokenRole ("while"); - + public static readonly TokenRole DoKeywordRole = new TokenRole("do"); + public static readonly TokenRole WhileKeywordRole = new TokenRole("while"); + public CSharpTokenNode DoToken { - get { return GetChildByRole (DoKeywordRole); } + get { return GetChildByRole(DoKeywordRole); } } - + public Statement EmbeddedStatement { - get { return GetChildByRole (Roles.EmbeddedStatement); } - set { SetChildByRole (Roles.EmbeddedStatement, value); } + get { return GetChildByRole(Roles.EmbeddedStatement); } + set { SetChildByRole(Roles.EmbeddedStatement, value); } } - + public CSharpTokenNode WhileToken { - get { return GetChildByRole (WhileKeywordRole); } + get { return GetChildByRole(WhileKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public Expression Condition { - get { return GetChildByRole (Roles.Condition); } - set { SetChildByRole (Roles.Condition, value); } + get { return GetChildByRole(Roles.Condition); } + set { SetChildByRole(Roles.Condition, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitDoWhileStatement (this); + visitor.VisitDoWhileStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitDoWhileStatement (this); + return visitor.VisitDoWhileStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitDoWhileStatement (this, data); + return visitor.VisitDoWhileStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { DoWhileStatement o = other as DoWhileStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/EmptyStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/EmptyStatement.cs index d85adaf2e..c76016963 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/EmptyStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/EmptyStatement.cs @@ -36,34 +36,34 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get; set; } - + public override TextLocation StartLocation { get { return Location; } } - + public override TextLocation EndLocation { get { - return new TextLocation (Location.Line, Location.Column + 1); + return new TextLocation(Location.Line, Location.Column + 1); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitEmptyStatement (this); + visitor.VisitEmptyStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitEmptyStatement (this); + return visitor.VisitEmptyStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitEmptyStatement (this, data); + return visitor.VisitEmptyStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { EmptyStatement o = other as EmptyStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ExpressionStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ExpressionStatement.cs index c9a1d320d..5a4f2a413 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ExpressionStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ExpressionStatement.cs @@ -33,38 +33,38 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class ExpressionStatement : Statement { public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitExpressionStatement (this); + visitor.VisitExpressionStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitExpressionStatement (this); + return visitor.VisitExpressionStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitExpressionStatement (this, 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; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/FixedStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/FixedStatement.cs index 6a0aee6ef..3b34ea2fb 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/FixedStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/FixedStatement.cs @@ -32,49 +32,49 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class FixedStatement : Statement { - public static readonly TokenRole FixedKeywordRole = new TokenRole ("fixed"); - + public static readonly TokenRole FixedKeywordRole = new TokenRole("fixed"); + public CSharpTokenNode FixedToken { - get { return GetChildByRole (FixedKeywordRole); } + get { return GetChildByRole(FixedKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } } - + public AstNodeCollection Variables { - get { return GetChildrenByRole (Roles.Variable); } + get { return GetChildrenByRole(Roles.Variable); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public Statement EmbeddedStatement { - get { return GetChildByRole (Roles.EmbeddedStatement); } - set { SetChildByRole (Roles.EmbeddedStatement, value); } + get { return GetChildByRole(Roles.EmbeddedStatement); } + set { SetChildByRole(Roles.EmbeddedStatement, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitFixedStatement (this); + visitor.VisitFixedStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitFixedStatement (this); + return visitor.VisitFixedStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitFixedStatement (this, data); + return visitor.VisitFixedStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { FixedStatement o = other as FixedStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForStatement.cs index decdaf46a..91784f0d4 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForStatement.cs @@ -32,60 +32,60 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class ForStatement : Statement { - public static readonly TokenRole ForKeywordRole = new TokenRole ("for"); + public static readonly TokenRole ForKeywordRole = new TokenRole("for"); public readonly static Role InitializerRole = new Role("Initializer", Statement.Null); public readonly static Role IteratorRole = new Role("Iterator", Statement.Null); - + public CSharpTokenNode ForToken { - get { return GetChildByRole (ForKeywordRole); } + get { return GetChildByRole(ForKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + /// /// Gets the list of initializer statements. /// Note: this contains multiple statements for "for (a = 2, b = 1; a > b; a--)", but contains /// only a single statement for "for (int a = 2, b = 1; a > b; a--)" (a single VariableDeclarationStatement with two variables) /// public AstNodeCollection Initializers { - get { return GetChildrenByRole (InitializerRole); } + get { return GetChildrenByRole(InitializerRole); } } - + public Expression Condition { - get { return GetChildByRole (Roles.Condition); } - set { SetChildByRole (Roles.Condition, value); } + get { return GetChildByRole(Roles.Condition); } + set { SetChildByRole(Roles.Condition, value); } } - + public AstNodeCollection Iterators { - get { return GetChildrenByRole (IteratorRole); } + get { return GetChildrenByRole(IteratorRole); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public Statement EmbeddedStatement { - get { return GetChildByRole (Roles.EmbeddedStatement); } - set { SetChildByRole (Roles.EmbeddedStatement, value); } + get { return GetChildByRole(Roles.EmbeddedStatement); } + set { SetChildByRole(Roles.EmbeddedStatement, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitForStatement (this); + visitor.VisitForStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitForStatement (this); + return visitor.VisitForStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitForStatement (this, data); + return visitor.VisitForStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ForStatement o = other as ForStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForeachStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForeachStatement.cs index ae42b4aa0..a01bc05de 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForeachStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForeachStatement.cs @@ -33,8 +33,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class ForeachStatement : Statement { public static readonly TokenRole AwaitRole = UnaryOperatorExpression.AwaitRole; - public static readonly TokenRole ForeachKeywordRole = new TokenRole ("foreach"); - public static readonly TokenRole InKeywordRole = new TokenRole ("in"); + public static readonly TokenRole ForeachKeywordRole = new TokenRole("foreach"); + public static readonly TokenRole InKeywordRole = new TokenRole("in"); public CSharpTokenNode AwaitToken { get { return GetChildByRole(AwaitRole); } @@ -46,56 +46,56 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } public CSharpTokenNode ForeachToken { - get { return GetChildByRole (ForeachKeywordRole); } + get { return GetChildByRole(ForeachKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstType VariableType { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } } public VariableDesignation VariableDesignation { get { return GetChildByRole(Roles.VariableDesignationRole); } set { SetChildByRole(Roles.VariableDesignationRole, value); } } - + public CSharpTokenNode InToken { - get { return GetChildByRole (InKeywordRole); } + get { return GetChildByRole(InKeywordRole); } } - + public Expression InExpression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public Statement EmbeddedStatement { - get { return GetChildByRole (Roles.EmbeddedStatement); } - set { SetChildByRole (Roles.EmbeddedStatement, value); } + get { return GetChildByRole(Roles.EmbeddedStatement); } + set { SetChildByRole(Roles.EmbeddedStatement, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitForeachStatement (this); + visitor.VisitForeachStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitForeachStatement (this); + return visitor.VisitForeachStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitForeachStatement (this, data); + return visitor.VisitForeachStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ForeachStatement o = other as ForeachStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/GotoStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/GotoStatement.cs index 9bddbe9eb..b1b064c01 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/GotoStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/GotoStatement.cs @@ -32,144 +32,144 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class GotoStatement : Statement { - public static readonly TokenRole GotoKeywordRole = new TokenRole ("goto"); - - public GotoStatement () + public static readonly TokenRole GotoKeywordRole = new TokenRole("goto"); + + public GotoStatement() { } - - public GotoStatement (string label) + + public GotoStatement(string label) { this.Label = label; } - + public CSharpTokenNode GotoToken { - get { return GetChildByRole (GotoKeywordRole); } + get { return GetChildByRole(GotoKeywordRole); } } - + public string Label { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { if (string.IsNullOrEmpty(value)) SetChildByRole(Roles.Identifier, null); else - SetChildByRole(Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitGotoStatement (this); + visitor.VisitGotoStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitGotoStatement (this); + return visitor.VisitGotoStatement(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitGotoStatement (this, data); + return visitor.VisitGotoStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { GotoStatement o = other as GotoStatement; return o != null && MatchString(this.Label, o.Label); } } - + /// /// or "goto case LabelExpression;" /// public class GotoCaseStatement : Statement { - public static readonly TokenRole GotoKeywordRole = new TokenRole ("goto"); - public static readonly TokenRole CaseKeywordRole = new TokenRole ("case"); - + public static readonly TokenRole GotoKeywordRole = new TokenRole("goto"); + public static readonly TokenRole CaseKeywordRole = new TokenRole("case"); + public CSharpTokenNode GotoToken { - get { return GetChildByRole (GotoKeywordRole); } + get { return GetChildByRole(GotoKeywordRole); } } - + public CSharpTokenNode CaseToken { - get { return GetChildByRole (CaseKeywordRole); } + get { return GetChildByRole(CaseKeywordRole); } } - + /// /// Used for "goto case LabelExpression;" /// public Expression LabelExpression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitGotoCaseStatement (this); + visitor.VisitGotoCaseStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitGotoCaseStatement (this); + return visitor.VisitGotoCaseStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitGotoCaseStatement (this, data); + return visitor.VisitGotoCaseStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { GotoCaseStatement o = other as GotoCaseStatement; return o != null && this.LabelExpression.DoMatch(o.LabelExpression, match); } } - + /// /// or "goto default;" /// public class GotoDefaultStatement : Statement { - public static readonly TokenRole GotoKeywordRole = new TokenRole ("goto"); - public static readonly TokenRole DefaultKeywordRole = new TokenRole ("default"); - + public static readonly TokenRole GotoKeywordRole = new TokenRole("goto"); + public static readonly TokenRole DefaultKeywordRole = new TokenRole("default"); + public CSharpTokenNode GotoToken { - get { return GetChildByRole (GotoKeywordRole); } + get { return GetChildByRole(GotoKeywordRole); } } - + public CSharpTokenNode DefaultToken { - get { return GetChildByRole (DefaultKeywordRole); } + get { return GetChildByRole(DefaultKeywordRole); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitGotoDefaultStatement (this); + visitor.VisitGotoDefaultStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitGotoDefaultStatement (this); + return visitor.VisitGotoDefaultStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitGotoDefaultStatement (this, data); + return visitor.VisitGotoDefaultStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { GotoDefaultStatement o = other as GotoDefaultStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/IfElseStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/IfElseStatement.cs index 38184981b..fece09f10 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/IfElseStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/IfElseStatement.cs @@ -32,68 +32,68 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class IfElseStatement : Statement { - public readonly static TokenRole IfKeywordRole = new TokenRole ("if"); + public readonly static TokenRole IfKeywordRole = new TokenRole("if"); public readonly static Role ConditionRole = Roles.Condition; public readonly static Role TrueRole = new Role("True", Statement.Null); - public readonly static TokenRole ElseKeywordRole = new TokenRole ("else"); + public readonly static TokenRole ElseKeywordRole = new TokenRole("else"); public readonly static Role FalseRole = new Role("False", Statement.Null); - + public CSharpTokenNode IfToken { - get { return GetChildByRole (IfKeywordRole); } + get { return GetChildByRole(IfKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public Expression Condition { - get { return GetChildByRole (ConditionRole); } - set { SetChildByRole (ConditionRole, value); } + get { return GetChildByRole(ConditionRole); } + set { SetChildByRole(ConditionRole, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public Statement TrueStatement { - get { return GetChildByRole (TrueRole); } - set { SetChildByRole (TrueRole, value); } + get { return GetChildByRole(TrueRole); } + set { SetChildByRole(TrueRole, value); } } - + public CSharpTokenNode ElseToken { - get { return GetChildByRole (ElseKeywordRole); } + get { return GetChildByRole(ElseKeywordRole); } } - + public Statement FalseStatement { - get { return GetChildByRole (FalseRole); } - set { SetChildByRole (FalseRole, value); } + get { return GetChildByRole(FalseRole); } + set { SetChildByRole(FalseRole, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitIfElseStatement (this); + visitor.VisitIfElseStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitIfElseStatement (this); + return visitor.VisitIfElseStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitIfElseStatement (this, data); + return visitor.VisitIfElseStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { IfElseStatement o = other as IfElseStatement; return o != null && this.Condition.DoMatch(o.Condition, match) && this.TrueStatement.DoMatch(o.TrueStatement, match) && this.FalseStatement.DoMatch(o.FalseStatement, match); } - + public IfElseStatement() { } - + public IfElseStatement(Expression condition, Statement trueStatement, Statement falseStatement = null) { this.Condition = condition; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LabelStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LabelStatement.cs index 57dd6d6da..ca56ec478 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LabelStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LabelStatement.cs @@ -34,37 +34,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public string Label { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier LabelToken { - get { return GetChildByRole (Roles.Identifier); } - set { SetChildByRole (Roles.Identifier, value); } + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } } public CSharpTokenNode ColonToken { - get { return GetChildByRole (Roles.Colon); } + get { return GetChildByRole(Roles.Colon); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitLabelStatement (this); + visitor.VisitLabelStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitLabelStatement (this); + return visitor.VisitLabelStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitLabelStatement (this, data); + return visitor.VisitLabelStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { LabelStatement o = other as LabelStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LockStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LockStatement.cs index b40293c09..a8f25c579 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LockStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LockStatement.cs @@ -32,45 +32,45 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class LockStatement : Statement { - public static readonly TokenRole LockKeywordRole = new TokenRole ("lock"); - + public static readonly TokenRole LockKeywordRole = new TokenRole("lock"); + public CSharpTokenNode LockToken { - get { return GetChildByRole (LockKeywordRole); } + get { return GetChildByRole(LockKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public Statement EmbeddedStatement { - get { return GetChildByRole (Roles.EmbeddedStatement); } - set { SetChildByRole (Roles.EmbeddedStatement, value); } + get { return GetChildByRole(Roles.EmbeddedStatement); } + set { SetChildByRole(Roles.EmbeddedStatement, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitLockStatement (this); + visitor.VisitLockStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitLockStatement (this); + return visitor.VisitLockStatement(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitLockStatement (this, data); + return visitor.VisitLockStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { LockStatement o = other as LockStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ReturnStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ReturnStatement.cs index 60c8d1790..75b96f4fe 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ReturnStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ReturnStatement.cs @@ -32,45 +32,45 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class ReturnStatement : Statement { - public static readonly TokenRole ReturnKeywordRole = new TokenRole ("return"); + public static readonly TokenRole ReturnKeywordRole = new TokenRole("return"); public CSharpTokenNode ReturnToken { - get { return GetChildByRole (ReturnKeywordRole); } + get { return GetChildByRole(ReturnKeywordRole); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public ReturnStatement () + + public ReturnStatement() { } - - public ReturnStatement (Expression returnExpression) + + public ReturnStatement(Expression returnExpression) { - AddChild (returnExpression, Roles.Expression); + AddChild(returnExpression, Roles.Expression); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitReturnStatement (this); + visitor.VisitReturnStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitReturnStatement (this); + return visitor.VisitReturnStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitReturnStatement (this, data); + return visitor.VisitReturnStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ReturnStatement o = other as ReturnStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/Statement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/Statement.cs index 5ffab0f7f..b278d1e3f 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/Statement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/Statement.cs @@ -30,8 +30,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public abstract class Statement : AstNode { #region Null - public new static readonly Statement Null = new NullStatement (); - + public new static readonly Statement Null = new NullStatement(); + sealed class NullStatement : Statement { public override bool IsNull { @@ -39,54 +39,54 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } } #endregion - + #region PatternPlaceholder public static implicit operator Statement(PatternMatching.Pattern pattern) { return pattern != null ? new PatternPlaceholder(pattern) : null; } - + sealed class PatternPlaceholder : Statement, PatternMatching.INode { readonly PatternMatching.Pattern child; - + public PatternPlaceholder(PatternMatching.Pattern child) { this.child = child; } - + public override NodeType NodeType { get { return NodeType.Pattern; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitPatternPlaceholder(this, child); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitPatternPlaceholder(this, child); } @@ -95,31 +95,31 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return visitor.VisitPatternPlaceholder(this, child, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return child.DoMatch(other, match); } - + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) { return child.DoMatchCollection(role, pos, match, backtrackingInfo); } } #endregion - + public new Statement Clone() { return (Statement)base.Clone(); } - + public Statement ReplaceWith(Func replaceFunction) { if (replaceFunction == null) throw new ArgumentNullException(nameof(replaceFunction)); return (Statement)base.ReplaceWith(node => replaceFunction((Statement)node)); } - + public override NodeType NodeType { get { return NodeType.Statement; } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs index 57bfabfa1..c6f3c5745 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs @@ -32,60 +32,60 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class SwitchStatement : Statement { - public static readonly TokenRole SwitchKeywordRole = new TokenRole ("switch"); + public static readonly TokenRole SwitchKeywordRole = new TokenRole("switch"); public static readonly Role SwitchSectionRole = new Role("SwitchSection"); - + public CSharpTokenNode SwitchToken { - get { return GetChildByRole (SwitchKeywordRole); } + get { return GetChildByRole(SwitchKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public CSharpTokenNode LBraceToken { - get { return GetChildByRole (Roles.LBrace); } + get { return GetChildByRole(Roles.LBrace); } } - + public AstNodeCollection SwitchSections { - get { return GetChildrenByRole (SwitchSectionRole); } + get { return GetChildrenByRole(SwitchSectionRole); } } - + public CSharpTokenNode RBraceToken { - get { return GetChildByRole (Roles.RBrace); } + get { return GetChildByRole(Roles.RBrace); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitSwitchStatement (this); + visitor.VisitSwitchStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitSwitchStatement (this); + return visitor.VisitSwitchStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitSwitchStatement (this, data); + return visitor.VisitSwitchStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { SwitchStatement o = other as SwitchStatement; return o != null && this.Expression.DoMatch(o.Expression, match) && this.SwitchSections.DoMatch(o.SwitchSections, match); } } - + public class SwitchSection : AstNode { #region PatternPlaceholder @@ -93,132 +93,132 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return pattern != null ? new PatternPlaceholder(pattern) : null; } - + sealed class PatternPlaceholder : SwitchSection, PatternMatching.INode { readonly PatternMatching.Pattern child; - + public PatternPlaceholder(PatternMatching.Pattern child) { this.child = child; } - + public override NodeType NodeType { get { return NodeType.Pattern; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitPatternPlaceholder(this, child); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitPatternPlaceholder(this, child); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitPatternPlaceholder(this, child, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return child.DoMatch(other, match); } - + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) { return child.DoMatchCollection(role, pos, match, backtrackingInfo); } } #endregion - + public static readonly Role CaseLabelRole = new Role("CaseLabel"); - + public override NodeType NodeType { get { return NodeType.Unknown; } } - + public AstNodeCollection CaseLabels { - get { return GetChildrenByRole (CaseLabelRole); } + get { return GetChildrenByRole(CaseLabelRole); } } - + public AstNodeCollection Statements { - get { return GetChildrenByRole (Roles.EmbeddedStatement); } + get { return GetChildrenByRole(Roles.EmbeddedStatement); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitSwitchSection (this); + visitor.VisitSwitchSection(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitSwitchSection (this); + return visitor.VisitSwitchSection(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitSwitchSection (this, data); + return visitor.VisitSwitchSection(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { SwitchSection o = other as SwitchSection; return o != null && this.CaseLabels.DoMatch(o.CaseLabels, match) && this.Statements.DoMatch(o.Statements, match); } } - + public class CaseLabel : AstNode { - public static readonly TokenRole CaseKeywordRole = new TokenRole ("case"); - public static readonly TokenRole DefaultKeywordRole = new TokenRole ("default"); - + public static readonly TokenRole CaseKeywordRole = new TokenRole("case"); + public static readonly TokenRole DefaultKeywordRole = new TokenRole("default"); + public override NodeType NodeType { get { return NodeType.Unknown; } } - + /// /// 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); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } public CSharpTokenNode ColonToken { - get { return GetChildByRole (Roles.Colon); } + get { return GetChildByRole(Roles.Colon); } } - public CaseLabel () + public CaseLabel() { } - - public CaseLabel (Expression expression) + + public CaseLabel(Expression expression) { this.Expression = expression; } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitCaseLabel (this); + visitor.VisitCaseLabel(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitCaseLabel (this); + return visitor.VisitCaseLabel(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitCaseLabel (this, data); + return visitor.VisitCaseLabel(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { CaseLabel o = other as CaseLabel; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ThrowStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ThrowStatement.cs index 6531f9507..a16d67a34 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ThrowStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ThrowStatement.cs @@ -32,45 +32,45 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class ThrowStatement : Statement { - public static readonly TokenRole ThrowKeywordRole = new TokenRole ("throw"); - + public static readonly TokenRole ThrowKeywordRole = new TokenRole("throw"); + public CSharpTokenNode ThrowToken { - get { return GetChildByRole (ThrowKeywordRole); } + get { return GetChildByRole(ThrowKeywordRole); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public ThrowStatement () + + public ThrowStatement() { } - - public ThrowStatement (Expression expression) + + public ThrowStatement(Expression expression) { - AddChild (expression, Roles.Expression); + AddChild(expression, Roles.Expression); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitThrowStatement (this); + visitor.VisitThrowStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitThrowStatement (this); + return visitor.VisitThrowStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitThrowStatement (this, data); + return visitor.VisitThrowStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ThrowStatement o = other as ThrowStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UncheckedStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UncheckedStatement.cs index a947d733a..f24f7213e 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UncheckedStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UncheckedStatement.cs @@ -32,41 +32,41 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class UncheckedStatement : Statement { - public static readonly TokenRole UncheckedKeywordRole = new TokenRole ("unchecked"); - + public static readonly TokenRole UncheckedKeywordRole = new TokenRole("unchecked"); + public CSharpTokenNode UncheckedToken { - get { return GetChildByRole (UncheckedKeywordRole); } + get { return GetChildByRole(UncheckedKeywordRole); } } - + public BlockStatement Body { - get { return GetChildByRole (Roles.Body); } - set { SetChildByRole (Roles.Body, value); } + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } } - - public UncheckedStatement () + + public UncheckedStatement() { } - - public UncheckedStatement (BlockStatement body) + + public UncheckedStatement(BlockStatement body) { - AddChild (body, Roles.Body); + AddChild(body, Roles.Body); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitUncheckedStatement (this); + visitor.VisitUncheckedStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitUncheckedStatement (this); + return visitor.VisitUncheckedStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitUncheckedStatement (this, data); + return visitor.VisitUncheckedStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { UncheckedStatement o = other as UncheckedStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UnsafeStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UnsafeStatement.cs index 751981417..1a977d5b9 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UnsafeStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UnsafeStatement.cs @@ -32,32 +32,32 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class UnsafeStatement : Statement { - public static readonly TokenRole UnsafeKeywordRole = new TokenRole ("unsafe"); - + public static readonly TokenRole UnsafeKeywordRole = new TokenRole("unsafe"); + public CSharpTokenNode UnsafeToken { - get { return GetChildByRole (UnsafeKeywordRole); } + get { return GetChildByRole(UnsafeKeywordRole); } } - + public BlockStatement Body { - get { return GetChildByRole (Roles.Body); } - set { SetChildByRole (Roles.Body, value); } + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitUnsafeStatement (this); + visitor.VisitUnsafeStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitUnsafeStatement (this); + return visitor.VisitUnsafeStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitUnsafeStatement (this, data); + return visitor.VisitUnsafeStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { UnsafeStatement o = other as UnsafeStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/VariableDeclarationStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/VariableDeclarationStatement.cs index 3ab595ce6..1a6066f17 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/VariableDeclarationStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/VariableDeclarationStatement.cs @@ -30,55 +30,55 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class VariableDeclarationStatement : Statement { public static readonly Role ModifierRole = EntityDeclaration.ModifierRole; - + public VariableDeclarationStatement() { } - + public VariableDeclarationStatement(AstType type, string name, Expression initializer = null) { this.Type = type; this.Variables.Add(new VariableInitializer(name, initializer)); } - + public Modifiers Modifiers { get { return EntityDeclaration.GetModifiers(this); } set { EntityDeclaration.SetModifiers(this, value); } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } } - + public AstNodeCollection Variables { - get { return GetChildrenByRole (Roles.Variable); } + get { return GetChildrenByRole(Roles.Variable); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public VariableInitializer GetVariable (string name) + + public VariableInitializer GetVariable(string name) { - return Variables.FirstOrNullObject (vi => vi.Name == name); + return Variables.FirstOrNullObject(vi => vi.Name == name); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitVariableDeclarationStatement (this); + visitor.VisitVariableDeclarationStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitVariableDeclarationStatement (this); + return visitor.VisitVariableDeclarationStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitVariableDeclarationStatement (this, data); + return visitor.VisitVariableDeclarationStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { VariableDeclarationStatement o = other as VariableDeclarationStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/WhileStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/WhileStatement.cs index 57211a096..3e852e35d 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/WhileStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/WhileStatement.cs @@ -32,45 +32,45 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class WhileStatement : Statement { - public static readonly TokenRole WhileKeywordRole = new TokenRole ("while"); - + public static readonly TokenRole WhileKeywordRole = new TokenRole("while"); + public CSharpTokenNode WhileToken { - get { return GetChildByRole (WhileKeywordRole); } + get { return GetChildByRole(WhileKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public Expression Condition { - get { return GetChildByRole (Roles.Condition); } - set { SetChildByRole (Roles.Condition, value); } + get { return GetChildByRole(Roles.Condition); } + set { SetChildByRole(Roles.Condition, value); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public Statement EmbeddedStatement { - get { return GetChildByRole (Roles.EmbeddedStatement); } - set { SetChildByRole (Roles.EmbeddedStatement, value); } + get { return GetChildByRole(Roles.EmbeddedStatement); } + set { SetChildByRole(Roles.EmbeddedStatement, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitWhileStatement (this); + visitor.VisitWhileStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitWhileStatement (this); + return visitor.VisitWhileStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitWhileStatement (this, data); + return visitor.VisitWhileStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { WhileStatement o = other as WhileStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/YieldBreakStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/YieldBreakStatement.cs index 8cb158c7b..4a777afa9 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/YieldBreakStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/YieldBreakStatement.cs @@ -32,36 +32,36 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class YieldBreakStatement : Statement { - public static readonly TokenRole YieldKeywordRole = new TokenRole ("yield"); - public static readonly TokenRole BreakKeywordRole = new TokenRole ("break"); - + public static readonly TokenRole YieldKeywordRole = new TokenRole("yield"); + public static readonly TokenRole BreakKeywordRole = new TokenRole("break"); + public CSharpTokenNode YieldToken { - get { return GetChildByRole (YieldKeywordRole); } + get { return GetChildByRole(YieldKeywordRole); } } - + public CSharpTokenNode BreakToken { - get { return GetChildByRole (BreakKeywordRole); } + get { return GetChildByRole(BreakKeywordRole); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitYieldBreakStatement (this); + visitor.VisitYieldBreakStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitYieldBreakStatement (this); + return visitor.VisitYieldBreakStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitYieldBreakStatement (this, data); + return visitor.VisitYieldBreakStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { YieldBreakStatement o = other as YieldBreakStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/YieldReturnStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/YieldReturnStatement.cs index 3ee6dd50f..235201ab2 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/YieldReturnStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/YieldReturnStatement.cs @@ -32,41 +32,41 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class YieldReturnStatement : Statement { - public static readonly TokenRole YieldKeywordRole = new TokenRole ("yield"); - public static readonly TokenRole ReturnKeywordRole = new TokenRole ("return"); - + public static readonly TokenRole YieldKeywordRole = new TokenRole("yield"); + public static readonly TokenRole ReturnKeywordRole = new TokenRole("return"); + public CSharpTokenNode YieldToken { - get { return GetChildByRole (YieldKeywordRole); } + get { return GetChildByRole(YieldKeywordRole); } } - + public CSharpTokenNode ReturnToken { - get { return GetChildByRole (ReturnKeywordRole); } + get { return GetChildByRole(ReturnKeywordRole); } } - + public Expression Expression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - + public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitYieldReturnStatement (this); + visitor.VisitYieldReturnStatement(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitYieldReturnStatement (this); + return visitor.VisitYieldReturnStatement(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitYieldReturnStatement (this, data); + return visitor.VisitYieldReturnStatement(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { YieldReturnStatement o = other as YieldReturnStatement; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxExtensions.cs b/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxExtensions.cs index 632e6bbbb..8d6cc4bc6 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxExtensions.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxExtensions.cs @@ -28,7 +28,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public static bool IsComparisonOperator(this OperatorType operatorType) { - switch (operatorType) { + switch (operatorType) + { case OperatorType.Equality: case OperatorType.Inequality: case OperatorType.GreaterThan: diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs b/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs index f16d84c2c..92e3bb63d 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System.Collections.Generic; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -33,15 +34,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class SyntaxTree : AstNode { public static readonly Role MemberRole = new Role("Member", AstNode.Null); - + public override NodeType NodeType { get { return NodeType.Unknown; } } - + string fileName; - + /// /// Gets/Sets the file name of this syntax tree. /// @@ -52,7 +53,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax fileName = value; } } - + public AstNodeCollection Members { get { return GetChildrenByRole(MemberRole); } } @@ -84,11 +85,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get; internal set; } - - public SyntaxTree () + + public SyntaxTree() { } - + /// /// Gets all defined types in this syntax tree. /// @@ -97,41 +98,44 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public IEnumerable GetTypes(bool includeInnerTypes = false) { - Stack nodeStack = new Stack (); + Stack nodeStack = new Stack(); nodeStack.Push(this); - while (nodeStack.Count > 0) { + while (nodeStack.Count > 0) + { var curNode = nodeStack.Pop(); - if (curNode is TypeDeclaration || curNode is DelegateDeclaration) { + if (curNode is TypeDeclaration || curNode is DelegateDeclaration) + { yield return (EntityDeclaration)curNode; } - foreach (var child in curNode.Children) { + foreach (var child in curNode.Children) + { if (!(child is Statement || child is Expression) && - (child.Role != Roles.TypeMemberRole || ((child is TypeDeclaration || child is DelegateDeclaration) && includeInnerTypes))) - nodeStack.Push (child); + (child.Role != Roles.TypeMemberRole || ((child is TypeDeclaration || child is DelegateDeclaration) && includeInnerTypes))) + nodeStack.Push(child); } } } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { SyntaxTree o = other as SyntaxTree; return o != null && this.Members.DoMatch(o.Members, match); } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitSyntaxTree (this); + visitor.VisitSyntaxTree(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitSyntaxTree (this); + return visitor.VisitSyntaxTree(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitSyntaxTree (this, data); + return visitor.VisitSyntaxTree(this, data); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TextLocation.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TextLocation.cs index 8f9746d8d..487a9cc1c 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TextLocation.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TextLocation.cs @@ -34,17 +34,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// Represents no text location (0, 0). /// public static readonly TextLocation Empty = new TextLocation(0, 0); - + /// /// Constant of the minimum line. /// - public const int MinLine = 1; - + public const int MinLine = 1; + /// /// Constant of the minimum column. /// public const int MinColumn = 1; - + /// /// Creates a TextLocation instance. /// @@ -53,23 +53,23 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.line = line; this.column = column; } - + int column, line; - + /// /// Gets the line number. /// public int Line { get { return line; } } - + /// /// Gets the column number. /// public int Column { get { return column; } } - + /// /// Gets whether the TextLocation instance is empty. /// @@ -78,7 +78,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return column < MinLine && line < MinColumn; } } - + /// /// Gets a string representation for debugging purposes. /// @@ -86,24 +86,25 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return string.Format(CultureInfo.InvariantCulture, "(Line {1}, Col {0})", this.column, this.line); } - + /// /// Gets a hash code. /// public override int GetHashCode() { - return unchecked (191 * column.GetHashCode() ^ line.GetHashCode()); + return unchecked(191 * column.GetHashCode() ^ line.GetHashCode()); } - + /// /// Equality test. /// public override bool Equals(object obj) { - if (!(obj is TextLocation)) return false; + if (!(obj is TextLocation)) + return false; return (TextLocation)obj == this; } - + /// /// Equality test. /// @@ -111,7 +112,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return this == other; } - + /// /// Equality test. /// @@ -119,7 +120,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return left.column == right.column && left.line == right.line; } - + /// /// Inequality test. /// @@ -127,7 +128,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return left.column != right.column || left.line != right.line; } - + /// /// Compares two text locations. /// @@ -140,7 +141,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax else return false; } - + /// /// Compares two text locations. /// @@ -153,7 +154,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax else return false; } - + /// /// Compares two text locations. /// @@ -161,7 +162,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return !(left > right); } - + /// /// Compares two text locations. /// @@ -169,7 +170,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return !(left < right); } - + /// /// Compares two text locations. /// @@ -183,33 +184,36 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return 1; } } - + public class TextLocationConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { return destinationType == typeof(TextLocation) || base.CanConvertTo(context, destinationType); } - + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { - if (value is string) { + if (value is string) + { string[] parts = ((string)value).Split(';', ','); - if (parts.Length == 2) { + if (parts.Length == 2) + { return new TextLocation(int.Parse(parts[0]), int.Parse(parts[1])); } } return base.ConvertFrom(context, culture, value); } - + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { - if (value is TextLocation) { + if (value is TextLocation) + { var loc = (TextLocation)value; return loc.Line + ";" + loc.Column; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TokenRole.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TokenRole.cs index 7ac213103..233637d6b 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TokenRole.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TokenRole.cs @@ -7,15 +7,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public sealed class TokenRole : Role { - internal readonly static List Tokens = new List (); - internal readonly static List TokenLengths = new List (); + internal readonly static List Tokens = new List(); + internal readonly static List TokenLengths = new List(); internal readonly uint TokenIndex; - static TokenRole () + static TokenRole() { // null token - Tokens.Add (""); - TokenLengths.Add (0); + Tokens.Add(""); + TokenLengths.Add(0); } /// @@ -25,7 +25,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get; private set; } - + /// /// Gets the char length of the token. /// @@ -35,24 +35,27 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } - public TokenRole(string token) : base (token, CSharpTokenNode.Null) + public TokenRole(string token) : base(token, CSharpTokenNode.Null) { this.Token = token; this.Length = token.Length; bool found = false; - for (int i = 0; i < Tokens.Count; i++) { - var existingToken = Tokens [i]; - if (existingToken == token) { + for (int i = 0; i < Tokens.Count; i++) + { + var existingToken = Tokens[i]; + if (existingToken == token) + { TokenIndex = (uint)i; found = true; break; } } - if (!found) { + if (!found) + { TokenIndex = (uint)Tokens.Count; - Tokens.Add (token); - TokenLengths.Add (this.Length); + Tokens.Add(token); + TokenLengths.Add(this.Length); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs index 4a34830aa..16f5cd4aa 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Immutable; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.TypeSystem; @@ -32,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public AstNodeCollection Elements { get { return GetChildrenByRole(ElementRole); } } - + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitTupleType(this); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/Accessor.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/Accessor.cs index 345aa9aca..bf98d9e9f 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/Accessor.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/Accessor.cs @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public class Accessor : EntityDeclaration { - public static readonly new Accessor Null = new NullAccessor (); + public static readonly new Accessor Null = new NullAccessor(); sealed class NullAccessor : Accessor { public override bool IsNull { @@ -41,42 +41,43 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } } - + public override NodeType NodeType { get { return NodeType.Unknown; } } - + public override SymbolKind SymbolKind { get { return SymbolKind.Method; } } - + /// /// Gets the 'get'/'set'/'init'/'add'/'remove' keyword /// public CSharpTokenNode Keyword { get { - for (AstNode child = this.FirstChild; child != null; child = child.NextSibling) { + for (AstNode child = this.FirstChild; child != null; child = child.NextSibling) + { if (child.Role == PropertyDeclaration.GetKeywordRole || child.Role == PropertyDeclaration.SetKeywordRole || child.Role == PropertyDeclaration.InitKeywordRole || child.Role == CustomEventDeclaration.AddKeywordRole || child.Role == CustomEventDeclaration.RemoveKeywordRole) @@ -87,27 +88,27 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return CSharpTokenNode.Null; } } - + public BlockStatement Body { - get { return GetChildByRole (Roles.Body); } - set { SetChildByRole (Roles.Body, value); } + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitAccessor (this); + visitor.VisitAccessor(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitAccessor (this); + return visitor.VisitAccessor(this); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitAccessor (this, data); + return visitor.VisitAccessor(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { Accessor o = other as Accessor; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ConstructorDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ConstructorDeclaration.cs index 1a9b1cc3b..890b77088 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ConstructorDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ConstructorDeclaration.cs @@ -31,52 +31,52 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class ConstructorDeclaration : EntityDeclaration { public static readonly Role InitializerRole = new Role("Initializer", ConstructorInitializer.Null); - + public override SymbolKind SymbolKind { get { return SymbolKind.Constructor; } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstNodeCollection Parameters { - get { return GetChildrenByRole (Roles.Parameter); } + get { return GetChildrenByRole(Roles.Parameter); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public CSharpTokenNode ColonToken { - get { return GetChildByRole (Roles.Colon); } + get { return GetChildByRole(Roles.Colon); } } - + public ConstructorInitializer Initializer { - get { return GetChildByRole (InitializerRole); } - set { SetChildByRole( InitializerRole, value); } + get { return GetChildByRole(InitializerRole); } + set { SetChildByRole(InitializerRole, value); } } - + public BlockStatement Body { - get { return GetChildByRole (Roles.Body); } - set { SetChildByRole (Roles.Body, value); } + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitConstructorDeclaration (this); + visitor.VisitConstructorDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitConstructorDeclaration (this); + return visitor.VisitConstructorDeclaration(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitConstructorDeclaration (this, data); + return visitor.VisitConstructorDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ConstructorDeclaration o = other as ConstructorDeclaration; @@ -84,19 +84,20 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax && this.Initializer.DoMatch(o.Initializer, match) && this.Body.DoMatch(o.Body, match); } } - - public enum ConstructorInitializerType { + + public enum ConstructorInitializerType + { Any, Base, This } - + public class ConstructorInitializer : AstNode { - public static readonly TokenRole BaseKeywordRole = new TokenRole ("base"); - public static readonly TokenRole ThisKeywordRole = new TokenRole ("this"); - - public static readonly new ConstructorInitializer Null = new NullConstructorInitializer (); + public static readonly TokenRole BaseKeywordRole = new TokenRole("base"); + public static readonly TokenRole ThisKeywordRole = new TokenRole("this"); + + public static readonly new ConstructorInitializer Null = new NullConstructorInitializer(); class NullConstructorInitializer : ConstructorInitializer { public override NodeType NodeType { @@ -104,45 +105,45 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return NodeType.Unknown; } } - + public override bool IsNull { get { return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } } - + public override NodeType NodeType { get { return NodeType.Unknown; } } - + public ConstructorInitializerType ConstructorInitializerType { get; set; } - + public CSharpTokenNode Keyword { get { if (ConstructorInitializerType == ConstructorInitializerType.Base) @@ -151,38 +152,38 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return GetChildByRole(ThisKeywordRole); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstNodeCollection Arguments { - get { return GetChildrenByRole (Roles.Argument); } + get { return GetChildrenByRole(Roles.Argument); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitConstructorInitializer (this); + visitor.VisitConstructorInitializer(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitConstructorInitializer (this); + return visitor.VisitConstructorInitializer(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitConstructorInitializer (this, data); + return visitor.VisitConstructorInitializer(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ConstructorInitializer o = other as ConstructorInitializer; - return o != null && !o.IsNull + return o != null && !o.IsNull && (this.ConstructorInitializerType == ConstructorInitializerType.Any || this.ConstructorInitializerType == o.ConstructorInitializerType) && this.Arguments.DoMatch(o.Arguments, match); } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/DestructorDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/DestructorDeclaration.cs index f2c25829e..5039831ee 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/DestructorDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/DestructorDeclaration.cs @@ -30,43 +30,43 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public class DestructorDeclaration : EntityDeclaration { - public static readonly TokenRole TildeRole = new TokenRole ("~"); - + public static readonly TokenRole TildeRole = new TokenRole("~"); + public CSharpTokenNode TildeToken { - get { return GetChildByRole (TildeRole); } + get { return GetChildByRole(TildeRole); } } - + public override SymbolKind SymbolKind { get { return SymbolKind.Destructor; } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } public BlockStatement Body { - get { return GetChildByRole (Roles.Body); } - set { SetChildByRole (Roles.Body, value); } + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitDestructorDeclaration (this); + visitor.VisitDestructorDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitDestructorDeclaration (this); + return visitor.VisitDestructorDeclaration(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitDestructorDeclaration (this, data); + return visitor.VisitDestructorDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { DestructorDeclaration o = other as DestructorDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs index a8e254c1d..d040f0483 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -27,90 +28,99 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public static readonly Role AttributeRole = new Role("Attribute"); public static readonly Role ModifierRole = new Role("Modifier"); public static readonly Role PrivateImplementationTypeRole = new Role("PrivateImplementationType", AstType.Null); - + public override NodeType NodeType { get { return NodeType.Member; } } - + public abstract SymbolKind SymbolKind { get; } - + public AstNodeCollection Attributes { - get { return base.GetChildrenByRole (AttributeRole); } + get { return base.GetChildrenByRole(AttributeRole); } } - + public Modifiers Modifiers { get { return GetModifiers(this); } set { SetModifiers(this, value); } } - - public bool HasModifier (Modifiers mod) + + public bool HasModifier(Modifiers mod) { return (Modifiers & mod) == mod; } - + public IEnumerable ModifierTokens { - get { return GetChildrenByRole (ModifierRole); } + get { return GetChildrenByRole(ModifierRole); } } - + public virtual string Name { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create(value, TextLocation.Empty)); } } - + public virtual Identifier NameToken { - get { return GetChildByRole (Roles.Identifier); } - set { SetChildByRole (Roles.Identifier, value); } + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } } - + public virtual AstType ReturnType { - get { return GetChildByRole (Roles.Type); } + get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } } public CSharpTokenNode SemicolonToken { - get { return GetChildByRole (Roles.Semicolon); } + get { return GetChildByRole(Roles.Semicolon); } } internal static Modifiers GetModifiers(AstNode node) { Modifiers m = 0; - foreach (CSharpModifierToken t in node.GetChildrenByRole (ModifierRole)) { + foreach (CSharpModifierToken t in node.GetChildrenByRole(ModifierRole)) + { m |= t.Modifier; } return m; } - + internal static void SetModifiers(AstNode node, Modifiers newValue) { Modifiers oldValue = GetModifiers(node); AstNode insertionPos = node.GetChildrenByRole(AttributeRole).LastOrDefault(); - foreach (Modifiers m in CSharpModifierToken.AllModifiers) { - if ((m & newValue) != 0) { - if ((m & oldValue) == 0) { + foreach (Modifiers m in CSharpModifierToken.AllModifiers) + { + if ((m & newValue) != 0) + { + if ((m & oldValue) == 0) + { // Modifier was added var newToken = new CSharpModifierToken(TextLocation.Empty, m); node.InsertChildAfter(insertionPos, newToken, ModifierRole); insertionPos = newToken; - } else { + } + else + { // Modifier already exists insertionPos = node.GetChildrenByRole(ModifierRole).First(t => t.Modifier == m); } - } else { - if ((m & oldValue) != 0) { + } + else + { + if ((m & oldValue) != 0) + { // Modifier was removed - node.GetChildrenByRole (ModifierRole).First(t => t.Modifier == m).Remove(); + node.GetChildrenByRole(ModifierRole).First(t => t.Modifier == m).Remove(); } } } } - - protected bool MatchAttributesAndModifiers (EntityDeclaration o, PatternMatching.Match match) + + protected bool MatchAttributesAndModifiers(EntityDeclaration o, PatternMatching.Match match) { - return (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) && this.Attributes.DoMatch (o.Attributes, match); + return (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) && this.Attributes.DoMatch(o.Attributes, match); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EnumMemberDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EnumMemberDeclaration.cs index ab7b8191e..cbf983454 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EnumMemberDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EnumMemberDeclaration.cs @@ -31,35 +31,35 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class EnumMemberDeclaration : EntityDeclaration { public static readonly Role InitializerRole = new Role("Initializer", Expression.Null); - + public override SymbolKind SymbolKind { get { return SymbolKind.Field; } } public CSharpTokenNode AssignToken { - get { return GetChildByRole (Roles.Assign); } + get { return GetChildByRole(Roles.Assign); } } public Expression Initializer { - get { return GetChildByRole (InitializerRole); } - set { SetChildByRole (InitializerRole, value); } + get { return GetChildByRole(InitializerRole); } + set { SetChildByRole(InitializerRole, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitEnumMemberDeclaration (this); + visitor.VisitEnumMemberDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitEnumMemberDeclaration (this); + return visitor.VisitEnumMemberDeclaration(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitEnumMemberDeclaration (this, data); + return visitor.VisitEnumMemberDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { EnumMemberDeclaration o = other as EnumMemberDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EventDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EventDeclaration.cs index a0c13e2d7..1abb7c739 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EventDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EventDeclaration.cs @@ -26,26 +26,27 @@ using System; using System.ComponentModel; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.CSharp.Syntax { public class EventDeclaration : EntityDeclaration { - public static readonly TokenRole EventKeywordRole = new TokenRole ("event"); - + public static readonly TokenRole EventKeywordRole = new TokenRole("event"); + public override SymbolKind SymbolKind { get { return SymbolKind.Event; } } public CSharpTokenNode EventToken { - get { return GetChildByRole (EventKeywordRole); } + get { return GetChildByRole(EventKeywordRole); } } public AstNodeCollection Variables { - get { return GetChildrenByRole (Roles.Variable); } + get { return GetChildrenByRole(Roles.Variable); } } - + // Hide .Name and .NameToken from users; the actual field names // are stored in the VariableInitializer. [EditorBrowsable(EditorBrowsableState.Never)] @@ -53,28 +54,28 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get { return string.Empty; } set { throw new NotSupportedException(); } } - + [EditorBrowsable(EditorBrowsableState.Never)] public override Identifier NameToken { get { return Identifier.Null; } set { throw new NotSupportedException(); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitEventDeclaration (this); + visitor.VisitEventDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitEventDeclaration (this); + return visitor.VisitEventDeclaration(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitEventDeclaration (this, data); + return visitor.VisitEventDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { EventDeclaration o = other as EventDeclaration; @@ -82,62 +83,62 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax && this.ReturnType.DoMatch(o.ReturnType, match) && this.Variables.DoMatch(o.Variables, match); } } - + public class CustomEventDeclaration : EntityDeclaration { - public static readonly TokenRole EventKeywordRole = new TokenRole ("event"); - public static readonly TokenRole AddKeywordRole = new TokenRole ("add"); - public static readonly TokenRole RemoveKeywordRole = new TokenRole ("remove"); - + public static readonly TokenRole EventKeywordRole = new TokenRole("event"); + public static readonly TokenRole AddKeywordRole = new TokenRole("add"); + public static readonly TokenRole RemoveKeywordRole = new TokenRole("remove"); + public static readonly Role AddAccessorRole = new Role("AddAccessor", Accessor.Null); public static readonly Role RemoveAccessorRole = new Role("RemoveAccessor", Accessor.Null); - + public override SymbolKind SymbolKind { get { return SymbolKind.Event; } } - + /// /// Gets/Sets the type reference of the interface that is explicitly implemented. /// Null node if this member is not an explicit interface implementation. /// public AstType PrivateImplementationType { - get { return GetChildByRole (PrivateImplementationTypeRole); } - set { SetChildByRole (PrivateImplementationTypeRole, value); } + get { return GetChildByRole(PrivateImplementationTypeRole); } + set { SetChildByRole(PrivateImplementationTypeRole, value); } } - + public CSharpTokenNode LBraceToken { - get { return GetChildByRole (Roles.LBrace); } + get { return GetChildByRole(Roles.LBrace); } } - + public Accessor AddAccessor { - get { return GetChildByRole (AddAccessorRole); } - set { SetChildByRole (AddAccessorRole, value); } + get { return GetChildByRole(AddAccessorRole); } + set { SetChildByRole(AddAccessorRole, value); } } - + public Accessor RemoveAccessor { - get { return GetChildByRole (RemoveAccessorRole); } - set { SetChildByRole (RemoveAccessorRole, value); } + get { return GetChildByRole(RemoveAccessorRole); } + set { SetChildByRole(RemoveAccessorRole, value); } } - + public CSharpTokenNode RBraceToken { - get { return GetChildByRole (Roles.RBrace); } + get { return GetChildByRole(Roles.RBrace); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitCustomEventDeclaration (this); + visitor.VisitCustomEventDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitCustomEventDeclaration (this); + return visitor.VisitCustomEventDeclaration(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitCustomEventDeclaration (this, data); + return visitor.VisitCustomEventDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { CustomEventDeclaration o = other as CustomEventDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FieldDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FieldDeclaration.cs index 6a2dca997..548b0333e 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FieldDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FieldDeclaration.cs @@ -26,6 +26,7 @@ using System; using System.ComponentModel; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -35,11 +36,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public override SymbolKind SymbolKind { get { return SymbolKind.Field; } } - + public AstNodeCollection Variables { - get { return GetChildrenByRole (Roles.Variable); } + get { return GetChildrenByRole(Roles.Variable); } } - + // Hide .Name and .NameToken from users; the actual field names // are stored in the VariableInitializer. [EditorBrowsable(EditorBrowsableState.Never)] @@ -47,28 +48,28 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get { return string.Empty; } set { throw new NotSupportedException(); } } - + [EditorBrowsable(EditorBrowsableState.Never)] public override Identifier NameToken { get { return Identifier.Null; } set { throw new NotSupportedException(); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitFieldDeclaration (this); + visitor.VisitFieldDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitFieldDeclaration (this); + return visitor.VisitFieldDeclaration(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitFieldDeclaration (this, data); + return visitor.VisitFieldDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { FieldDeclaration o = other as FieldDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs index b9c2f3d20..32e8a7512 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs @@ -29,41 +29,41 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public class FixedFieldDeclaration : EntityDeclaration { - public static readonly TokenRole FixedKeywordRole = new TokenRole ("fixed"); - public static readonly Role VariableRole = new Role ("FixedVariable"); - + public static readonly TokenRole FixedKeywordRole = new TokenRole("fixed"); + public static readonly Role VariableRole = new Role("FixedVariable"); + public override SymbolKind SymbolKind { get { return SymbolKind.Field; } } - + public CSharpTokenNode FixedToken { - get { return GetChildByRole (FixedKeywordRole); } + get { return GetChildByRole(FixedKeywordRole); } } public AstNodeCollection Variables { - get { return GetChildrenByRole (VariableRole); } + get { return GetChildrenByRole(VariableRole); } } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitFixedFieldDeclaration (this); + visitor.VisitFixedFieldDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitFixedFieldDeclaration (this); + return visitor.VisitFixedFieldDeclaration(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitFixedFieldDeclaration (this, data); + return visitor.VisitFixedFieldDeclaration(this, data); } - protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { var o = other as FixedFieldDeclaration; - return o != null && this.MatchAttributesAndModifiers (o, match) - && this.ReturnType.DoMatch (o.ReturnType, match) && this.Variables.DoMatch (o.Variables, match); + return o != null && this.MatchAttributesAndModifiers(o, match) + && this.ReturnType.DoMatch(o.ReturnType, match) && this.Variables.DoMatch(o.Variables, match); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedVariableInitializer.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedVariableInitializer.cs index f4a826bcb..56c602300 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedVariableInitializer.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedVariableInitializer.cs @@ -37,12 +37,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return NodeType.Unknown; } } - + public FixedVariableInitializer() { } - - public FixedVariableInitializer (string name, Expression initializer = null) + + public FixedVariableInitializer(string name, Expression initializer = null) { this.Name = name; this.CountExpression = initializer; @@ -50,54 +50,54 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public string Name { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier NameToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } - + public CSharpTokenNode LBracketToken { - get { return GetChildByRole (Roles.LBracket); } + get { return GetChildByRole(Roles.LBracket); } } public Expression CountExpression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } public CSharpTokenNode RBracketToken { - get { return GetChildByRole (Roles.RBracket); } + get { return GetChildByRole(Roles.RBracket); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitFixedVariableInitializer (this); + visitor.VisitFixedVariableInitializer(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitFixedVariableInitializer (this); + return visitor.VisitFixedVariableInitializer(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitFixedVariableInitializer (this, data); + return visitor.VisitFixedVariableInitializer(this, data); } - - protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { var o = other as FixedVariableInitializer; - return o != null && MatchString (this.Name, o.Name) && this.CountExpression.DoMatch (o.CountExpression, match); + return o != null && MatchString(this.Name, o.Name) && this.CountExpression.DoMatch(o.CountExpression, match); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/IndexerDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/IndexerDeclaration.cs index e4493a836..bad5ce81b 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/IndexerDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/IndexerDeclaration.cs @@ -26,13 +26,14 @@ using System; using System.ComponentModel; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.CSharp.Syntax { public class IndexerDeclaration : EntityDeclaration { - public static readonly TokenRole ThisKeywordRole = new TokenRole ("this"); + public static readonly TokenRole ThisKeywordRole = new TokenRole("this"); public static readonly Role GetterRole = PropertyDeclaration.GetterRole; public static readonly Role SetterRole = PropertyDeclaration.SetterRole; public static readonly Role ExpressionBodyRole = new Role("ExpressionBody", Expression.Null); @@ -40,21 +41,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public override SymbolKind SymbolKind { get { return SymbolKind.Indexer; } } - + /// /// Gets/Sets the type reference of the interface that is explicitly implemented. /// Null node if this member is not an explicit interface implementation. /// public AstType PrivateImplementationType { - get { return GetChildByRole (PrivateImplementationTypeRole); } - set { SetChildByRole (PrivateImplementationTypeRole, value); } + get { return GetChildByRole(PrivateImplementationTypeRole); } + set { SetChildByRole(PrivateImplementationTypeRole, value); } } - + public override string Name { get { return "Item"; } set { throw new NotSupportedException(); } } - + [EditorBrowsable(EditorBrowsableState.Never)] public override Identifier NameToken { get { return Identifier.Null; } @@ -62,37 +63,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } public CSharpTokenNode LBracketToken { - get { return GetChildByRole (Roles.LBracket); } + get { return GetChildByRole(Roles.LBracket); } } public CSharpTokenNode ThisToken { - get { return GetChildByRole (ThisKeywordRole); } + get { return GetChildByRole(ThisKeywordRole); } } - + public AstNodeCollection Parameters { - get { return GetChildrenByRole (Roles.Parameter); } + get { return GetChildrenByRole(Roles.Parameter); } } - + public CSharpTokenNode RBracketToken { - get { return GetChildByRole (Roles.RBracket); } + get { return GetChildByRole(Roles.RBracket); } } - + public CSharpTokenNode LBraceToken { - get { return GetChildByRole (Roles.LBrace); } + get { return GetChildByRole(Roles.LBrace); } } - + public Accessor Getter { get { return GetChildByRole(GetterRole); } set { SetChildByRole(GetterRole, value); } } - + public Accessor Setter { get { return GetChildByRole(SetterRole); } set { SetChildByRole(SetterRole, value); } } - + public CSharpTokenNode RBraceToken { - get { return GetChildByRole (Roles.RBrace); } + get { return GetChildByRole(Roles.RBrace); } } public Expression ExpressionBody { @@ -100,21 +101,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax set { SetChildByRole(ExpressionBodyRole, value); } } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitIndexerDeclaration (this); + visitor.VisitIndexerDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitIndexerDeclaration (this); + return visitor.VisitIndexerDeclaration(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitIndexerDeclaration (this, data); + return visitor.VisitIndexerDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { IndexerDeclaration o = other as IndexerDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/MethodDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/MethodDeclaration.cs index c7da3d4ea..d01822868 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/MethodDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/MethodDeclaration.cs @@ -33,63 +33,63 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public override SymbolKind SymbolKind { get { return SymbolKind.Method; } } - + /// /// Gets/Sets the type reference of the interface that is explicitly implemented. /// Null node if this member is not an explicit interface implementation. /// public AstType PrivateImplementationType { - get { return GetChildByRole (PrivateImplementationTypeRole); } - set { SetChildByRole (PrivateImplementationTypeRole, value); } + get { return GetChildByRole(PrivateImplementationTypeRole); } + set { SetChildByRole(PrivateImplementationTypeRole, value); } } - + public AstNodeCollection TypeParameters { - get { return GetChildrenByRole (Roles.TypeParameter); } + get { return GetChildrenByRole(Roles.TypeParameter); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstNodeCollection Parameters { - get { return GetChildrenByRole (Roles.Parameter); } + get { return GetChildrenByRole(Roles.Parameter); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public AstNodeCollection Constraints { - get { return GetChildrenByRole (Roles.Constraint); } + get { return GetChildrenByRole(Roles.Constraint); } } - + public BlockStatement Body { - get { return GetChildByRole (Roles.Body); } - set { SetChildByRole (Roles.Body, value); } + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } } - + public bool IsExtensionMethod { get { - ParameterDeclaration pd = (ParameterDeclaration)GetChildByRole (Roles.Parameter); + ParameterDeclaration pd = (ParameterDeclaration)GetChildByRole(Roles.Parameter); return pd != null && pd.HasThisModifier; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitMethodDeclaration (this); + visitor.VisitMethodDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitMethodDeclaration (this); + return visitor.VisitMethodDeclaration(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitMethodDeclaration (this, data); + return visitor.VisitMethodDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { MethodDeclaration o = other as MethodDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs index c7777db8f..c0f8236b8 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs @@ -26,6 +26,7 @@ using System; using System.ComponentModel; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -46,7 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax UnaryPlus, UnaryNegation, - + // Binary operators Multiply, Division, @@ -67,41 +68,41 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax Implicit, Explicit } - + public class OperatorDeclaration : EntityDeclaration { - public static readonly TokenRole OperatorKeywordRole = new TokenRole ("operator"); - + public static readonly TokenRole OperatorKeywordRole = new TokenRole("operator"); + // Unary operators - public static readonly TokenRole LogicalNotRole = new TokenRole ("!"); - public static readonly TokenRole OnesComplementRole = new TokenRole ("~"); - public static readonly TokenRole IncrementRole = new TokenRole ("++"); - public static readonly TokenRole DecrementRole = new TokenRole ("--"); - public static readonly TokenRole TrueRole = new TokenRole ("true"); - public static readonly TokenRole FalseRole = new TokenRole ("false"); + public static readonly TokenRole LogicalNotRole = new TokenRole("!"); + public static readonly TokenRole OnesComplementRole = new TokenRole("~"); + public static readonly TokenRole IncrementRole = new TokenRole("++"); + public static readonly TokenRole DecrementRole = new TokenRole("--"); + public static readonly TokenRole TrueRole = new TokenRole("true"); + public static readonly TokenRole FalseRole = new TokenRole("false"); // Unary and Binary operators - public static readonly TokenRole AdditionRole = new TokenRole ("+"); - public static readonly TokenRole SubtractionRole = new TokenRole ("-"); + public static readonly TokenRole AdditionRole = new TokenRole("+"); + public static readonly TokenRole SubtractionRole = new TokenRole("-"); // Binary operators - public static readonly TokenRole MultiplyRole = new TokenRole ("*"); - public static readonly TokenRole DivisionRole = new TokenRole ("/"); - public static readonly TokenRole ModulusRole = new TokenRole ("%"); - public static readonly TokenRole BitwiseAndRole = new TokenRole ("&"); - public static readonly TokenRole BitwiseOrRole = new TokenRole ("|"); - public static readonly TokenRole ExclusiveOrRole = new TokenRole ("^"); - public static readonly TokenRole LeftShiftRole = new TokenRole ("<<"); - public static readonly TokenRole RightShiftRole = new TokenRole (">>"); - public static readonly TokenRole EqualityRole = new TokenRole ("=="); - public static readonly TokenRole InequalityRole = new TokenRole ("!="); - public static readonly TokenRole GreaterThanRole = new TokenRole (">"); - public static readonly TokenRole LessThanRole = new TokenRole ("<"); - public static readonly TokenRole GreaterThanOrEqualRole = new TokenRole (">="); - public static readonly TokenRole LessThanOrEqualRole = new TokenRole ("<="); - - public static readonly TokenRole ExplicitRole = new TokenRole ("explicit"); - public static readonly TokenRole ImplicitRole = new TokenRole ("implicit"); + public static readonly TokenRole MultiplyRole = new TokenRole("*"); + public static readonly TokenRole DivisionRole = new TokenRole("/"); + public static readonly TokenRole ModulusRole = new TokenRole("%"); + public static readonly TokenRole BitwiseAndRole = new TokenRole("&"); + public static readonly TokenRole BitwiseOrRole = new TokenRole("|"); + public static readonly TokenRole ExclusiveOrRole = new TokenRole("^"); + public static readonly TokenRole LeftShiftRole = new TokenRole("<<"); + public static readonly TokenRole RightShiftRole = new TokenRole(">>"); + public static readonly TokenRole EqualityRole = new TokenRole("=="); + public static readonly TokenRole InequalityRole = new TokenRole("!="); + public static readonly TokenRole GreaterThanRole = new TokenRole(">"); + public static readonly TokenRole LessThanRole = new TokenRole("<"); + public static readonly TokenRole GreaterThanOrEqualRole = new TokenRole(">="); + public static readonly TokenRole LessThanOrEqualRole = new TokenRole("<="); + + public static readonly TokenRole ExplicitRole = new TokenRole("explicit"); + public static readonly TokenRole ImplicitRole = new TokenRole("implicit"); static readonly string[][] names; @@ -139,9 +140,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public override SymbolKind SymbolKind { get { return SymbolKind.Operator; } } - + OperatorType operatorType; - + public OperatorType OperatorType { get { return operatorType; } set { @@ -149,157 +150,159 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax operatorType = value; } } - + public CSharpTokenNode OperatorToken { - get { return GetChildByRole (OperatorKeywordRole); } + get { return GetChildByRole(OperatorKeywordRole); } } - + public CSharpTokenNode OperatorTypeToken { - get { return GetChildByRole (GetRole (OperatorType)); } + get { return GetChildByRole(GetRole(OperatorType)); } } - + public CSharpTokenNode LParToken { - get { return GetChildByRole (Roles.LPar); } + get { return GetChildByRole(Roles.LPar); } } - + public AstNodeCollection Parameters { - get { return GetChildrenByRole (Roles.Parameter); } + get { return GetChildrenByRole(Roles.Parameter); } } - + public CSharpTokenNode RParToken { - get { return GetChildByRole (Roles.RPar); } + get { return GetChildByRole(Roles.RPar); } } - + public BlockStatement Body { - get { return GetChildByRole (Roles.Body); } - set { SetChildByRole (Roles.Body, value); } + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } } - + /// /// Gets the operator type from the method name, or null, if the method does not represent one of the known operator types. /// public static OperatorType? GetOperatorType(string methodName) { - for (int i = 0; i < names.Length; ++i) { + for (int i = 0; i < names.Length; ++i) + { if (names[i][1] == methodName) return (OperatorType)i; } return null; } - - public static TokenRole GetRole (OperatorType type) + + public static TokenRole GetRole(OperatorType type) { - switch (type) { - case OperatorType.LogicalNot: - return LogicalNotRole; - case OperatorType.OnesComplement: - return OnesComplementRole; - case OperatorType.Increment: - return IncrementRole; - case OperatorType.Decrement: - return DecrementRole; - case OperatorType.True: - return TrueRole; - case OperatorType.False: - return FalseRole; - - case OperatorType.Addition: - case OperatorType.UnaryPlus: - return AdditionRole; - case OperatorType.Subtraction: - case OperatorType.UnaryNegation: - return SubtractionRole; - - case OperatorType.Multiply: - return MultiplyRole; - case OperatorType.Division: - return DivisionRole; - case OperatorType.Modulus: - return ModulusRole; - case OperatorType.BitwiseAnd: - return BitwiseAndRole; - case OperatorType.BitwiseOr: - return BitwiseOrRole; - case OperatorType.ExclusiveOr: - return ExclusiveOrRole; - case OperatorType.LeftShift: - return LeftShiftRole; - case OperatorType.RightShift: - return RightShiftRole; - case OperatorType.Equality: - return EqualityRole; - case OperatorType.Inequality: - return InequalityRole; - case OperatorType.GreaterThan: - return GreaterThanRole; - case OperatorType.LessThan: - return LessThanRole; - case OperatorType.GreaterThanOrEqual: - return GreaterThanOrEqualRole; - case OperatorType.LessThanOrEqual: - return LessThanOrEqualRole; - - case OperatorType.Implicit: - return ImplicitRole; - case OperatorType.Explicit: - return ExplicitRole; - - default: - throw new System.ArgumentOutOfRangeException (); + switch (type) + { + case OperatorType.LogicalNot: + return LogicalNotRole; + case OperatorType.OnesComplement: + return OnesComplementRole; + case OperatorType.Increment: + return IncrementRole; + case OperatorType.Decrement: + return DecrementRole; + case OperatorType.True: + return TrueRole; + case OperatorType.False: + return FalseRole; + + case OperatorType.Addition: + case OperatorType.UnaryPlus: + return AdditionRole; + case OperatorType.Subtraction: + case OperatorType.UnaryNegation: + return SubtractionRole; + + case OperatorType.Multiply: + return MultiplyRole; + case OperatorType.Division: + return DivisionRole; + case OperatorType.Modulus: + return ModulusRole; + case OperatorType.BitwiseAnd: + return BitwiseAndRole; + case OperatorType.BitwiseOr: + return BitwiseOrRole; + case OperatorType.ExclusiveOr: + return ExclusiveOrRole; + case OperatorType.LeftShift: + return LeftShiftRole; + case OperatorType.RightShift: + return RightShiftRole; + case OperatorType.Equality: + return EqualityRole; + case OperatorType.Inequality: + return InequalityRole; + case OperatorType.GreaterThan: + return GreaterThanRole; + case OperatorType.LessThan: + return LessThanRole; + case OperatorType.GreaterThanOrEqual: + return GreaterThanOrEqualRole; + case OperatorType.LessThanOrEqual: + return LessThanOrEqualRole; + + case OperatorType.Implicit: + return ImplicitRole; + case OperatorType.Explicit: + return ExplicitRole; + + default: + throw new System.ArgumentOutOfRangeException(); } } - + /// /// Gets the method name for the operator type. ("op_Addition", "op_Implicit", etc.) /// - public static string GetName (OperatorType? type) + public static string GetName(OperatorType? type) { if (type == null) return null; return names[(int)type][1]; } - + /// /// Gets the token for the operator type ("+", "implicit", etc.) /// - public static string GetToken (OperatorType type) + public static string GetToken(OperatorType type) { return names[(int)type][0]; } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitOperatorDeclaration (this); + visitor.VisitOperatorDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitOperatorDeclaration (this); + return visitor.VisitOperatorDeclaration(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitOperatorDeclaration (this, data); + return visitor.VisitOperatorDeclaration(this, data); } - + public override string Name { - get { return GetName (this.OperatorType); } + get { return GetName(this.OperatorType); } set { throw new NotSupportedException(); } } - + [EditorBrowsable(EditorBrowsableState.Never)] public override Identifier NameToken { get { return Identifier.Null; } set { throw new NotSupportedException(); } } - - protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { OperatorDeclaration o = other as OperatorDeclaration; - return o != null && this.MatchAttributesAndModifiers (o, match) && this.OperatorType == o.OperatorType - && this.ReturnType.DoMatch (o.ReturnType, match) - && this.Parameters.DoMatch (o.Parameters, match) && this.Body.DoMatch (o.Body, match); + return o != null && this.MatchAttributesAndModifiers(o, match) && this.OperatorType == o.OperatorType + && this.ReturnType.DoMatch(o.ReturnType, match) + && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs index b100f12bd..e2c4e9ffc 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs @@ -105,7 +105,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public CSharpTokenNode ThisKeyword { get { - if (hasThisModifier) { + if (hasThisModifier) + { return GetChildByRole(ThisModifierRole); } return CSharpTokenNode.Null; @@ -121,7 +122,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } ParameterModifier parameterModifier; - + public ParameterModifier ParameterModifier { get { return parameterModifier; } set { @@ -129,54 +130,54 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax parameterModifier = value; } } - + public AstType Type { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } } - + public string Name { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier NameToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } public CSharpTokenNode AssignToken { - get { return GetChildByRole (Roles.Assign); } + get { return GetChildByRole(Roles.Assign); } } public Expression DefaultExpression { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitParameterDeclaration (this); + visitor.VisitParameterDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitParameterDeclaration (this); + return visitor.VisitParameterDeclaration(this); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitParameterDeclaration (this, data); + return visitor.VisitParameterDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ParameterDeclaration o = other as ParameterDeclaration; @@ -184,11 +185,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax && this.Type.DoMatch(o.Type, match) && MatchString(this.Name, o.Name) && this.DefaultExpression.DoMatch(o.DefaultExpression, match); } - + public ParameterDeclaration() { } - + public ParameterDeclaration(AstType type, string name, ParameterModifier modifier = ParameterModifier.None) { Type = type; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs index 34ac8039a..f7fd87434 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs @@ -30,9 +30,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public class PropertyDeclaration : EntityDeclaration { - public static readonly TokenRole GetKeywordRole = new TokenRole ("get"); - public static readonly TokenRole SetKeywordRole = new TokenRole ("set"); - public static readonly TokenRole InitKeywordRole = new TokenRole ("init"); + public static readonly TokenRole GetKeywordRole = new TokenRole("get"); + public static readonly TokenRole SetKeywordRole = new TokenRole("set"); + public static readonly TokenRole InitKeywordRole = new TokenRole("init"); public static readonly Role GetterRole = new Role("Getter", Accessor.Null); public static readonly Role SetterRole = new Role("Setter", Accessor.Null); public static readonly Role ExpressionBodyRole = new Role("ExpressionBody", Expression.Null); @@ -40,32 +40,32 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public override SymbolKind SymbolKind { get { return SymbolKind.Property; } } - + /// /// Gets/Sets the type reference of the interface that is explicitly implemented. /// Null node if this member is not an explicit interface implementation. /// public AstType PrivateImplementationType { - get { return GetChildByRole (PrivateImplementationTypeRole); } - set { SetChildByRole (PrivateImplementationTypeRole, value); } + get { return GetChildByRole(PrivateImplementationTypeRole); } + set { SetChildByRole(PrivateImplementationTypeRole, value); } } - + public CSharpTokenNode LBraceToken { - get { return GetChildByRole (Roles.LBrace); } + get { return GetChildByRole(Roles.LBrace); } } - + public Accessor Getter { get { return GetChildByRole(GetterRole); } set { SetChildByRole(GetterRole, value); } } - + public Accessor Setter { get { return GetChildByRole(SetterRole); } set { SetChildByRole(SetterRole, value); } } - + public CSharpTokenNode RBraceToken { - get { return GetChildByRole (Roles.RBrace); } + get { return GetChildByRole(Roles.RBrace); } } public CSharpTokenNode AssignToken { @@ -82,21 +82,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax set { SetChildByRole(ExpressionBodyRole, value); } } - public override void AcceptVisitor (IAstVisitor visitor) + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitPropertyDeclaration (this); + visitor.VisitPropertyDeclaration(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitPropertyDeclaration (this); + return visitor.VisitPropertyDeclaration(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitPropertyDeclaration (this, data); + return visitor.VisitPropertyDeclaration(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { PropertyDeclaration o = other as PropertyDeclaration; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/VariableInitializer.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/VariableInitializer.cs index 91eeafd76..d5b74faa8 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/VariableInitializer.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/VariableInitializer.cs @@ -30,8 +30,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class VariableInitializer : AstNode { #region Null - public new static readonly VariableInitializer Null = new NullVariableInitializer (); - + public new static readonly VariableInitializer Null = new NullVariableInitializer(); + sealed class NullVariableInitializer : VariableInitializer { public override bool IsNull { @@ -39,22 +39,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { visitor.VisitNullNode(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { return visitor.VisitNullNode(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNullNode(this, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; @@ -67,57 +67,57 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return pattern != null ? new PatternPlaceholder(pattern) : null; } - + sealed class PatternPlaceholder : VariableInitializer, PatternMatching.INode { readonly PatternMatching.Pattern child; - + public PatternPlaceholder(PatternMatching.Pattern child) { this.child = child; } - + public override NodeType NodeType { get { return NodeType.Pattern; } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitPatternPlaceholder (this, child); + visitor.VisitPatternPlaceholder(this, child); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitPatternPlaceholder (this, child); + return visitor.VisitPatternPlaceholder(this, child); } - + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitPatternPlaceholder(this, child, data); } - + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return child.DoMatch(other, match); } - + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) { return child.DoMatchCollection(role, pos, match, backtrackingInfo); } } #endregion - + public override NodeType NodeType { get { return NodeType.Unknown; } } - + public VariableInitializer() { } - + public VariableInitializer(string name, Expression initializer = null) { this.Name = name; @@ -126,44 +126,44 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public string Name { get { - return GetChildByRole (Roles.Identifier).Name; + return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value)); + SetChildByRole(Roles.Identifier, Identifier.Create(value)); } } - + public Identifier NameToken { get { - return GetChildByRole (Roles.Identifier); + return GetChildByRole(Roles.Identifier); } set { - SetChildByRole (Roles.Identifier, value); + SetChildByRole(Roles.Identifier, value); } } - + public CSharpTokenNode AssignToken { - get { return GetChildByRole (Roles.Assign); } + get { return GetChildByRole(Roles.Assign); } } - + public Expression Initializer { - get { return GetChildByRole (Roles.Expression); } - set { SetChildByRole (Roles.Expression, value); } + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } } - - public override void AcceptVisitor (IAstVisitor visitor) + + public override void AcceptVisitor(IAstVisitor visitor) { - visitor.VisitVariableInitializer (this); + visitor.VisitVariableInitializer(this); } - - public override T AcceptVisitor (IAstVisitor visitor) + + public override T AcceptVisitor(IAstVisitor visitor) { - return visitor.VisitVariableInitializer (this); + return visitor.VisitVariableInitializer(this); } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitVariableInitializer (this, data); + return visitor.VisitVariableInitializer(this, data); } protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 03f79997b..b4f187319 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -22,6 +22,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Reflection; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.Semantics; @@ -37,7 +38,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public class TypeSystemAstBuilder { readonly CSharpResolver resolver; - + #region Constructor /// /// Creates a new TypeSystemAstBuilder. @@ -52,7 +53,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.resolver = resolver; InitProperties(); } - + /// /// Creates a new TypeSystemAstBuilder. /// @@ -61,7 +62,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax InitProperties(); } #endregion - + #region Properties void InitProperties() { @@ -77,37 +78,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.UseAliases = true; this.UseSpecialConstants = true; } - + /// /// Specifies whether the ast builder should add annotations to type references. /// The default value is . /// public bool AddTypeReferenceAnnotations { get; set; } - + /// /// Specifies whether the ast builder should add ResolveResult annotations to AST nodes. /// The default value is . /// public bool AddResolveResultAnnotations { get; set; } - + /// /// Controls the accessibility modifiers are shown. /// The default value is . /// public bool ShowAccessibility { get; set; } - + /// /// Controls the non-accessibility modifiers are shown. /// The default value is . /// public bool ShowModifiers { get; set; } - + /// /// Controls whether base type references are shown. /// The default value is . /// public bool ShowBaseTypes { get; set; } - + /// /// Controls whether type parameter declarations are shown. /// The default value is . @@ -119,26 +120,26 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// The default value is . /// public bool ShowTypeParametersForUnboundTypes { get; set; } - + /// /// Controls whether constraints on type parameter declarations are shown. /// Has no effect if ShowTypeParameters is false. /// The default value is . /// public bool ShowTypeParameterConstraints { get; set; } - + /// /// Controls whether the names of parameters are shown. /// The default value is . /// public bool ShowParameterNames { get; set; } - + /// /// Controls whether to show default values of optional parameters, and the values of constant fields. /// The default value is . /// public bool ShowConstantValues { get; set; } - + /// /// Controls whether to show attributes. /// The default value is . @@ -170,13 +171,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// for use in expression context. /// public NameLookupMode NameLookupMode { get; set; } - + /// /// Controls whether to generate a body that throws a System.NotImplementedException. /// The default value is . /// public bool GenerateBody { get; set; } - + /// /// Controls whether to generate custom events. /// The default value is . @@ -187,7 +188,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// Controls whether unbound type argument names are inserted in the ast or not. /// The default value is . /// - public bool ConvertUnboundTypeArguments { get; set;} + public bool ConvertUnboundTypeArguments { get; set; } /// /// Controls whether aliases should be used inside the type name or not. @@ -232,22 +233,29 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public AstType ConvertType(FullTypeName fullTypeName) { - if (resolver != null) { - foreach (var asm in resolver.Compilation.Modules) { + if (resolver != null) + { + foreach (var asm in resolver.Compilation.Modules) + { var def = asm.GetTypeDefinition(fullTypeName); - if (def != null) { + if (def != null) + { return ConvertType(def); } } } TopLevelTypeName top = fullTypeName.TopLevelTypeName; AstType type; - if (string.IsNullOrEmpty(top.Namespace)) { + if (string.IsNullOrEmpty(top.Namespace)) + { type = MakeSimpleType(top.Name); - } else { + } + else + { type = MakeMemberType(MakeSimpleType(top.Namespace), top.Name); } - for (int i = 0; i < fullTypeName.NestingLevel; i++) { + for (int i = 0; i < fullTypeName.NestingLevel; i++) + { type = MakeMemberType(type, fullTypeName.GetNestedTypeName(i)); } return type; @@ -255,62 +263,87 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax AstType ConvertTypeHelper(IType type) { - if (type is TypeWithElementType typeWithElementType) { - if (typeWithElementType is PointerType) { + if (type is TypeWithElementType typeWithElementType) + { + if (typeWithElementType is PointerType) + { return ConvertType(typeWithElementType.ElementType).MakePointerType(); - } else if (typeWithElementType is ArrayType) { + } + else if (typeWithElementType is ArrayType) + { var astType = ConvertType(typeWithElementType.ElementType).MakeArrayType(((ArrayType)type).Dimensions); if (type.Nullability == Nullability.Nullable) return astType.MakeNullableType(); else return astType; - } else if (typeWithElementType is ByReferenceType) { + } + else if (typeWithElementType is ByReferenceType) + { return ConvertType(typeWithElementType.ElementType).MakeRefType(); - } else { + } + else + { // not supported as type in C# return ConvertType(typeWithElementType.ElementType); } - } else if (type is NullabilityAnnotatedType nat) { + } + else if (type is NullabilityAnnotatedType nat) + { var astType = ConvertType(nat.TypeWithoutAnnotation); if (nat.Nullability == Nullability.Nullable) astType = astType.MakeNullableType(); return astType; - } else if (type is TupleType tuple) { + } + else if (type is TupleType tuple) + { var astType = new TupleAstType(); - foreach (var (etype, ename) in tuple.ElementTypes.Zip(tuple.ElementNames)) { + foreach (var (etype, ename) in tuple.ElementTypes.Zip(tuple.ElementNames)) + { astType.Elements.Add(new TupleTypeElement { Type = ConvertType(etype), Name = ename }); } return astType; - } else { + } + else + { AstType astType; - switch (type) { + switch (type) + { case ITypeDefinition _: case UnknownType _: - if (type.IsUnbound()) { - if (ShowTypeParametersForUnboundTypes) { + if (type.IsUnbound()) + { + if (ShowTypeParametersForUnboundTypes) + { astType = ConvertTypeHelper(type, type.TypeArguments); - } else { + } + else + { IType[] typeArguments = new IType[type.TypeParameterCount]; - for (int i = 0; i < typeArguments.Length; i++) { + for (int i = 0; i < typeArguments.Length; i++) + { typeArguments[i] = SpecialType.UnboundTypeArgument; } astType = ConvertTypeHelper(type, typeArguments); } - } else { + } + else + { astType = ConvertTypeHelper(type, EmptyList.Instance); } break; case ParameterizedType pt: - if (UseNullableSpecifierForValueTypes && pt.IsKnownType(KnownTypeCode.NullableOfT)) { + if (UseNullableSpecifierForValueTypes && pt.IsKnownType(KnownTypeCode.NullableOfT)) + { return ConvertType(pt.TypeArguments[0]).MakeNullableType(); } astType = ConvertTypeHelper(pt.GenericType, pt.TypeArguments); break; default: - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.Dynamic: case TypeKind.NInt: case TypeKind.NUInt: @@ -322,56 +355,70 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } break; } - if (type.Nullability == Nullability.Nullable) { + if (type.Nullability == Nullability.Nullable) + { AddTypeAnnotation(astType, type.ChangeNullability(Nullability.Oblivious)); astType = astType.MakeNullableType(); } return astType; } } - + AstType ConvertTypeHelper(IType genericType, IReadOnlyList typeArguments) { ITypeDefinition typeDef = genericType.GetDefinition(); Debug.Assert(typeDef != null || genericType.Kind == TypeKind.Unknown); Debug.Assert(typeArguments.Count >= genericType.TypeParameterCount); - if (UseKeywordsForBuiltinTypes && typeDef != null) { + if (UseKeywordsForBuiltinTypes && typeDef != null) + { string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode); - if (keyword != null) { + if (keyword != null) + { return new PrimitiveType(keyword); } } - + // The number of type parameters belonging to outer classes int outerTypeParameterCount = genericType.DeclaringType?.TypeParameterCount ?? 0; - - if (resolver != null && typeDef != null) { + + if (resolver != null && typeDef != null) + { // Look if there's an alias to the target type - if (UseAliases) { - for (ResolvedUsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) { - foreach (var pair in usingScope.UsingAliases) { - if (pair.Value is TypeResolveResult) { + if (UseAliases) + { + for (ResolvedUsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) + { + foreach (var pair in usingScope.UsingAliases) + { + if (pair.Value is TypeResolveResult) + { if (TypeMatches(pair.Value.Type, typeDef, typeArguments)) return MakeSimpleType(pair.Key); } } } } - + IType[] localTypeArguments; - if (typeDef.TypeParameterCount > outerTypeParameterCount) { + if (typeDef.TypeParameterCount > outerTypeParameterCount) + { localTypeArguments = new IType[typeDef.TypeParameterCount - outerTypeParameterCount]; - for (int i = 0; i < localTypeArguments.Length; i++) { + for (int i = 0; i < localTypeArguments.Length; i++) + { localTypeArguments[i] = typeArguments[outerTypeParameterCount + i]; } - } else { + } + else + { localTypeArguments = Empty.Array; } ResolveResult rr = resolver.LookupSimpleNameOrTypeName(typeDef.Name, localTypeArguments, NameLookupMode); TypeResolveResult trr = rr as TypeResolveResult; - if (trr != null || (localTypeArguments.Length == 0 && resolver.IsVariableReferenceWithSameType(rr, typeDef.Name, out trr))) { - if (!trr.IsError && TypeMatches(trr.Type, typeDef, typeArguments)) { + if (trr != null || (localTypeArguments.Length == 0 && resolver.IsVariableReferenceWithSameType(rr, typeDef.Name, out trr))) + { + if (!trr.IsError && TypeMatches(trr.Type, typeDef, typeArguments)) + { // We can use the short type name SimpleType shortResult = MakeSimpleType(typeDef.Name); AddTypeArguments(shortResult, typeDef.TypeParameters, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount); @@ -379,24 +426,31 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } } - - if (AlwaysUseShortTypeNames || (typeDef == null && genericType.DeclaringType == null)) { + + if (AlwaysUseShortTypeNames || (typeDef == null && genericType.DeclaringType == null)) + { var shortResult = MakeSimpleType(genericType.Name); AddTypeArguments(shortResult, genericType.TypeParameters, typeArguments, outerTypeParameterCount, genericType.TypeParameterCount); return shortResult; } MemberType result = new MemberType(); - if (genericType.DeclaringType != null) { + if (genericType.DeclaringType != null) + { // Handle nested types result.Target = ConvertTypeHelper(genericType.DeclaringType, typeArguments); - } else { + } + else + { // Handle top-level types - if (string.IsNullOrEmpty(genericType.Namespace)) { + if (string.IsNullOrEmpty(genericType.Namespace)) + { result.Target = new SimpleType("global"); if (AddResolveResultAnnotations && resolver != null) result.Target.AddAnnotation(new NamespaceResolveResult(resolver.Compilation.RootNamespace)); result.IsDoubleColon = true; - } else { + } + else + { result.Target = ConvertNamespace(genericType.Namespace, out _); } } @@ -404,23 +458,28 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax AddTypeArguments(result, genericType.TypeParameters, typeArguments, outerTypeParameterCount, genericType.TypeParameterCount); return result; } - + /// /// Gets whether 'type' is the same as 'typeDef' parameterized with the given type arguments. /// bool TypeMatches(IType type, ITypeDefinition typeDef, IReadOnlyList typeArguments) { - if (typeDef.TypeParameterCount == 0) { + if (typeDef.TypeParameterCount == 0) + { return TypeDefMatches(typeDef, type); - } else { + } + else + { if (!TypeDefMatches(typeDef, type.GetDefinition())) return false; ParameterizedType pt = type as ParameterizedType; - if (pt == null) { + if (pt == null) + { return typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument); } var ta = pt.TypeArguments; - for (int i = 0; i < ta.Count; i++) { + for (int i = 0; i < ta.Count; i++) + { if (!ta[i].Equals(typeArguments[i])) return false; } @@ -451,24 +510,33 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax void AddTypeArguments(AstType result, IReadOnlyList typeParameters, IReadOnlyList typeArguments, int startIndex, int endIndex) { Debug.Assert(endIndex <= typeParameters.Count); - for (int i = startIndex; i < endIndex; i++) { - if (ConvertUnboundTypeArguments && typeArguments[i].Kind == TypeKind.UnboundTypeArgument) { + for (int i = startIndex; i < endIndex; i++) + { + if (ConvertUnboundTypeArguments && typeArguments[i].Kind == TypeKind.UnboundTypeArgument) + { result.AddChild(MakeSimpleType(typeParameters[i].Name), Roles.TypeArgument); - } else { + } + else + { result.AddChild(ConvertType(typeArguments[i]), Roles.TypeArgument); } } } - + public AstType ConvertNamespace(string namespaceName, out NamespaceResolveResult nrr) { - if (resolver != null) { + if (resolver != null) + { // Look if there's an alias to the target namespace - if (UseAliases) { - for (ResolvedUsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) { - foreach (var pair in usingScope.UsingAliases) { + if (UseAliases) + { + for (ResolvedUsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) + { + foreach (var pair in usingScope.UsingAliases) + { nrr = pair.Value as NamespaceResolveResult; - if (nrr != null && nrr.NamespaceName == namespaceName) { + if (nrr != null && nrr.NamespaceName == namespaceName) + { var ns = MakeSimpleType(pair.Key); if (AddResolveResultAnnotations) ns.AddAnnotation(nrr); @@ -478,15 +546,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } } - + int pos = namespaceName.LastIndexOf('.'); - if (pos < 0) { - if (IsValidNamespace(namespaceName, out nrr)) { + if (pos < 0) + { + if (IsValidNamespace(namespaceName, out nrr)) + { var ns = MakeSimpleType(namespaceName); if (AddResolveResultAnnotations && nrr != null) ns.AddAnnotation(nrr); return ns; - } else { + } + else + { var target = new SimpleType("global"); if (AddResolveResultAnnotations) target.AddAnnotation(new NamespaceResolveResult(resolver.Compilation.RootNamespace)); @@ -495,14 +567,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax IsDoubleColon = true, MemberName = namespaceName }; - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { var @namespace = resolver.Compilation.RootNamespace.GetChildNamespace(namespaceName); if (@namespace != null) ns.AddAnnotation(nrr = new NamespaceResolveResult(@namespace)); } return ns; } - } else { + } + else + { string parentNamespace = namespaceName.Substring(0, pos); string localNamespace = namespaceName.Substring(pos + 1); var parentNS = ConvertNamespace(parentNamespace, out var parentNRR); @@ -511,16 +586,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax MemberName = localNamespace }; nrr = null; - if (AddResolveResultAnnotations && parentNRR != null) { + if (AddResolveResultAnnotations && parentNRR != null) + { var newNamespace = parentNRR.Namespace.GetChildNamespace(localNamespace); - if (newNamespace != null) { + if (newNamespace != null) + { ns.AddAnnotation(nrr = new NamespaceResolveResult(newNamespace)); } } return ns; } } - + bool IsValidNamespace(string firstNamespacePart, out NamespaceResolveResult nrr) { nrr = null; @@ -550,7 +627,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { Attribute attr = new Attribute(); attr.Type = ConvertAttributeType(attribute.AttributeType); - switch (attr.Type) { + switch (attr.Type) + { case SimpleType st: if (st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - 9); @@ -560,29 +638,36 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax mt.MemberName = mt.MemberName.Substring(0, mt.MemberName.Length - 9); break; } - if (AddResolveResultAnnotations && attribute.Constructor != null) { + if (AddResolveResultAnnotations && attribute.Constructor != null) + { attr.AddAnnotation(new MemberResolveResult(null, attribute.Constructor)); } var parameters = attribute.Constructor?.Parameters ?? EmptyList.Instance; - for (int i = 0; i < attribute.FixedArguments.Length; i++) { + for (int i = 0; i < attribute.FixedArguments.Length; i++) + { var arg = attribute.FixedArguments[i]; var p = (i < parameters.Count) ? parameters[i] : null; attr.Arguments.Add(ConvertConstantValue(p?.Type ?? arg.Type, arg.Type, arg.Value)); } - if (attribute.NamedArguments.Length > 0) { + if (attribute.NamedArguments.Length > 0) + { InitializedObjectResolveResult targetResult = new InitializedObjectResolveResult(attribute.AttributeType); - foreach (var namedArg in attribute.NamedArguments) { + foreach (var namedArg in attribute.NamedArguments) + { NamedExpression namedArgument = new NamedExpression(namedArg.Name, ConvertConstantValue(namedArg.Type, namedArg.Value)); - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { IMember member = CustomAttribute.MemberForNamedArgument(attribute.AttributeType, namedArg); - if (member != null) { + if (member != null) + { namedArgument.AddAnnotation(new MemberResolveResult(targetResult, member)); } } attr.Arguments.Add(namedArgument); } } - if (attribute.HasDecodeErrors) { + if (attribute.HasDecodeErrors) + { attr.HasArgumentList = true; attr.AddChild(new Comment("Could not decode attribute arguments.", CommentType.MultiLine), Roles.Comment); // insert explicit rpar token to make the comment appear within the parentheses @@ -612,11 +697,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax AstType astType = ConvertTypeHelper(type); string shortName = null; - if (type.Name.Length > 9 && type.Name.EndsWith("Attribute", StringComparison.Ordinal)) { + if (type.Name.Length > 9 && type.Name.EndsWith("Attribute", StringComparison.Ordinal)) + { shortName = type.Name.Remove(type.Name.Length - 9); } - if (AlwaysUseShortTypeNames) { - switch (astType) { + if (AlwaysUseShortTypeNames) + { + switch (astType) + { case SimpleType st: st.Identifier = shortName; break; @@ -624,7 +712,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax mt.MemberName = shortName; break; } - } else if (resolver != null) { + } + else if (resolver != null) + { ApplyShortAttributeNameIfPossible(type, astType, shortName); } AddTypeAnnotation(astType, type); @@ -634,35 +724,50 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax private void ApplyShortAttributeNameIfPossible(IType type, AstType astType, string shortName) { - switch (astType) { + switch (astType) + { case SimpleType st: ResolveResult shortRR = null; ResolveResult withExtraAttrSuffix = resolver.LookupSimpleNameOrTypeName(type.Name + "Attribute", EmptyList.Instance, NameLookupMode.Type); - if (shortName != null) { + if (shortName != null) + { shortRR = resolver.LookupSimpleNameOrTypeName(shortName, EmptyList.Instance, NameLookupMode.Type); } // short type is either unknown or not an attribute type -> we can use the short name. - if (shortRR != null && (shortRR is UnknownIdentifierResolveResult || !IsAttributeType(shortRR))) { + if (shortRR != null && (shortRR is UnknownIdentifierResolveResult || !IsAttributeType(shortRR))) + { st.Identifier = shortName; - } else if (IsAttributeType(withExtraAttrSuffix)) { + } + else if (IsAttributeType(withExtraAttrSuffix)) + { // typeName + "Attribute" is an attribute type -> we cannot use long type name, add '@' to disable implicit "Attribute" suffix. st.Identifier = '@' + st.Identifier; } break; case MemberType mt: - if (type.DeclaringType != null) { + if (type.DeclaringType != null) + { var declaringTypeDef = type.DeclaringType.GetDefinition(); - if (declaringTypeDef != null) { - if (shortName != null && !declaringTypeDef.GetNestedTypes(t => t.TypeParameterCount == 0 && t.Name == shortName).Any(IsAttributeType)) { + if (declaringTypeDef != null) + { + if (shortName != null && !declaringTypeDef.GetNestedTypes(t => t.TypeParameterCount == 0 && t.Name == shortName).Any(IsAttributeType)) + { mt.MemberName = shortName; - } else if (declaringTypeDef.GetNestedTypes(t => t.TypeParameterCount == 0 && t.Name == type.Name + "Attribute").Any(IsAttributeType)) { + } + else if (declaringTypeDef.GetNestedTypes(t => t.TypeParameterCount == 0 && t.Name == type.Name + "Attribute").Any(IsAttributeType)) + { mt.MemberName = '@' + mt.MemberName; } } - } else if (mt.Target.GetResolveResult() is NamespaceResolveResult nrr) { - if (shortName != null && !IsAttributeType(nrr.Namespace.GetTypeDefinition(shortName, 0))) { + } + else if (mt.Target.GetResolveResult() is NamespaceResolveResult nrr) + { + if (shortName != null && !IsAttributeType(nrr.Namespace.GetTypeDefinition(shortName, 0))) + { mt.MemberName = shortName; - } else if (IsAttributeType(nrr.Namespace.GetTypeDefinition(type.Name + "Attribute", 0))) { + } + else if (IsAttributeType(nrr.Namespace.GetTypeDefinition(type.Name + "Attribute", 0))) + { mt.MemberName = '@' + mt.MemberName; } } @@ -694,32 +799,39 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (rr == null) throw new ArgumentNullException(nameof(rr)); bool isBoxing = false; - if (rr is ConversionResolveResult crr) { + if (rr is ConversionResolveResult crr) + { // unpack ConversionResolveResult if necessary // (e.g. a boxing conversion or string->object reference conversion) rr = crr.Input; isBoxing = crr.Conversion.IsBoxingConversion; } - - if (rr is TypeOfResolveResult) { + + if (rr is TypeOfResolveResult) + { var expr = new TypeOfExpression(ConvertType(((TypeOfResolveResult)rr).ReferencedType)); if (AddResolveResultAnnotations) expr.AddAnnotation(rr); return expr; - } else if (rr is ArrayCreateResolveResult acrr) { + } + else if (rr is ArrayCreateResolveResult acrr) + { ArrayCreateExpression ace = new ArrayCreateExpression(); ace.Type = ConvertType(acrr.Type); - if (ace.Type is ComposedType composedType) { + if (ace.Type is ComposedType composedType) + { composedType.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); if (!composedType.HasNullableSpecifier && composedType.PointerRank == 0) ace.Type = composedType.BaseType; } - - if (acrr.SizeArguments != null && acrr.InitializerElements == null) { + + if (acrr.SizeArguments != null && acrr.InitializerElements == null) + { ace.AdditionalArraySpecifiers.FirstOrNullObject().Remove(); ace.Arguments.AddRange(acrr.SizeArguments.Select(ConvertConstantValue)); } - if (acrr.InitializerElements != null) { + if (acrr.InitializerElements != null) + { ArrayInitializerExpression initializer = new ArrayInitializerExpression(); initializer.Elements.AddRange(acrr.InitializerElements.Select(ConvertConstantValue)); ace.Initializer = initializer; @@ -727,9 +839,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (AddResolveResultAnnotations) ace.AddAnnotation(rr); return ace; - } else if (rr.IsCompileTimeConstant) { + } + else if (rr.IsCompileTimeConstant) + { var expr = ConvertConstantValue(rr.Type, rr.ConstantValue); - if (isBoxing && (rr.Type.IsCSharpSmallIntegerType() || rr.Type.IsCSharpNativeIntegerType())) { + if (isBoxing && (rr.Type.IsCSharpSmallIntegerType() || rr.Type.IsCSharpNativeIntegerType())) + { // C# does not have small integer literal types. // We need to add a cast so that the integer literal gets boxed as the correct type. expr = new CastExpression(ConvertType(rr.Type), expr); @@ -737,7 +852,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax expr.AddAnnotation(rr); } return expr; - } else { + } + else + { return new ErrorExpression(); } } @@ -764,46 +881,61 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { if (type == null) throw new ArgumentNullException(nameof(type)); - if (constantValue == null) { - if (type.IsReferenceType == true || type.IsKnownType(KnownTypeCode.NullableOfT)) { + if (constantValue == null) + { + if (type.IsReferenceType == true || type.IsKnownType(KnownTypeCode.NullableOfT)) + { var expr = new NullReferenceExpression(); if (AddResolveResultAnnotations) expr.AddAnnotation(new ConstantResolveResult(SpecialType.NullType, null)); return expr; - } else { + } + else + { var expr = new DefaultValueExpression(ConvertType(type)); if (AddResolveResultAnnotations) expr.AddAnnotation(new ConstantResolveResult(type, null)); return expr; } - } else if (constantValue is IType typeofType) { + } + else if (constantValue is IType typeofType) + { var expr = new TypeOfExpression(ConvertType(typeofType)); if (AddResolveResultAnnotations) expr.AddAnnotation(new TypeOfResolveResult(type, typeofType)); return expr; - } else if (constantValue is ImmutableArray> arr) { + } + else if (constantValue is ImmutableArray> arr) + { var elementType = (type as ArrayType)?.ElementType ?? SpecialType.UnknownType; var expr = new ArrayCreateExpression(); expr.Type = ConvertType(type); - if (expr.Type is ComposedType composedType) { + if (expr.Type is ComposedType composedType) + { composedType.ArraySpecifiers.MoveTo(expr.AdditionalArraySpecifiers); if (!composedType.HasNullableSpecifier && composedType.PointerRank == 0) expr.Type = composedType.BaseType; } expr.Initializer = new ArrayInitializerExpression(arr.Select(e => ConvertConstantValue(elementType, e.Type, e.Value))); return expr; - } else { + } + else + { IType underlyingType = NullableType.GetUnderlyingType(type); - if (underlyingType.Kind == TypeKind.Enum) { + if (underlyingType.Kind == TypeKind.Enum) + { return ConvertEnumValue(underlyingType, (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false)); - } else { + } + else + { if (IsSpecialConstant(underlyingType, constantValue, out var expr)) return expr; if (underlyingType.IsKnownType(KnownTypeCode.Double) || underlyingType.IsKnownType(KnownTypeCode.Single)) return ConvertFloatingPointLiteral(underlyingType, constantValue); IType literalType = underlyingType; bool integerTypeMismatch = underlyingType.IsCSharpSmallIntegerType() || underlyingType.IsCSharpNativeIntegerType(); - if (integerTypeMismatch) { + if (integerTypeMismatch) + { // C# does not have integer literals of small integer types, // use `int` literal instead. // It also doesn't have native integer literals, those also use `int` (or `uint` for `nuint`). @@ -813,13 +945,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax literalType = compilation?.FindType(unsigned ? KnownTypeCode.UInt32 : KnownTypeCode.Int32); } LiteralFormat format = LiteralFormat.None; - if (PrintIntegralValuesAsHex) { + if (PrintIntegralValuesAsHex) + { format = LiteralFormat.HexadecimalNumber; } expr = new PrimitiveExpression(constantValue, format); if (AddResolveResultAnnotations && literalType != null) expr.AddAnnotation(new ConstantResolveResult(literalType, constantValue)); - if (integerTypeMismatch && !type.Equals(expectedType)) { + if (integerTypeMismatch && !type.Equals(expectedType)) + { expr = new CastExpression(ConvertType(type), expr); } return expr; @@ -834,7 +968,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return false; // find IType of constant in compilation. var constantType = expectedType; - if (!expectedType.IsKnownType(info.Type)) { + if (!expectedType.IsKnownType(info.Type)) + { var compilation = resolver?.Compilation ?? expectedType.GetDefinition()?.Compilation; if (compilation == null) return false; @@ -842,11 +977,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } // if the field definition cannot be found, do not generate a reference to the field. var field = constantType.GetFields(p => p.Name == info.Member).SingleOrDefault(); - if (!UseSpecialConstants || field == null) { + if (!UseSpecialConstants || field == null) + { // +Infty, -Infty and NaN, cannot be represented in their encoded form. // Use an equivalent arithmetic expression instead. - if (info.Type == KnownTypeCode.Double) { - switch ((double)constant) { + if (info.Type == KnownTypeCode.Double) + { + switch ((double)constant) + { case double.NegativeInfinity: // (-1.0 / 0.0) var left = new PrimitiveExpression(-1.0).WithoutILInstruction().WithRR(new ConstantResolveResult(constantType, -1.0)); var right = new PrimitiveExpression(0.0).WithoutILInstruction().WithRR(new ConstantResolveResult(constantType, 0.0)); @@ -867,8 +1005,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - if (info.Type == KnownTypeCode.Single) { - switch ((float)constant) { + if (info.Type == KnownTypeCode.Single) + { + switch ((float)constant) + { case float.NegativeInfinity: // (-1.0f / 0.0f) var left = new PrimitiveExpression(-1.0f).WithoutILInstruction().WithRR(new ConstantResolveResult(constantType, -1.0f)); var right = new PrimitiveExpression(0.0f).WithoutILInstruction().WithRR(new ConstantResolveResult(constantType, 0.0f)); @@ -949,7 +1089,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { return type.HasAttribute(KnownAttribute.Flags, inherit: false); } - + Expression ConvertEnumValue(IType type, long val) { ITypeDefinition enumDefinition = type.GetDefinition(); @@ -958,20 +1098,24 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax .Select(PrepareConstant) .Where(f => f.field != null) .ToArray(); - foreach (var (value, field) in fields) { - if (value == val) { + foreach (var (value, field) in fields) + { + if (value == val) + { var mre = new MemberReferenceExpression(new TypeReferenceExpression(ConvertType(type)), field.Name); if (AddResolveResultAnnotations) mre.AddAnnotation(new MemberResolveResult(mre.Target.GetResolveResult(), field)); return mre; } } - if (IsFlagsEnum(enumDefinition)) { + if (IsFlagsEnum(enumDefinition)) + { long enumValue = val; Expression expr = null; long negatedEnumValue = ~val; // limit negatedEnumValue to the appropriate range - switch (enumBaseTypeCode) { + switch (enumBaseTypeCode) + { case TypeCode.Byte: case TypeCode.SByte: negatedEnumValue &= byte.MaxValue; @@ -986,11 +1130,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax break; } Expression negatedExpr = null; - foreach (var (fieldValue, field) in fields.OrderByDescending(f => CalculateHammingWeight(unchecked((ulong)f.value)))) { + foreach (var (fieldValue, field) in fields.OrderByDescending(f => CalculateHammingWeight(unchecked((ulong)f.value)))) + { if (fieldValue == 0) - continue; // skip None enum value + continue; // skip None enum value - if ((fieldValue & enumValue) == fieldValue) { + if ((fieldValue & enumValue) == fieldValue) + { var fieldExpression = new MemberReferenceExpression(new TypeReferenceExpression(ConvertType(type)), field.Name); if (expr == null) expr = fieldExpression; @@ -999,7 +1145,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax enumValue &= ~fieldValue; } - if ((fieldValue & negatedEnumValue) == fieldValue) { + if ((fieldValue & negatedEnumValue) == fieldValue) + { var fieldExpression = new MemberReferenceExpression(new TypeReferenceExpression(ConvertType(type)), field.Name); if (negatedExpr == null) negatedExpr = fieldExpression; @@ -1009,12 +1156,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax negatedEnumValue &= ~fieldValue; } } - if (enumValue == 0 && expr != null) { - if (!(negatedEnumValue == 0 && negatedExpr != null && negatedExpr.Descendants.Count() < expr.Descendants.Count())) { + if (enumValue == 0 && expr != null) + { + if (!(negatedEnumValue == 0 && negatedExpr != null && negatedExpr.Descendants.Count() < expr.Descendants.Count())) + { return expr; } } - if (negatedEnumValue == 0 && negatedExpr != null) { + if (negatedEnumValue == 0 && negatedExpr != null) + { return new UnaryOperatorExpression(UnaryOperatorType.BitNot, negatedExpr); } } @@ -1056,9 +1206,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax static bool IsEqual(long num, long den, object constantValue, bool isDouble) { - if (isDouble) { + if (isDouble) + { return (double)constantValue == num / (double)den; - } else { + } + else + { return (float)constantValue == num / (float)den; } } @@ -1076,14 +1229,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax Expression expr = null; string str; - if (isDouble) { - if (Math.Floor((double)constantValue) == (double)constantValue) { + if (isDouble) + { + if (Math.Floor((double)constantValue) == (double)constantValue) + { expr = new PrimitiveExpression(constantValue); } str = ((double)constantValue).ToString("r"); - } else { - if (Math.Floor((float)constantValue) == (float)constantValue) { + } + else + { + if (Math.Floor((float)constantValue) == (float)constantValue) + { expr = new PrimitiveExpression(constantValue); } @@ -1092,11 +1250,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax bool useFraction = (str.Length - (str.StartsWith("-", StringComparison.OrdinalIgnoreCase) ? 2 : 1) > 5); - if (useFraction && expr == null && UseSpecialConstants) { + if (useFraction && expr == null && UseSpecialConstants) + { IType mathType; if (isDouble) mathType = compilation.FindType(typeof(Math)); - else { + else + { mathType = compilation.FindType(new TopLevelTypeName("System", "MathF")); var typeDef = mathType.GetDefinition(); if (typeDef == null @@ -1111,12 +1271,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ?? TryExtractExpression(mathType, type, constantValue, "E", isDouble); } - if (useFraction && expr == null) { + if (useFraction && expr == null) + { (long num, long den) = isDouble ? FractionApprox((double)constantValue, MAX_DENOMINATOR) : FractionApprox((float)constantValue, MAX_DENOMINATOR); - if (IsValidFraction(num, den) && IsEqual(num, den, constantValue, isDouble) && Math.Abs(num) != 1 && Math.Abs(den) != 1) { + if (IsValidFraction(num, den) && IsEqual(num, den, constantValue, isDouble) && Math.Abs(num) != 1 && Math.Abs(den) != 1) + { var left = MakeConstant(type, num); var right = MakeConstant(type, den); return new BinaryOperatorExpression(left, BinaryOperatorType.Divide, right).WithoutILInstruction() @@ -1147,9 +1309,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { AstType mathAstType = ConvertType(mathType); var fieldRef = new MemberReferenceExpression(new TypeReferenceExpression(mathAstType), memberName); - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { var field = mathType.GetFields(f => f.Name == memberName).FirstOrDefault(); - if (field != null) { + if (field != null) + { fieldRef.WithRR(new MemberResolveResult(mathAstType.GetResolveResult(), field)); } } @@ -1167,27 +1331,35 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax // Math.PI or Math.E or (float)Math.PI or (float)Math.E or MathF.PI or MathF.E Expression expr = fieldReference; - if (n != 1) { - if (n == -1) { + if (n != 1) + { + if (n == -1) + { // -field expr = new UnaryOperatorExpression(UnaryOperatorType.Minus, expr); - } else { + } + else + { // field * n expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Multiply, MakeConstant(type, n)); } } - if (d != 1) { + if (d != 1) + { // field * n / d or -field / d or field / d expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Divide, MakeConstant(type, d)); } - if (isDouble) { + if (isDouble) + { double field = memberName == "PI" ? Math.PI : Math.E; double approxValue = field * n / d; if (approxValue == (double)literalValue) return expr; - } else { + } + else + { float field = memberName == "PI" ? MathF_PI : MathF_E; float approxValue = field * n / d; if (approxValue == (float)literalValue) @@ -1197,21 +1369,27 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax // Math.PI or Math.E or (float)Math.PI or (float)Math.E or MathF.PI or MathF.E expr = fieldReference.Detach(); - if (d == 1) { + if (d == 1) + { // n / field expr = new BinaryOperatorExpression(MakeConstant(type, n), BinaryOperatorType.Divide, expr); - } else { + } + else + { // n / (d * field) expr = new BinaryOperatorExpression(MakeConstant(type, d), BinaryOperatorType.Multiply, expr); expr = new BinaryOperatorExpression(MakeConstant(type, n), BinaryOperatorType.Divide, expr); } - if (isDouble) { + if (isDouble) + { double field = memberName == "PI" ? Math.PI : Math.E; double approxValue = (double)n / ((double)d * field); if (approxValue == (double)literalValue) return expr; - } else { + } + else + { float field = memberName == "PI" ? MathF_PI : MathF_E; float approxValue = (float)n / ((float)d * field); if (approxValue == (float)literalValue) @@ -1225,7 +1403,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ? FractionApprox((double)literalValue / (memberName == "PI" ? Math.PI : Math.E), MAX_DENOMINATOR) : FractionApprox((float)literalValue / (memberName == "PI" ? MathF_PI : MathF_E), MAX_DENOMINATOR); - if (IsValidFraction(num, den)) { + if (IsValidFraction(num, den)) + { return ExtractExpression(num, den); } @@ -1233,7 +1412,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ? FractionApprox((double)literalValue * (memberName == "PI" ? Math.PI : Math.E), MAX_DENOMINATOR) : FractionApprox((float)literalValue * (memberName == "PI" ? MathF_PI : MathF_E), MAX_DENOMINATOR); - if (IsValidFraction(num, den)) { + if (IsValidFraction(num, den)) + { return ExtractExpression(num, den); } @@ -1277,16 +1457,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax double v = value; - while (m[1, 0] * (ai = (long)v) + m[1, 1] <= maxDenominator) { + while (m[1, 0] * (ai = (long)v) + m[1, 1] <= maxDenominator) + { long t = m[0, 0] * ai + m[0, 1]; m[0, 1] = m[0, 0]; m[0, 0] = t; t = m[1, 0] * ai + m[1, 1]; m[1, 1] = m[1, 0]; m[1, 0] = t; - if (v - ai == 0) break; + if (v - ai == 0) + break; v = 1 / (v - ai); - if (Math.Abs(v) > long.MaxValue) break; // value cannot be stored in fraction without overflow + if (Math.Abs(v) > long.MaxValue) + break; // value cannot be stored in fraction without overflow } if (m[1, 0] == 0) @@ -1314,46 +1497,63 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (parameter == null) throw new ArgumentNullException(nameof(parameter)); ParameterDeclaration decl = new ParameterDeclaration(); - if (parameter.IsRef) { + if (parameter.IsRef) + { decl.ParameterModifier = ParameterModifier.Ref; - } else if (parameter.IsOut) { + } + else if (parameter.IsOut) + { decl.ParameterModifier = ParameterModifier.Out; - } else if (parameter.IsIn) { + } + else if (parameter.IsIn) + { decl.ParameterModifier = ParameterModifier.In; - } else if (parameter.IsParams) { + } + else if (parameter.IsParams) + { decl.ParameterModifier = ParameterModifier.Params; } - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(parameter.GetAttributes())); } IType parameterType; - if (parameter.Type.Kind == TypeKind.ByReference) { + if (parameter.Type.Kind == TypeKind.ByReference) + { // avoid 'out ref' parameterType = ((ByReferenceType)parameter.Type).ElementType; - } else { + } + else + { parameterType = parameter.Type; } decl.Type = ConvertType(parameterType); - if (this.ShowParameterNames) { + if (this.ShowParameterNames) + { decl.Name = parameter.Name; } - if (parameter.IsOptional && parameter.HasConstantValueInSignature && this.ShowConstantValues) { - try { + if (parameter.IsOptional && parameter.HasConstantValueInSignature && this.ShowConstantValues) + { + try + { decl.DefaultExpression = ConvertConstantValue(parameterType, parameter.GetConstantValue(throwOnInvalidMetadata: true)); - } catch (BadImageFormatException ex) { + } + catch (BadImageFormatException ex) + { decl.DefaultExpression = new ErrorExpression(ex.Message); } } return decl; } #endregion - + #region Convert Entity public AstNode ConvertSymbol(ISymbol symbol) { if (symbol == null) throw new ArgumentNullException(nameof(symbol)); - switch (symbol.SymbolKind) { + switch (symbol.SymbolKind) + { case SymbolKind.Namespace: return ConvertNamespaceDeclaration((INamespace)symbol); case SymbolKind.Variable: @@ -1369,12 +1569,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax throw new ArgumentException("Invalid value for SymbolKind: " + symbol.SymbolKind); } } - + public EntityDeclaration ConvertEntity(IEntity entity) { if (entity == null) throw new ArgumentNullException(nameof(entity)); - switch (entity.SymbolKind) { + switch (entity.SymbolKind) + { case SymbolKind.TypeDefinition: return ConvertTypeDefinition((ITypeDefinition)entity); case SymbolKind.Field: @@ -1401,34 +1602,45 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax throw new ArgumentException("Invalid value for SymbolKind: " + entity.SymbolKind); } } - + EntityDeclaration ConvertTypeDefinition(ITypeDefinition typeDefinition) { Modifiers modifiers = Modifiers.None; - if (this.ShowAccessibility) { + if (this.ShowAccessibility) + { modifiers |= ModifierFromAccessibility(typeDefinition.Accessibility); } - if (this.ShowModifiers) { - if (typeDefinition.IsStatic) { + if (this.ShowModifiers) + { + if (typeDefinition.IsStatic) + { modifiers |= Modifiers.Static; - } else if (typeDefinition.IsAbstract) { + } + else if (typeDefinition.IsAbstract) + { modifiers |= Modifiers.Abstract; - } else if (typeDefinition.IsSealed) { + } + else if (typeDefinition.IsSealed) + { modifiers |= Modifiers.Sealed; } } - + ClassType classType; - switch (typeDefinition.Kind) { + switch (typeDefinition.Kind) + { case TypeKind.Struct: case TypeKind.Void: classType = ClassType.Struct; modifiers &= ~Modifiers.Sealed; - if (ShowModifiers) { - if (typeDefinition.IsReadOnly) { + if (ShowModifiers) + { + if (typeDefinition.IsReadOnly) + { modifiers |= Modifiers.Readonly; } - if (typeDefinition.IsByRefLike) { + if (typeDefinition.IsByRefLike) + { modifiers |= Modifiers.Ref; } } @@ -1443,56 +1655,75 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax break; case TypeKind.Delegate: IMethod invoke = typeDefinition.GetDelegateInvokeMethod(); - if (invoke != null) { + if (invoke != null) + { return ConvertDelegate(invoke, modifiers); - } else { + } + else + { goto default; } default: classType = ClassType.Class; break; } - + var decl = new TypeDeclaration(); decl.ClassType = classType; decl.Modifiers = modifiers; - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(typeDefinition.GetAttributes())); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new TypeResolveResult(typeDefinition)); } decl.Name = typeDefinition.Name == "_" ? "@_" : typeDefinition.Name; - + int outerTypeParameterCount = (typeDefinition.DeclaringTypeDefinition == null) ? 0 : typeDefinition.DeclaringTypeDefinition.TypeParameterCount; - - if (this.ShowTypeParameters) { - foreach (ITypeParameter tp in typeDefinition.TypeParameters.Skip(outerTypeParameterCount)) { + + if (this.ShowTypeParameters) + { + foreach (ITypeParameter tp in typeDefinition.TypeParameters.Skip(outerTypeParameterCount)) + { decl.TypeParameters.Add(ConvertTypeParameter(tp)); } } - - if (this.ShowBaseTypes) { - foreach (IType baseType in typeDefinition.DirectBaseTypes) { + + if (this.ShowBaseTypes) + { + foreach (IType baseType in typeDefinition.DirectBaseTypes) + { // if the declared type is an enum, replace all references to System.Enum with the enum-underlying type - if (typeDefinition.Kind == TypeKind.Enum && baseType.IsKnownType(KnownTypeCode.Enum)) { - if (!typeDefinition.EnumUnderlyingType.IsKnownType(KnownTypeCode.Int32)) { + if (typeDefinition.Kind == TypeKind.Enum && baseType.IsKnownType(KnownTypeCode.Enum)) + { + if (!typeDefinition.EnumUnderlyingType.IsKnownType(KnownTypeCode.Int32)) + { decl.BaseTypes.Add(ConvertType(typeDefinition.EnumUnderlyingType)); } - // if the declared type is a struct, ignore System.ValueType - } else if ((typeDefinition.Kind == TypeKind.Struct || typeDefinition.Kind == TypeKind.Void) && baseType.IsKnownType(KnownTypeCode.ValueType)) { + // if the declared type is a struct, ignore System.ValueType + } + else if ((typeDefinition.Kind == TypeKind.Struct || typeDefinition.Kind == TypeKind.Void) && baseType.IsKnownType(KnownTypeCode.ValueType)) + { continue; - // always ignore System.Object - } else if (baseType.IsKnownType(KnownTypeCode.Object)) { + // always ignore System.Object + } + else if (baseType.IsKnownType(KnownTypeCode.Object)) + { continue; - } else { + } + else + { decl.BaseTypes.Add(ConvertType(baseType)); } } } - - if (this.ShowTypeParameters && this.ShowTypeParameterConstraints) { - foreach (ITypeParameter tp in typeDefinition.TypeParameters.Skip(outerTypeParameterCount)) { + + if (this.ShowTypeParameters && this.ShowTypeParameterConstraints) + { + foreach (ITypeParameter tp in typeDefinition.TypeParameters.Skip(outerTypeParameterCount)) + { var constraint = ConvertTypeParameterConstraint(tp); if (constraint != null) decl.Constraints.Add(constraint); @@ -1504,36 +1735,44 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax DelegateDeclaration ConvertDelegate(IMethod invokeMethod, Modifiers modifiers) { ITypeDefinition d = invokeMethod.DeclaringTypeDefinition; - + DelegateDeclaration decl = new DelegateDeclaration(); decl.Modifiers = modifiers & ~Modifiers.Sealed; - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(d.GetAttributes())); decl.Attributes.AddRange(ConvertAttributes(invokeMethod.GetReturnTypeAttributes(), "return")); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new TypeResolveResult(d)); } decl.ReturnType = ConvertType(invokeMethod.ReturnType); - if (invokeMethod.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) { + if (invokeMethod.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) + { ct.HasReadOnlySpecifier = true; } decl.Name = d.Name; - + int outerTypeParameterCount = (d.DeclaringTypeDefinition == null) ? 0 : d.DeclaringTypeDefinition.TypeParameterCount; - - if (this.ShowTypeParameters) { - foreach (ITypeParameter tp in d.TypeParameters.Skip(outerTypeParameterCount)) { + + if (this.ShowTypeParameters) + { + foreach (ITypeParameter tp in d.TypeParameters.Skip(outerTypeParameterCount)) + { decl.TypeParameters.Add(ConvertTypeParameter(tp)); } } - - foreach (IParameter p in invokeMethod.Parameters) { + + foreach (IParameter p in invokeMethod.Parameters) + { decl.Parameters.Add(ConvertParameter(p)); } - - if (this.ShowTypeParameters && this.ShowTypeParameterConstraints) { - foreach (ITypeParameter tp in d.TypeParameters.Skip(outerTypeParameterCount)) { + + if (this.ShowTypeParameters && this.ShowTypeParameterConstraints) + { + foreach (ITypeParameter tp in d.TypeParameters.Skip(outerTypeParameterCount)) + { var constraint = ConvertTypeParameterConstraint(tp); if (constraint != null) decl.Constraints.Add(constraint); @@ -1541,61 +1780,78 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } return decl; } - + FieldDeclaration ConvertField(IField field) { FieldDeclaration decl = new FieldDeclaration(); - if (ShowModifiers) { + if (ShowModifiers) + { Modifiers m = GetMemberModifiers(field); - if (field.IsConst) { + if (field.IsConst) + { m &= ~Modifiers.Static; m |= Modifiers.Const; - } else if (field.IsReadOnly) { + } + else if (field.IsReadOnly) + { m |= Modifiers.Readonly; - } else if (field.IsVolatile) { + } + else if (field.IsVolatile) + { m |= Modifiers.Volatile; } decl.Modifiers = m; } - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(field.GetAttributes())); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new MemberResolveResult(null, field)); } decl.ReturnType = ConvertType(field.ReturnType); Expression initializer = null; - if (field.IsConst && this.ShowConstantValues) { - try { + if (field.IsConst && this.ShowConstantValues) + { + try + { initializer = ConvertConstantValue(field.Type, field.GetConstantValue(throwOnInvalidMetadata: true)); - } catch (BadImageFormatException ex) { + } + catch (BadImageFormatException ex) + { initializer = new ErrorExpression(ex.Message); } } decl.Variables.Add(new VariableInitializer(field.Name, initializer)); return decl; } - + BlockStatement GenerateBodyBlock() { - if (GenerateBody) { + if (GenerateBody) + { return new BlockStatement { new ThrowStatement(new ObjectCreateExpression(ConvertType(new TopLevelTypeName("System", "NotImplementedException", 0)))) }; - } else { + } + else + { return BlockStatement.Null; } } - + Accessor ConvertAccessor(IMethod accessor, MethodSemanticsAttributes kind, Accessibility ownerAccessibility, bool addParameterAttribute) { if (accessor == null) return Accessor.Null; Accessor decl = new Accessor(); - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(accessor.GetAttributes())); decl.Attributes.AddRange(ConvertAttributes(accessor.GetReturnTypeAttributes(), "return")); - if (addParameterAttribute && accessor.Parameters.Count > 0) { + if (addParameterAttribute && accessor.Parameters.Count > 0) + { decl.Attributes.AddRange(ConvertAttributes(accessor.Parameters.Last().GetAttributes(), "param")); } } @@ -1611,51 +1867,62 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax MethodSemanticsAttributes.Remover => CustomEventDeclaration.RemoveKeywordRole, _ => null }; - if (kind == MethodSemanticsAttributes.Setter && SupportInitAccessors && accessor.IsInitOnly) { + if (kind == MethodSemanticsAttributes.Setter && SupportInitAccessors && accessor.IsInitOnly) + { keywordRole = PropertyDeclaration.InitKeywordRole; } - if (keywordRole != null) { + if (keywordRole != null) + { decl.AddChild(new CSharpTokenNode(TextLocation.Empty, keywordRole), keywordRole); } - if (accessor.IsInitOnly && keywordRole != PropertyDeclaration.InitKeywordRole) { + if (accessor.IsInitOnly && keywordRole != PropertyDeclaration.InitKeywordRole) + { decl.AddChild(new Comment("init", CommentType.MultiLine), Roles.Comment); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new MemberResolveResult(null, accessor)); } - if (GenerateBody) { + if (GenerateBody) + { decl.Body = GenerateBodyBlock(); - } else { + } + else + { decl.AddChild(new CSharpTokenNode(TextLocation.Empty, Roles.Semicolon), Roles.Semicolon); } return decl; } - + PropertyDeclaration ConvertProperty(IProperty property) { PropertyDeclaration decl = new PropertyDeclaration(); decl.Modifiers = GetMemberModifiers(property); - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(property.GetAttributes())); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new MemberResolveResult(null, property)); } decl.ReturnType = ConvertType(property.ReturnType); - if (property.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) { + if (property.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) + { ct.HasReadOnlySpecifier = true; } decl.Name = property.Name; decl.Getter = ConvertAccessor(property.Getter, MethodSemanticsAttributes.Getter, property.Accessibility, false); decl.Setter = ConvertAccessor(property.Setter, MethodSemanticsAttributes.Setter, property.Accessibility, true); - decl.PrivateImplementationType = GetExplicitInterfaceType (property); + decl.PrivateImplementationType = GetExplicitInterfaceType(property); MergeReadOnlyModifiers(decl, decl.Getter, decl.Setter); return decl; } - + static void MergeReadOnlyModifiers(EntityDeclaration decl, Accessor accessor1, Accessor accessor2) { - if (accessor1.HasModifier(Modifiers.Readonly) && accessor2.HasModifier(Modifiers.Readonly)) { + if (accessor1.HasModifier(Modifiers.Readonly) && accessor2.HasModifier(Modifiers.Readonly)) + { accessor1.Modifiers &= ~Modifiers.Readonly; accessor2.Modifiers &= ~Modifiers.Readonly; decl.Modifiers |= Modifiers.Readonly; @@ -1665,51 +1932,62 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { IndexerDeclaration decl = new IndexerDeclaration(); decl.Modifiers = GetMemberModifiers(indexer); - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(indexer.GetAttributes())); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new MemberResolveResult(null, indexer)); } decl.ReturnType = ConvertType(indexer.ReturnType); - if (indexer.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) { + if (indexer.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) + { ct.HasReadOnlySpecifier = true; } - foreach (IParameter p in indexer.Parameters) { + foreach (IParameter p in indexer.Parameters) + { decl.Parameters.Add(ConvertParameter(p)); } decl.Getter = ConvertAccessor(indexer.Getter, MethodSemanticsAttributes.Getter, indexer.Accessibility, false); decl.Setter = ConvertAccessor(indexer.Setter, MethodSemanticsAttributes.Setter, indexer.Accessibility, true); - decl.PrivateImplementationType = GetExplicitInterfaceType (indexer); + decl.PrivateImplementationType = GetExplicitInterfaceType(indexer); MergeReadOnlyModifiers(decl, decl.Getter, decl.Setter); return decl; } - + EntityDeclaration ConvertEvent(IEvent ev) { - if (this.UseCustomEvents) { + if (this.UseCustomEvents) + { CustomEventDeclaration decl = new CustomEventDeclaration(); decl.Modifiers = GetMemberModifiers(ev); - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(ev.GetAttributes())); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new MemberResolveResult(null, ev)); } decl.ReturnType = ConvertType(ev.ReturnType); decl.Name = ev.Name; - decl.AddAccessor = ConvertAccessor(ev.AddAccessor, MethodSemanticsAttributes.Adder, ev.Accessibility, true); + decl.AddAccessor = ConvertAccessor(ev.AddAccessor, MethodSemanticsAttributes.Adder, ev.Accessibility, true); decl.RemoveAccessor = ConvertAccessor(ev.RemoveAccessor, MethodSemanticsAttributes.Remover, ev.Accessibility, true); - decl.PrivateImplementationType = GetExplicitInterfaceType (ev); + decl.PrivateImplementationType = GetExplicitInterfaceType(ev); MergeReadOnlyModifiers(decl, decl.AddAccessor, decl.RemoveAccessor); return decl; - } else { + } + else + { EventDeclaration decl = new EventDeclaration(); decl.Modifiers = GetMemberModifiers(ev); - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(ev.GetAttributes())); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new MemberResolveResult(null, ev)); } decl.ReturnType = ConvertType(ev.ReturnType); @@ -1717,75 +1995,87 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return decl; } } - + MethodDeclaration ConvertMethod(IMethod method) { MethodDeclaration decl = new MethodDeclaration(); decl.Modifiers = GetMemberModifiers(method); - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(method.GetAttributes())); decl.Attributes.AddRange(ConvertAttributes(method.GetReturnTypeAttributes(), "return")); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new MemberResolveResult(null, method)); } decl.ReturnType = ConvertType(method.ReturnType); - if (method.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) { + if (method.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) + { ct.HasReadOnlySpecifier = true; } decl.Name = method.Name; - - if (this.ShowTypeParameters) { - foreach (ITypeParameter tp in method.TypeParameters) { + + if (this.ShowTypeParameters) + { + foreach (ITypeParameter tp in method.TypeParameters) + { decl.TypeParameters.Add(ConvertTypeParameter(tp)); } } - - foreach (IParameter p in method.Parameters) { + + foreach (IParameter p in method.Parameters) + { decl.Parameters.Add(ConvertParameter(p)); } if (method.IsExtensionMethod && method.ReducedFrom == null && decl.Parameters.Any()) decl.Parameters.First().HasThisModifier = true; - - if (this.ShowTypeParameters && this.ShowTypeParameterConstraints && !method.IsOverride && !method.IsExplicitInterfaceImplementation) { - foreach (ITypeParameter tp in method.TypeParameters) { + + if (this.ShowTypeParameters && this.ShowTypeParameterConstraints && !method.IsOverride && !method.IsExplicitInterfaceImplementation) + { + foreach (ITypeParameter tp in method.TypeParameters) + { var constraint = ConvertTypeParameterConstraint(tp); if (constraint != null) decl.Constraints.Add(constraint); } } decl.Body = GenerateBodyBlock(); - decl.PrivateImplementationType = GetExplicitInterfaceType (method); + decl.PrivateImplementationType = GetExplicitInterfaceType(method); return decl; } - + EntityDeclaration 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 = ConvertType(op.ReturnType); - if (op.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) { + if (op.ReturnTypeIsRefReadOnly && decl.ReturnType is ComposedType ct && ct.HasRefSpecifier) + { ct.HasReadOnlySpecifier = true; } - foreach (IParameter p in op.Parameters) { + foreach (IParameter p in op.Parameters) + { decl.Parameters.Add(ConvertParameter(p)); } - if (ShowAttributes) { + if (ShowAttributes) + { decl.Attributes.AddRange(ConvertAttributes(op.GetAttributes())); decl.Attributes.AddRange(ConvertAttributes(op.GetReturnTypeAttributes(), "return")); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new MemberResolveResult(null, op)); } decl.Body = GenerateBodyBlock(); return decl; } - + ConstructorDeclaration ConvertConstructor(IMethod ctor) { ConstructorDeclaration decl = new ConstructorDeclaration(); @@ -1794,16 +2084,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax decl.Attributes.AddRange(ConvertAttributes(ctor.GetAttributes())); if (ctor.DeclaringTypeDefinition != null) decl.Name = ctor.DeclaringTypeDefinition.Name; - foreach (IParameter p in ctor.Parameters) { + foreach (IParameter p in ctor.Parameters) + { decl.Parameters.Add(ConvertParameter(p)); } - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new MemberResolveResult(null, ctor)); } decl.Body = GenerateBodyBlock(); return decl; } - + DestructorDeclaration ConvertDestructor(IMethod dtor) { DestructorDeclaration decl = new DestructorDeclaration(); @@ -1811,18 +2103,20 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax decl.Attributes.AddRange(ConvertAttributes(dtor.GetAttributes())); if (dtor.DeclaringTypeDefinition != null) decl.Name = dtor.DeclaringTypeDefinition.Name; - if (AddResolveResultAnnotations) { + if (AddResolveResultAnnotations) + { decl.AddAnnotation(new MemberResolveResult(null, dtor)); } decl.Body = GenerateBodyBlock(); return decl; } #endregion - + #region Convert Modifiers public static Modifiers ModifierFromAccessibility(Accessibility accessibility) { - switch (accessibility) { + switch (accessibility) + { case Accessibility.Private: return Modifiers.Private; case Accessibility.Public: @@ -1839,16 +2133,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return Modifiers.None; } } - + bool NeedsAccessibility(IMember member) { var declaringType = member.DeclaringType; if (member.IsExplicitInterfaceImplementation) return false; - if (declaringType != null && declaringType.Kind == TypeKind.Interface) { + if (declaringType != null && declaringType.Kind == TypeKind.Interface) + { return member.Accessibility != Accessibility.Public; } - switch (member.SymbolKind) { + switch (member.SymbolKind) + { case SymbolKind.Constructor: return !member.IsStatic; case SymbolKind.Destructor: @@ -1859,26 +2155,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return true; } } - + Modifiers GetMemberModifiers(IMember member) { Modifiers m = Modifiers.None; - if (this.ShowAccessibility && NeedsAccessibility(member)) { - m |= ModifierFromAccessibility (member.Accessibility); + if (this.ShowAccessibility && NeedsAccessibility(member)) + { + m |= ModifierFromAccessibility(member.Accessibility); } - if (this.ShowModifiers) { - if (member is LocalFunctionMethod localFunction) { - if (localFunction.IsStaticLocalFunction) { + if (this.ShowModifiers) + { + if (member is LocalFunctionMethod localFunction) + { + if (localFunction.IsStaticLocalFunction) + { m |= Modifiers.Static; } - } else if (member.IsStatic) { + } + else if (member.IsStatic) + { m |= Modifiers.Static; - } else { + } + else + { var declaringType = member.DeclaringType; - if (declaringType.Kind == TypeKind.Interface) { + if (declaringType.Kind == TypeKind.Interface) + { if (!member.IsVirtual && !member.IsAbstract && !member.IsOverride && member.Accessibility != Accessibility.Private && member is IMethod method2 && method2.HasBody) m |= Modifiers.Sealed; - } else { + } + else + { if (member.IsAbstract) m |= Modifiers.Abstract; else if (member.IsVirtual && !member.IsOverride) @@ -1895,7 +2202,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return m; } #endregion - + #region Convert Type Parameter internal TypeParameterDeclaration ConvertTypeParameter(ITypeParameter tp) { @@ -1906,33 +2213,48 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax decl.Attributes.AddRange(ConvertAttributes(tp.GetAttributes())); return decl; } - + internal Constraint ConvertTypeParameterConstraint(ITypeParameter tp) { - if (!tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint && tp.NullabilityConstraint != Nullability.NotNullable && tp.DirectBaseTypes.All(IsObjectOrValueType)) { + if (!tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint && tp.NullabilityConstraint != Nullability.NotNullable && tp.DirectBaseTypes.All(IsObjectOrValueType)) + { return null; } Constraint c = new Constraint(); c.TypeParameter = MakeSimpleType(tp.Name); - if (tp.HasReferenceTypeConstraint) { - if (tp.NullabilityConstraint == Nullability.Nullable) { + if (tp.HasReferenceTypeConstraint) + { + if (tp.NullabilityConstraint == Nullability.Nullable) + { c.BaseTypes.Add(new PrimitiveType("class").MakeNullableType()); - } else { + } + else + { c.BaseTypes.Add(new PrimitiveType("class")); } - } else if (tp.HasValueTypeConstraint) { - if (tp.HasUnmanagedConstraint) { + } + else if (tp.HasValueTypeConstraint) + { + if (tp.HasUnmanagedConstraint) + { c.BaseTypes.Add(new PrimitiveType("unmanaged")); - } else { + } + else + { c.BaseTypes.Add(new PrimitiveType("struct")); } - } else if (tp.NullabilityConstraint == Nullability.NotNullable) { + } + else if (tp.NullabilityConstraint == Nullability.NotNullable) + { c.BaseTypes.Add(new PrimitiveType("notnull")); } - foreach (TypeConstraint t in tp.TypeConstraints) { - if (!IsObjectOrValueType(t.Type) || t.Attributes.Count > 0) { + foreach (TypeConstraint t in tp.TypeConstraints) + { + if (!IsObjectOrValueType(t.Type) || t.Attributes.Count > 0) + { AstType astType = ConvertType(t.Type); - if (t.Attributes.Count > 0) { + if (t.Attributes.Count > 0) + { var attrSection = new AttributeSection(); attrSection.Attributes.AddRange(t.Attributes.Select(ConvertAttribute)); astType = new ComposedType { @@ -1943,19 +2265,20 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax c.BaseTypes.Add(astType); } } - if (tp.HasDefaultConstructorConstraint && !tp.HasValueTypeConstraint) { + if (tp.HasDefaultConstructorConstraint && !tp.HasValueTypeConstraint) + { c.BaseTypes.Add(new PrimitiveType("new")); } return c; } - + static bool IsObjectOrValueType(IType type) { ITypeDefinition d = type.GetDefinition(); return d != null && (d.KnownTypeCode == KnownTypeCode.Object || d.KnownTypeCode == KnownTypeCode.ValueType); } #endregion - + #region Convert Variable public VariableDeclarationStatement ConvertVariable(IVariable v) { @@ -1963,10 +2286,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax decl.Modifiers = v.IsConst ? Modifiers.Const : Modifiers.None; decl.Type = ConvertType(v.Type); Expression initializer = null; - if (v.IsConst) { - try { + if (v.IsConst) + { + try + { initializer = ConvertConstantValue(v.Type, v.GetConstantValue(throwOnInvalidMetadata: true)); - } catch (BadImageFormatException ex) { + } + catch (BadImageFormatException ex) + { initializer = new ErrorExpression(ex.Message); } } @@ -1974,18 +2301,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return decl; } #endregion - + NamespaceDeclaration ConvertNamespaceDeclaration(INamespace ns) { return new NamespaceDeclaration(ns.FullName); } - AstType GetExplicitInterfaceType (IMember member) + AstType GetExplicitInterfaceType(IMember member) { - if (member.IsExplicitInterfaceImplementation) { - var baseMember = member.ExplicitlyImplementedInterfaceMembers.FirstOrDefault (); + if (member.IsExplicitInterfaceImplementation) + { + var baseMember = member.ExplicitlyImplementedInterfaceMembers.FirstOrDefault(); if (baseMember != null) - return ConvertType (baseMember.DeclaringType); + return ConvertType(baseMember.DeclaringType); } return null; } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs b/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs index 16f067a96..4070a4988 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -28,17 +29,18 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public class AddCheckedBlocks : IAstTransform { #region Annotation - sealed class CheckedUncheckedAnnotation { + sealed class CheckedUncheckedAnnotation + { /// /// true=checked, false=unchecked /// public bool IsChecked; } - + public static readonly object CheckedAnnotation = new CheckedUncheckedAnnotation { IsChecked = true }; public static readonly object UncheckedAnnotation = new CheckedUncheckedAnnotation { IsChecked = false }; #endregion - + /* We treat placing checked/unchecked blocks as an optimization problem, with the following goals: 1. Use minimum number of checked blocks+expressions @@ -59,51 +61,51 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms If the checked block was closed as early as possible, the variable r would have to be declared outside (this would work, but look badly) */ - + #region struct Cost struct Cost { // highest possible cost so that the Blocks+Expressions addition doesn't overflow public static readonly Cost Infinite = new Cost(0x3fffffff, 0x3fffffff); - + public readonly int Blocks; public readonly int Expressions; - + public Cost(int blocks, int expressions) { this.Blocks = blocks; this.Expressions = expressions; } - + public static bool operator <(Cost a, Cost b) { return a.Blocks + a.Expressions < b.Blocks + b.Expressions || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks < b.Blocks; } - + public static bool operator >(Cost a, Cost b) { return a.Blocks + a.Expressions > b.Blocks + b.Expressions || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks > b.Blocks; } - + public static bool operator <=(Cost a, Cost b) { return a.Blocks + a.Expressions < b.Blocks + b.Expressions || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks <= b.Blocks; } - + public static bool operator >=(Cost a, Cost b) { return a.Blocks + a.Expressions > b.Blocks + b.Expressions || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks >= b.Blocks; } - + public static Cost operator +(Cost a, Cost b) { return new Cost(a.Blocks + b.Blocks, a.Expressions + b.Expressions); } - + public override string ToString() { return string.Format("[{0} + {1}]", Blocks, Expressions); @@ -115,9 +117,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms /// internal Cost WrapInCheckedExpr() { - if (Expressions == 0) { + if (Expressions == 0) + { return new Cost(Blocks, 1); - } else { + } + else + { // hack: penalize multiple layers of nested expressions // This doesn't really fit into the original idea of minimizing the number of block+expressions; // but tends to produce better-looking results due to less nesting. @@ -126,7 +131,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } #endregion - + #region class InsertedNode /// /// Holds the blocks and expressions that should be inserted @@ -141,38 +146,38 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return a; return new InsertedNodeList(a, b); } - + public abstract void Insert(); } - + class InsertedNodeList : InsertedNode { readonly InsertedNode child1, child2; - + public InsertedNodeList(AddCheckedBlocks.InsertedNode child1, AddCheckedBlocks.InsertedNode child2) { this.child1 = child1; this.child2 = child2; } - + public override void Insert() { child1.Insert(); child2.Insert(); } } - + class InsertedExpression : InsertedNode { readonly Expression expression; readonly bool isChecked; - + public InsertedExpression(Expression expression, bool isChecked) { this.expression = expression; this.isChecked = isChecked; } - + public override void Insert() { if (isChecked) @@ -181,26 +186,27 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms expression.ReplaceWith(e => new UncheckedExpression { Expression = e }); } } - + class InsertedBlock : InsertedNode { readonly Statement firstStatement; // inclusive readonly Statement lastStatement; // exclusive readonly bool isChecked; - + public InsertedBlock(Statement firstStatement, Statement lastStatement, bool isChecked) { this.firstStatement = firstStatement; this.lastStatement = lastStatement; this.isChecked = isChecked; } - + public override void Insert() { BlockStatement newBlock = new BlockStatement(); // Move all statements except for the first Statement next; - for (Statement stmt = firstStatement.GetNextStatement(); stmt != lastStatement; stmt = next) { + for (Statement stmt = firstStatement.GetNextStatement(); stmt != lastStatement; stmt = next) + { next = stmt.GetNextStatement(); newBlock.Add(stmt.Detach()); } @@ -214,7 +220,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } #endregion - + #region class Result /// /// Holds the result of an insertion operation. @@ -227,21 +233,25 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public InsertedNode NodesToInsertInUncheckedContext; } #endregion - + public void Run(AstNode node, TransformContext context) { BlockStatement block = node as BlockStatement; - if (block == null) { - for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + if (block == null) + { + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) + { Run(child, context); } - } else { + } + else + { Result r = GetResultFromBlock(block); if (r.NodesToInsertInUncheckedContext != null) r.NodesToInsertInUncheckedContext.Insert(); } } - + Result GetResultFromBlock(BlockStatement block) { // For a block, we are tracking 4 possibilities: @@ -259,34 +269,39 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms Cost costUncheckedContextCheckedBlockOpen = Cost.Infinite; InsertedNode nodesUncheckedContextCheckedBlockOpen = null; Statement checkedBlockStart = null; - + Statement statement = block.Statements.FirstOrDefault(); - while (true) { + while (true) + { // Blocks can be closed 'for free'. We use '<=' so that blocks are closed as late as possible (goal 4b) - if (costCheckedContextUncheckedBlockOpen <= costCheckedContext) { + if (costCheckedContextUncheckedBlockOpen <= costCheckedContext) + { costCheckedContext = costCheckedContextUncheckedBlockOpen; nodesCheckedContext = nodesCheckedContextUncheckedBlockOpen + new InsertedBlock(uncheckedBlockStart, statement, false); } - if (costUncheckedContextCheckedBlockOpen <= costUncheckedContext) { + if (costUncheckedContextCheckedBlockOpen <= costUncheckedContext) + { costUncheckedContext = costUncheckedContextCheckedBlockOpen; nodesUncheckedContext = nodesUncheckedContextCheckedBlockOpen + new InsertedBlock(checkedBlockStart, statement, true); } if (statement == null) break; // Now try opening blocks. We use '<=' so that blocks are opened as late as possible. (goal 4a) - if (costCheckedContext + new Cost(1, 0) <= costCheckedContextUncheckedBlockOpen) { + if (costCheckedContext + new Cost(1, 0) <= costCheckedContextUncheckedBlockOpen) + { costCheckedContextUncheckedBlockOpen = costCheckedContext + new Cost(1, 0); nodesCheckedContextUncheckedBlockOpen = nodesCheckedContext; uncheckedBlockStart = statement; } - if (costUncheckedContext + new Cost(1, 0) <= costUncheckedContextCheckedBlockOpen) { + if (costUncheckedContext + new Cost(1, 0) <= costUncheckedContextCheckedBlockOpen) + { costUncheckedContextCheckedBlockOpen = costUncheckedContext + new Cost(1, 0); nodesUncheckedContextCheckedBlockOpen = nodesUncheckedContext; checkedBlockStart = statement; } // Now handle the statement Result stmtResult = GetResult(statement); - + costCheckedContext += stmtResult.CostInCheckedContext; nodesCheckedContext += stmtResult.NodesToInsertInCheckedContext; costCheckedContextUncheckedBlockOpen += stmtResult.CostInUncheckedContext; @@ -295,8 +310,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms nodesUncheckedContext += stmtResult.NodesToInsertInUncheckedContext; costUncheckedContextCheckedBlockOpen += stmtResult.CostInCheckedContext; nodesUncheckedContextCheckedBlockOpen += stmtResult.NodesToInsertInCheckedContext; - - if (statement is LabelStatement || statement is LocalFunctionDeclarationStatement) { + + if (statement is LabelStatement || statement is LocalFunctionDeclarationStatement) + { // We can't move labels into blocks because that might cause goto-statements // to be unable to jump to the labels. // Also, we can't move local functions into blocks, because that might cause @@ -304,22 +320,23 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms costCheckedContextUncheckedBlockOpen = Cost.Infinite; costUncheckedContextCheckedBlockOpen = Cost.Infinite; } - + statement = statement.GetNextStatement(); } - + return new Result { CostInCheckedContext = costCheckedContext, NodesToInsertInCheckedContext = nodesCheckedContext, CostInUncheckedContext = costUncheckedContext, NodesToInsertInUncheckedContext = nodesUncheckedContext }; } - + Result GetResult(AstNode node) { if (node is BlockStatement) return GetResultFromBlock((BlockStatement)node); Result result = new Result(); - for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) + { Result childResult = GetResult(child); result.CostInCheckedContext += childResult.CostInCheckedContext; result.NodesToInsertInCheckedContext += childResult.NodesToInsertInCheckedContext; @@ -327,9 +344,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms result.NodesToInsertInUncheckedContext += childResult.NodesToInsertInUncheckedContext; } Expression expr = node as Expression; - if (expr != null) { + if (expr != null) + { CheckedUncheckedAnnotation annotation = expr.Annotation(); - if (annotation != null) { + if (annotation != null) + { // If the annotation requires this node to be in a specific context, add a huge cost to the other context // That huge cost gives us the option to ignore a required checked/unchecked expression when there wouldn't be any // solution otherwise. (e.g. "for (checked(M().x += 1); true; unchecked(M().x += 2)) {}") @@ -339,16 +358,22 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms result.CostInCheckedContext += new Cost(10000, 0); } // Embed this node in an checked/unchecked expression: - if (expr.Parent is ExpressionStatement) { + if (expr.Parent is ExpressionStatement) + { // We cannot use checked/unchecked for top-level-expressions. - } else if (expr.Role.IsValid(Expression.Null)) { + } + else if (expr.Role.IsValid(Expression.Null)) + { // We use '<' so that expressions are introduced on the deepest level possible (goal 3) var costIfWrapWithChecked = result.CostInCheckedContext.WrapInCheckedExpr(); var costIfWrapWithUnchecked = result.CostInUncheckedContext.WrapInCheckedExpr(); - if (costIfWrapWithChecked < result.CostInUncheckedContext) { + if (costIfWrapWithChecked < result.CostInUncheckedContext) + { result.CostInUncheckedContext = costIfWrapWithChecked; result.NodesToInsertInUncheckedContext = result.NodesToInsertInCheckedContext + new InsertedExpression(expr, true); - } else if (costIfWrapWithUnchecked < result.CostInCheckedContext) { + } + else if (costIfWrapWithUnchecked < result.CostInCheckedContext) + { result.CostInCheckedContext = costIfWrapWithUnchecked; result.NodesToInsertInCheckedContext = result.NodesToInsertInUncheckedContext + new InsertedExpression(expr, false); } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/AddXmlDocumentationTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/AddXmlDocumentationTransform.cs index 490dcdc33..b3f02dee0 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/AddXmlDocumentationTransform.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/AddXmlDocumentationTransform.cs @@ -21,6 +21,7 @@ using System.IO; using System.Linq; using System.Reflection.Metadata; using System.Xml; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.TypeSystem; @@ -36,29 +37,35 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { if (!context.Settings.ShowXmlDocumentation || context.DecompileRun.DocumentationProvider == null) return; - try { + try + { var provider = context.DecompileRun.DocumentationProvider; - foreach (var entityDecl in rootNode.DescendantsAndSelf.OfType()) { + foreach (var entityDecl in rootNode.DescendantsAndSelf.OfType()) + { if (!(entityDecl.GetSymbol() is IEntity entity)) continue; string doc = provider.GetDocumentation(entity); - if (doc != null) { + if (doc != null) + { InsertXmlDocumentation(entityDecl, new StringReader(doc)); } } - } catch (XmlException ex) { + } + catch (XmlException ex) + { string[] msg = (" Exception while reading XmlDoc: " + ex).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var insertionPoint = rootNode.FirstChild; for (int i = 0; i < msg.Length; i++) rootNode.InsertChildBefore(insertionPoint, new Comment(msg[i], CommentType.Documentation), Roles.Comment); } } - + static void InsertXmlDocumentation(AstNode node, StringReader r) { // Find the first non-empty line: string firstLine; - do { + do + { firstLine = r.ReadLine(); if (firstLine == null) return; @@ -67,11 +74,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms string line = firstLine; int skippedWhitespaceLines = 0; // Copy all lines from input to output, except for empty lines at the end. - while (line != null) { - if (string.IsNullOrWhiteSpace(line)) { + while (line != null) + { + if (string.IsNullOrWhiteSpace(line)) + { skippedWhitespaceLines++; - } else { - while (skippedWhitespaceLines > 0) { + } + else + { + while (skippedWhitespaceLines > 0) + { Comment emptyLine = new Comment(string.Empty, CommentType.Documentation); emptyLine.AddAnnotation(node.GetResolveResult()); node.Parent.InsertChildBefore(node, emptyLine, Roles.Comment); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/CombineQueryExpressions.cs b/ICSharpCode.Decompiler/CSharp/Transforms/CombineQueryExpressions.cs index a8a178da2..b0f53dd74 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/CombineQueryExpressions.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/CombineQueryExpressions.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; @@ -35,39 +36,49 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return; CombineQueries(rootNode, new Dictionary()); } - + static readonly InvocationExpression castPattern = new InvocationExpression { Target = new MemberReferenceExpression { Target = new AnyNode("inExpr"), MemberName = "Cast", TypeArguments = { new AnyNode("targetType") } - }}; - + } + }; + void CombineQueries(AstNode node, Dictionary fromOrLetIdentifiers) { AstNode next; - for (AstNode child = node.FirstChild; child != null; child = next) { + for (AstNode child = node.FirstChild; child != null; child = next) + { // store reference to next child before transformation next = child.NextSibling; CombineQueries(child, fromOrLetIdentifiers); } QueryExpression query = node as QueryExpression; - if (query != null) { + if (query != null) + { QueryFromClause fromClause = (QueryFromClause)query.Clauses.First(); QueryExpression innerQuery = fromClause.Expression as QueryExpression; - if (innerQuery != null) { - if (TryRemoveTransparentIdentifier(query, fromClause, innerQuery, fromOrLetIdentifiers)) { + if (innerQuery != null) + { + if (TryRemoveTransparentIdentifier(query, fromClause, innerQuery, fromOrLetIdentifiers)) + { RemoveTransparentIdentifierReferences(query, fromOrLetIdentifiers); - } else { + } + else + { QueryContinuationClause continuation = new QueryContinuationClause(); continuation.PrecedingQuery = innerQuery.Detach(); continuation.Identifier = fromClause.Identifier; continuation.CopyAnnotationsFrom(fromClause); fromClause.ReplaceWith(continuation); } - } else { + } + else + { Match m = castPattern.Match(fromClause.Expression); - if (m.Success) { + if (m.Success) + { fromClause.Type = m.Get("targetType").Single().Detach(); fromClause.Expression = m.Get("inExpr").Single().Detach(); } @@ -96,7 +107,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { return identifier.StartsWith("<>", StringComparison.Ordinal) && (identifier.Contains("TransparentIdentifier") || identifier.Contains("TranspIdent")); } - + bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, Dictionary letClauses) { if (!IsTransparentIdentifier(fromClause.Identifier)) @@ -113,12 +124,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms selectClause.Remove(); // Move clauses from innerQuery to query QueryClause insertionPos = null; - foreach (var clause in innerQuery.Clauses) { + foreach (var clause in innerQuery.Clauses) + { query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach()); } - foreach (var expr in match.Get("expr")) { - switch (expr) { + foreach (var expr in match.Get("expr")) + { + switch (expr) + { case IdentifierExpression identifier: letClauses[identifier.Identifier] = identifier.Annotation(); break; @@ -126,7 +140,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms AddQueryLetClause(member.MemberName, member); break; case NamedExpression namedExpression: - if (namedExpression.Expression is IdentifierExpression identifierExpression && namedExpression.Name == identifierExpression.Identifier) { + if (namedExpression.Expression is IdentifierExpression identifierExpression && namedExpression.Name == identifierExpression.Identifier) + { letClauses[namedExpression.Name] = identifierExpression.Annotation(); continue; } @@ -145,19 +160,22 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms query.Clauses.InsertAfter(insertionPos, letClause); } } - + /// /// Removes all occurrences of transparent identifiers /// void RemoveTransparentIdentifierReferences(AstNode node, Dictionary fromOrLetIdentifiers) { - foreach (AstNode child in node.Children) { + foreach (AstNode child in node.Children) + { RemoveTransparentIdentifierReferences(child, fromOrLetIdentifiers); } MemberReferenceExpression mre = node as MemberReferenceExpression; - if (mre != null) { + if (mre != null) + { IdentifierExpression ident = mre.Target as IdentifierExpression; - if (ident != null && IsTransparentIdentifier(ident.Identifier)) { + if (ident != null && IsTransparentIdentifier(ident.Identifier)) + { IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName); mre.TypeArguments.MoveTo(newIdent.TypeArguments); newIdent.CopyAnnotationsFrom(mre); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/ContextTrackingVisitor.cs b/ICSharpCode.Decompiler/CSharp/Transforms/ContextTrackingVisitor.cs index 3f3015a33..5f60b62f7 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/ContextTrackingVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/ContextTrackingVisitor.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Diagnostics; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.TypeSystem; @@ -29,13 +30,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { protected ITypeDefinition currentTypeDefinition; protected IMethod currentMethod; - + protected void Initialize(TransformContext context) { currentTypeDefinition = context.CurrentTypeDefinition; currentMethod = context.CurrentMember as IMethod; } - + protected void Uninitialize() { currentTypeDefinition = null; @@ -45,65 +46,83 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public override TResult VisitTypeDeclaration(TypeDeclaration typeDeclaration) { ITypeDefinition oldType = currentTypeDefinition; - try { + try + { currentTypeDefinition = typeDeclaration.GetSymbol() as ITypeDefinition; return base.VisitTypeDeclaration(typeDeclaration); - } finally { + } + finally + { currentTypeDefinition = oldType; } } - + public override TResult VisitMethodDeclaration(MethodDeclaration methodDeclaration) { var oldMethod = currentMethod; - try { + try + { currentMethod = methodDeclaration.GetSymbol() as IMethod; return base.VisitMethodDeclaration(methodDeclaration); - } finally { + } + finally + { currentMethod = oldMethod; } } - + public override TResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) { var oldMethod = currentMethod; - try { + try + { currentMethod = constructorDeclaration.GetSymbol() as IMethod; return base.VisitConstructorDeclaration(constructorDeclaration); - } finally { + } + finally + { currentMethod = oldMethod; } } - + public override TResult VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration) { var oldMethod = currentMethod; - try { + try + { currentMethod = destructorDeclaration.GetSymbol() as IMethod; return base.VisitDestructorDeclaration(destructorDeclaration); - } finally { + } + finally + { currentMethod = oldMethod; } } - + public override TResult VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration) { var oldMethod = currentMethod; - try { + try + { currentMethod = operatorDeclaration.GetSymbol() as IMethod; return base.VisitOperatorDeclaration(operatorDeclaration); - } finally { + } + finally + { currentMethod = oldMethod; } } - + public override TResult VisitAccessor(Accessor accessor) { var oldMethod = currentMethod; - try { + try + { currentMethod = accessor.GetSymbol() as IMethod; return base.VisitAccessor(accessor); - } finally { + } + finally + { currentMethod = oldMethod; } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/CustomPatterns.cs b/ICSharpCode.Decompiler/CSharp/Transforms/CustomPatterns.cs index 1297ee504..0926035ed 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/CustomPatterns.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/CustomPatterns.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.Semantics; @@ -28,22 +29,25 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { readonly string ns; readonly string name; - + public TypePattern(Type type) { this.ns = type.Namespace; this.name = type.Name; } - + public override bool DoMatch(INode other, Match match) { ComposedType ct = other as ComposedType; AstType o; - if (ct != null && !ct.HasRefSpecifier && !ct.HasNullableSpecifier && ct.PointerRank == 0 && !ct.ArraySpecifiers.Any()) { + if (ct != null && !ct.HasRefSpecifier && !ct.HasNullableSpecifier && ct.PointerRank == 0 && !ct.ArraySpecifiers.Any()) + { // Special case: ILSpy sometimes produces a ComposedType but then removed all array specifiers // from it. In that case, we need to look at the base type for the annotations. o = ct.BaseType; - } else { + } + else + { o = other as AstType; if (o == null) return false; @@ -51,44 +55,45 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var trr = o.GetResolveResult() as TypeResolveResult; return trr != null && trr.Type.Namespace == ns && trr.Type.Name == name; } - + public override string ToString() { return name; } } - + sealed class LdTokenPattern : Pattern { AnyNode childNode; - + public LdTokenPattern(string groupName) { this.childNode = new AnyNode(groupName); } - + public override bool DoMatch(INode other, Match match) { InvocationExpression ie = other as InvocationExpression; - if (ie != null && ie.Annotation() != null && ie.Arguments.Count == 1) { + if (ie != null && ie.Annotation() != null && ie.Arguments.Count == 1) + { return childNode.DoMatch(ie.Arguments.Single(), match); } return false; } - + public override string ToString() { return "ldtoken(...)"; } } - + /// /// typeof-Pattern that applies on the expanded form of typeof (prior to ReplaceMethodCallsWithOperators) /// sealed class TypeOfPattern : Pattern { INode childNode; - + public TypeOfPattern(string groupName) { childNode = new MemberReferenceExpression( @@ -99,12 +104,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms new TypeOfExpression(new AnyNode(groupName)) ), "TypeHandle"); } - + public override bool DoMatch(INode other, Match match) { return childNode.DoMatch(other, match); } - + public override string ToString() { return "typeof(...)"; diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DecimalConstantTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DecimalConstantTransform.cs index 4642290a0..ea9d78ff9 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DecimalConstantTransform.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DecimalConstantTransform.cs @@ -28,15 +28,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public class DecimalConstantTransform : DepthFirstAstVisitor, IAstTransform { static readonly PrimitiveType decimalType = new PrimitiveType("decimal"); - + public override void VisitFieldDeclaration(FieldDeclaration fieldDeclaration) { const Modifiers staticReadOnly = Modifiers.Static | Modifiers.Readonly; - if ((fieldDeclaration.Modifiers & staticReadOnly) == staticReadOnly && decimalType.IsMatch(fieldDeclaration.ReturnType)) { - foreach (var attributeSection in fieldDeclaration.Attributes) { - foreach (var attribute in attributeSection.Attributes) { + if ((fieldDeclaration.Modifiers & staticReadOnly) == staticReadOnly && decimalType.IsMatch(fieldDeclaration.ReturnType)) + { + foreach (var attributeSection in fieldDeclaration.Attributes) + { + foreach (var attribute in attributeSection.Attributes) + { var t = attribute.Type.GetSymbol() as IType; - if (t != null && t.Name == "DecimalConstantAttribute" && t.Namespace == "System.Runtime.CompilerServices") { + if (t != null && t.Name == "DecimalConstantAttribute" && t.Namespace == "System.Runtime.CompilerServices") + { attribute.Remove(); if (attributeSection.Attributes.Count == 0) attributeSection.Remove(); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index b7f1932c9..ebd436c06 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.Transforms; @@ -47,7 +48,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms /// internal int level; internal AstNode nextNode; - + /// Go up one level internal InsertionPoint Up() { @@ -56,18 +57,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms nextNode = nextNode.Parent }; } - + internal InsertionPoint UpTo(int targetLevel) { InsertionPoint result = this; - while (result.level > targetLevel) { + while (result.level > targetLevel) + { result.nextNode = result.nextNode.Parent; result.level -= 1; } return result; } } - + [DebuggerDisplay("VariableToDeclare(Name={Name})")] class VariableToDeclare { @@ -79,7 +81,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms /// Whether the variable needs to be default-initialized. /// public bool DefaultInitialization; - + /// /// Integer value that can be used to compare to VariableToDeclare instances /// to determine which variable was used first in the source code. @@ -88,7 +90,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms /// that comes first in the source code. /// public int SourceOrder; - + /// /// The insertion point, i.e. the node before which the variable declaration should be inserted. /// @@ -113,13 +115,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms this.SourceOrder = sourceOrder; } } - + readonly Dictionary variableDict = new Dictionary(); TransformContext context; public void Run(AstNode rootNode, TransformContext context) { - try { + try + { if (this.context != null) throw new InvalidOperationException("Reentrancy in DeclareVariables?"); this.context = context; @@ -130,7 +133,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms InsertDeconstructionVariableDeclarations(); InsertVariableDeclarations(context); UpdateAnnotations(rootNode); - } finally { + } + finally + { this.context = null; variableDict.Clear(); } @@ -153,7 +158,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public AstNode GetDeclarationPoint(ILVariable variable) { VariableToDeclare v = variableDict[variable]; - while (v.ReplacementDueToCollision != null) { + while (v.ReplacementDueToCollision != null) + { v = v.ReplacementDueToCollision; } return v.InsertionPoint.nextNode; @@ -176,16 +182,21 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms #region EnsureExpressionStatementsAreValid void EnsureExpressionStatementsAreValid(AstNode rootNode) { - foreach (var stmt in rootNode.DescendantsAndSelf.OfType()) { - if (!IsValidInStatementExpression(stmt.Expression)) { + foreach (var stmt in rootNode.DescendantsAndSelf.OfType()) + { + if (!IsValidInStatementExpression(stmt.Expression)) + { // fetch ILFunction var function = stmt.Ancestors.SelectMany(a => a.Annotations.OfType()).First(f => f.Parent == null); // if possible use C# 7.0 discard-assignment - if (context.Settings.Discards && !ExpressionBuilder.HidesVariableWithName(function, "_")) { + if (context.Settings.Discards && !ExpressionBuilder.HidesVariableWithName(function, "_")) + { stmt.Expression = new AssignmentExpression( new IdentifierExpression("_"), // no ResolveResult stmt.Expression.Detach()); - } else { + } + else + { // assign result to dummy variable var type = stmt.Expression.GetResolveResult().Type; var v = function.RegisterVariable( @@ -203,14 +214,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms private static bool IsValidInStatementExpression(Expression expr) { - switch (expr) { + switch (expr) + { case InvocationExpression _: case ObjectCreateExpression _: case AssignmentExpression _: case ErrorExpression _: return true; case UnaryOperatorExpression uoe: - switch (uoe.Operator) { + switch (uoe.Operator) + { case UnaryOperatorType.PostIncrement: case UnaryOperatorType.PostDecrement: case UnaryOperatorType.Increment: @@ -244,22 +257,32 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void FindInsertionPoints(AstNode node, int nodeLevel) { BlockContainer scope = node.Annotation(); - if (scope != null && (scope.EntryPoint.IncomingEdgeCount > 1 || scope.Parent is ILFunction)) { + if (scope != null && (scope.EntryPoint.IncomingEdgeCount > 1 || scope.Parent is ILFunction)) + { // track loops and function bodies as scopes, for comparison with CaptureScope. scopeTracking.Add((new InsertionPoint { level = nodeLevel, nextNode = node }, scope)); - } else { + } + else + { scope = null; // don't remove a scope if we didn't add one } - try { - for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + try + { + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) + { FindInsertionPoints(child, nodeLevel + 1); } - if (node is IdentifierExpression identExpr) { + if (node is IdentifierExpression identExpr) + { var rr = identExpr.GetResolveResult() as ILVariableResolveResult; - if (rr != null && VariableNeedsDeclaration(rr.Variable.Kind)) { + if (rr != null && VariableNeedsDeclaration(rr.Variable.Kind)) + { FindInsertionPointForVariable(rr.Variable); - } else if (identExpr.Annotation() is ILFunction localFunction && localFunction.Kind == ILFunctionKind.LocalFunction) { - foreach (var v in localFunction.CapturedVariables) { + } + else if (identExpr.Annotation() is ILFunction localFunction && localFunction.Kind == ILFunctionKind.LocalFunction) + { + foreach (var v in localFunction.CapturedVariables) + { if (VariableNeedsDeclaration(v.Kind)) FindInsertionPointForVariable(v); } @@ -269,21 +292,29 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { InsertionPoint newPoint; int startIndex = scopeTracking.Count - 1; - if (variable.CaptureScope != null && startIndex > 0 && variable.CaptureScope != scopeTracking[startIndex].Scope) { + if (variable.CaptureScope != null && startIndex > 0 && variable.CaptureScope != scopeTracking[startIndex].Scope) + { while (startIndex > 0 && scopeTracking[startIndex].Scope != variable.CaptureScope) startIndex--; newPoint = scopeTracking[startIndex + 1].InsertionPoint; - } else { + } + else + { newPoint = new InsertionPoint { level = nodeLevel, nextNode = identExpr }; - if (variable.HasInitialValue) { + if (variable.HasInitialValue) + { // Uninitialized variables are logically initialized at the beginning of the function // Because it's possible that the variable has a loop-carried dependency, // declare it outside of any loops. - while (startIndex >= 0) { - if (scopeTracking[startIndex].Scope.EntryPoint.IncomingEdgeCount > 1) { + while (startIndex >= 0) + { + if (scopeTracking[startIndex].Scope.EntryPoint.IncomingEdgeCount > 1) + { // declare variable outside of loop newPoint = scopeTracking[startIndex].InsertionPoint; - } else if (scopeTracking[startIndex].Scope.Parent is ILFunction) { + } + else if (scopeTracking[startIndex].Scope.Parent is ILFunction) + { // stop at beginning of function break; } @@ -291,16 +322,21 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } } - if (variableDict.TryGetValue(variable, out VariableToDeclare v)) { + if (variableDict.TryGetValue(variable, out VariableToDeclare v)) + { v.InsertionPoint = FindCommonParent(v.InsertionPoint, newPoint); - } else { + } + else + { v = new VariableToDeclare(variable, variable.HasInitialValue, newPoint, identExpr, sourceOrder: variableDict.Count); variableDict.Add(variable, v); } } } - } finally { + } + finally + { if (scope != null) scopeTracking.RemoveAt(scopeTracking.Count - 1); } @@ -308,7 +344,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms internal static bool VariableNeedsDeclaration(VariableKind kind) { - switch (kind) { + switch (kind) + { case VariableKind.PinnedRegionLocal: case VariableKind.Parameter: case VariableKind.ExceptionLocal: @@ -320,7 +357,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return true; } } - + /// /// Finds an insertion point in a common parent instruction. /// @@ -331,7 +368,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms newPoint = newPoint.UpTo(oldPoint.level); Debug.Assert(newPoint.level == oldPoint.level); // Then go up the tree until both points share the same parent: - while (oldPoint.nextNode.Parent != newPoint.nextNode.Parent) { + while (oldPoint.nextNode.Parent != newPoint.nextNode.Parent) + { oldPoint = oldPoint.Up(); newPoint = newPoint.Up(); } @@ -339,7 +377,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return oldPoint; } #endregion - + /// /// Some variable declarations in C# are illegal (colliding), /// even though the variable live ranges are not overlapping. @@ -373,12 +411,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void ResolveCollisions() { var multiDict = new MultiDictionary(); - foreach (var v in variableDict.Values) { + foreach (var v in variableDict.Values) + { // We can only insert variable declarations in blocks, but FindInsertionPoints() didn't // guarantee that it finds only blocks. // Fix that up now. - while (!(v.InsertionPoint.nextNode.Parent is BlockStatement)) { - if (v.InsertionPoint.nextNode.Parent is ForStatement f && v.InsertionPoint.nextNode == f.Initializers.FirstOrDefault() && IsMatchingAssignment(v, out _)) { + while (!(v.InsertionPoint.nextNode.Parent is BlockStatement)) + { + if (v.InsertionPoint.nextNode.Parent is ForStatement f && v.InsertionPoint.nextNode == f.Initializers.FirstOrDefault() && IsMatchingAssignment(v, out _)) + { // Special case: the initializer of a ForStatement can also declare a variable (with scope local to the for loop). break; } @@ -390,26 +431,31 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms // later we might decide to declare the variable more locally (as 'out var') instead if still possible. // Go through all potentially colliding variables: - foreach (var prev in multiDict[v.Name]) { + foreach (var prev in multiDict[v.Name]) + { if (prev.RemovedDueToCollision) continue; // Go up until both nodes are on the same level: InsertionPoint point1 = prev.InsertionPoint.UpTo(v.InsertionPoint.level); InsertionPoint point2 = v.InsertionPoint.UpTo(prev.InsertionPoint.level); Debug.Assert(point1.level == point2.level); - if (point1.nextNode.Parent == point2.nextNode.Parent) { + if (point1.nextNode.Parent == point2.nextNode.Parent) + { // We found a collision! v.InvolvedInCollision = true; prev.ReplacementDueToCollision = v; // Continue checking other entries in multiDict against the new position of `v`. - if (prev.SourceOrder < v.SourceOrder) { + if (prev.SourceOrder < v.SourceOrder) + { // Switch v's insertion point to prev's insertion point: v.InsertionPoint = point1; // Since prev was first, it has the correct SourceOrder/FirstUse values // for the new combined variable: v.SourceOrder = prev.SourceOrder; v.FirstUse = prev.FirstUse; - } else { + } + else + { // v is first in source order, so it keeps its old insertion point // (and other properties), except that the insertion point is // moved up to prev's level. @@ -421,7 +467,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms // the old v.InsertionPoint or the old prev.InsertionPoint already collided with x. } } - + multiDict.Add(v.Name, v); } } @@ -429,7 +475,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms private void InsertDeconstructionVariableDeclarations() { var usedVariables = new HashSet(); - foreach (var g in variableDict.Values.GroupBy(v => v.InsertionPoint.nextNode)) { + foreach (var g in variableDict.Values.GroupBy(v => v.InsertionPoint.nextNode)) + { if (!(g.Key is ExpressionStatement { Expression: AssignmentExpression { Left: TupleExpression left, Operator: AssignmentOperatorType.Assign } assignment })) continue; usedVariables.Clear(); @@ -442,7 +489,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var designation = StatementBuilder.TranslateDeconstructionDesignation(deconstruct, isForeach: false); left.ReplaceWith(new DeclarationExpression { Type = new SimpleType("var"), Designation = designation }); - foreach (var v in usedVariables) { + foreach (var v in usedVariables) + { variableDict[v].DeclaredInDeconstruction = true; } @@ -467,7 +515,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms bool IsMatchingAssignment(VariableToDeclare v, out AssignmentExpression assignment) { assignment = v.InsertionPoint.nextNode as AssignmentExpression; - if (assignment == null) { + if (assignment == null) + { assignment = (v.InsertionPoint.nextNode as ExpressionStatement)?.Expression as AssignmentExpression; if (assignment == null) return false; @@ -492,50 +541,67 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void InsertVariableDeclarations(TransformContext context) { var replacements = new List<(AstNode, AstNode)>(); - foreach (var (ilVariable, v) in variableDict) { + foreach (var (ilVariable, v) in variableDict) + { if (v.RemovedDueToCollision || v.DeclaredInDeconstruction) continue; - if (CombineDeclarationAndInitializer(v, context) && IsMatchingAssignment(v, out AssignmentExpression assignment)) { + if (CombineDeclarationAndInitializer(v, context) && IsMatchingAssignment(v, out AssignmentExpression assignment)) + { // 'int v; v = expr;' can be combined to 'int v = expr;' AstType type; - if (context.Settings.AnonymousTypes && v.Type.ContainsAnonymousType()) { + if (context.Settings.AnonymousTypes && v.Type.ContainsAnonymousType()) + { type = new SimpleType("var"); - } else { + } + else + { type = context.TypeSystemAstBuilder.ConvertType(v.Type); } - if (v.ILVariable.IsRefReadOnly && type is ComposedType composedType && composedType.HasRefSpecifier) { + if (v.ILVariable.IsRefReadOnly && type is ComposedType composedType && composedType.HasRefSpecifier) + { composedType.HasReadOnlySpecifier = true; } - if (v.ILVariable.Kind == VariableKind.PinnedLocal) { + if (v.ILVariable.Kind == VariableKind.PinnedLocal) + { type.InsertChildAfter(null, new Comment("pinned", CommentType.MultiLine), Roles.Comment); } var vds = new VariableDeclarationStatement(type, v.Name, assignment.Right.Detach()); var init = vds.Variables.Single(); init.AddAnnotation(assignment.Left.GetResolveResult()); - foreach (object annotation in assignment.Left.Annotations.Concat(assignment.Annotations)) { - if (!(annotation is ResolveResult)) { + foreach (object annotation in assignment.Left.Annotations.Concat(assignment.Annotations)) + { + if (!(annotation is ResolveResult)) + { init.AddAnnotation(annotation); } } replacements.Add((v.InsertionPoint.nextNode, vds)); - } else if (CanBeDeclaredAsOutVariable(v, out var dirExpr)) { + } + else if (CanBeDeclaredAsOutVariable(v, out var dirExpr)) + { // 'T v; SomeCall(out v);' can be combined to 'SomeCall(out var v);' AstType type; - if (context.Settings.AnonymousTypes && v.Type.ContainsAnonymousType()) { + if (context.Settings.AnonymousTypes && v.Type.ContainsAnonymousType()) + { type = new SimpleType("var"); - } else { + } + else + { type = context.TypeSystemAstBuilder.ConvertType(v.Type); } var ovd = new OutVarDeclarationExpression(type, v.Name); ovd.Variable.AddAnnotation(new ILVariableResolveResult(ilVariable)); ovd.CopyAnnotationsFrom(dirExpr); replacements.Add((dirExpr, ovd)); - } else { + } + else + { // Insert a separate declaration statement. Expression initializer = null; AstType type = context.TypeSystemAstBuilder.ConvertType(v.Type); - if (v.DefaultInitialization) { + if (v.DefaultInitialization) + { initializer = new DefaultValueExpression(type.Clone()); } var vds = new VariableDeclarationStatement(type, v.Name, initializer); @@ -548,7 +614,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } // perform replacements at end, so that we don't replace a node while it is still referenced by a VariableToDeclare - foreach (var (oldNode, newNode) in replacements) { + foreach (var (oldNode, newNode) in replacements) + { oldNode.ReplaceWith(newNode); } } @@ -562,11 +629,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return false; if (v.DefaultInitialization) return false; - for (AstNode node = v.FirstUse; node != null; node = node.Parent) { - if (node.Role == Roles.EmbeddedStatement) { + for (AstNode node = v.FirstUse; node != null; node = node.Parent) + { + if (node.Role == Roles.EmbeddedStatement) + { return false; } - switch (node) { + switch (node) + { case IfElseStatement _: // variable declared in if condition appears in parent scope case ExpressionStatement _: return node == v.InsertionPoint.nextNode; @@ -582,9 +652,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms /// void UpdateAnnotations(AstNode rootNode) { - foreach (var node in rootNode.Descendants) { + foreach (var node in rootNode.Descendants) + { ILVariable ilVar; - switch (node) { + switch (node) + { case IdentifierExpression id: ilVar = id.GetILVariable(); break; @@ -594,10 +666,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms default: continue; } - if (ilVar == null || !VariableNeedsDeclaration(ilVar.Kind)) continue; + if (ilVar == null || !VariableNeedsDeclaration(ilVar.Kind)) + continue; var v = variableDict[ilVar]; - if (!v.RemovedDueToCollision) continue; - while (v.RemovedDueToCollision) { + if (!v.RemovedDueToCollision) + continue; + while (v.RemovedDueToCollision) + { v = v.ReplacementDueToCollision; } node.RemoveAnnotations(); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs b/ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs index 91eaa7e7b..06dd0911b 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.Semantics; @@ -38,7 +39,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return true; return false; } - + string ReplaceInvalid(string s) { string name = string.Concat(s.Select(ch => IsValid(ch) ? ch.ToString() : string.Format("_{0:X4}", (int)ch))); @@ -46,15 +47,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms name = "_" + name; return name; } - + public void Run(AstNode rootNode, TransformContext context) { - foreach (var ident in rootNode.DescendantsAndSelf.OfType()) { + foreach (var ident in rootNode.DescendantsAndSelf.OfType()) + { ident.Name = ReplaceInvalid(ident.Name); } } } - + /// /// This transform is used to remove assembly-attributes that are generated by the compiler, /// thus don't need to be declared. (We have to remove them, in order to avoid conflicts while compiling.) @@ -64,10 +66,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { public void Run(AstNode rootNode, TransformContext context) { - foreach (var section in rootNode.Children.OfType()) { + foreach (var section in rootNode.Children.OfType()) + { if (section.AttributeTarget != "assembly") continue; - foreach (var attribute in section.Attributes) { + foreach (var attribute in section.Attributes) + { var trr = attribute.Type.Annotation(); if (trr != null && trr.Type.FullName == "System.Runtime.Versioning.TargetFrameworkAttribute") attribute.Remove(); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs b/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs index 145da07af..4048df940 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -36,32 +37,39 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public void Run(AstNode rootNode, TransformContext context) { var renamedSymbols = new Dictionary(); - foreach (var typeDecl in rootNode.DescendantsAndSelf.OfType()) { + foreach (var typeDecl in rootNode.DescendantsAndSelf.OfType()) + { var memberNames = typeDecl.Members.Select(m => { - var type = m.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole); - return type.IsNull ? m.Name : type + "." + m.Name; - }).ToHashSet(); + var type = m.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole); + return type.IsNull ? m.Name : type + "." + m.Name; + }).ToHashSet(); // memberNames does not include fields or non-custom events because those // don't have a single name, but a list of VariableInitializers. - foreach (var fieldDecl in typeDecl.Members.OfType()) { + foreach (var fieldDecl in typeDecl.Members.OfType()) + { if (fieldDecl.Variables.Count != 1) continue; string oldName = fieldDecl.Variables.Single().Name; ISymbol symbol = fieldDecl.GetSymbol(); - if (memberNames.Contains(oldName) && ((IField)symbol).Accessibility == Accessibility.Private) { + if (memberNames.Contains(oldName) && ((IField)symbol).Accessibility == Accessibility.Private) + { string newName = PickNewName(memberNames, oldName); - if (symbol != null) { + if (symbol != null) + { fieldDecl.Variables.Single().Name = newName; renamedSymbols[symbol] = newName; } } } } - - foreach (var node in rootNode.DescendantsAndSelf) { - if (node is IdentifierExpression || node is MemberReferenceExpression) { + + foreach (var node in rootNode.DescendantsAndSelf) + { + if (node is IdentifierExpression || node is MemberReferenceExpression) + { ISymbol symbol = node.GetSymbol(); - if (symbol != null && renamedSymbols.TryGetValue(symbol, out string newName)) { + if (symbol != null && renamedSymbols.TryGetValue(symbol, out string newName)) + { node.GetChildByRole(Roles.Identifier).Name = newName; } } @@ -72,7 +80,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { if (!memberNames.Contains("m_" + name)) return "m_" + name; - for (int num = 2;; num++) { + for (int num = 2; ; num++) + { string newName = name + num; if (!memberNames.Contains(newName)) return newName; diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/FlattenSwitchBlocks.cs b/ICSharpCode.Decompiler/CSharp/Transforms/FlattenSwitchBlocks.cs index 5e9908aaf..4ccdf7296 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/FlattenSwitchBlocks.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/FlattenSwitchBlocks.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.CSharp.Syntax; namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -29,7 +30,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return true; if (node is BlockStatement) return false; - foreach (var child in node.Children) { + foreach (var child in node.Children) + { if (ContainsLocalDeclaration(child)) return true; } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs index 0e23d86cc..832b131a1 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.TypeSystem; @@ -51,8 +52,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void InitializeContext(UsingScope usingScope) { this.resolveContextStack = new Stack(); - if (!string.IsNullOrEmpty(context.CurrentTypeDefinition?.Namespace)) { - foreach (string ns in context.CurrentTypeDefinition.Namespace.Split('.')) { + if (!string.IsNullOrEmpty(context.CurrentTypeDefinition?.Namespace)) + { + foreach (string ns in context.CurrentTypeDefinition.Namespace.Split('.')) + { usingScope = new UsingScope(usingScope, ns); } } @@ -65,15 +68,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { var previousContext = resolveContextStack.Peek(); var usingScope = previousContext.CurrentUsingScope.UnresolvedUsingScope; - foreach (string ident in namespaceDeclaration.Identifiers) { + foreach (string ident in namespaceDeclaration.Identifiers) + { usingScope = new UsingScope(usingScope, ident); } var currentContext = new CSharpTypeResolveContext(previousContext.CurrentModule, usingScope.Resolve(previousContext.Compilation)); resolveContextStack.Push(currentContext); - try { + try + { this.resolver = new CSharpResolver(currentContext); base.VisitNamespaceDeclaration(namespaceDeclaration); - } finally { + } + finally + { this.resolver = new CSharpResolver(previousContext); resolveContextStack.Pop(); } @@ -84,10 +91,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var previousContext = resolveContextStack.Peek(); var currentContext = previousContext.WithCurrentTypeDefinition(typeDeclaration.GetSymbol() as ITypeDefinition); resolveContextStack.Push(currentContext); - try { + try + { this.resolver = new CSharpResolver(currentContext); base.VisitTypeDeclaration(typeDeclaration); - } finally { + } + finally + { this.resolver = new CSharpResolver(previousContext); resolveContextStack.Pop(); } @@ -101,7 +111,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return; IReadOnlyList typeArguments; MemberReferenceExpression memberRefExpr; - switch (invocationExpression.Target) { + switch (invocationExpression.Target) + { case MemberReferenceExpression mre: typeArguments = mre.TypeArguments.Any() ? method.TypeArguments : EmptyList.Instance; memberRefExpr = mre; @@ -110,51 +121,65 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms typeArguments = ide.TypeArguments.Any() ? method.TypeArguments : EmptyList.Instance; memberRefExpr = null; break; - default: return; + default: + return; } - + var firstArgument = invocationExpression.Arguments.First(); if (firstArgument is NamedArgumentExpression) return; var target = firstArgument.GetResolveResult(); - if (target is ConstantResolveResult crr && crr.ConstantValue == null) { + if (target is ConstantResolveResult crr && crr.ConstantValue == null) + { target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion); } ResolveResult[] args = new ResolveResult[invocationExpression.Arguments.Count - 1]; string[] argNames = null; int pos = 0; - foreach (var arg in invocationExpression.Arguments.Skip(1)) { - if (arg is NamedArgumentExpression nae) { - if (argNames == null) { + foreach (var arg in invocationExpression.Arguments.Skip(1)) + { + if (arg is NamedArgumentExpression nae) + { + if (argNames == null) + { argNames = new string[args.Length]; } argNames[pos] = nae.Name; args[pos] = nae.Expression.GetResolveResult(); - } else { + } + else + { args[pos] = arg.GetResolveResult(); } pos++; } if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames)) return; - if (firstArgument is DirectionExpression dirExpr) { + if (firstArgument is DirectionExpression dirExpr) + { if (!context.Settings.RefExtensionMethods || dirExpr.FieldDirection == FieldDirection.Out) return; firstArgument = dirExpr.Expression; target = firstArgument.GetResolveResult(); dirExpr.Detach(); - } else if (firstArgument is NullReferenceExpression) { + } + else if (firstArgument is NullReferenceExpression) + { Debug.Assert(context.RequiredNamespacesSuperset.Contains(method.Parameters[0].Type.Namespace)); firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach())); } - if (invocationExpression.Target is IdentifierExpression identifierExpression) { + if (invocationExpression.Target is IdentifierExpression identifierExpression) + { identifierExpression.Detach(); memberRefExpr = new MemberReferenceExpression(firstArgument.Detach(), method.Name, identifierExpression.TypeArguments.Detach()); invocationExpression.Target = memberRefExpr; - } else { + } + else + { memberRefExpr.Target = firstArgument.Detach(); } - if (invocationExpression.GetResolveResult() is CSharpInvocationResolveResult irr) { + if (invocationExpression.GetResolveResult() is CSharpInvocationResolveResult irr) + { // do not forget to update the CSharpInvocationResolveResult => set IsExtensionMethodInvocation == true invocationExpression.RemoveAnnotations(); var newResolveResult = new CSharpInvocationResolveResult( @@ -182,7 +207,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public static bool CanTransformToExtensionMethodCall(IMethod method, CSharpTypeResolveContext resolveContext, bool ignoreTypeArguments = false, bool ignoreArgumentNames = true) { - if (method.Parameters.Count == 0) return false; + if (method.Parameters.Count == 0) + return false; var targetType = method.Parameters.Select(p => new ResolveResult(p.Type)).First(); var paramTypes = method.Parameters.Skip(1).Select(p => new ResolveResult(p.Type)).ToArray(); var paramNames = ignoreArgumentNames ? null : method.Parameters.SelectReadOnlyArray(p => p.Name); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs index d4a4b7555..ba957df7c 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -36,23 +37,27 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms DecompileQueries(rootNode); // After all queries were decompiled, detect degenerate queries (queries not property terminated with 'select' or 'group') // and fix them, either by adding a degenerate select, or by combining them with another query. - foreach (QueryExpression query in rootNode.Descendants.OfType()) { + foreach (QueryExpression query in rootNode.Descendants.OfType()) + { QueryFromClause fromClause = (QueryFromClause)query.Clauses.First(); - if (IsDegenerateQuery(query)) { + if (IsDegenerateQuery(query)) + { // introduce select for degenerate query query.Clauses.Add(new QuerySelectClause { Expression = new IdentifierExpression(fromClause.Identifier).CopyAnnotationsFrom(fromClause) }); } // See if the data source of this query is a degenerate query, // and combine the queries if possible. QueryExpression innerQuery = fromClause.Expression as QueryExpression; - while (IsDegenerateQuery(innerQuery)) { + while (IsDegenerateQuery(innerQuery)) + { QueryFromClause innerFromClause = (QueryFromClause)innerQuery.Clauses.First(); if (fromClause.Identifier != innerFromClause.Identifier) break; // Replace the fromClause with all clauses from the inner query fromClause.Remove(); QueryClause insertionPos = null; - foreach (var clause in innerQuery.Clauses) { + foreach (var clause in innerQuery.Clauses) + { query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach()); } fromClause = innerFromClause; @@ -60,7 +65,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } } - + bool IsDegenerateQuery(QueryExpression query) { if (query == null) @@ -68,20 +73,21 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var lastClause = query.Clauses.LastOrDefault(); return !(lastClause is QuerySelectClause || lastClause is QueryGroupClause); } - + void DecompileQueries(AstNode node) { QueryExpression query = DecompileQuery(node as InvocationExpression); if (query != null) node.ReplaceWith(query); AstNode next; - for (AstNode child = (query ?? node).FirstChild; child != null; child = next) { + for (AstNode child = (query ?? node).FirstChild; child != null; child = next) + { // store reference to next child before transformation next = child.NextSibling; DecompileQueries(child); } } - + QueryExpression DecompileQuery(InvocationExpression invocation) { if (invocation == null) @@ -89,167 +95,184 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression; if (mre == null || IsNullConditional(mre.Target)) return null; - switch (mre.MemberName) { - case "Select": { - if (invocation.Arguments.Count != 1) - return null; - if (!IsComplexQuery(mre)) - return null; - Expression expr = invocation.Arguments.Single(); - if (MatchSimpleLambda(expr, out ParameterDeclaration parameter, out Expression body)) { - QueryExpression query = new QueryExpression(); - query.Clauses.Add(MakeFromClause(parameter, mre.Target.Detach())); - query.Clauses.Add(new QuerySelectClause { Expression = WrapExpressionInParenthesesIfNecessary(body.Detach(), parameter.Name) }.CopyAnnotationsFrom(expr)); - return query; - } + switch (mre.MemberName) + { + case "Select": + { + if (invocation.Arguments.Count != 1) + return null; + if (!IsComplexQuery(mre)) return null; + Expression expr = invocation.Arguments.Single(); + if (MatchSimpleLambda(expr, out ParameterDeclaration parameter, out Expression body)) + { + QueryExpression query = new QueryExpression(); + query.Clauses.Add(MakeFromClause(parameter, mre.Target.Detach())); + query.Clauses.Add(new QuerySelectClause { Expression = WrapExpressionInParenthesesIfNecessary(body.Detach(), parameter.Name) }.CopyAnnotationsFrom(expr)); + return query; } + return null; + } case "GroupBy": + { + if (invocation.Arguments.Count == 2) { - if (invocation.Arguments.Count == 2) { - Expression keyLambda = invocation.Arguments.ElementAt(0); - Expression projectionLambda = invocation.Arguments.ElementAt(1); - if (MatchSimpleLambda(keyLambda, out ParameterDeclaration parameter1, out Expression keySelector) - && MatchSimpleLambda(projectionLambda, out ParameterDeclaration parameter2, out Expression elementSelector) - && parameter1.Name == parameter2.Name) { - QueryExpression query = new QueryExpression(); - query.Clauses.Add(MakeFromClause(parameter1, mre.Target.Detach())); - var queryGroupClause = new QueryGroupClause { - Projection = elementSelector.Detach(), - Key = keySelector.Detach() - }; - queryGroupClause.AddAnnotation(new QueryGroupClauseAnnotation(keyLambda.Annotation(), projectionLambda.Annotation())); - query.Clauses.Add(queryGroupClause); - return query; - } - } else if (invocation.Arguments.Count == 1) { - Expression lambda = invocation.Arguments.Single(); - if (MatchSimpleLambda(lambda, out ParameterDeclaration parameter, out Expression keySelector)) { - QueryExpression query = new QueryExpression(); - query.Clauses.Add(MakeFromClause(parameter, mre.Target.Detach())); - query.Clauses.Add(new QueryGroupClause { Projection = new IdentifierExpression(parameter.Name).CopyAnnotationsFrom(parameter), Key = keySelector.Detach() }); - return query; - } + Expression keyLambda = invocation.Arguments.ElementAt(0); + Expression projectionLambda = invocation.Arguments.ElementAt(1); + if (MatchSimpleLambda(keyLambda, out ParameterDeclaration parameter1, out Expression keySelector) + && MatchSimpleLambda(projectionLambda, out ParameterDeclaration parameter2, out Expression elementSelector) + && parameter1.Name == parameter2.Name) + { + QueryExpression query = new QueryExpression(); + query.Clauses.Add(MakeFromClause(parameter1, mre.Target.Detach())); + var queryGroupClause = new QueryGroupClause { + Projection = elementSelector.Detach(), + Key = keySelector.Detach() + }; + queryGroupClause.AddAnnotation(new QueryGroupClauseAnnotation(keyLambda.Annotation(), projectionLambda.Annotation())); + query.Clauses.Add(queryGroupClause); + return query; } - return null; } - case "SelectMany": + else if (invocation.Arguments.Count == 1) { - if (invocation.Arguments.Count != 2) - return null; - var fromExpressionLambda = invocation.Arguments.ElementAt(0); - if (!MatchSimpleLambda(fromExpressionLambda, out ParameterDeclaration parameter, out Expression collectionSelector)) - return null; - if (IsNullConditional(collectionSelector)) - return null; - LambdaExpression lambda = invocation.Arguments.ElementAt(1) as LambdaExpression; - if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression) { - ParameterDeclaration p1 = lambda.Parameters.ElementAt(0); - ParameterDeclaration p2 = lambda.Parameters.ElementAt(1); - if (p1.Name == parameter.Name) { - QueryExpression query = new QueryExpression(); - query.Clauses.Add(MakeFromClause(p1, mre.Target.Detach())); - query.Clauses.Add(MakeFromClause(p2, collectionSelector.Detach()).CopyAnnotationsFrom(fromExpressionLambda)); - query.Clauses.Add(new QuerySelectClause { Expression = WrapExpressionInParenthesesIfNecessary(((Expression)lambda.Body).Detach(), parameter.Name) }); - return query; - } + Expression lambda = invocation.Arguments.Single(); + if (MatchSimpleLambda(lambda, out ParameterDeclaration parameter, out Expression keySelector)) + { + QueryExpression query = new QueryExpression(); + query.Clauses.Add(MakeFromClause(parameter, mre.Target.Detach())); + query.Clauses.Add(new QueryGroupClause { Projection = new IdentifierExpression(parameter.Name).CopyAnnotationsFrom(parameter), Key = keySelector.Detach() }); + return query; } - return null; } - case "Where": + return null; + } + case "SelectMany": + { + if (invocation.Arguments.Count != 2) + return null; + var fromExpressionLambda = invocation.Arguments.ElementAt(0); + if (!MatchSimpleLambda(fromExpressionLambda, out ParameterDeclaration parameter, out Expression collectionSelector)) + return null; + if (IsNullConditional(collectionSelector)) + return null; + LambdaExpression lambda = invocation.Arguments.ElementAt(1) as LambdaExpression; + if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression) { - if (invocation.Arguments.Count != 1) - return null; - if (!IsComplexQuery(mre)) - return null; - Expression expr = invocation.Arguments.Single(); - if (MatchSimpleLambda(expr, out ParameterDeclaration parameter, out Expression body)) { + ParameterDeclaration p1 = lambda.Parameters.ElementAt(0); + ParameterDeclaration p2 = lambda.Parameters.ElementAt(1); + if (p1.Name == parameter.Name) + { QueryExpression query = new QueryExpression(); - query.Clauses.Add(MakeFromClause(parameter, mre.Target.Detach())); - query.Clauses.Add(new QueryWhereClause { Condition = body.Detach() }.CopyAnnotationsFrom(expr)); + query.Clauses.Add(MakeFromClause(p1, mre.Target.Detach())); + query.Clauses.Add(MakeFromClause(p2, collectionSelector.Detach()).CopyAnnotationsFrom(fromExpressionLambda)); + query.Clauses.Add(new QuerySelectClause { Expression = WrapExpressionInParenthesesIfNecessary(((Expression)lambda.Body).Detach(), parameter.Name) }); return query; } + } + return null; + } + case "Where": + { + if (invocation.Arguments.Count != 1) return null; + if (!IsComplexQuery(mre)) + return null; + Expression expr = invocation.Arguments.Single(); + if (MatchSimpleLambda(expr, out ParameterDeclaration parameter, out Expression body)) + { + QueryExpression query = new QueryExpression(); + query.Clauses.Add(MakeFromClause(parameter, mre.Target.Detach())); + query.Clauses.Add(new QueryWhereClause { Condition = body.Detach() }.CopyAnnotationsFrom(expr)); + return query; } + return null; + } case "OrderBy": case "OrderByDescending": case "ThenBy": case "ThenByDescending": + { + if (invocation.Arguments.Count != 1) + return null; + if (!IsComplexQuery(mre)) + return null; + var lambda = invocation.Arguments.Single(); + if (MatchSimpleLambda(lambda, out ParameterDeclaration parameter, out Expression orderExpression)) { - if (invocation.Arguments.Count != 1) - return null; - if (!IsComplexQuery(mre)) - return null; - var lambda = invocation.Arguments.Single(); - if (MatchSimpleLambda(lambda, out ParameterDeclaration parameter, out Expression orderExpression)) { - if (ValidateThenByChain(invocation, parameter.Name)) { - QueryOrderClause orderClause = new QueryOrderClause(); - while (mre.MemberName == "ThenBy" || mre.MemberName == "ThenByDescending") { - // insert new ordering at beginning - orderClause.Orderings.InsertAfter( - null, new QueryOrdering { - Expression = orderExpression.Detach(), - Direction = (mre.MemberName == "ThenBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending) - }.CopyAnnotationsFrom(lambda)); - - InvocationExpression tmp = (InvocationExpression)mre.Target; - mre = (MemberReferenceExpression)tmp.Target; - lambda = tmp.Arguments.Single(); - MatchSimpleLambda(lambda, out parameter, out orderExpression); - } + if (ValidateThenByChain(invocation, parameter.Name)) + { + QueryOrderClause orderClause = new QueryOrderClause(); + while (mre.MemberName == "ThenBy" || mre.MemberName == "ThenByDescending") + { // insert new ordering at beginning orderClause.Orderings.InsertAfter( null, new QueryOrdering { Expression = orderExpression.Detach(), - Direction = (mre.MemberName == "OrderBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending) + Direction = (mre.MemberName == "ThenBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending) }.CopyAnnotationsFrom(lambda)); - QueryExpression query = new QueryExpression(); - query.Clauses.Add(MakeFromClause(parameter, mre.Target.Detach())); - query.Clauses.Add(orderClause); - return query; + InvocationExpression tmp = (InvocationExpression)mre.Target; + mre = (MemberReferenceExpression)tmp.Target; + lambda = tmp.Arguments.Single(); + MatchSimpleLambda(lambda, out parameter, out orderExpression); } + // insert new ordering at beginning + orderClause.Orderings.InsertAfter( + null, new QueryOrdering { + Expression = orderExpression.Detach(), + Direction = (mre.MemberName == "OrderBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending) + }.CopyAnnotationsFrom(lambda)); + + QueryExpression query = new QueryExpression(); + query.Clauses.Add(MakeFromClause(parameter, mre.Target.Detach())); + query.Clauses.Add(orderClause); + return query; } - return null; } + return null; + } case "Join": case "GroupJoin": + { + if (invocation.Arguments.Count != 4) + return null; + Expression source1 = mre.Target; + Expression source2 = invocation.Arguments.ElementAt(0); + if (IsNullConditional(source2)) + return null; + Expression outerLambda = invocation.Arguments.ElementAt(1); + if (!MatchSimpleLambda(outerLambda, out ParameterDeclaration element1, out Expression key1)) + return null; + Expression innerLambda = invocation.Arguments.ElementAt(2); + if (!MatchSimpleLambda(innerLambda, out ParameterDeclaration element2, out Expression key2)) + return null; + LambdaExpression lambda = invocation.Arguments.ElementAt(3) as LambdaExpression; + if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression) { - if (invocation.Arguments.Count != 4) - return null; - Expression source1 = mre.Target; - Expression source2 = invocation.Arguments.ElementAt(0); - if (IsNullConditional(source2)) - return null; - Expression outerLambda = invocation.Arguments.ElementAt(1); - if (!MatchSimpleLambda(outerLambda, out ParameterDeclaration element1, out Expression key1)) - return null; - Expression innerLambda = invocation.Arguments.ElementAt(2); - if (!MatchSimpleLambda(innerLambda, out ParameterDeclaration element2, out Expression key2)) - return null; - LambdaExpression lambda = invocation.Arguments.ElementAt(3) as LambdaExpression; - if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression) { - ParameterDeclaration p1 = lambda.Parameters.ElementAt(0); - ParameterDeclaration p2 = lambda.Parameters.ElementAt(1); - if (p1.Name == element1.Name && (p2.Name == element2.Name || mre.MemberName == "GroupJoin")) { - QueryExpression query = new QueryExpression(); - query.Clauses.Add(MakeFromClause(element1, source1.Detach())); - QueryJoinClause joinClause = new QueryJoinClause(); - joinClause.JoinIdentifier = element2.Name; // join elementName2 - joinClause.InExpression = source2.Detach(); // in source2 - joinClause.OnExpression = key1.Detach(); // on key1 - joinClause.EqualsExpression = key2.Detach(); // equals key2 - if (mre.MemberName == "GroupJoin") { - joinClause.IntoIdentifier = p2.Name; // into p2.Name - } - joinClause.AddAnnotation(new QueryJoinClauseAnnotation(outerLambda.Annotation(), innerLambda.Annotation())); - query.Clauses.Add(joinClause); - query.Clauses.Add(new QuerySelectClause { Expression = ((Expression)lambda.Body).Detach() }.CopyAnnotationsFrom(lambda)); - return query; + ParameterDeclaration p1 = lambda.Parameters.ElementAt(0); + ParameterDeclaration p2 = lambda.Parameters.ElementAt(1); + if (p1.Name == element1.Name && (p2.Name == element2.Name || mre.MemberName == "GroupJoin")) + { + QueryExpression query = new QueryExpression(); + query.Clauses.Add(MakeFromClause(element1, source1.Detach())); + QueryJoinClause joinClause = new QueryJoinClause(); + joinClause.JoinIdentifier = element2.Name; // join elementName2 + joinClause.InExpression = source2.Detach(); // in source2 + joinClause.OnExpression = key1.Detach(); // on key1 + joinClause.EqualsExpression = key2.Detach(); // equals key2 + if (mre.MemberName == "GroupJoin") + { + joinClause.IntoIdentifier = p2.Name; // into p2.Name } + joinClause.AddAnnotation(new QueryJoinClauseAnnotation(outerLambda.Annotation(), innerLambda.Annotation())); + query.Clauses.Add(joinClause); + query.Clauses.Add(new QuerySelectClause { Expression = ((Expression)lambda.Body).Detach() }.CopyAnnotationsFrom(lambda)); + return query; } - return null; } + return null; + } default: return null; } @@ -320,7 +343,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return false; if (parameter.Name != expectedParameterName) return false; - + if (mre.MemberName == "OrderBy" || mre.MemberName == "OrderByDescending") return true; else if (mre.MemberName == "ThenBy" || mre.MemberName == "ThenByDescending") @@ -328,13 +351,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms else return false; } - + /// Matches simple lambdas of the form "a => b" bool MatchSimpleLambda(Expression expr, out ParameterDeclaration parameter, out Expression body) { - if (expr is LambdaExpression lambda && lambda.Parameters.Count == 1 && lambda.Body is Expression) { + if (expr is LambdaExpression lambda && lambda.Parameters.Count == 1 && lambda.Body is Expression) + { ParameterDeclaration p = lambda.Parameters.Single(); - if (p.ParameterModifier == ParameterModifier.None) { + if (p.ParameterModifier == ParameterModifier.None) + { parameter = p; body = (Expression)lambda.Body; return true; diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs index cd97b257b..bd5d69e7c 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; @@ -34,24 +35,26 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { return node.AcceptVisitor(new IntroduceUnsafeModifier()); } - + protected override bool VisitChildren(AstNode node) { bool result = false; AstNode next; - for (AstNode child = node.FirstChild; child != null; child = next) { + for (AstNode child = node.FirstChild; child != null; child = next) + { // Store next to allow the loop to continue // if the visitor removes/replaces child. next = child.NextSibling; result |= child.AcceptVisitor(this); } - if (result && node is EntityDeclaration && !(node is Accessor)) { + if (result && node is EntityDeclaration && !(node is Accessor)) + { ((EntityDeclaration)node).Modifiers |= Modifiers.Unsafe; return false; } return result; } - + public override bool VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression) { base.VisitPointerReferenceExpression(pointerReferenceExpression); @@ -82,9 +85,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public override bool VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression) { bool result = base.VisitUnaryOperatorExpression(unaryOperatorExpression); - if (unaryOperatorExpression.Operator == UnaryOperatorType.Dereference) { + if (unaryOperatorExpression.Operator == UnaryOperatorType.Dereference) + { var bop = unaryOperatorExpression.Expression as BinaryOperatorExpression; - if (bop != null && bop.Operator == BinaryOperatorType.Add + if (bop != null && bop.Operator == BinaryOperatorType.Add && bop.GetResolveResult() is OperatorResolveResult orr && orr.Operands.FirstOrDefault()?.Type.Kind == TypeKind.Pointer) { @@ -97,18 +101,23 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms unaryOperatorExpression.ReplaceWith(indexer); } return true; - } else if (unaryOperatorExpression.Operator == UnaryOperatorType.AddressOf) { + } + else if (unaryOperatorExpression.Operator == UnaryOperatorType.AddressOf) + { return true; - } else { + } + else + { return result; } } - + public override bool VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) { bool result = base.VisitMemberReferenceExpression(memberReferenceExpression); UnaryOperatorExpression uoe = memberReferenceExpression.Target as UnaryOperatorExpression; - if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference) { + if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference) + { PointerReferenceExpression pre = new PointerReferenceExpression(); pre.Target = uoe.Expression.Detach(); pre.MemberName = memberReferenceExpression.MemberName; @@ -119,10 +128,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms memberReferenceExpression.ReplaceWith(pre); } var rr = memberReferenceExpression.GetResolveResult(); - if (rr != null) { + if (rr != null) + { if (rr.Type is PointerType) return true; - if (rr is MemberResolveResult mrr && mrr.Member.ReturnType.Kind == TypeKind.Delegate) { + if (rr is MemberResolveResult mrr && mrr.Member.ReturnType.Kind == TypeKind.Delegate) + { var method = mrr.Member.ReturnType.GetDefinition()?.GetDelegateInvokeMethod(); if (method != null && (method.ReturnType is PointerType || method.Parameters.Any(p => p.Type is PointerType))) return true; @@ -136,10 +147,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { bool result = base.VisitIdentifierExpression(identifierExpression); var rr = identifierExpression.GetResolveResult(); - if (rr != null) { + if (rr != null) + { if (rr.Type is PointerType) return true; - if (rr is MemberResolveResult mrr && mrr.Member.ReturnType.Kind == TypeKind.Delegate) { + if (rr is MemberResolveResult mrr && mrr.Member.ReturnType.Kind == TypeKind.Delegate) + { var method = mrr.Member.ReturnType.GetDefinition()?.GetDelegateInvokeMethod(); if (method != null && (method.ReturnType is PointerType || method.Parameters.Any(p => p.Type is PointerType))) return true; @@ -157,7 +170,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return true; return result; } - + public override bool VisitInvocationExpression(InvocationExpression invocationExpression) { bool result = base.VisitInvocationExpression(invocationExpression); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs index 3d5180139..e4e02e24d 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.TypeSystem; @@ -39,21 +40,24 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms // First determine all the namespaces that need to be imported: var requiredImports = new FindRequiredImports(context); rootNode.AcceptVisitor(requiredImports); - + var usingScope = new UsingScope(); rootNode.AddAnnotation(usingScope); - if (context.Settings.UsingDeclarations) { + if (context.Settings.UsingDeclarations) + { var insertionPoint = rootNode.Children.LastOrDefault(n => n is PreProcessorDirective p && p.Type == PreProcessorDirectiveType.Define); // Now add using declarations for those namespaces: - foreach (string ns in requiredImports.ImportedNamespaces.OrderByDescending(n => n)) { + foreach (string ns in requiredImports.ImportedNamespaces.OrderByDescending(n => n)) + { Debug.Assert(context.RequiredNamespacesSuperset.Contains(ns), $"Should not insert using declaration for namespace that is missing from the superset: {ns}"); // we go backwards (OrderByDescending) through the list of namespaces because we insert them backwards // (always inserting at the start of the list) string[] parts = ns.Split('.'); AstType nsType = new SimpleType(parts[0]); - for (int i = 1; i < parts.Length; i++) { + for (int i = 1; i < parts.Length; i++) + { nsType = new MemberType { Target = nsType, MemberName = parts[i] }; } if (nsType.ToTypeReference(NameLookupMode.TypeInUsingDeclaration) is TypeOrNamespaceReference reference) @@ -65,24 +69,25 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms // verify that the SimpleTypes refer to the correct type (no ambiguities) rootNode.AcceptVisitor(new FullyQualifyAmbiguousTypeNamesVisitor(context, usingScope)); } - + sealed class FindRequiredImports : DepthFirstAstVisitor { string currentNamespace; public readonly HashSet DeclaredNamespaces = new HashSet() { string.Empty }; public readonly HashSet ImportedNamespaces = new HashSet(); - + public FindRequiredImports(TransformContext context) { this.currentNamespace = context.CurrentTypeDefinition?.Namespace ?? string.Empty; } - + bool IsParentOfCurrentNamespace(string ns) { if (ns.Length == 0) return true; - if (currentNamespace.StartsWith(ns, StringComparison.Ordinal)) { + if (currentNamespace.StartsWith(ns, StringComparison.Ordinal)) + { if (currentNamespace.Length == ns.Length) return true; if (currentNamespace[ns.Length] == '.') @@ -90,20 +95,22 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } return false; } - + public override void VisitSimpleType(SimpleType simpleType) { var trr = simpleType.Annotation(); - if (trr != null && !IsParentOfCurrentNamespace(trr.Type.Namespace)) { + if (trr != null && !IsParentOfCurrentNamespace(trr.Type.Namespace)) + { ImportedNamespaces.Add(trr.Type.Namespace); } base.VisitSimpleType(simpleType); // also visit type arguments } - + public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) { string oldNamespace = currentNamespace; - foreach (string ident in namespaceDeclaration.Identifiers) { + foreach (string ident in namespaceDeclaration.Identifiers) + { currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident); DeclaredNamespaces.Add(currentNamespace); } @@ -111,7 +118,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms currentNamespace = oldNamespace; } } - + sealed class FullyQualifyAmbiguousTypeNamesVisitor : DepthFirstAstVisitor { readonly Stack context; @@ -119,19 +126,24 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms readonly DecompilerSettings settings; TypeSystemAstBuilder astBuilder; - + public FullyQualifyAmbiguousTypeNamesVisitor(TransformContext context, UsingScope usingScope) { this.ignoreUsingScope = !context.Settings.UsingDeclarations; this.settings = context.Settings; CSharpTypeResolveContext currentContext; - if (ignoreUsingScope) { + if (ignoreUsingScope) + { currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainModule); - } else { + } + else + { this.context = new Stack(); - if (!string.IsNullOrEmpty(context.CurrentTypeDefinition?.Namespace)) { - foreach (string ns in context.CurrentTypeDefinition.Namespace.Split('.')) { + if (!string.IsNullOrEmpty(context.CurrentTypeDefinition?.Namespace)) + { + foreach (string ns in context.CurrentTypeDefinition.Namespace.Split('.')) + { usingScope = new UsingScope(usingScope, ns); } } @@ -144,8 +156,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms TypeSystemAstBuilder CreateAstBuilder(CSharpTypeResolveContext context, IL.ILFunction function = null) { CSharpResolver resolver = new CSharpResolver(context); - if (function != null) { - foreach (var v in function.Variables) { + if (function != null) + { + foreach (var v in function.Variables) + { if (v.Kind != IL.VariableKind.Parameter) resolver = resolver.AddVariable(new DefaultVariable(v.Type, v.Name)); } @@ -157,42 +171,51 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms UseAliases = true }; } - + public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) { - if (ignoreUsingScope) { + if (ignoreUsingScope) + { base.VisitNamespaceDeclaration(namespaceDeclaration); return; } var previousContext = context.Peek(); var usingScope = previousContext.CurrentUsingScope.UnresolvedUsingScope; - foreach (string ident in namespaceDeclaration.Identifiers) { + foreach (string ident in namespaceDeclaration.Identifiers) + { usingScope = new UsingScope(usingScope, ident); } var currentContext = new CSharpTypeResolveContext(previousContext.CurrentModule, usingScope.Resolve(previousContext.Compilation)); context.Push(currentContext); - try { + try + { astBuilder = CreateAstBuilder(currentContext); base.VisitNamespaceDeclaration(namespaceDeclaration); - } finally { + } + finally + { astBuilder = CreateAstBuilder(previousContext); context.Pop(); } } - + public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration) { - if (ignoreUsingScope) { + if (ignoreUsingScope) + { base.VisitTypeDeclaration(typeDeclaration); return; } var previousContext = context.Peek(); var currentContext = previousContext.WithCurrentTypeDefinition(typeDeclaration.GetSymbol() as ITypeDefinition); context.Push(currentContext); - try { + try + { astBuilder = CreateAstBuilder(currentContext); base.VisitTypeDeclaration(typeDeclaration); - } finally { + } + finally + { astBuilder = CreateAstBuilder(previousContext); context.Pop(); } @@ -225,28 +248,38 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void Visit(T entityDeclaration, Action baseCall) where T : EntityDeclaration { - if (ignoreUsingScope) { + if (ignoreUsingScope) + { baseCall(entityDeclaration); return; } - if (entityDeclaration.GetSymbol() is IMethod method) { + if (entityDeclaration.GetSymbol() is IMethod method) + { var previousContext = context.Peek(); CSharpTypeResolveContext currentContext; - if (CSharpDecompiler.IsWindowsFormsInitializeComponentMethod(method)) { + if (CSharpDecompiler.IsWindowsFormsInitializeComponentMethod(method)) + { currentContext = new CSharpTypeResolveContext(previousContext.CurrentModule); - } else { + } + else + { currentContext = previousContext.WithCurrentMember(method); } context.Push(currentContext); - try { + try + { var function = entityDeclaration.Annotation(); astBuilder = CreateAstBuilder(currentContext, function); baseCall(entityDeclaration); - } finally { + } + finally + { astBuilder = CreateAstBuilder(previousContext); context.Pop(); } - } else { + } + else + { baseCall(entityDeclaration); } } @@ -254,25 +287,31 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public override void VisitSimpleType(SimpleType simpleType) { TypeResolveResult rr; - if ((rr = simpleType.Annotation()) == null) { + if ((rr = simpleType.Annotation()) == null) + { base.VisitSimpleType(simpleType); return; } astBuilder.NameLookupMode = simpleType.GetNameLookupMode(); - if (astBuilder.NameLookupMode == NameLookupMode.Type) { + if (astBuilder.NameLookupMode == NameLookupMode.Type) + { AstType outermostType = simpleType; while (outermostType.Parent is AstType) outermostType = (AstType)outermostType.Parent; - if (outermostType.Parent is TypeReferenceExpression) { + if (outermostType.Parent is TypeReferenceExpression) + { // ILSpy uses TypeReferenceExpression in expression context even when the C# parser // wouldn't know that it's a type reference. // Fall back to expression-mode lookup in these cases: astBuilder.NameLookupMode = NameLookupMode.Expression; } } - if (simpleType.Parent is Syntax.Attribute) { + if (simpleType.Parent is Syntax.Attribute) + { simpleType.ReplaceWith(astBuilder.ConvertAttributeType(rr.Type)); - } else { + } + else + { simpleType.ReplaceWith(astBuilder.ConvertType(rr.Type)); } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs b/ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs index b4b88cbc1..e4034be38 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; @@ -62,15 +63,23 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void DoTransform(Statement statement, Statement parent) { - if (statement.IsNull) return; - if (context.Settings.AlwaysUseBraces) { - if (!IsElseIf(statement, parent)) { + if (statement.IsNull) + return; + if (context.Settings.AlwaysUseBraces) + { + if (!IsElseIf(statement, parent)) + { InsertBlock(statement); } - } else { - if (statement is BlockStatement b && b.Statements.Count == 1 && IsAllowedAsEmbeddedStatement(b.Statements.First(), parent)) { + } + else + { + if (statement is BlockStatement b && b.Statements.Count == 1 && IsAllowedAsEmbeddedStatement(b.Statements.First(), parent)) + { statement.ReplaceWith(b.Statements.First().Detach()); - } else if (!IsAllowedAsEmbeddedStatement(statement, parent)) { + } + else if (!IsAllowedAsEmbeddedStatement(statement, parent)) + { InsertBlock(statement); } } @@ -83,13 +92,18 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms static void InsertBlock(Statement statement) { - if (statement.IsNull) return; - if (!(statement is BlockStatement)) { + if (statement.IsNull) + return; + if (!(statement is BlockStatement)) + { var b = new BlockStatement(); statement.ReplaceWith(b); - if (statement is EmptyStatement && !statement.Children.Any()) { + if (statement is EmptyStatement && !statement.Children.Any()) + { b.CopyAnnotationsFrom(statement); - } else { + } + else + { b.Add(statement); } } @@ -97,7 +111,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms bool IsAllowedAsEmbeddedStatement(Statement statement, Statement parent) { - switch (statement) { + switch (statement) + { case IfElseStatement ies: return parent is IfElseStatement && ies.Role == IfElseStatement.FalseRole; case VariableDeclarationStatement vds: @@ -124,7 +139,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) { - if (context.Settings.UseExpressionBodyForCalculatedGetterOnlyProperties) { + if (context.Settings.UseExpressionBodyForCalculatedGetterOnlyProperties) + { SimplifyPropertyDeclaration(propertyDeclaration); } base.VisitPropertyDeclaration(propertyDeclaration); @@ -132,7 +148,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public override void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration) { - if (context.Settings.UseExpressionBodyForCalculatedGetterOnlyProperties) { + if (context.Settings.UseExpressionBodyForCalculatedGetterOnlyProperties) + { SimplifyIndexerDeclaration(indexerDeclaration); } base.VisitIndexerDeclaration(indexerDeclaration); @@ -144,9 +161,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms Name = Pattern.AnyString, PrivateImplementationType = new AnyNodeOrNull(), ReturnType = new AnyNode(), - Getter = new Accessor() { + Getter = new Accessor() { Modifiers = Modifiers.Any, - Body = new BlockStatement() { new ReturnStatement(new AnyNode("expression")) } + Body = new BlockStatement() { new ReturnStatement(new AnyNode("expression")) } } }; @@ -158,7 +175,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms ReturnType = new AnyNode(), Getter = new Accessor() { Modifiers = Modifiers.Any, - Body = new BlockStatement() { new ReturnStatement(new AnyNode("expression")) } + Body = new BlockStatement() { new ReturnStatement(new AnyNode("expression")) } } }; diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs index 84372eef8..92ef7b02c 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs @@ -20,10 +20,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; -using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Semantics; +using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.CSharp.Transforms { @@ -34,17 +35,20 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { readonly DeclareVariables declareVariables = new DeclareVariables(); TransformContext context; - + public void Run(AstNode rootNode, TransformContext context) { if (this.context != null) throw new InvalidOperationException("Reentrancy in PatternStatementTransform.Run?"); - try { + try + { this.context = context; base.Initialize(context); declareVariables.Analyze(rootNode); rootNode.AcceptVisitor(this); - } finally { + } + finally + { this.context = null; base.Uninitialize(); declareVariables.ClearAnalysisResults(); @@ -57,9 +61,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms // Go through the children, and keep visiting a node as long as it changes. // Because some transforms delete/replace nodes before and after the node being transformed, we rely // on the transform's return value to know where we need to keep iterating. - for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) + { AstNode oldChild; - do { + do + { oldChild = child; child = child.AcceptVisitor(this); Debug.Assert(child != null && child.Parent == node); @@ -67,7 +73,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } return node; } - + public override AstNode VisitExpressionStatement(ExpressionStatement expressionStatement) { AstNode result = TransformForeachOnMultiDimArray(expressionStatement); @@ -94,29 +100,31 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return simplifiedIfElse; return base.VisitIfElseStatement(ifElseStatement); } - + public override AstNode VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) { - if (context.Settings.AutomaticProperties) { + if (context.Settings.AutomaticProperties) + { AstNode result = TransformAutomaticProperty(propertyDeclaration); if (result != null) return result; } return base.VisitPropertyDeclaration(propertyDeclaration); } - + public override AstNode VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration) { // first apply transforms to the accessor bodies base.VisitCustomEventDeclaration(eventDeclaration); - if (context.Settings.AutomaticEvents) { + if (context.Settings.AutomaticEvents) + { AstNode result = TransformAutomaticEvents(eventDeclaration); if (result != null) return result; } return eventDeclaration; } - + public override AstNode VisitMethodDeclaration(MethodDeclaration methodDeclaration) { return TransformDestructor(methodDeclaration) ?? base.VisitMethodDeclaration(methodDeclaration); @@ -132,7 +140,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return TransformTryCatchFinally(tryCatchStatement) ?? base.VisitTryCatchStatement(tryCatchStatement); } #endregion - + /// /// $variable = $initializer; /// @@ -161,23 +169,27 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms Right = new AnyNode() })) } - }}; + } + }; public ForStatement TransformFor(ExpressionStatement node) { if (!context.Settings.ForStatement) return null; Match m1 = variableAssignPattern.Match(node); - if (!m1.Success) return null; + if (!m1.Success) + return null; var variable = m1.Get("variable").Single().GetILVariable(); AstNode next = node.NextSibling; - if (next is ForStatement forStatement && ForStatementUsesVariable(forStatement, variable)) { + if (next is ForStatement forStatement && ForStatementUsesVariable(forStatement, variable)) + { node.Remove(); next.InsertChildAfter(null, node, ForStatement.InitializerRole); return (ForStatement)next; } Match m3 = forPattern.Match(next); - if (!m3.Success) return null; + if (!m3.Success) + return null; // ensure the variable in the for pattern is the same as in the declaration if (variable != m3.Get("ident").Single().GetILVariable()) return null; @@ -226,7 +238,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms bool IteratorVariablesDeclaredInsideLoopBody(Statement iteratorStatement) { - foreach (var id in iteratorStatement.DescendantsAndSelf.OfType()) { + foreach (var id in iteratorStatement.DescendantsAndSelf.OfType()) + { var v = id.GetILVariable(); if (v == null || !DeclareVariables.VariableNeedsDeclaration(v.Kind)) continue; @@ -272,24 +285,28 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms bool VariableCanBeUsedAsForeachLocal(IL.ILVariable itemVar, Statement loop) { - if (itemVar == null || !(itemVar.Kind == IL.VariableKind.Local || itemVar.Kind == IL.VariableKind.StackSlot)) { + if (itemVar == null || !(itemVar.Kind == IL.VariableKind.Local || itemVar.Kind == IL.VariableKind.StackSlot)) + { // only locals/temporaries can be converted into foreach loop variable return false; } var blockContainer = loop.Annotation(); - if (!itemVar.IsSingleDefinition) { + if (!itemVar.IsSingleDefinition) + { // foreach variable cannot be assigned to. // As a special case, we accept taking the address for a method call, // but only if the call is the only use, so that any mutation by the call // cannot be observed. - if (!AddressUsedForSingleCall(itemVar, blockContainer)) { + if (!AddressUsedForSingleCall(itemVar, blockContainer)) + { return false; } } - if (itemVar.CaptureScope != null && itemVar.CaptureScope != blockContainer) { + if (itemVar.CaptureScope != null && itemVar.CaptureScope != blockContainer) + { // captured variables cannot be declared in the loop unless the loop is their capture scope return false; } @@ -300,13 +317,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms static bool AddressUsedForSingleCall(IL.ILVariable v, IL.BlockContainer loop) { - if (v.StoreCount == 1 && v.AddressCount == 1 && v.LoadCount == 0 && v.Type.IsReferenceType == false) { + if (v.StoreCount == 1 && v.AddressCount == 1 && v.LoadCount == 0 && v.Type.IsReferenceType == false) + { if (v.AddressInstructions[0].Parent is IL.Call call && v.AddressInstructions[0].ChildIndex == 0 - && !call.Method.IsStatic) { + && !call.Method.IsStatic) + { // used as this pointer for a method call // this is OK iff the call is not within a nested loop - for (var node = call.Parent; node != null; node = node.Parent) { + for (var node = call.Parent; node != null; node = node.Parent) + { if (node == loop) return true; else if (node is IL.BlockContainer) @@ -319,9 +339,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms Statement TransformForeachOnArray(ForStatement forStatement) { - if (!context.Settings.ForEachStatement) return null; + if (!context.Settings.ForEachStatement) + return null; Match m = forOnArrayPattern.Match(forStatement); - if (!m.Success) return null; + if (!m.Success) + return null; var itemVariable = m.Get("itemVariable").Single().GetILVariable(); var indexVariable = m.Get("indexVariable").Single().GetILVariable(); var arrayVariable = m.Get("arrayVariable").Single().GetILVariable(); @@ -411,7 +433,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { index = null; var m = variableAssignLowerBoundPattern.Match(statement); - if (!m.Success) return false; + if (!m.Success) + return false; if (!int.TryParse(m.Get("index").Single().Value.ToString(), out int i) || indexNum != i) return false; index = m.Get("variable").Single().GetILVariable(); @@ -426,9 +449,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms lowerBounds = new IL.ILVariable[upperBounds.Length]; Statement stmt = firstInitializerStatement; Match m = default(Match); - while (i < upperBounds.Length && MatchLowerBound(i, out IL.ILVariable indexVariable, collection, stmt)) { + while (i < upperBounds.Length && MatchLowerBound(i, out IL.ILVariable indexVariable, collection, stmt)) + { m = forOnArrayMultiDimPattern.Match(stmt.GetNextStatement()); - if (!m.Success) return false; + if (!m.Success) + return false; var upperBound = m.Get("upperBoundVariable").Single().GetILVariable(); if (upperBounds[i] != upperBound) return false; @@ -449,7 +474,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms Statement TransformForeachOnMultiDimArray(ExpressionStatement expressionStatement) { - if (!context.Settings.ForEachStatement) return null; + if (!context.Settings.ForEachStatement) + return null; Match m; Statement stmt = expressionStatement; IL.ILVariable collection = null; @@ -457,15 +483,20 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms List statementsToDelete = new List(); int i = 0; // first we look for all the upper bound initializations - do { + do + { m = variableAssignUpperBoundPattern.Match(stmt); - if (!m.Success) break; - if (upperBounds == null) { + if (!m.Success) + break; + if (upperBounds == null) + { collection = m.Get("collection").Single().GetILVariable(); if (!(collection?.Type is Decompiler.TypeSystem.ArrayType arrayType)) break; upperBounds = new IL.ILVariable[arrayType.Dimensions]; - } else { + } + else + { statementsToDelete.Add(stmt); } var nextCollection = m.Get("collection").Single().GetILVariable(); @@ -536,7 +567,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms Left = new Backreference("fieldReference"), Right = new IdentifierExpression("value") } - }} + } + } }; static readonly PropertyDeclaration automaticReadonlyPropertyPattern = new PropertyDeclaration { @@ -562,7 +594,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return false; if (!property.Getter.IsCompilerGenerated()) return false; - if (property.Setter is IMethod setter) { + if (property.Setter is IMethod setter) + { if (!setter.IsCompilerGenerated()) return false; if (setter.HasReadonlyModifier()) @@ -578,11 +611,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return null; IField field = null; Match m = automaticPropertyPattern.Match(propertyDeclaration); - if (m.Success) { + if (m.Success) + { field = m.Get("fieldReference").Single().GetSymbol() as IField; - } else { + } + else + { Match m2 = automaticReadonlyPropertyPattern.Match(propertyDeclaration); - if (m2.Success) { + if (m2.Success) + { field = m2.Get("fieldReference").Single().GetSymbol() as IField; } } @@ -590,7 +627,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return null; if (propertyDeclaration.Setter.HasModifier(Modifiers.Readonly)) return null; - if (field.IsCompilerGenerated() && field.DeclaringTypeDefinition == property.DeclaringTypeDefinition) { + if (field.IsCompilerGenerated() && field.DeclaringTypeDefinition == property.DeclaringTypeDefinition) + { RemoveCompilerGeneratedAttribute(propertyDeclaration.Getter.Attributes); RemoveCompilerGeneratedAttribute(propertyDeclaration.Setter.Attributes); propertyDeclaration.Getter.Body = null; @@ -601,7 +639,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var attributes = field.GetAttributes() .Where(a => !attributeTypesToRemoveFromAutoProperties.Contains(a.AttributeType.FullName)) .Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray(); - if (attributes.Length > 0) { + if (attributes.Length > 0) + { var section = new AttributeSection { AttributeTarget = "field" }; @@ -612,7 +651,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms // Since the property instance is not changed, we can continue in the visitor as usual, so return null return null; } - + void RemoveCompilerGeneratedAttribute(AstNodeCollection attributeSections) { RemoveCompilerGeneratedAttribute(attributeSections, "System.Runtime.CompilerServices.CompilerGeneratedAttribute"); @@ -620,10 +659,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void RemoveCompilerGeneratedAttribute(AstNodeCollection attributeSections, params string[] attributesToRemove) { - foreach (AttributeSection section in attributeSections) { - foreach (var attr in section.Attributes) { + foreach (AttributeSection section in attributeSections) + { + foreach (var attr in section.Attributes) + { var tr = attr.Type.GetSymbol() as IType; - if (tr != null && attributesToRemove.Contains(tr.FullName)) { + if (tr != null && attributesToRemove.Contains(tr.FullName)) + { attr.Remove(); } } @@ -635,14 +677,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public override AstNode VisitIdentifier(Identifier identifier) { - if (context.Settings.AutomaticProperties) { + if (context.Settings.AutomaticProperties) + { var newIdentifier = ReplaceBackingFieldUsage(identifier); - if (newIdentifier != null) { + if (newIdentifier != null) + { identifier.ReplaceWith(newIdentifier); return newIdentifier; } } - if (context.Settings.AutomaticEvents) { + if (context.Settings.AutomaticEvents) + { var newIdentifier = ReplaceEventFieldAnnotation(identifier); if (newIdentifier != null) return newIdentifier; @@ -685,7 +730,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms Identifier ReplaceBackingFieldUsage(Identifier identifier) { - if (NameCouldBeBackingFieldOfAutomaticProperty(identifier.Name, out _)) { + if (NameCouldBeBackingFieldOfAutomaticProperty(identifier.Name, out _)) + { var parent = identifier.Parent; var mrr = parent.Annotation(); var field = mrr?.Member as IField; @@ -708,7 +754,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms if (field == null) return null; var @event = field.DeclaringType.GetEvents(ev => ev.Name == field.Name, GetMemberOptions.IgnoreInheritedMembers).SingleOrDefault(); - if (@event != null && currentMethod.AccessorOwner != @event) { + if (@event != null && currentMethod.AccessorOwner != @event) + { parent.RemoveAnnotations(); parent.AddAnnotation(new MemberResolveResult(mrr.TargetResult, @event)); return identifier; @@ -851,7 +898,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return false; Expression fieldExpression = m.Get("field").Single(); // field name must match event name - switch (fieldExpression) { + switch (fieldExpression) + { case IdentifierExpression identifier: if (identifier.Identifier != ev.Name) return false; @@ -935,14 +983,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { if (!ev.PrivateImplementationType.IsNull) return null; - if (!ev.Modifiers.HasFlag(Modifiers.Abstract)) { + if (!ev.Modifiers.HasFlag(Modifiers.Abstract)) + { if (!CheckAutomaticEventV4AggressivelyInlined(ev) && !CheckAutomaticEventV4(ev) && !CheckAutomaticEventV2(ev) && !CheckAutomaticEventV4MCS(ev)) return null; } RemoveCompilerGeneratedAttribute(ev.AddAccessor.Attributes, attributeTypesToRemoveFromAutoEvents); EventDeclaration ed = new EventDeclaration(); ev.Attributes.MoveTo(ed.Attributes); - foreach (var attr in ev.AddAccessor.Attributes) { + foreach (var attr in ev.AddAccessor.Attributes) + { attr.AttributeTarget = "method"; ed.Attributes.Add(attr.Detach()); } @@ -951,14 +1001,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms ed.Variables.Add(new VariableInitializer(ev.Name)); ed.CopyAnnotationsFrom(ev); - if (ev.GetSymbol() is IEvent eventDef) { + if (ev.GetSymbol() is IEvent eventDef) + { IField field = eventDef.DeclaringType.GetFields(f => f.Name == ev.Name, GetMemberOptions.IgnoreInheritedMembers).SingleOrDefault(); - if (field != null) { + if (field != null) + { ed.AddAnnotation(field); var attributes = field.GetAttributes() .Where(a => !attributeTypesToRemoveFromAutoEvents.Contains(a.AttributeType.FullName)) .Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray(); - if (attributes.Length > 0) { + if (attributes.Length > 0) + { var section = new AttributeSection { AttributeTarget = "field" }; @@ -994,7 +1047,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms DestructorDeclaration TransformDestructor(MethodDeclaration methodDef) { Match m = destructorPattern.Match(methodDef); - if (m.Success) { + if (m.Success) + { DestructorDeclaration dd = new DestructorDeclaration(); methodDef.Attributes.MoveTo(dd.Attributes); dd.CopyAnnotationsFrom(methodDef); @@ -1010,7 +1064,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms DestructorDeclaration TransformDestructorBody(DestructorDeclaration dtorDef) { Match m = destructorBodyPattern.Match(dtorDef.Body); - if (m.Success) { + if (m.Success) + { dtorDef.Body = m.Get("body").Single().Detach(); return dtorDef; } @@ -1028,14 +1083,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms }, FinallyBlock = new AnyNode() }; - + /// /// Simplify nested 'try { try {} catch {} } finally {}'. /// This transformation must run after the using/lock tranformations. /// TryCatchStatement TransformTryCatchFinally(TryCatchStatement tryFinally) { - if (tryCatchFinallyPattern.IsMatch(tryFinally)) { + if (tryCatchFinallyPattern.IsMatch(tryFinally)) + { TryCatchStatement tryCatch = (TryCatchStatement)tryFinally.TryBlock.Statements.Single(); tryFinally.TryBlock = tryCatch.TryBlock.Detach(); tryCatch.CatchClauses.MoveTo(tryFinally.CatchClauses); @@ -1046,8 +1102,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms #endregion #region Simplify cascading if-else-if statements - static readonly IfElseStatement cascadingIfElsePattern = new IfElseStatement - { + static readonly IfElseStatement cascadingIfElsePattern = new IfElseStatement { Condition = new AnyNode(), TrueStatement = new AnyNode(), FalseStatement = new BlockStatement { @@ -1067,11 +1122,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms AstNode SimplifyCascadingIfElseStatements(IfElseStatement node) { Match m = cascadingIfElsePattern.Match(node); - if (m.Success) { + if (m.Success) + { IfElseStatement elseIf = m.Get("nestedIfStatement").Single(); node.FalseStatement = elseIf.Detach(); } - + return null; } @@ -1080,12 +1136,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms /// public override AstNode VisitBinaryOperatorExpression(BinaryOperatorExpression expr) { - switch (expr.Operator) { + switch (expr.Operator) + { case BinaryOperatorType.ConditionalAnd: case BinaryOperatorType.ConditionalOr: // a && (b && c) ==> (a && b) && c var bAndC = expr.Right as BinaryOperatorExpression; - if (bAndC != null && bAndC.Operator == expr.Operator) { + if (bAndC != null && bAndC.Operator == expr.Operator) + { // make bAndC the parent and expr the child var b = bAndC.Left.Detach(); var c = bAndC.Right.Detach(); @@ -1112,10 +1170,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public override AstNode VisitFixedStatement(FixedStatement fixedStatement) { - if (context.Settings.PatternBasedFixedStatement) { - foreach (var v in fixedStatement.Variables) { + if (context.Settings.PatternBasedFixedStatement) + { + foreach (var v in fixedStatement.Variables) + { var m = addressOfPinnableReference.Match(v.Initializer); - if (m.Success) { + if (m.Success) + { v.Initializer = m.Get("target").Single().Detach(); } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/PrettifyAssignments.cs b/ICSharpCode.Decompiler/CSharp/Transforms/PrettifyAssignments.cs index 3f1c869f6..d2ae9b2d5 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/PrettifyAssignments.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/PrettifyAssignments.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.TypeSystem; @@ -44,22 +45,28 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms base.VisitAssignmentExpression(assignment); // Combine "x = x op y" into "x op= y" BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression; - if (binary != null && assignment.Operator == AssignmentOperatorType.Assign) { - if (CanConvertToCompoundAssignment(assignment.Left) && assignment.Left.IsMatch(binary.Left)) { + if (binary != null && assignment.Operator == AssignmentOperatorType.Assign) + { + if (CanConvertToCompoundAssignment(assignment.Left) && assignment.Left.IsMatch(binary.Left)) + { assignment.Operator = GetAssignmentOperatorForBinaryOperator(binary.Operator); - if (assignment.Operator != AssignmentOperatorType.Assign) { + if (assignment.Operator != AssignmentOperatorType.Assign) + { // If we found a shorter operator, get rid of the BinaryOperatorExpression: assignment.CopyAnnotationsFrom(binary); assignment.Right = binary.Right; } } } - if (context.Settings.IntroduceIncrementAndDecrement && assignment.Operator == AssignmentOperatorType.Add || assignment.Operator == AssignmentOperatorType.Subtract) { + if (context.Settings.IntroduceIncrementAndDecrement && assignment.Operator == AssignmentOperatorType.Add || assignment.Operator == AssignmentOperatorType.Subtract) + { // detect increment/decrement var rr = assignment.Right.GetResolveResult(); - if (rr.IsCompileTimeConstant && rr.Type.IsCSharpPrimitiveIntegerType() && CSharpPrimitiveCast.Cast(rr.Type.GetTypeCode(), 1, false).Equals(rr.ConstantValue)) { + if (rr.IsCompileTimeConstant && rr.Type.IsCSharpPrimitiveIntegerType() && CSharpPrimitiveCast.Cast(rr.Type.GetTypeCode(), 1, false).Equals(rr.ConstantValue)) + { // only if it's not a custom operator - if (assignment.Annotation() == null && assignment.Annotation() == null && assignment.Annotation() == null) { + if (assignment.Annotation() == null && assignment.Annotation() == null && assignment.Annotation() == null) + { UnaryOperatorType type; // When the parent is an expression statement, pre- or post-increment doesn't matter; // so we can pick post-increment which is more commonly used (for (int i = 0; i < x; i++)) @@ -75,7 +82,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public static AssignmentOperatorType GetAssignmentOperatorForBinaryOperator(BinaryOperatorType bop) { - switch (bop) { + switch (bop) + { case BinaryOperatorType.Add: return AssignmentOperatorType.Add; case BinaryOperatorType.Subtract: @@ -123,9 +131,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void IAstTransform.Run(AstNode node, TransformContext context) { this.context = context; - try { + try + { node.AcceptVisitor(this); - } finally { + } + finally + { this.context = null; } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/RemoveCLSCompliantAttribute.cs b/ICSharpCode.Decompiler/CSharp/Transforms/RemoveCLSCompliantAttribute.cs index 56c35ae12..2dd3050de 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/RemoveCLSCompliantAttribute.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/RemoveCLSCompliantAttribute.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.Semantics; @@ -34,10 +35,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { public void Run(AstNode rootNode, TransformContext context) { - foreach (var section in rootNode.Children.OfType()) { + foreach (var section in rootNode.Children.OfType()) + { if (section.AttributeTarget == "assembly") continue; - foreach (var attribute in section.Attributes) { + foreach (var attribute in section.Attributes) + { var trr = attribute.Type.Annotation(); if (trr != null && trr.Type.FullName == "System.CLSCompliantAttribute") attribute.Remove(); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs b/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs index e50eb7134..f9680a498 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.Semantics; @@ -58,21 +59,26 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var arguments = invocationExpression.Arguments.ToArray(); // Reduce "String.Concat(a, b)" to "a + b" - if (IsStringConcat(method) && CheckArgumentsForStringConcat(arguments)) { + if (IsStringConcat(method) && CheckArgumentsForStringConcat(arguments)) + { bool isInExpressionTree = invocationExpression.Ancestors.OfType().Any( lambda => lambda.Annotation()?.Kind == IL.ILFunctionKind.ExpressionTree); Expression arg0 = arguments[0].Detach(); Expression arg1 = arguments[1].Detach(); - if (!isInExpressionTree) { + if (!isInExpressionTree) + { arg1 = RemoveRedundantToStringInConcat(arg1, method, isLastArgument: arguments.Length == 2).Detach(); - if (arg1.GetResolveResult().Type.IsKnownType(KnownTypeCode.String)) { + if (arg1.GetResolveResult().Type.IsKnownType(KnownTypeCode.String)) + { arg0 = RemoveRedundantToStringInConcat(arg0, method, isLastArgument: false).Detach(); } } var expr = new BinaryOperatorExpression(arg0, BinaryOperatorType.Add, arg1); - for (int i = 2; i < arguments.Length; i++) { + for (int i = 2; i < arguments.Length; i++) + { var arg = arguments[i].Detach(); - if (!isInExpressionTree) { + if (!isInExpressionTree) + { arg = RemoveRedundantToStringInConcat(arg, method, isLastArgument: i == arguments.Length - 1).Detach(); } expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arg); @@ -82,10 +88,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return; } - switch (method.FullName) { + switch (method.FullName) + { case "System.Type.GetTypeFromHandle": - if (arguments.Length == 1) { - if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) { + if (arguments.Length == 1) + { + if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) + { Expression target = ((MemberReferenceExpression)arguments[0]).Target; target.CopyInstructionsFrom(invocationExpression); invocationExpression.ReplaceWith(target); @@ -93,40 +102,42 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } break; - /* - case "System.Reflection.FieldInfo.GetFieldFromHandle": - // TODO : This is dead code because LdTokenAnnotation is not added anywhere: - if (arguments.Length == 1) { - MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression; - if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation() != null) { - invocationExpression.ReplaceWith(mre.Target); - return; - } - } else if (arguments.Length == 2) { - MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression; - MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression; - if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation() != null) { - if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression) { - Expression oldArg = ((InvocationExpression)mre1.Target).Arguments.Single(); - FieldReference field = oldArg.Annotation(); - if (field != null) { - AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach(); - oldArg.ReplaceWith(new MemberReferenceExpression(new TypeReferenceExpression(declaringType), field.Name).CopyAnnotationsFrom(oldArg)); - invocationExpression.ReplaceWith(mre1.Target); - return; - } + /* + case "System.Reflection.FieldInfo.GetFieldFromHandle": + // TODO : This is dead code because LdTokenAnnotation is not added anywhere: + if (arguments.Length == 1) { + MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression; + if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation() != null) { + invocationExpression.ReplaceWith(mre.Target); + return; + } + } else if (arguments.Length == 2) { + MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression; + MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression; + if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation() != null) { + if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression) { + Expression oldArg = ((InvocationExpression)mre1.Target).Arguments.Single(); + FieldReference field = oldArg.Annotation(); + if (field != null) { + AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach(); + oldArg.ReplaceWith(new MemberReferenceExpression(new TypeReferenceExpression(declaringType), field.Name).CopyAnnotationsFrom(oldArg)); + invocationExpression.ReplaceWith(mre1.Target); + return; } } } - break; - */ + } + break; + */ case "System.Activator.CreateInstance": - if (arguments.Length == 0 && method.TypeArguments.Count == 1 && IsInstantiableTypeParameter(method.TypeArguments[0])) { + if (arguments.Length == 0 && method.TypeArguments.Count == 1 && IsInstantiableTypeParameter(method.TypeArguments[0])) + { invocationExpression.ReplaceWith(new ObjectCreateExpression(context.TypeSystemAstBuilder.ConvertType(method.TypeArguments.First()))); } break; case "System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray": - if (arguments.Length == 2 && context.Settings.Ranges) { + if (arguments.Length == 2 && context.Settings.Ranges) + { var slicing = new IndexerExpression(arguments[0].Detach(), arguments[1].Detach()); slicing.CopyAnnotationsFrom(invocationExpression); invocationExpression.ReplaceWith(slicing); @@ -135,7 +146,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } BinaryOperatorType? bop = GetBinaryOperatorTypeFromMetadataName(method.Name); - if (bop != null && arguments.Length == 2) { + if (bop != null && arguments.Length == 2) + { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression invocationExpression.ReplaceWith( new BinaryOperatorExpression( @@ -147,11 +159,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return; } UnaryOperatorType? uop = GetUnaryOperatorTypeFromMetadataName(method.Name); - if (uop != null && arguments.Length == 1) { - if (uop == UnaryOperatorType.Increment || uop == UnaryOperatorType.Decrement) { + if (uop != null && arguments.Length == 1) + { + if (uop == UnaryOperatorType.Increment || uop == UnaryOperatorType.Decrement) + { // `op_Increment(a)` is not equivalent to `++a`, // because it doesn't assign the incremented value to a. - if (method.DeclaringType.IsKnownType(KnownTypeCode.Decimal)) { + if (method.DeclaringType.IsKnownType(KnownTypeCode.Decimal)) + { // Legacy csc optimizes "d + 1m" to "op_Increment(d)", // so reverse that optimization here: invocationExpression.ReplaceWith( @@ -170,7 +185,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms ); return; } - if (method.Name == "op_Explicit" && arguments.Length == 1) { + if (method.Name == "op_Explicit" && arguments.Length == 1) + { arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.ReturnType), arguments[0].UnwrapInDirectionExpression()) @@ -178,14 +194,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms ); return; } - if (method.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition) { + if (method.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition) + { invocationExpression.ReplaceWith(arguments[0].UnwrapInDirectionExpression()); return; } return; } - + bool IsInstantiableTypeParameter(IType type) { return type is ITypeParameter tp && tp.HasDefaultConstructorConstraint; @@ -215,13 +232,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms // To ensure the decompiled code's behavior matches the original IL behavior, // no matter which compiler is used to recompile it, we require that all // implicit ToString() calls except for the last are free of side effects. - foreach (var arg in arguments.SkipLast(1)) { - if (!ToStringIsKnownEffectFree(arg.GetResolveResult().Type)) { + foreach (var arg in arguments.SkipLast(1)) + { + if (!ToStringIsKnownEffectFree(arg.GetResolveResult().Type)) + { return false; } } - foreach (var arg in arguments) { - if (arg.GetResolveResult() is InvocationResolveResult rr && IsStringConcat(rr.Member)) { + foreach (var arg in arguments) + { + if (arg.GetResolveResult() is InvocationResolveResult rr && IsStringConcat(rr.Member)) + { // Roslyn + mcs also flatten nested string.Concat() invocations within a operator+ use, // which causes it to use the incorrect evaluation order despite the code using an // explicit string.Concat() call. @@ -263,7 +284,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms if (!m.Success) return expr; - if (!concatMethod.Parameters.All(IsStringParameter)) { + if (!concatMethod.Parameters.All(IsStringParameter)) + { // If we're using a string.Concat() overload involving object parameters, // string.Concat() itself already calls ToString() so the C# compiler shouldn't // generate additional ToString() calls in this case. @@ -272,15 +294,18 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var toStringMethod = m.Get("call").Single().GetSymbol() as IMethod; var target = m.Get("target").Single(); var type = target.GetResolveResult().Type; - if (!(isLastArgument || ToStringIsKnownEffectFree(type))) { + if (!(isLastArgument || ToStringIsKnownEffectFree(type))) + { // ToString() order of evaluation matters, see CheckArgumentsForStringConcat(). return expr; } - if (type.IsReferenceType != false && !m.Has("nullConditional")) { + if (type.IsReferenceType != false && !m.Has("nullConditional")) + { // ToString() might throw NullReferenceException, but the builtin operator+ doesn't. return expr; } - if (!ToStringIsKnownEffectFree(type) && toStringMethod != null && IL.Transforms.ILInlining.MethodRequiresCopyForReadonlyLValue(toStringMethod)) { + if (!ToStringIsKnownEffectFree(type) && toStringMethod != null && IL.Transforms.ILInlining.MethodRequiresCopyForReadonlyLValue(toStringMethod)) + { // ToString() on a struct may mutate the struct. // For operator+ the C# compiler creates a temporary copy before implicitly calling ToString(), // whereas an explicit ToString() call would mutate the original lvalue. @@ -304,7 +329,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms static bool ToStringIsKnownEffectFree(IType type) { type = NullableType.GetUnderlyingType(type); - switch (type.GetDefinition()?.KnownTypeCode) { + switch (type.GetDefinition()?.KnownTypeCode) + { case KnownTypeCode.Boolean: case KnownTypeCode.Char: case KnownTypeCode.SByte: @@ -329,7 +355,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms static BinaryOperatorType? GetBinaryOperatorTypeFromMetadataName(string name) { - switch (name) { + switch (name) + { case "op_Addition": return BinaryOperatorType.Add; case "op_Subtraction": @@ -369,7 +396,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms static UnaryOperatorType? GetUnaryOperatorTypeFromMetadataName(string name) { - switch (name) { + switch (name) + { case "op_LogicalNot": return UnaryOperatorType.Not; case "op_OnesComplement": @@ -401,9 +429,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms base.VisitCastExpression(castExpression); // Handle methodof Match m = getMethodOrConstructorFromHandlePattern.Match(castExpression); - if (m.Success) { + if (m.Success) + { IMethod method = m.Get("method").Single().GetSymbol() as IMethod; - if (m.Has("declaringType") && method != null) { + if (m.Has("declaringType") && method != null) + { Expression newNode = new MemberReferenceExpression(new TypeReferenceExpression(m.Get("declaringType").Single().Detach()), method.Name); newNode = new InvocationExpression(newNode, method.Parameters.Select(p => new TypeReferenceExpression(context.TypeSystemAstBuilder.ConvertType(p.Type)))); m.Get("method").Single().ReplaceWith(newNode); @@ -414,10 +444,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void IAstTransform.Run(AstNode rootNode, TransformContext context) { - try { + try + { this.context = context; rootNode.AcceptVisitor(this); - } finally { + } + finally + { this.context = null; } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs b/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs index 4ae4e8398..1e4ec47a8 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs @@ -18,6 +18,7 @@ using System.Collections.Immutable; using System.Threading; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.TypeSystem; diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs b/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs index f531e28fc..85fe07b43 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs @@ -18,9 +18,11 @@ using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.TypeSystem; + using SRM = System.Reflection.Metadata; namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -37,7 +39,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { this.context = context; - try { + try + { // If we're viewing some set of members (fields are direct children of SyntaxTree), // we also need to handle those: HandleInstanceFieldInitializers(node.Children); @@ -46,7 +49,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms node.AcceptVisitor(this); RemoveSingleEmptyConstructor(node.Children, context.CurrentTypeDefinition); - } finally { + } + finally + { this.context = null; } } @@ -57,7 +62,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return; var currentCtor = (IMethod)constructorDeclaration.GetSymbol(); ConstructorInitializer ci; - switch (stmt.Expression) { + switch (stmt.Expression) + { // Pattern for reference types: // this..ctor(...); case InvocationExpression invocation: @@ -140,7 +146,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { var instanceCtors = members.OfType().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => !thisCallPattern.IsMatch(ctor.Body.Statements.FirstOrDefault())).ToArray(); - if (instanceCtorsNotChainingWithThis.Length > 0) { + if (instanceCtorsNotChainingWithThis.Length > 0) + { var ctorMethodDef = instanceCtorsNotChainingWithThis[0].GetSymbol() as IMethod; if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsReferenceType == false) return; @@ -150,7 +157,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms // Recognize field or property initializers: // Translate first statement in all ctors (if all ctors have the same statement) into an initializer. bool allSame; - do { + do + { Match m = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[0].Body.FirstOrDefault()); if (!m.Success) break; @@ -167,9 +175,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms break; allSame = true; - for (int i = 1; i < instanceCtorsNotChainingWithThis.Length; i++) { + for (int i = 1; i < instanceCtorsNotChainingWithThis.Length; i++) + { var otherMatch = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[i].Body.FirstOrDefault()); - if (!otherMatch.Success) { + if (!otherMatch.Success) + { allSame = false; break; } @@ -179,15 +189,20 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms if (!initializer.IsMatch(otherMatch.Get("initializer").Single())) allSame = false; } - if (allSame) { + if (allSame) + { foreach (var ctor in instanceCtorsNotChainingWithThis) ctor.Body.First().Remove(); - if (ctorIsUnsafe && IntroduceUnsafeModifier.IsUnsafe(initializer)) { + if (ctorIsUnsafe && IntroduceUnsafeModifier.IsUnsafe(initializer)) + { fieldOrPropertyOrEventDecl.Modifiers |= Modifiers.Unsafe; } - if (fieldOrPropertyOrEventDecl is PropertyDeclaration pd) { + if (fieldOrPropertyOrEventDecl is PropertyDeclaration pd) + { pd.Initializer = initializer.Detach(); - } else { + } + else + { fieldOrPropertyOrEventDecl.GetChildrenByRole(Roles.Variable).Single().Initializer = initializer.Detach(); } } @@ -198,12 +213,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void RemoveSingleEmptyConstructor(IEnumerable members, ITypeDefinition contextTypeDefinition) { // if we're outside of a type definition skip this altogether - if (contextTypeDefinition == null) return; + if (contextTypeDefinition == null) + return; // first get non-static constructor declarations from the AST var instanceCtors = members.OfType().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); // if there's exactly one ctor and it's part of a type declaration or there's more than one member in the current selection // we can remove the constructor. (We do not want to hide the constructor if the user explicitly selected it in the tree view.) - if (instanceCtors.Length == 1 && (instanceCtors[0].Parent is TypeDeclaration || members.Skip(1).Any())) { + if (instanceCtors.Length == 1 && (instanceCtors[0].Parent is TypeDeclaration || members.Skip(1).Any())) + { var ctor = instanceCtors[0]; // dynamically create a pattern of an empty ctor ConstructorDeclaration emptyCtorPattern = new ConstructorDeclaration(); @@ -212,7 +229,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms emptyCtorPattern.Modifiers |= Modifiers.Unsafe; emptyCtorPattern.Body = new BlockStatement(); - if (emptyCtorPattern.IsMatch(ctor)) { + if (emptyCtorPattern.IsMatch(ctor)) + { bool retainBecauseOfDocumentation = ctor.GetSymbol() is IMethod ctorMethod && context.Settings.ShowXmlDocumentation && context.DecompileRun.DocumentationProvider?.GetDocumentation(ctorMethod) != null; @@ -226,15 +244,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { // Translate static constructor into field initializers if the class is BeforeFieldInit var staticCtor = members.OfType().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static); - if (staticCtor != null) { + if (staticCtor != null) + { bool ctorIsUnsafe = staticCtor.HasModifier(Modifiers.Unsafe); IMethod ctorMethod = staticCtor.GetSymbol() as IMethod; - if (!ctorMethod.MetadataToken.IsNil) { + if (!ctorMethod.MetadataToken.IsNil) + { var metadata = context.TypeSystem.MainModule.PEFile.Metadata; SRM.MethodDefinition ctorMethodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)ctorMethod.MetadataToken); SRM.TypeDefinition declaringType = metadata.GetTypeDefinition(ctorMethodDef.GetDeclaringType()); - if (declaringType.HasFlag(System.Reflection.TypeAttributes.BeforeFieldInit)) { - while (true) { + if (declaringType.HasFlag(System.Reflection.TypeAttributes.BeforeFieldInit)) + { + while (true) + { ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement; if (es == null) break; @@ -247,7 +269,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var fieldOrPropertyDecl = members.FirstOrDefault(f => f.GetSymbol() == fieldOrProperty) as EntityDeclaration; if (fieldOrPropertyDecl == null) break; - if (ctorIsUnsafe && IntroduceUnsafeModifier.IsUnsafe(assignment.Right)) { + if (ctorIsUnsafe && IntroduceUnsafeModifier.IsUnsafe(assignment.Right)) + { fieldOrPropertyDecl.Modifiers |= Modifiers.Unsafe; } if (fieldOrPropertyDecl is FieldDeclaration fd) diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs index 3365867da..9ccda1dde 100644 --- a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.IL; @@ -37,23 +38,23 @@ namespace ICSharpCode.Decompiler.CSharp struct ExpressionWithILInstruction { public readonly Expression Expression; - + public IEnumerable ILInstructions { get { return Expression.Annotations.OfType(); } } - + internal ExpressionWithILInstruction(Expression expression) { Debug.Assert(expression != null); this.Expression = expression; } - + public static implicit operator Expression(ExpressionWithILInstruction expression) { return expression.Expression; } } - + /// /// Helper struct so that the compiler can ensure we don't forget both the ILInstruction annotation and the ResolveResult annotation. /// Use '.WithRR(...)'. @@ -61,11 +62,11 @@ namespace ICSharpCode.Decompiler.CSharp struct ExpressionWithResolveResult { public readonly Expression Expression; - + // Because ResolveResult is frequently accessed within the ExpressionBuilder, we put it directly // in this struct instead of accessing it through the list of annotations. public readonly ResolveResult ResolveResult; - + public IType Type { get { return ResolveResult.Type; } } @@ -84,13 +85,13 @@ namespace ICSharpCode.Decompiler.CSharp this.Expression = expression; this.ResolveResult = resolveResult; } - + public static implicit operator Expression(ExpressionWithResolveResult expression) { return expression.Expression; } } - + /// /// Output of C# ExpressionBuilder -- a decompiled C# expression that has both a resolve result and ILInstruction annotation. /// @@ -103,26 +104,26 @@ namespace ICSharpCode.Decompiler.CSharp struct TranslatedExpression { public readonly Expression Expression; - + // Because ResolveResult is frequently accessed within the ExpressionBuilder, we put it directly // in this struct instead of accessing it through the list of annotations. public readonly ResolveResult ResolveResult; - + public IEnumerable ILInstructions { get { return Expression.Annotations.OfType(); } } - + public IType Type { get { return ResolveResult.Type; } } - + internal TranslatedExpression(Expression expression) { Debug.Assert(expression != null); this.Expression = expression; this.ResolveResult = expression.Annotation() ?? ErrorResolveResult.UnknownError; } - + internal TranslatedExpression(Expression expression, ResolveResult resolveResult) { Debug.Assert(expression != null && resolveResult != null); @@ -130,22 +131,22 @@ namespace ICSharpCode.Decompiler.CSharp this.ResolveResult = resolveResult; this.Expression = expression; } - + public static implicit operator Expression(TranslatedExpression expression) { return expression.Expression; } - + public static implicit operator ExpressionWithResolveResult(TranslatedExpression expression) { return new ExpressionWithResolveResult(expression.Expression, expression.ResolveResult); } - + public static implicit operator ExpressionWithILInstruction(TranslatedExpression expression) { return new ExpressionWithILInstruction(expression.Expression); } - + /// /// Returns a new TranslatedExpression that represents the specified descendant expression. /// All ILInstruction annotations from the current expression are copied to the descendant expression. @@ -155,7 +156,8 @@ namespace ICSharpCode.Decompiler.CSharp { if (descendant == Expression) return this; - for (AstNode parent = descendant.Parent; parent != null; parent = parent.Parent) { + for (AstNode parent = descendant.Parent; parent != null; parent = parent.Parent) + { foreach (var inst in parent.Annotations.OfType()) descendant.AddAnnotation(inst); if (parent == Expression) @@ -191,30 +193,40 @@ namespace ICSharpCode.Decompiler.CSharp public TranslatedExpression ConvertTo(IType targetType, ExpressionBuilder expressionBuilder, bool checkForOverflow = false, bool allowImplicitConversion = false) { var type = this.Type; - if (type.Equals(targetType)) { + if (type.Equals(targetType)) + { // Make explicit conversion implicit, if possible - if (allowImplicitConversion) { - switch (ResolveResult) { - case ConversionResolveResult conversion: { + if (allowImplicitConversion) + { + switch (ResolveResult) + { + case ConversionResolveResult conversion: + { if (Expression is CastExpression cast && CastCanBeMadeImplicit( Resolver.CSharpConversions.Get(expressionBuilder.compilation), conversion.Conversion, conversion.Input.Type, type, targetType - )) { + )) + { var result = this.UnwrapChild(cast.Expression); - if (conversion.Conversion.IsUserDefined) { + if (conversion.Conversion.IsUserDefined) + { result.Expression.AddAnnotation(new ImplicitConversionAnnotation(conversion)); } return result; - } else if (Expression is ObjectCreateExpression oce && conversion.Conversion.IsMethodGroupConversion - && oce.Arguments.Count == 1 && expressionBuilder.settings.UseImplicitMethodGroupConversion) { + } + else if (Expression is ObjectCreateExpression oce && conversion.Conversion.IsMethodGroupConversion + && oce.Arguments.Count == 1 && expressionBuilder.settings.UseImplicitMethodGroupConversion) + { return this.UnwrapChild(oce.Arguments.Single()); } break; } - case InvocationResolveResult invocation: { - if (Expression is ObjectCreateExpression oce && oce.Arguments.Count == 1 && invocation.Type.IsKnownType(KnownTypeCode.NullableOfT)) { + case InvocationResolveResult invocation: + { + if (Expression is ObjectCreateExpression oce && oce.Arguments.Count == 1 && invocation.Type.IsKnownType(KnownTypeCode.NullableOfT)) + { return this.UnwrapChild(oce.Arguments.Single()); } break; @@ -223,17 +235,22 @@ namespace ICSharpCode.Decompiler.CSharp } return this; } - if (targetType.Kind == TypeKind.Void || targetType.Kind == TypeKind.None) { + if (targetType.Kind == TypeKind.Void || targetType.Kind == TypeKind.None) + { return this; // don't attempt to insert cast to '?' or 'void' as these are not valid. - } else if (targetType.Kind == TypeKind.Unknown) { + } + else if (targetType.Kind == TypeKind.Unknown) + { // don't attempt cast to '?', or casts between an unknown type and a known type with same name - if (targetType.Name == "?" || targetType.ReflectionName == type.ReflectionName) { + if (targetType.Name == "?" || targetType.ReflectionName == type.ReflectionName) + { return this; } // However we still want explicit casts to types that are merely unresolved } var convAnnotation = this.Expression.Annotation(); - if (convAnnotation != null) { + if (convAnnotation != null) + { // If an implicit user-defined conversion was stripped from this expression; // it needs to be re-introduced before we can apply other casts to this expression. // This happens when the CallBuilder discovers that the conversion is necessary in @@ -244,7 +261,8 @@ namespace ICSharpCode.Decompiler.CSharp .WithRR(convAnnotation.ConversionResolveResult) .ConvertTo(targetType, expressionBuilder, checkForOverflow, allowImplicitConversion); } - if (Expression is ThrowExpression && allowImplicitConversion) { + if (Expression is ThrowExpression && allowImplicitConversion) + { return this; // Throw expressions have no type and are implicitly convertible to any type } if (Expression is TupleExpression tupleExpr && targetType is TupleType targetTupleType @@ -253,7 +271,8 @@ namespace ICSharpCode.Decompiler.CSharp // Conversion of a tuple literal: convert element-wise var newTupleExpr = new TupleExpression(); var newElementRRs = new List(); - foreach (var (elementExpr, elementTargetType) in tupleExpr.Elements.Zip(targetTupleType.ElementTypes)) { + foreach (var (elementExpr, elementTargetType) in tupleExpr.Elements.Zip(targetTupleType.ElementTypes)) + { var newElementExpr = new TranslatedExpression(elementExpr.Detach()) .ConvertTo(elementTargetType, expressionBuilder, checkForOverflow, allowImplicitConversion); newTupleExpr.Elements.Add(newElementExpr.Expression); @@ -261,7 +280,7 @@ namespace ICSharpCode.Decompiler.CSharp } return newTupleExpr.WithILInstruction(this.ILInstructions) .WithRR(new TupleResolveResult( - expressionBuilder.compilation, newElementRRs.ToImmutableArray(), + expressionBuilder.compilation, newElementRRs.ToImmutableArray(), valueTupleAssembly: targetTupleType.GetDefinition()?.ParentModule )); } @@ -276,7 +295,8 @@ namespace ICSharpCode.Decompiler.CSharp return unwrapped; return unwrapped.ConvertTo(targetType, expressionBuilder, checkForOverflow, allowImplicitConversion); } - if (Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.NullConditional && targetType.IsReferenceType == true) { + if (Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.NullConditional && targetType.IsReferenceType == true) + { // "(T)(x?).AccessChain" is invalid, but "((T)x)?.AccessChain" is valid and equivalent return new UnaryOperatorExpression( UnaryOperatorType.NullConditional, @@ -286,7 +306,8 @@ namespace ICSharpCode.Decompiler.CSharp IType utype = NullableType.GetUnderlyingType(type); IType targetUType = NullableType.GetUnderlyingType(targetType); if (type.IsKnownType(KnownTypeCode.Boolean) && !targetUType.IsKnownType(KnownTypeCode.Boolean) - && targetUType.GetStackType().IsIntegerType()) { + && targetUType.GetStackType().IsIntegerType()) + { // convert from boolean to integer (or enum) return new ConditionalExpression( this.Expression, @@ -294,68 +315,93 @@ namespace ICSharpCode.Decompiler.CSharp LdcI4(compilation, 0).ConvertTo(targetType, expressionBuilder, checkForOverflow) ).WithoutILInstruction().WithRR(new ResolveResult(targetType)); } - if (targetType.IsKnownType(KnownTypeCode.Boolean)) { + if (targetType.IsKnownType(KnownTypeCode.Boolean)) + { // convert to boolean through byte, to simulate the truncation to 8 bits return this.ConvertTo(compilation.FindType(KnownTypeCode.Byte), expressionBuilder, checkForOverflow) .ConvertToBoolean(expressionBuilder); } - + // Special-case IntPtr and UIntPtr: they behave extremely weird, see IntPtr.txt for details. - if (type.IsKnownType(KnownTypeCode.IntPtr)) { // Conversion from IntPtr - // Direct cast only works correctly for IntPtr -> long. - // IntPtr -> int works correctly only in checked context. - // Everything else can be worked around by casting via long. - if (!(targetType.IsKnownType(KnownTypeCode.Int64) || targetType.Kind == TypeKind.NInt || checkForOverflow && targetType.IsKnownType(KnownTypeCode.Int32))) { + if (type.IsKnownType(KnownTypeCode.IntPtr)) + { // Conversion from IntPtr + // Direct cast only works correctly for IntPtr -> long. + // IntPtr -> int works correctly only in checked context. + // Everything else can be worked around by casting via long. + if (!(targetType.IsKnownType(KnownTypeCode.Int64) || targetType.Kind == TypeKind.NInt || checkForOverflow && targetType.IsKnownType(KnownTypeCode.Int32))) + { var convertVia = expressionBuilder.settings.NativeIntegers ? SpecialType.NInt : compilation.FindType(KnownTypeCode.Int64); return this.ConvertTo(convertVia, expressionBuilder, checkForOverflow) .ConvertTo(targetType, expressionBuilder, checkForOverflow, allowImplicitConversion); } - } else if (type.IsKnownType(KnownTypeCode.UIntPtr)) { // Conversion from UIntPtr - // Direct cast only works correctly for UIntPtr -> ulong. - // UIntPtr -> uint works correctly only in checked context. - // Everything else can be worked around by casting via ulong. - if (!(targetType.IsKnownType(KnownTypeCode.UInt64) || targetType.Kind == TypeKind.NUInt || checkForOverflow && targetType.IsKnownType(KnownTypeCode.UInt32))) { + } + else if (type.IsKnownType(KnownTypeCode.UIntPtr)) + { // Conversion from UIntPtr + // Direct cast only works correctly for UIntPtr -> ulong. + // UIntPtr -> uint works correctly only in checked context. + // Everything else can be worked around by casting via ulong. + if (!(targetType.IsKnownType(KnownTypeCode.UInt64) || targetType.Kind == TypeKind.NUInt || checkForOverflow && targetType.IsKnownType(KnownTypeCode.UInt32))) + { var convertVia = expressionBuilder.settings.NativeIntegers ? SpecialType.NUInt : compilation.FindType(KnownTypeCode.UInt64); return this.ConvertTo(convertVia, expressionBuilder, checkForOverflow) .ConvertTo(targetType, expressionBuilder, checkForOverflow, allowImplicitConversion); } } - if (targetUType.IsKnownType(KnownTypeCode.IntPtr)) { // Conversion to IntPtr - if (type.IsKnownType(KnownTypeCode.Int32) || type.Kind == TypeKind.NInt) { + if (targetUType.IsKnownType(KnownTypeCode.IntPtr)) + { // Conversion to IntPtr + if (type.IsKnownType(KnownTypeCode.Int32) || type.Kind == TypeKind.NInt) + { // normal casts work for int/nint (both in checked and unchecked context) // note that pointers only allow normal casts in unchecked contexts - } else if (expressionBuilder.settings.NativeIntegers) { + } + else if (expressionBuilder.settings.NativeIntegers) + { // if native integer types are available, prefer using those return this.ConvertTo(SpecialType.NInt, expressionBuilder, checkForOverflow) .ConvertTo(targetType, expressionBuilder, checkForOverflow, allowImplicitConversion); - } else if (checkForOverflow) { + } + else if (checkForOverflow) + { // if overflow-checking is enabled, we can simply cast via long: // (and long itself works directly in checked context) - if (!type.IsKnownType(KnownTypeCode.Int64)) { + if (!type.IsKnownType(KnownTypeCode.Int64)) + { return this.ConvertTo(compilation.FindType(KnownTypeCode.Int64), expressionBuilder, checkForOverflow) .ConvertTo(targetType, expressionBuilder, checkForOverflow); } - } else if (type.Kind != TypeKind.Pointer) { + } + else if (type.Kind != TypeKind.Pointer) + { // If overflow-checking is disabled, the only way to truncate to native size // without throwing an exception in 32-bit mode is to use a pointer type. return this.ConvertTo(new PointerType(compilation.FindType(KnownTypeCode.Void)), expressionBuilder, checkForOverflow) .ConvertTo(targetType, expressionBuilder, checkForOverflow); } - } else if (targetUType.IsKnownType(KnownTypeCode.UIntPtr)) { // Conversion to UIntPtr - if (type.IsKnownType(KnownTypeCode.UInt32) || type.Kind == TypeKind.Pointer || type.Kind == TypeKind.NUInt) { + } + else if (targetUType.IsKnownType(KnownTypeCode.UIntPtr)) + { // Conversion to UIntPtr + if (type.IsKnownType(KnownTypeCode.UInt32) || type.Kind == TypeKind.Pointer || type.Kind == TypeKind.NUInt) + { // normal casts work for uint/nuint and pointers (both in checked and unchecked context) - } else if (expressionBuilder.settings.NativeIntegers) { + } + else if (expressionBuilder.settings.NativeIntegers) + { // if native integer types are available, prefer using those return this.ConvertTo(SpecialType.NUInt, expressionBuilder, checkForOverflow) .ConvertTo(targetType, expressionBuilder, checkForOverflow, allowImplicitConversion); - } else if (checkForOverflow) { + } + else if (checkForOverflow) + { // if overflow-checking is enabled, we can simply cast via ulong: // (and ulong itself works directly in checked context) - if (!type.IsKnownType(KnownTypeCode.UInt64)) { + if (!type.IsKnownType(KnownTypeCode.UInt64)) + { return this.ConvertTo(compilation.FindType(KnownTypeCode.UInt64), expressionBuilder, checkForOverflow) .ConvertTo(targetType, expressionBuilder, checkForOverflow); } - } else { + } + else + { // If overflow-checking is disabled, the only way to truncate to native size // without throwing an exception in 32-bit mode is to use a pointer type. return this.ConvertTo(new PointerType(compilation.FindType(KnownTypeCode.Void)), expressionBuilder, checkForOverflow) @@ -363,29 +409,35 @@ namespace ICSharpCode.Decompiler.CSharp } } - if (targetType.Kind == TypeKind.Pointer && type.Kind == TypeKind.Enum) { + if (targetType.Kind == TypeKind.Pointer && type.Kind == TypeKind.Enum) + { // enum to pointer: C# doesn't allow such casts // -> convert via underlying type return this.ConvertTo(type.GetEnumUnderlyingType(), expressionBuilder, checkForOverflow) .ConvertTo(targetType, expressionBuilder, checkForOverflow); - } else if (targetUType.Kind == TypeKind.Enum && type.Kind == TypeKind.Pointer) { + } + else if (targetUType.Kind == TypeKind.Enum && type.Kind == TypeKind.Pointer) + { // pointer to enum: C# doesn't allow such casts // -> convert via underlying type return this.ConvertTo(targetUType.GetEnumUnderlyingType(), expressionBuilder, checkForOverflow) .ConvertTo(targetType, expressionBuilder, checkForOverflow); } if (targetType.Kind == TypeKind.Pointer && type.IsKnownType(KnownTypeCode.Char) - || targetUType.IsKnownType(KnownTypeCode.Char) && type.Kind == TypeKind.Pointer) { + || targetUType.IsKnownType(KnownTypeCode.Char) && type.Kind == TypeKind.Pointer) + { // char <-> pointer: C# doesn't allow such casts // -> convert via ushort return this.ConvertTo(compilation.FindType(KnownTypeCode.UInt16), expressionBuilder, checkForOverflow) .ConvertTo(targetType, expressionBuilder, checkForOverflow); } - if (targetType.Kind == TypeKind.Pointer && type.Kind == TypeKind.ByReference && Expression is DirectionExpression) { + if (targetType.Kind == TypeKind.Pointer && type.Kind == TypeKind.ByReference && Expression is DirectionExpression) + { // convert from reference to pointer Expression arg = ((DirectionExpression)Expression).Expression.Detach(); var pointerType = new PointerType(((ByReferenceType)type).ElementType); - if (arg is UnaryOperatorExpression argUOE && argUOE.Operator == UnaryOperatorType.Dereference) { + if (arg is UnaryOperatorExpression argUOE && argUOE.Operator == UnaryOperatorType.Dereference) + { // &*ptr -> ptr return new TranslatedExpression(argUOE).UnwrapChild(argUOE.Expression) .ConvertTo(targetType, expressionBuilder); @@ -396,13 +448,16 @@ namespace ICSharpCode.Decompiler.CSharp // perform remaining pointer cast, if necessary return pointerExpr.ConvertTo(targetType, expressionBuilder); } - if (targetType.Kind == TypeKind.ByReference) { - if (NormalizeTypeVisitor.TypeErasure.EquivalentTypes(targetType, this.Type)) { + if (targetType.Kind == TypeKind.ByReference) + { + if (NormalizeTypeVisitor.TypeErasure.EquivalentTypes(targetType, this.Type)) + { return this; } var elementType = ((ByReferenceType)targetType).ElementType; if (this.Expression is DirectionExpression thisDir && this.ILInstructions.Any(i => i.OpCode == OpCode.AddressOf) - && thisDir.Expression.GetResolveResult()?.Type.GetStackType() == elementType.GetStackType()) { + && thisDir.Expression.GetResolveResult()?.Type.GetStackType() == elementType.GetStackType()) + { // When converting a reference to a temporary to a different type, // apply the cast to the temporary instead. var convertedTemp = this.UnwrapChild(thisDir.Expression).ConvertTo(elementType, expressionBuilder, checkForOverflow); @@ -410,7 +465,8 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(this.ILInstructions) .WithRR(new ByReferenceResolveResult(convertedTemp.ResolveResult, ReferenceKind.Ref)); } - if (this.Type.Kind == TypeKind.ByReference && !IsFixedVariable()) { + if (this.Type.Kind == TypeKind.ByReference && !IsFixedVariable()) + { // Convert between managed reference types. // We can't do this by going through a pointer type because that would temporarily stop GC tracking. // Instead, emit `ref Unsafe.As(ref expr)` @@ -423,11 +479,14 @@ namespace ICSharpCode.Decompiler.CSharp var arg = this.ConvertTo(new PointerType(elementType), expressionBuilder, checkForOverflow); Expression expr; ResolveResult elementRR; - if (arg.Expression is UnaryOperatorExpression unary && unary.Operator == UnaryOperatorType.AddressOf) { + if (arg.Expression is UnaryOperatorExpression unary && unary.Operator == UnaryOperatorType.AddressOf) + { // If we already have an address -> unwrap expr = arg.UnwrapChild(unary.Expression); elementRR = expr.GetResolveResult(); - } else { + } + else + { // Otherwise dereference the pointer: expr = new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg.Expression); elementRR = new ResolveResult(elementType); @@ -450,23 +509,30 @@ namespace ICSharpCode.Decompiler.CSharp .ConvertTo(targetType, expressionBuilder, checkForOverflow, allowImplicitConversion); } var rr = expressionBuilder.resolver.WithCheckForOverflow(checkForOverflow).ResolveCast(targetType, ResolveResult); - if (rr.IsCompileTimeConstant && !rr.IsError) { + if (rr.IsCompileTimeConstant && !rr.IsError) + { var convertedResult = expressionBuilder.ConvertConstantValue(rr, allowImplicitConversion) .WithILInstruction(this.ILInstructions); - if (convertedResult.Expression is PrimitiveExpression outputLiteral && this.Expression is PrimitiveExpression inputLiteral) { + if (convertedResult.Expression is PrimitiveExpression outputLiteral && this.Expression is PrimitiveExpression inputLiteral) + { outputLiteral.Format = inputLiteral.Format; } return convertedResult; - } else if (rr.IsError && targetType.IsReferenceType == true && type.IsReferenceType == true) { + } + else if (rr.IsError && targetType.IsReferenceType == true && type.IsReferenceType == true) + { // Conversion between two reference types, but no direct cast allowed? cast via object // Just make sure we avoid infinite recursion even if the resolver falsely claims we can't cast directly: - if (!(targetType.IsKnownType(KnownTypeCode.Object) || type.IsKnownType(KnownTypeCode.Object))) { + if (!(targetType.IsKnownType(KnownTypeCode.Object) || type.IsKnownType(KnownTypeCode.Object))) + { return this.ConvertTo(compilation.FindType(KnownTypeCode.Object), expressionBuilder) .ConvertTo(targetType, expressionBuilder, checkForOverflow, allowImplicitConversion); } } - if (targetType.Kind == TypeKind.Pointer && (0.Equals(ResolveResult.ConstantValue) || 0u.Equals(ResolveResult.ConstantValue))) { - if (allowImplicitConversion) { + if (targetType.Kind == TypeKind.Pointer && (0.Equals(ResolveResult.ConstantValue) || 0u.Equals(ResolveResult.ConstantValue))) + { + if (allowImplicitConversion) + { return new NullReferenceExpression() .WithILInstruction(this.ILInstructions) .WithRR(new ConstantResolveResult(targetType, null)); @@ -475,19 +541,25 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(this.ILInstructions) .WithRR(new ConstantResolveResult(targetType, null)); } - if (allowImplicitConversion) { - if (conversions.ImplicitConversion(ResolveResult, targetType).IsValid) { + if (allowImplicitConversion) + { + if (conversions.ImplicitConversion(ResolveResult, targetType).IsValid) + { return this; } - } else { - if (NormalizeTypeVisitor.IgnoreNullabilityAndTuples.EquivalentTypes(type, targetType)) { + } + else + { + if (NormalizeTypeVisitor.IgnoreNullabilityAndTuples.EquivalentTypes(type, targetType)) + { // avoid an explicit cast when types differ only in nullability of reference types return this; } } var castExpr = new CastExpression(expressionBuilder.ConvertType(targetType), Expression); bool needsCheckAnnotation = targetUType.GetStackType().IsIntegerType(); - if (needsCheckAnnotation) { + if (needsCheckAnnotation) + { castExpr.AddAnnotation(checkForOverflow ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); } return castExpr.WithoutILInstruction().WithRR(rr); @@ -495,10 +567,13 @@ namespace ICSharpCode.Decompiler.CSharp bool IsFixedVariable() { - if (this.Expression is DirectionExpression dirExpr) { + if (this.Expression is DirectionExpression dirExpr) + { var inst = dirExpr.Expression.Annotation(); return inst != null && PointerArithmeticOffset.IsFixedVariable(inst); - } else { + } + else + { return false; } } @@ -510,25 +585,29 @@ namespace ICSharpCode.Decompiler.CSharp /// bool CastCanBeMadeImplicit(Resolver.CSharpConversions conversions, Conversion conversion, IType inputType, IType oldTargetType, IType newTargetType) { - if (!conversion.IsImplicit) { + if (!conversion.IsImplicit) + { // If the cast was required for the old conversion, avoid making it implicit. return false; } if (oldTargetType.Kind == TypeKind.NInt || oldTargetType.Kind == TypeKind.NUInt - || newTargetType.Kind == TypeKind.NInt || newTargetType.Kind == TypeKind.NUInt) { + || newTargetType.Kind == TypeKind.NInt || newTargetType.Kind == TypeKind.NUInt) + { // nint has identity conversion with IntPtr, but the two have different implicit conversions return false; } - if (conversion.IsBoxingConversion) { + if (conversion.IsBoxingConversion) + { return conversions.IsBoxingConversionOrInvolvingTypeParameter(inputType, newTargetType); } - if (conversion.IsInterpolatedStringConversion) { + if (conversion.IsInterpolatedStringConversion) + { return newTargetType.IsKnownType(KnownTypeCode.FormattableString) || newTargetType.IsKnownType(KnownTypeCode.IFormattable); } return conversions.IdentityConversion(oldTargetType, newTargetType); } - + TranslatedExpression LdcI4(ICompilation compilation, int val) { return new PrimitiveExpression(val) @@ -550,7 +629,8 @@ namespace ICSharpCode.Decompiler.CSharp return this; if (typeFilter != null && !typeFilter(rr.Input.Type)) return this; - if (this.Expression is CastExpression cast) { + if (this.Expression is CastExpression cast) + { return this.UnwrapChild(cast.Expression); } return this; @@ -566,28 +646,37 @@ namespace ICSharpCode.Decompiler.CSharp /// public TranslatedExpression ConvertToBoolean(ExpressionBuilder expressionBuilder, bool negate = false) { - if (Type.IsKnownType(KnownTypeCode.Boolean) || Type.Kind == TypeKind.Unknown) { - if (negate) { + if (Type.IsKnownType(KnownTypeCode.Boolean) || Type.Kind == TypeKind.Unknown) + { + if (negate) + { return expressionBuilder.LogicNot(this).WithoutILInstruction(); - } else { + } + else + { return this; } } Debug.Assert(Type.GetStackType().IsIntegerType()); IType boolType = expressionBuilder.compilation.FindType(KnownTypeCode.Boolean); - if (ResolveResult.IsCompileTimeConstant && ResolveResult.ConstantValue is int) { + if (ResolveResult.IsCompileTimeConstant && ResolveResult.ConstantValue is int) + { bool val = (int)ResolveResult.ConstantValue != 0; val ^= negate; return new PrimitiveExpression(val) .WithILInstruction(this.ILInstructions) .WithRR(new ConstantResolveResult(boolType, val)); - } else if (ResolveResult.IsCompileTimeConstant && ResolveResult.ConstantValue is byte) { + } + else if (ResolveResult.IsCompileTimeConstant && ResolveResult.ConstantValue is byte) + { bool val = (byte)ResolveResult.ConstantValue != 0; val ^= negate; return new PrimitiveExpression(val) .WithILInstruction(this.ILInstructions) .WithRR(new ConstantResolveResult(boolType, val)); - } else if (Type.Kind == TypeKind.Pointer) { + } + else if (Type.Kind == TypeKind.Pointer) + { var nullRef = new NullReferenceExpression() .WithoutILInstruction() .WithRR(new ConstantResolveResult(SpecialType.NullType, null)); @@ -595,8 +684,10 @@ namespace ICSharpCode.Decompiler.CSharp return new BinaryOperatorExpression(Expression, op, nullRef.Expression) .WithoutILInstruction() .WithRR(new OperatorResolveResult(boolType, System.Linq.Expressions.ExpressionType.NotEqual, - this.ResolveResult, nullRef.ResolveResult)); - } else { + this.ResolveResult, nullRef.ResolveResult)); + } + else + { var zero = new PrimitiveExpression(0) .WithoutILInstruction() .WithRR(new ConstantResolveResult(expressionBuilder.compilation.FindType(KnownTypeCode.Int32), 0)); @@ -604,7 +695,7 @@ namespace ICSharpCode.Decompiler.CSharp return new BinaryOperatorExpression(Expression, op, zero.Expression) .WithoutILInstruction() .WithRR(new OperatorResolveResult(boolType, System.Linq.Expressions.ExpressionType.NotEqual, - this.ResolveResult, zero.ResolveResult)); + this.ResolveResult, zero.ResolveResult)); } } } diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedStatement.cs b/ICSharpCode.Decompiler/CSharp/TranslatedStatement.cs index 5da752107..f489520bc 100644 --- a/ICSharpCode.Decompiler/CSharp/TranslatedStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/TranslatedStatement.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; diff --git a/ICSharpCode.Decompiler/CSharp/TypeSystem/AliasNamespaceReference.cs b/ICSharpCode.Decompiler/CSharp/TypeSystem/AliasNamespaceReference.cs index c8fd57043..1bb991dee 100644 --- a/ICSharpCode.Decompiler/CSharp/TypeSystem/AliasNamespaceReference.cs +++ b/ICSharpCode.Decompiler/CSharp/TypeSystem/AliasNamespaceReference.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; @@ -34,39 +35,39 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem public sealed class AliasNamespaceReference : TypeOrNamespaceReference, ISupportsInterning { readonly string identifier; - + public AliasNamespaceReference(string identifier) { if (identifier == null) throw new ArgumentNullException(nameof(identifier)); this.identifier = identifier; } - + public string Identifier { get { return identifier; } } - + public override ResolveResult Resolve(CSharpResolver resolver) { return resolver.ResolveAlias(identifier); } - + public override IType ResolveType(CSharpResolver resolver) { // alias cannot refer to types return SpecialType.NoType; } - + public override string ToString() { return identifier + "::"; } - + int ISupportsInterning.GetHashCodeForInterning() { return identifier.GetHashCode(); } - + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { AliasNamespaceReference anr = other as AliasNamespaceReference; diff --git a/ICSharpCode.Decompiler/CSharp/TypeSystem/CSharpTypeResolveContext.cs b/ICSharpCode.Decompiler/CSharp/TypeSystem/CSharpTypeResolveContext.cs index 34d6eb836..986ee1020 100644 --- a/ICSharpCode.Decompiler/CSharp/TypeSystem/CSharpTypeResolveContext.cs +++ b/ICSharpCode.Decompiler/CSharp/TypeSystem/CSharpTypeResolveContext.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.CSharp.TypeSystem @@ -28,7 +29,7 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem readonly ITypeDefinition currentTypeDefinition; readonly IMember currentMember; readonly string[] methodTypeParameterNames; - + public CSharpTypeResolveContext(IModule module, ResolvedUsingScope usingScope = null, ITypeDefinition typeDefinition = null, IMember member = null) { if (module == null) @@ -38,7 +39,7 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem this.currentTypeDefinition = typeDefinition; this.currentMember = member; } - + private CSharpTypeResolveContext(IModule module, ResolvedUsingScope usingScope, ITypeDefinition typeDefinition, IMember member, string[] methodTypeParameterNames) { this.module = module; @@ -47,47 +48,47 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem this.currentMember = member; this.methodTypeParameterNames = methodTypeParameterNames; } - + public ResolvedUsingScope CurrentUsingScope { get { return currentUsingScope; } } - + public ICompilation Compilation { get { return module.Compilation; } } - + public IModule CurrentModule { get { return module; } } - + public ITypeDefinition CurrentTypeDefinition { get { return currentTypeDefinition; } } - + public IMember CurrentMember { get { return currentMember; } } - + public CSharpTypeResolveContext WithCurrentTypeDefinition(ITypeDefinition typeDefinition) { return new CSharpTypeResolveContext(module, currentUsingScope, typeDefinition, currentMember, methodTypeParameterNames); } - + ITypeResolveContext ITypeResolveContext.WithCurrentTypeDefinition(ITypeDefinition typeDefinition) { return WithCurrentTypeDefinition(typeDefinition); } - + public CSharpTypeResolveContext WithCurrentMember(IMember member) { return new CSharpTypeResolveContext(module, currentUsingScope, currentTypeDefinition, member, methodTypeParameterNames); } - + ITypeResolveContext ITypeResolveContext.WithCurrentMember(IMember member) { return WithCurrentMember(member); } - + public CSharpTypeResolveContext WithUsingScope(ResolvedUsingScope usingScope) { return new CSharpTypeResolveContext(module, usingScope, currentTypeDefinition, currentMember, methodTypeParameterNames); diff --git a/ICSharpCode.Decompiler/CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs b/ICSharpCode.Decompiler/CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs index 024b64e2d..4418f9cd3 100644 --- a/ICSharpCode.Decompiler/CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs +++ b/ICSharpCode.Decompiler/CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; @@ -36,7 +37,7 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem readonly string identifier; readonly IList typeArguments; readonly NameLookupMode lookupMode; - + public MemberTypeOrNamespaceReference(TypeOrNamespaceReference target, string identifier, IList typeArguments, NameLookupMode lookupMode = NameLookupMode.Type) { if (target == null) @@ -48,23 +49,23 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem this.typeArguments = typeArguments ?? EmptyList.Instance; this.lookupMode = lookupMode; } - + public string Identifier { get { return identifier; } } - + public TypeOrNamespaceReference Target { get { return target; } } - + public IList TypeArguments { get { return typeArguments; } } - + public NameLookupMode LookupMode { get { return lookupMode; } } - + /// /// Adds a suffix to the identifier. /// Does not modify the existing type reference, but returns a new one. @@ -73,7 +74,7 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem { return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments, lookupMode); } - + public override ResolveResult Resolve(CSharpResolver resolver) { ResolveResult targetRR = target.Resolve(resolver); @@ -82,13 +83,13 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem IReadOnlyList typeArgs = typeArguments.Resolve(resolver.CurrentTypeResolveContext); return resolver.ResolveMemberAccess(targetRR, identifier, typeArgs, lookupMode); } - + public override IType ResolveType(CSharpResolver resolver) { TypeResolveResult trr = Resolve(resolver) as TypeResolveResult; return trr != null ? trr.Type : new UnknownType(null, identifier, typeArguments.Count); } - + public override string ToString() { if (typeArguments.Count == 0) @@ -96,11 +97,12 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem else return target.ToString() + "." + identifier + "<" + string.Join(",", typeArguments) + ">"; } - + int ISupportsInterning.GetHashCodeForInterning() { int hashCode = 0; - unchecked { + unchecked + { hashCode += 1000000007 * target.GetHashCode(); hashCode += 1000000033 * identifier.GetHashCode(); hashCode += 1000000087 * typeArguments.GetHashCode(); @@ -108,7 +110,7 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem } return hashCode; } - + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { MemberTypeOrNamespaceReference o = other as MemberTypeOrNamespaceReference; diff --git a/ICSharpCode.Decompiler/CSharp/TypeSystem/ResolvedUsingScope.cs b/ICSharpCode.Decompiler/CSharp/TypeSystem/ResolvedUsingScope.cs index 2fffd1491..c6e10cfbd 100644 --- a/ICSharpCode.Decompiler/CSharp/TypeSystem/ResolvedUsingScope.cs +++ b/ICSharpCode.Decompiler/CSharp/TypeSystem/ResolvedUsingScope.cs @@ -21,6 +21,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.Semantics; @@ -37,10 +38,10 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem { readonly CSharpTypeResolveContext parentContext; readonly UsingScope usingScope; - + internal readonly ConcurrentDictionary ResolveCache = new ConcurrentDictionary(); internal List> AllExtensionMethods; - + public ResolvedUsingScope(CSharpTypeResolveContext context, UsingScope usingScope) { if (context == null) @@ -49,32 +50,41 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem throw new ArgumentNullException(nameof(usingScope)); this.parentContext = context; this.usingScope = usingScope; - if (usingScope.Parent != null) { + if (usingScope.Parent != null) + { if (context.CurrentUsingScope == null) throw new InvalidOperationException(); - } else { + } + else + { if (context.CurrentUsingScope != null) throw new InvalidOperationException(); } } - + public UsingScope UnresolvedUsingScope { get { return usingScope; } } - + INamespace @namespace; - + public INamespace Namespace { get { INamespace result = LazyInit.VolatileRead(ref this.@namespace); - if (result != null) { + if (result != null) + { return result; - } else { - if (parentContext.CurrentUsingScope != null) { + } + else + { + if (parentContext.CurrentUsingScope != null) + { result = parentContext.CurrentUsingScope.Namespace.GetChildNamespace(usingScope.ShortNamespaceName); if (result == null) result = new DummyNamespace(parentContext.CurrentUsingScope.Namespace, usingScope.ShortNamespaceName); - } else { + } + else + { result = parentContext.Compilation.RootNamespace; } Debug.Assert(result != null); @@ -82,22 +92,26 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem } } } - + public ResolvedUsingScope Parent { get { return parentContext.CurrentUsingScope; } } - + IList usings; - + public IList Usings { get { var result = LazyInit.VolatileRead(ref this.usings); - if (result != null) { + if (result != null) + { return result; - } else { + } + else + { result = new List(); CSharpResolver resolver = new CSharpResolver(parentContext.WithUsingScope(this)); - foreach (var u in usingScope.Usings) { + foreach (var u in usingScope.Usings) + { INamespace ns = u.ResolveNamespace(resolver); if (ns != null && !result.Contains(ns)) result.Add(ns); @@ -106,23 +120,30 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem } } } - + IList> usingAliases; - + public IList> UsingAliases { get { var result = LazyInit.VolatileRead(ref this.usingAliases); - if (result != null) { + if (result != null) + { return result; - } else { + } + else + { CSharpResolver resolver = new CSharpResolver(parentContext.WithUsingScope(this)); result = new KeyValuePair[usingScope.UsingAliases.Count]; - for (int i = 0; i < result.Count; i++) { + for (int i = 0; i < result.Count; i++) + { var rr = usingScope.UsingAliases[i].Value.Resolve(resolver); - if (rr is TypeResolveResult) { - rr = new AliasTypeResolveResult (usingScope.UsingAliases[i].Key, (TypeResolveResult)rr); - } else if (rr is NamespaceResolveResult) { - rr = new AliasNamespaceResolveResult (usingScope.UsingAliases[i].Key, (NamespaceResolveResult)rr); + if (rr is TypeResolveResult) + { + rr = new AliasTypeResolveResult(usingScope.UsingAliases[i].Key, (TypeResolveResult)rr); + } + else if (rr is NamespaceResolveResult) + { + rr = new AliasNamespaceResolveResult(usingScope.UsingAliases[i].Key, (NamespaceResolveResult)rr); } result[i] = new KeyValuePair( usingScope.UsingAliases[i].Key, @@ -133,11 +154,11 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem } } } - + public IList ExternAliases { get { return usingScope.ExternAliases; } } - + /// /// Gets whether this using scope has an alias (either using or extern) /// with the specified name. @@ -146,57 +167,57 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem { return usingScope.HasAlias(identifier); } - + sealed class DummyNamespace : INamespace { readonly INamespace parentNamespace; readonly string name; - + public DummyNamespace(INamespace parentNamespace, string name) { this.parentNamespace = parentNamespace; this.name = name; } - + public string ExternAlias { get; set; } - + string INamespace.FullName { get { return NamespaceDeclaration.BuildQualifiedName(parentNamespace.FullName, name); } } - + public string Name { get { return name; } } - + SymbolKind ISymbol.SymbolKind { get { return SymbolKind.Namespace; } } - + INamespace INamespace.ParentNamespace { get { return parentNamespace; } } - + IEnumerable INamespace.ChildNamespaces { get { return EmptyList.Instance; } } - + IEnumerable INamespace.Types { get { return EmptyList.Instance; } } - + IEnumerable INamespace.ContributingModules { get { return EmptyList.Instance; } } - + ICompilation ICompilationProvider.Compilation { get { return parentNamespace.Compilation; } } - + INamespace INamespace.GetChildNamespace(string name) { return null; } - + ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount) { return null; diff --git a/ICSharpCode.Decompiler/CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs b/ICSharpCode.Decompiler/CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs index 8a3bc901f..ded6bccbc 100644 --- a/ICSharpCode.Decompiler/CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs +++ b/ICSharpCode.Decompiler/CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; @@ -35,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem readonly string identifier; readonly IList typeArguments; readonly NameLookupMode lookupMode; - + public SimpleTypeOrNamespaceReference(string identifier, IList typeArguments, NameLookupMode lookupMode = NameLookupMode.Type) { if (identifier == null) @@ -44,19 +45,19 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem this.typeArguments = typeArguments ?? EmptyList.Instance; this.lookupMode = lookupMode; } - + public string Identifier { get { return identifier; } } - + public IList TypeArguments { get { return typeArguments; } } - + public NameLookupMode LookupMode { get { return lookupMode; } } - + /// /// Adds a suffix to the identifier. /// Does not modify the existing type reference, but returns a new one. @@ -65,19 +66,19 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem { return new SimpleTypeOrNamespaceReference(identifier + suffix, typeArguments, lookupMode); } - + public override ResolveResult Resolve(CSharpResolver resolver) { var typeArgs = typeArguments.Resolve(resolver.CurrentTypeResolveContext); return resolver.LookupSimpleNameOrTypeName(identifier, typeArgs, lookupMode); } - + public override IType ResolveType(CSharpResolver resolver) { TypeResolveResult trr = Resolve(resolver) as TypeResolveResult; return trr != null ? trr.Type : new UnknownType(null, identifier, typeArguments.Count); } - + public override string ToString() { if (typeArguments.Count == 0) @@ -85,18 +86,19 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem else return identifier + "<" + string.Join(",", typeArguments) + ">"; } - + int ISupportsInterning.GetHashCodeForInterning() { int hashCode = 0; - unchecked { + unchecked + { hashCode += 1000000021 * identifier.GetHashCode(); hashCode += 1000000033 * typeArguments.GetHashCode(); hashCode += 1000000087 * (int)lookupMode; } return hashCode; } - + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { SimpleTypeOrNamespaceReference o = other as SimpleTypeOrNamespaceReference; diff --git a/ICSharpCode.Decompiler/CSharp/TypeSystem/TypeOrNamespaceReference.cs b/ICSharpCode.Decompiler/CSharp/TypeSystem/TypeOrNamespaceReference.cs index 2ed10e5f4..c9ed00c32 100644 --- a/ICSharpCode.Decompiler/CSharp/TypeSystem/TypeOrNamespaceReference.cs +++ b/ICSharpCode.Decompiler/CSharp/TypeSystem/TypeOrNamespaceReference.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; @@ -33,12 +34,12 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem /// Resolves the reference and returns the ResolveResult. /// public abstract ResolveResult Resolve(CSharpResolver resolver); - + /// /// Returns the type that is referenced; or an UnknownType if the type isn't found. /// public abstract IType ResolveType(CSharpResolver resolver); - + /// /// Returns the namespace that is referenced; or null if no such namespace is found. /// @@ -47,7 +48,7 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem NamespaceResolveResult nrr = Resolve(resolver) as NamespaceResolveResult; return nrr != null ? nrr.Namespace : null; } - + IType ITypeReference.Resolve(ITypeResolveContext context) { // Strictly speaking, we might have to resolve the type in a nested compilation, similar @@ -55,25 +56,26 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem // However, in almost all cases this will work correctly - if the resulting type is only available in the // nested compilation and not in this, we wouldn't be able to map it anyways. var ctx = context as CSharpTypeResolveContext; - if (ctx == null) { + if (ctx == null) + { ctx = new CSharpTypeResolveContext(context.CurrentModule ?? context.Compilation.MainModule, null, context.CurrentTypeDefinition, context.CurrentMember); } return ResolveType(new CSharpResolver(ctx)); - + // A potential issue might be this scenario: - + // Assembly 1: // class A { public class Nested {} } - + // Assembly 2: (references asm 1) // class B : A {} - + // Assembly 3: (references asm 1 and 2) // class C { public B.Nested Field; } - + // Assembly 4: (references asm 1 and 3, but not 2): // uses C.Field; - + // Here we would not be able to resolve 'B.Nested' in the compilation of assembly 4, as type B is missing there. } } diff --git a/ICSharpCode.Decompiler/CSharp/TypeSystem/UsingScope.cs b/ICSharpCode.Decompiler/CSharp/TypeSystem/UsingScope.cs index 6d8af6849..05ef4e6eb 100644 --- a/ICSharpCode.Decompiler/CSharp/TypeSystem/UsingScope.cs +++ b/ICSharpCode.Decompiler/CSharp/TypeSystem/UsingScope.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -37,28 +38,28 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem IList usings; IList> usingAliases; IList externAliases; - + protected override void FreezeInternal() { usings = FreezableHelper.FreezeList(usings); usingAliases = FreezableHelper.FreezeList(usingAliases); externAliases = FreezableHelper.FreezeList(externAliases); - + // In current model (no child scopes), it makes sense to freeze the parent as well // to ensure the whole lookup chain is immutable. if (parent != null) parent.Freeze(); - + base.FreezeInternal(); } - + /// /// Creates a new root using scope. /// public UsingScope() { } - + /// /// Creates a new nested using scope. /// @@ -73,17 +74,17 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem this.parent = parent; this.shortName = shortName; } - + public UsingScope Parent { get { return parent; } } - + public string ShortNamespaceName { get { return shortName; } } - + public string NamespaceName { get { if (parent != null) @@ -91,14 +92,14 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem else return shortName; } -// set { -// if (value == null) -// throw new ArgumentNullException("NamespaceName"); -// FreezableHelper.ThrowIfFrozen(this); -// namespaceName = value; -// } + // set { + // if (value == null) + // throw new ArgumentNullException("NamespaceName"); + // FreezableHelper.ThrowIfFrozen(this); + // namespaceName = value; + // } } - + public IList Usings { get { if (usings == null) @@ -106,7 +107,7 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem return usings; } } - + public IList> UsingAliases { get { if (usingAliases == null) @@ -114,7 +115,7 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem return usingAliases; } } - + public IList ExternAliases { get { if (externAliases == null) @@ -122,30 +123,32 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem return externAliases; } } - -// public IList ChildScopes { -// get { -// if (childScopes == null) -// childScopes = new List(); -// return childScopes; -// } -// } - + + // public IList ChildScopes { + // get { + // if (childScopes == null) + // childScopes = new List(); + // return childScopes; + // } + // } + /// /// Gets whether this using scope has an alias (either using or extern) /// with the specified name. /// public bool HasAlias(string identifier) { - if (usingAliases != null) { - foreach (var pair in usingAliases) { + if (usingAliases != null) + { + foreach (var pair in usingAliases) + { if (pair.Key == identifier) return true; } } return externAliases != null && externAliases.Contains(identifier); } - + /// /// Resolves the namespace represented by this using scope. /// @@ -153,7 +156,8 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem { CacheManager cache = compilation.CacheManager; ResolvedUsingScope resolved = cache.GetShared(this) as ResolvedUsingScope; - if (resolved == null) { + if (resolved == null) + { var csContext = new CSharpTypeResolveContext(compilation.MainModule, parent != null ? parent.Resolve(compilation) : null); resolved = (ResolvedUsingScope)cache.GetOrAddShared(this, new ResolvedUsingScope(csContext, this)); } diff --git a/ICSharpCode.Decompiler/DebugInfo/AsyncDebugInfo.cs b/ICSharpCode.Decompiler/DebugInfo/AsyncDebugInfo.cs index 658f3d9ca..ed26d98f7 100644 --- a/ICSharpCode.Decompiler/DebugInfo/AsyncDebugInfo.cs +++ b/ICSharpCode.Decompiler/DebugInfo/AsyncDebugInfo.cs @@ -32,7 +32,8 @@ namespace ICSharpCode.Decompiler.DebugInfo { BlobBuilder blob = new BlobBuilder(); blob.WriteUInt32((uint)CatchHandlerOffset); - foreach (var await in Awaits) { + foreach (var await in Awaits) + { blob.WriteUInt32((uint)await.YieldOffset); blob.WriteUInt32((uint)await.ResumeOffset); blob.WriteCompressedInteger(MetadataTokens.GetToken(moveNext)); diff --git a/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs b/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs index cb04bc4da..828107a0e 100644 --- a/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs +++ b/ICSharpCode.Decompiler/DebugInfo/DebugInfoGenerator.cs @@ -23,6 +23,7 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; + using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; @@ -66,7 +67,8 @@ namespace ICSharpCode.Decompiler.DebugInfo public void GenerateImportScopes(MetadataBuilder metadata, ImportScopeHandle globalImportScope) { - foreach (var scope in importScopes) { + foreach (var scope in importScopes) + { var blob = EncodeImports(metadata, scope); scope.Handle = metadata.AddImportScope(scope.Parent == null ? globalImportScope : scope.Parent.Handle, blob); } @@ -76,7 +78,8 @@ namespace ICSharpCode.Decompiler.DebugInfo { var writer = new BlobBuilder(); - foreach (var import in scope.Imports) { + foreach (var import in scope.Imports) + { writer.WriteByte((byte)ImportDefinitionKind.ImportNamespace); writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(metadata.GetOrAddBlobUTF8(import))); } @@ -135,9 +138,12 @@ namespace ICSharpCode.Decompiler.DebugInfo public override void VisitQueryFromClause(QueryFromClause queryFromClause) { - if (queryFromClause.Parent.FirstChild != queryFromClause) { + if (queryFromClause.Parent.FirstChild != queryFromClause) + { HandleMethod(queryFromClause); - } else { + } + else + { base.VisitQueryFromClause(queryFromClause); } } @@ -145,7 +151,8 @@ namespace ICSharpCode.Decompiler.DebugInfo public override void VisitQueryGroupClause(QueryGroupClause queryGroupClause) { var annotation = queryGroupClause.Annotation(); - if (annotation == null) { + if (annotation == null) + { base.VisitQueryGroupClause(queryGroupClause); return; } @@ -156,7 +163,8 @@ namespace ICSharpCode.Decompiler.DebugInfo public override void VisitQueryJoinClause(QueryJoinClause queryJoinClause) { var annotation = queryJoinClause.Annotation(); - if (annotation == null) { + if (annotation == null) + { base.VisitQueryJoinClause(queryJoinClause); return; } @@ -201,7 +209,8 @@ namespace ICSharpCode.Decompiler.DebugInfo MethodDefinitionHandle handle = (MethodDefinitionHandle)method.MetadataToken; var file = typeSystem.MainModule.PEFile; MethodDefinition md = file.Metadata.GetMethodDefinition(handle); - if (md.HasBody()) { + if (md.HasBody()) + { HandleMethodBody(function, file.Reader.GetMethodBody(md.RelativeVirtualAddress)); } } @@ -211,14 +220,17 @@ namespace ICSharpCode.Decompiler.DebugInfo var method = function.MoveNextMethod ?? function.Method; var localVariables = new HashSet(ILVariableKeyComparer); - if (!methodBody.LocalSignature.IsNil) { + if (!methodBody.LocalSignature.IsNil) + { #if DEBUG var types = typeSystem.MainModule.DecodeLocalSignature(methodBody.LocalSignature, new TypeSystem.GenericContext(method)); #endif - foreach (var v in function.Variables) { - if (v.Index != null && v.Kind.IsLocal()) { + foreach (var v in function.Variables) + { + if (v.Index != null && v.Kind.IsLocal()) + { #if DEBUG Debug.Assert(v.Index < types.Length && v.Type.Equals(types[v.Index.Value])); #endif diff --git a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs index 28038144a..86829f0a1 100644 --- a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs +++ b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs @@ -28,6 +28,7 @@ using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using System.Security.Cryptography; using System.Text; + using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; @@ -68,7 +69,8 @@ namespace ICSharpCode.Decompiler.DebugInfo return Path.Combine(WholeProjectDecompiler.CleanUpFileName(typeName.Namespace), WholeProjectDecompiler.CleanUpFileName(typeName.Name) + ".cs"); } - foreach (var sourceFile in reader.GetTopLevelTypeDefinitions().GroupBy(BuildFileNameFromTypeName)) { + foreach (var sourceFile in reader.GetTopLevelTypeDefinitions().GroupBy(BuildFileNameFromTypeName)) + { // Generate syntax tree var syntaxTree = decompiler.DecompileTypes(sourceFile); if (!syntaxTree.HasChildren) @@ -86,7 +88,8 @@ namespace ICSharpCode.Decompiler.DebugInfo var debugInfoGen = new DebugInfoGenerator(decompiler.TypeSystem); syntaxTree.AcceptVisitor(debugInfoGen); - lock (metadata) { + lock (metadata) + { var sourceBlob = WriteSourceToBlob(metadata, sourceText, out var sourceCheckSum); var name = metadata.GetOrAddDocumentName(sourceFile.Key); @@ -105,12 +108,14 @@ namespace ICSharpCode.Decompiler.DebugInfo localScopes.AddRange(debugInfoGen.LocalScopes); - foreach (var function in debugInfoGen.Functions) { + foreach (var function in debugInfoGen.Functions) + { var method = function.MoveNextMethod ?? function.Method; var methodHandle = (MethodDefinitionHandle)method.MetadataToken; sequencePoints.TryGetValue(function, out var points); ProcessMethod(methodHandle, document, points, syntaxTree); - if (function.MoveNextMethod != null) { + if (function.MoveNextMethod != null) + { stateMachineMethods.Add(( (MethodDefinitionHandle)function.MoveNextMethod.MetadataToken, (MethodDefinitionHandle)function.Method.MetadataToken @@ -121,7 +126,8 @@ namespace ICSharpCode.Decompiler.DebugInfo metadata.GetOrAddBlob(BuildStateMachineHoistedLocalScopes(function)) )); } - if (function.IsAsync) { + if (function.IsAsync) + { customMethodDebugInfo.Add((methodHandle, metadata.GetOrAddGuid(KnownGuids.MethodSteppingInformation), metadata.GetOrAddBlob(function.AsyncDebugInfo.BuildBlob(methodHandle)))); @@ -130,30 +136,38 @@ namespace ICSharpCode.Decompiler.DebugInfo } } - foreach (var method in reader.MethodDefinitions) { + foreach (var method in reader.MethodDefinitions) + { var md = reader.GetMethodDefinition(method); - if (sequencePointBlobs.TryGetValue(method, out var info)) { + if (sequencePointBlobs.TryGetValue(method, out var info)) + { metadata.AddMethodDebugInformation(info.Document, info.SequencePoints); - } else { + } + else + { metadata.AddMethodDebugInformation(default, default); } } localScopes.Sort((x, y) => { - if (x.Method != y.Method) { + if (x.Method != y.Method) + { return MetadataTokens.GetRowNumber(x.Method) - MetadataTokens.GetRowNumber(y.Method); } - if (x.Offset != y.Offset) { + if (x.Offset != y.Offset) + { return x.Offset - y.Offset; } return y.Length - x.Length; }); - foreach (var localScope in localScopes) { + foreach (var localScope in localScopes) + { int nextRow = metadata.GetRowCount(TableIndex.LocalVariable) + 1; var firstLocalVariable = MetadataTokens.LocalVariableHandle(nextRow); - foreach (var local in localScope.Locals.OrderBy(l => l.Index)) { + foreach (var local in localScope.Locals.OrderBy(l => l.Index)) + { var localVarName = local.Name != null ? metadata.GetOrAddString(local.Name) : default; metadata.AddLocalVariable(LocalVariableAttributes.None, local.Index.Value, localVarName); } @@ -163,15 +177,18 @@ namespace ICSharpCode.Decompiler.DebugInfo } stateMachineMethods.SortBy(row => MetadataTokens.GetRowNumber(row.MoveNextMethod)); - foreach (var row in stateMachineMethods) { + foreach (var row in stateMachineMethods) + { metadata.AddStateMachineMethod(row.MoveNextMethod, row.KickoffMethod); } customMethodDebugInfo.SortBy(row => MetadataTokens.GetRowNumber(row.Parent)); - foreach (var row in customMethodDebugInfo) { + foreach (var row in customMethodDebugInfo) + { metadata.AddCustomDebugInformation(row.Parent, row.Guid, row.Blob); } customDebugInfo.SortBy(row => MetadataTokens.GetRowNumber(row.Parent)); - foreach (var row in customDebugInfo) { + foreach (var row in customDebugInfo) + { metadata.AddCustomDebugInformation(row.Parent, row.Guid, row.Blob); } @@ -189,10 +206,13 @@ namespace ICSharpCode.Decompiler.DebugInfo var methodDef = reader.GetMethodDefinition(method); int localSignatureRowId; MethodBodyBlock methodBody; - if (methodDef.RelativeVirtualAddress != 0) { + if (methodDef.RelativeVirtualAddress != 0) + { methodBody = file.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); localSignatureRowId = methodBody.LocalSignature.IsNil ? 0 : MetadataTokens.GetRowNumber(methodBody.LocalSignature); - } else { + } + else + { methodBody = null; localSignatureRowId = 0; } @@ -206,7 +226,8 @@ namespace ICSharpCode.Decompiler.DebugInfo static BlobBuilder BuildStateMachineHoistedLocalScopes(ILFunction function) { var builder = new BlobBuilder(); - foreach (var variable in function.Variables.Where(v => v.StateMachineField != null).OrderBy(v => MetadataTokens.GetRowNumber(v.StateMachineField.MetadataToken))) { + foreach (var variable in function.Variables.Where(v => v.StateMachineField != null).OrderBy(v => MetadataTokens.GetRowNumber(v.StateMachineField.MetadataToken))) + { builder.WriteUInt32(0); builder.WriteUInt32((uint)function.CodeSize); } @@ -216,7 +237,8 @@ namespace ICSharpCode.Decompiler.DebugInfo static BlobHandle WriteSourceToBlob(MetadataBuilder metadata, string sourceText, out byte[] sourceCheckSum) { var builder = new BlobBuilder(); - using (var memory = new MemoryStream()) { + using (var memory = new MemoryStream()) + { var deflate = new DeflateStream(memory, CompressionLevel.Optimal, leaveOpen: true); byte[] bytes = Encoding.UTF8.GetBytes(sourceText); deflate.Write(bytes, 0, bytes.Length); @@ -224,7 +246,8 @@ namespace ICSharpCode.Decompiler.DebugInfo byte[] buffer = memory.ToArray(); builder.WriteInt32(bytes.Length); // compressed builder.WriteBytes(buffer); - using (var hasher = SHA256.Create()) { + using (var hasher = SHA256.Create()) + { sourceCheckSum = hasher.ComputeHash(bytes); } } @@ -244,7 +267,8 @@ namespace ICSharpCode.Decompiler.DebugInfo int previousStartLine = -1; int previousStartColumn = -1; - for (int i = 0; i < sequencePoints.Count; i++) { + for (int i = 0; i < sequencePoints.Count; i++) + { var sequencePoint = sequencePoints[i]; // delta IL offset: if (i > 0) @@ -253,7 +277,8 @@ namespace ICSharpCode.Decompiler.DebugInfo writer.WriteCompressedInteger(sequencePoint.Offset); previousOffset = sequencePoint.Offset; - if (sequencePoint.IsHidden) { + if (sequencePoint.IsHidden) + { writer.WriteInt16(0); continue; } @@ -263,16 +288,22 @@ namespace ICSharpCode.Decompiler.DebugInfo writer.WriteCompressedInteger(lineDelta); - if (lineDelta == 0) { + if (lineDelta == 0) + { writer.WriteCompressedInteger(columnDelta); - } else { + } + else + { writer.WriteCompressedSignedInteger(columnDelta); } - if (previousStartLine < 0) { + if (previousStartLine < 0) + { writer.WriteCompressedInteger(sequencePoint.StartLine); writer.WriteCompressedInteger(sequencePoint.StartColumn); - } else { + } + else + { writer.WriteCompressedSignedInteger(sequencePoint.StartLine - previousStartLine); writer.WriteCompressedSignedInteger(sequencePoint.StartColumn - previousStartColumn); } @@ -287,7 +318,8 @@ namespace ICSharpCode.Decompiler.DebugInfo static ImmutableArray GetRowCounts(MetadataReader reader) { var builder = ImmutableArray.CreateBuilder(MetadataTokens.TableCount); - for (int i = 0; i < MetadataTokens.TableCount; i++) { + for (int i = 0; i < MetadataTokens.TableCount; i++) + { builder.Add(reader.GetTableRowCount((TableIndex)i)); } diff --git a/ICSharpCode.Decompiler/DecompileRun.cs b/ICSharpCode.Decompiler/DecompileRun.cs index 59318d09c..c917f1a6a 100644 --- a/ICSharpCode.Decompiler/DecompileRun.cs +++ b/ICSharpCode.Decompiler/DecompileRun.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Text; using System.Threading; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.TypeSystem; @@ -16,7 +17,9 @@ namespace ICSharpCode.Decompiler public DecompilerSettings Settings { get; } public IDocumentationProvider DocumentationProvider { get; set; } - Lazy usingScope => new Lazy(() => CreateUsingScope(Namespaces)); + Lazy usingScope => + new Lazy(() => CreateUsingScope(Namespaces)); + public CSharp.TypeSystem.UsingScope UsingScope => usingScope.Value; public DecompileRun(DecompilerSettings settings) @@ -27,13 +30,16 @@ namespace ICSharpCode.Decompiler CSharp.TypeSystem.UsingScope CreateUsingScope(HashSet requiredNamespacesSuperset) { var usingScope = new CSharp.TypeSystem.UsingScope(); - foreach (var ns in requiredNamespacesSuperset) { + foreach (var ns in requiredNamespacesSuperset) + { string[] parts = ns.Split('.'); AstType nsType = new SimpleType(parts[0]); - for (int i = 1; i < parts.Length; i++) { + for (int i = 1; i < parts.Length; i++) + { nsType = new MemberType { Target = nsType, MemberName = parts[i] }; } - var reference = nsType.ToTypeReference(CSharp.Resolver.NameLookupMode.TypeInUsingDeclaration) as CSharp.TypeSystem.TypeOrNamespaceReference; + var reference = nsType.ToTypeReference(CSharp.Resolver.NameLookupMode.TypeInUsingDeclaration) + as CSharp.TypeSystem.TypeOrNamespaceReference; if (reference != null) usingScope.Usings.Add(reference); } diff --git a/ICSharpCode.Decompiler/DecompilerException.cs b/ICSharpCode.Decompiler/DecompilerException.cs index c7e4394a0..ef3ba7d17 100644 --- a/ICSharpCode.Decompiler/DecompilerException.cs +++ b/ICSharpCode.Decompiler/DecompilerException.cs @@ -20,12 +20,12 @@ using System; using System.Diagnostics; using System.IO; using System.Reflection; -using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security; using System.Text; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -44,7 +44,8 @@ namespace ICSharpCode.Decompiler public IModule Module { get; } public PEFile File { get; } - public DecompilerException(MetadataModule module, IEntity decompiledEntity, Exception innerException, string message = null) + public DecompilerException(MetadataModule module, IEntity decompiledEntity, + Exception innerException, string message = null) : base(message ?? GetDefaultMessage(decompiledEntity), innerException) { this.File = module.PEFile; @@ -80,7 +81,8 @@ namespace ICSharpCode.Decompiler throw new ArgumentNullException(nameof(exception)); string exceptionType = GetTypeName(exception); string stacktrace = GetStackTrace(exception); - while (exception.InnerException != null) { + while (exception.InnerException != null) + { exception = exception.InnerException; stacktrace = GetStackTrace(exception) + Environment.NewLine @@ -105,11 +107,13 @@ namespace ICSharpCode.Decompiler static string GetStackTrace(Exception exception) { - // Output stacktrace in custom format (very similar to Exception.StackTrace property on English systems). + // Output stacktrace in custom format (very similar to Exception.StackTrace + // property on English systems). // Include filenames where available, but no paths. StackTrace stackTrace = new StackTrace(exception, true); StringBuilder b = new StringBuilder(); - for (int i = 0; i < stackTrace.FrameCount; i++) { + for (int i = 0; i < stackTrace.FrameCount; i++) + { StackFrame frame = stackTrace.GetFrame(i); MethodBase method = frame.GetMethod(); if (method == null) @@ -120,16 +124,19 @@ namespace ICSharpCode.Decompiler b.Append(" at "); Type declaringType = method.DeclaringType; - if (declaringType != null) { + if (declaringType != null) + { b.Append(declaringType.FullName.Replace('+', '.')); b.Append('.'); } b.Append(method.Name); // output type parameters, if any - if ((method is MethodInfo) && ((MethodInfo)method).IsGenericMethod) { + if ((method is MethodInfo) && ((MethodInfo)method).IsGenericMethod) + { Type[] genericArguments = ((MethodInfo)method).GetGenericArguments(); b.Append('['); - for (int j = 0; j < genericArguments.Length; j++) { + for (int j = 0; j < genericArguments.Length; j++) + { if (j > 0) b.Append(','); b.Append(genericArguments[j].Name); @@ -140,15 +147,20 @@ namespace ICSharpCode.Decompiler // output parameters, if any b.Append('('); ParameterInfo[] parameters = method.GetParameters(); - for (int j = 0; j < parameters.Length; j++) { + for (int j = 0; j < parameters.Length; j++) + { if (j > 0) b.Append(", "); - if (parameters[j].ParameterType != null) { + if (parameters[j].ParameterType != null) + { b.Append(parameters[j].ParameterType.Name); - } else { + } + else + { b.Append('?'); } - if (!string.IsNullOrEmpty(parameters[j].Name)) { + if (!string.IsNullOrEmpty(parameters[j].Name)) + { b.Append(' '); b.Append(parameters[j].Name); } @@ -156,23 +168,32 @@ namespace ICSharpCode.Decompiler b.Append(')'); // source location - if (frame.GetILOffset() >= 0) { + if (frame.GetILOffset() >= 0) + { string filename = null; - try { + try + { string fullpath = frame.GetFileName(); if (fullpath != null) filename = Path.GetFileName(fullpath); - } catch (SecurityException) { + } + catch (SecurityException) + { // StackFrame.GetFileName requires PathDiscovery permission - } catch (ArgumentException) { + } + catch (ArgumentException) + { // Path.GetFileName might throw on paths with invalid chars } b.Append(" in "); - if (filename != null) { + if (filename != null) + { b.Append(filename); b.Append(":line "); b.Append(frame.GetFileLineNumber()); - } else { + } + else + { b.Append("offset "); b.Append(frame.GetILOffset()); } diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index 56627b9de..8cf6d3a7f 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -19,6 +19,7 @@ using System; using System.ComponentModel; using System.Runtime.CompilerServices; + using ICSharpCode.Decompiler.CSharp.OutputVisitor; namespace ICSharpCode.Decompiler @@ -40,8 +41,9 @@ namespace ICSharpCode.Decompiler /// appropriate for the specified language version. /// /// - /// This does not imply that the resulting code strictly uses only language features from that version. - /// Language constructs like generics or ref locals cannot be removed from the compiled code. + /// This does not imply that the resulting code strictly uses only language features from + /// that version. Language constructs like generics or ref locals cannot be removed from + /// the compiled code. /// public DecompilerSettings(CSharp.LanguageVersion languageVersion) { @@ -55,13 +57,15 @@ namespace ICSharpCode.Decompiler { // By default, all decompiler features are enabled. // Disable some of them based on language version: - if (languageVersion < CSharp.LanguageVersion.CSharp2) { + if (languageVersion < CSharp.LanguageVersion.CSharp2) + { anonymousMethods = false; liftNullables = false; yieldReturn = false; useImplicitMethodGroupConversion = false; } - if (languageVersion < CSharp.LanguageVersion.CSharp3) { + if (languageVersion < CSharp.LanguageVersion.CSharp3) + { anonymousTypes = false; useLambdaSyntax = false; objectCollectionInitializers = false; @@ -70,15 +74,18 @@ namespace ICSharpCode.Decompiler queryExpressions = false; expressionTrees = false; } - if (languageVersion < CSharp.LanguageVersion.CSharp4) { + if (languageVersion < CSharp.LanguageVersion.CSharp4) + { dynamic = false; namedArguments = false; optionalArguments = false; } - if (languageVersion < CSharp.LanguageVersion.CSharp5) { + if (languageVersion < CSharp.LanguageVersion.CSharp5) + { asyncAwait = false; } - if (languageVersion < CSharp.LanguageVersion.CSharp6) { + if (languageVersion < CSharp.LanguageVersion.CSharp6) + { awaitInCatchFinally = false; useExpressionBodyForCalculatedGetterOnlyProperties = false; nullPropagation = false; @@ -86,7 +93,8 @@ namespace ICSharpCode.Decompiler dictionaryInitializers = false; extensionMethodsInCollectionInitializers = false; } - if (languageVersion < CSharp.LanguageVersion.CSharp7) { + if (languageVersion < CSharp.LanguageVersion.CSharp7) + { outVariables = false; throwExpressions = false; tupleTypes = false; @@ -95,19 +103,22 @@ namespace ICSharpCode.Decompiler localFunctions = false; deconstruction = false; } - if (languageVersion < CSharp.LanguageVersion.CSharp7_2) { + if (languageVersion < CSharp.LanguageVersion.CSharp7_2) + { introduceReadonlyAndInModifiers = false; introduceRefModifiersOnStructs = false; nonTrailingNamedArguments = false; refExtensionMethods = false; } - if (languageVersion < CSharp.LanguageVersion.CSharp7_3) { + if (languageVersion < CSharp.LanguageVersion.CSharp7_3) + { introduceUnmanagedConstraint = false; stackAllocInitializers = false; tupleComparisons = false; patternBasedFixedStatement = false; } - if (languageVersion < CSharp.LanguageVersion.CSharp8_0) { + if (languageVersion < CSharp.LanguageVersion.CSharp8_0) + { nullableReferenceTypes = false; readOnlyMethods = false; asyncUsingAndForEachStatement = false; @@ -117,7 +128,8 @@ namespace ICSharpCode.Decompiler ranges = false; switchExpressions = false; } - if (languageVersion < CSharp.LanguageVersion.Preview) { + if (languageVersion < CSharp.LanguageVersion.Preview) + { nativeIntegers = false; initAccessors = false; } @@ -127,14 +139,18 @@ namespace ICSharpCode.Decompiler { if (nativeIntegers || initAccessors) return CSharp.LanguageVersion.Preview; - if (nullableReferenceTypes || readOnlyMethods || asyncEnumerator || asyncUsingAndForEachStatement || staticLocalFunctions || ranges || switchExpressions) + if (nullableReferenceTypes || readOnlyMethods || asyncEnumerator || asyncUsingAndForEachStatement + || staticLocalFunctions || ranges || switchExpressions) return CSharp.LanguageVersion.CSharp8_0; - if (introduceUnmanagedConstraint || tupleComparisons || stackAllocInitializers || patternBasedFixedStatement) + if (introduceUnmanagedConstraint || tupleComparisons || stackAllocInitializers + || patternBasedFixedStatement) return CSharp.LanguageVersion.CSharp7_3; - if (introduceRefModifiersOnStructs || introduceReadonlyAndInModifiers || nonTrailingNamedArguments || refExtensionMethods) + if (introduceRefModifiersOnStructs || introduceReadonlyAndInModifiers + || nonTrailingNamedArguments || refExtensionMethods) return CSharp.LanguageVersion.CSharp7_2; // C# 7.1 missing - if (outVariables || throwExpressions || tupleTypes || tupleConversions || discards || localFunctions) + if (outVariables || throwExpressions || tupleTypes || tupleConversions + || discards || localFunctions) return CSharp.LanguageVersion.CSharp7; if (awaitInCatchFinally || useExpressionBodyForCalculatedGetterOnlyProperties || nullPropagation || stringInterpolation || dictionaryInitializers || extensionMethodsInCollectionInitializers) @@ -143,7 +159,8 @@ namespace ICSharpCode.Decompiler return CSharp.LanguageVersion.CSharp5; if (dynamic || namedArguments || optionalArguments) return CSharp.LanguageVersion.CSharp4; - if (anonymousTypes || objectCollectionInitializers || automaticProperties || queryExpressions || expressionTrees) + if (anonymousTypes || objectCollectionInitializers || automaticProperties + || queryExpressions || expressionTrees) return CSharp.LanguageVersion.CSharp3; if (anonymousMethods || liftNullables || yieldReturn || useImplicitMethodGroupConversion) return CSharp.LanguageVersion.CSharp2; @@ -160,7 +177,8 @@ namespace ICSharpCode.Decompiler public bool NativeIntegers { get { return nativeIntegers; } set { - if (nativeIntegers != value) { + if (nativeIntegers != value) + { nativeIntegers = value; OnPropertyChanged(); } @@ -177,7 +195,8 @@ namespace ICSharpCode.Decompiler public bool InitAccessors { get { return initAccessors; } set { - if (initAccessors != value) { + if (initAccessors != value) + { initAccessors = value; OnPropertyChanged(); } @@ -194,7 +213,8 @@ namespace ICSharpCode.Decompiler public bool SwitchExpressions { get { return switchExpressions; } set { - if (switchExpressions != value) { + if (switchExpressions != value) + { switchExpressions = value; OnPropertyChanged(); } @@ -211,7 +231,8 @@ namespace ICSharpCode.Decompiler public bool AnonymousMethods { get { return anonymousMethods; } set { - if (anonymousMethods != value) { + if (anonymousMethods != value) + { anonymousMethods = value; OnPropertyChanged(); } @@ -228,7 +249,8 @@ namespace ICSharpCode.Decompiler public bool AnonymousTypes { get { return anonymousTypes; } set { - if (anonymousTypes != value) { + if (anonymousTypes != value) + { anonymousTypes = value; OnPropertyChanged(); } @@ -245,7 +267,8 @@ namespace ICSharpCode.Decompiler public bool UseLambdaSyntax { get { return useLambdaSyntax; } set { - if (useLambdaSyntax != value) { + if (useLambdaSyntax != value) + { useLambdaSyntax = value; OnPropertyChanged(); } @@ -262,7 +285,8 @@ namespace ICSharpCode.Decompiler public bool ExpressionTrees { get { return expressionTrees; } set { - if (expressionTrees != value) { + if (expressionTrees != value) + { expressionTrees = value; OnPropertyChanged(); } @@ -279,7 +303,8 @@ namespace ICSharpCode.Decompiler public bool YieldReturn { get { return yieldReturn; } set { - if (yieldReturn != value) { + if (yieldReturn != value) + { yieldReturn = value; OnPropertyChanged(); } @@ -296,7 +321,8 @@ namespace ICSharpCode.Decompiler public bool Dynamic { get { return dynamic; } set { - if (dynamic != value) { + if (dynamic != value) + { dynamic = value; OnPropertyChanged(); } @@ -313,7 +339,8 @@ namespace ICSharpCode.Decompiler public bool AsyncAwait { get { return asyncAwait; } set { - if (asyncAwait != value) { + if (asyncAwait != value) + { asyncAwait = value; OnPropertyChanged(); } @@ -331,7 +358,8 @@ namespace ICSharpCode.Decompiler public bool AwaitInCatchFinally { get { return awaitInCatchFinally; } set { - if (awaitInCatchFinally != value) { + if (awaitInCatchFinally != value) + { awaitInCatchFinally = value; OnPropertyChanged(); } @@ -349,7 +377,8 @@ namespace ICSharpCode.Decompiler public bool AsyncEnumerator { get { return asyncEnumerator; } set { - if (asyncEnumerator != value) { + if (asyncEnumerator != value) + { asyncEnumerator = value; OnPropertyChanged(); } @@ -366,7 +395,8 @@ namespace ICSharpCode.Decompiler public bool DecimalConstants { get { return decimalConstants; } set { - if (decimalConstants != value) { + if (decimalConstants != value) + { decimalConstants = value; OnPropertyChanged(); } @@ -383,7 +413,8 @@ namespace ICSharpCode.Decompiler public bool FixedBuffers { get { return fixedBuffers; } set { - if (fixedBuffers != value) { + if (fixedBuffers != value) + { fixedBuffers = value; OnPropertyChanged(); } @@ -400,7 +431,8 @@ namespace ICSharpCode.Decompiler public bool LiftNullables { get { return liftNullables; } set { - if (liftNullables != value) { + if (liftNullables != value) + { liftNullables = value; OnPropertyChanged(); } @@ -417,7 +449,8 @@ namespace ICSharpCode.Decompiler public bool NullPropagation { get { return nullPropagation; } set { - if (nullPropagation != value) { + if (nullPropagation != value) + { nullPropagation = value; OnPropertyChanged(); } @@ -434,7 +467,8 @@ namespace ICSharpCode.Decompiler public bool AutomaticProperties { get { return automaticProperties; } set { - if (automaticProperties != value) { + if (automaticProperties != value) + { automaticProperties = value; OnPropertyChanged(); } @@ -451,7 +485,8 @@ namespace ICSharpCode.Decompiler public bool AutomaticEvents { get { return automaticEvents; } set { - if (automaticEvents != value) { + if (automaticEvents != value) + { automaticEvents = value; OnPropertyChanged(); } @@ -468,7 +503,8 @@ namespace ICSharpCode.Decompiler public bool UsingStatement { get { return usingStatement; } set { - if (usingStatement != value) { + if (usingStatement != value) + { usingStatement = value; OnPropertyChanged(); } @@ -485,7 +521,8 @@ namespace ICSharpCode.Decompiler public bool UseEnhancedUsing { get { return useEnhancedUsing; } set { - if (useEnhancedUsing != value) { + if (useEnhancedUsing != value) + { useEnhancedUsing = value; OnPropertyChanged(); } @@ -502,7 +539,8 @@ namespace ICSharpCode.Decompiler public bool AlwaysUseBraces { get { return alwaysUseBraces; } set { - if (alwaysUseBraces != value) { + if (alwaysUseBraces != value) + { alwaysUseBraces = value; OnPropertyChanged(); } @@ -519,7 +557,8 @@ namespace ICSharpCode.Decompiler public bool ForEachStatement { get { return forEachStatement; } set { - if (forEachStatement != value) { + if (forEachStatement != value) + { forEachStatement = value; OnPropertyChanged(); } @@ -536,7 +575,8 @@ namespace ICSharpCode.Decompiler public bool LockStatement { get { return lockStatement; } set { - if (lockStatement != value) { + if (lockStatement != value) + { lockStatement = value; OnPropertyChanged(); } @@ -550,7 +590,8 @@ namespace ICSharpCode.Decompiler public bool SwitchStatementOnString { get { return switchStatementOnString; } set { - if (switchStatementOnString != value) { + if (switchStatementOnString != value) + { switchStatementOnString = value; OnPropertyChanged(); } @@ -564,7 +605,8 @@ namespace ICSharpCode.Decompiler public bool UsingDeclarations { get { return usingDeclarations; } set { - if (usingDeclarations != value) { + if (usingDeclarations != value) + { usingDeclarations = value; OnPropertyChanged(); } @@ -578,7 +620,8 @@ namespace ICSharpCode.Decompiler public bool ExtensionMethods { get { return extensionMethods; } set { - if (extensionMethods != value) { + if (extensionMethods != value) + { extensionMethods = value; OnPropertyChanged(); } @@ -592,7 +635,8 @@ namespace ICSharpCode.Decompiler public bool QueryExpressions { get { return queryExpressions; } set { - if (queryExpressions != value) { + if (queryExpressions != value) + { queryExpressions = value; OnPropertyChanged(); } @@ -611,7 +655,8 @@ namespace ICSharpCode.Decompiler public bool UseImplicitMethodGroupConversion { get { return useImplicitMethodGroupConversion; } set { - if (useImplicitMethodGroupConversion != value) { + if (useImplicitMethodGroupConversion != value) + { useImplicitMethodGroupConversion = value; OnPropertyChanged(); } @@ -631,7 +676,8 @@ namespace ICSharpCode.Decompiler public bool AlwaysCastTargetsOfExplicitInterfaceImplementationCalls { get { return alwaysCastTargetsOfExplicitInterfaceImplementationCalls; } set { - if (alwaysCastTargetsOfExplicitInterfaceImplementationCalls != value) { + if (alwaysCastTargetsOfExplicitInterfaceImplementationCalls != value) + { alwaysCastTargetsOfExplicitInterfaceImplementationCalls = value; OnPropertyChanged(); } @@ -651,7 +697,8 @@ namespace ICSharpCode.Decompiler public bool AlwaysQualifyMemberReferences { get { return alwaysQualifyMemberReferences; } set { - if (alwaysQualifyMemberReferences != value) { + if (alwaysQualifyMemberReferences != value) + { alwaysQualifyMemberReferences = value; OnPropertyChanged(); } @@ -671,7 +718,8 @@ namespace ICSharpCode.Decompiler public bool AlwaysShowEnumMemberValues { get { return alwaysShowEnumMemberValues; } set { - if (alwaysShowEnumMemberValues != value) { + if (alwaysShowEnumMemberValues != value) + { alwaysShowEnumMemberValues = value; OnPropertyChanged(); } @@ -688,7 +736,8 @@ namespace ICSharpCode.Decompiler public bool UseDebugSymbols { get { return useDebugSymbols; } set { - if (useDebugSymbols != value) { + if (useDebugSymbols != value) + { useDebugSymbols = value; OnPropertyChanged(); } @@ -703,11 +752,9 @@ namespace ICSharpCode.Decompiler /// [Category("C# 1.0 / VS .NET")] [Description("DecompilerSettings.ArrayInitializerExpressions")] - public bool ArrayInitializers - { + public bool ArrayInitializers { get { return arrayInitializers; } - set - { + set { if (arrayInitializers != value) { arrayInitializers = value; @@ -726,7 +773,8 @@ namespace ICSharpCode.Decompiler public bool ObjectOrCollectionInitializers { get { return objectCollectionInitializers; } set { - if (objectCollectionInitializers != value) { + if (objectCollectionInitializers != value) + { objectCollectionInitializers = value; OnPropertyChanged(); } @@ -744,7 +792,8 @@ namespace ICSharpCode.Decompiler public bool DictionaryInitializers { get { return dictionaryInitializers; } set { - if (dictionaryInitializers != value) { + if (dictionaryInitializers != value) + { dictionaryInitializers = value; OnPropertyChanged(); } @@ -762,7 +811,8 @@ namespace ICSharpCode.Decompiler public bool ExtensionMethodsInCollectionInitializers { get { return extensionMethodsInCollectionInitializers; } set { - if (extensionMethodsInCollectionInitializers != value) { + if (extensionMethodsInCollectionInitializers != value) + { extensionMethodsInCollectionInitializers = value; OnPropertyChanged(); } @@ -779,7 +829,8 @@ namespace ICSharpCode.Decompiler public bool RefExtensionMethods { get { return refExtensionMethods; } set { - if (refExtensionMethods != value) { + if (refExtensionMethods != value) + { refExtensionMethods = value; OnPropertyChanged(); } @@ -796,7 +847,8 @@ namespace ICSharpCode.Decompiler public bool StringInterpolation { get { return stringInterpolation; } set { - if (stringInterpolation != value) { + if (stringInterpolation != value) + { stringInterpolation = value; OnPropertyChanged(); } @@ -813,7 +865,8 @@ namespace ICSharpCode.Decompiler public bool ShowXmlDocumentation { get { return showXmlDocumentation; } set { - if (showXmlDocumentation != value) { + if (showXmlDocumentation != value) + { showXmlDocumentation = value; OnPropertyChanged(); } @@ -826,7 +879,8 @@ namespace ICSharpCode.Decompiler public bool FoldBraces { get { return foldBraces; } set { - if (foldBraces != value) { + if (foldBraces != value) + { foldBraces = value; OnPropertyChanged(); } @@ -839,7 +893,8 @@ namespace ICSharpCode.Decompiler public bool ExpandMemberDefinitions { get { return expandMemberDefinitions; } set { - if (expandMemberDefinitions != value) { + if (expandMemberDefinitions != value) + { expandMemberDefinitions = value; OnPropertyChanged(); } @@ -852,7 +907,8 @@ namespace ICSharpCode.Decompiler public bool ExpandUsingDeclarations { get { return expandUsingDeclarations; } set { - if (expandUsingDeclarations != value) { + if (expandUsingDeclarations != value) + { expandUsingDeclarations = value; OnPropertyChanged(); } @@ -869,7 +925,8 @@ namespace ICSharpCode.Decompiler public bool DecompileMemberBodies { get { return decompileMemberBodies; } set { - if (decompileMemberBodies != value) { + if (decompileMemberBodies != value) + { decompileMemberBodies = value; OnPropertyChanged(); } @@ -879,14 +936,16 @@ namespace ICSharpCode.Decompiler bool useExpressionBodyForCalculatedGetterOnlyProperties = true; /// - /// Gets/Sets whether simple calculated getter-only property declarations should use expression body syntax. + /// Gets/Sets whether simple calculated getter-only property declarations + /// should use expression body syntax. /// [Category("C# 6.0 / VS 2015")] [Description("DecompilerSettings.UseExpressionBodiedMemberSyntaxForGetOnlyProperties")] public bool UseExpressionBodyForCalculatedGetterOnlyProperties { get { return useExpressionBodyForCalculatedGetterOnlyProperties; } set { - if (useExpressionBodyForCalculatedGetterOnlyProperties != value) { + if (useExpressionBodyForCalculatedGetterOnlyProperties != value) + { useExpressionBodyForCalculatedGetterOnlyProperties = value; OnPropertyChanged(); } @@ -903,7 +962,8 @@ namespace ICSharpCode.Decompiler public bool OutVariables { get { return outVariables; } set { - if (outVariables != value) { + if (outVariables != value) + { outVariables = value; OnPropertyChanged(); } @@ -921,7 +981,8 @@ namespace ICSharpCode.Decompiler public bool Discards { get { return discards; } set { - if (discards != value) { + if (discards != value) + { discards = value; OnPropertyChanged(); } @@ -938,7 +999,8 @@ namespace ICSharpCode.Decompiler public bool IntroduceRefModifiersOnStructs { get { return introduceRefModifiersOnStructs; } set { - if (introduceRefModifiersOnStructs != value) { + if (introduceRefModifiersOnStructs != value) + { introduceRefModifiersOnStructs = value; OnPropertyChanged(); } @@ -952,11 +1014,13 @@ namespace ICSharpCode.Decompiler /// and with the 'in' modifier on parameters. /// [Category("C# 7.2 / VS 2017.4")] - [Description("DecompilerSettings.IsReadOnlyAttributeShouldBeReplacedWithReadonlyInModifiersOnStructsParameters")] + [Description("DecompilerSettings." + + "IsReadOnlyAttributeShouldBeReplacedWithReadonlyInModifiersOnStructsParameters")] public bool IntroduceReadonlyAndInModifiers { get { return introduceReadonlyAndInModifiers; } set { - if (introduceReadonlyAndInModifiers != value) { + if (introduceReadonlyAndInModifiers != value) + { introduceReadonlyAndInModifiers = value; OnPropertyChanged(); } @@ -970,7 +1034,8 @@ namespace ICSharpCode.Decompiler public bool ReadOnlyMethods { get { return readOnlyMethods; } set { - if (readOnlyMethods != value) { + if (readOnlyMethods != value) + { readOnlyMethods = value; OnPropertyChanged(); } @@ -984,7 +1049,8 @@ namespace ICSharpCode.Decompiler public bool AsyncUsingAndForEachStatement { get { return asyncUsingAndForEachStatement; } set { - if (asyncUsingAndForEachStatement != value) { + if (asyncUsingAndForEachStatement != value) + { asyncUsingAndForEachStatement = value; OnPropertyChanged(); } @@ -998,11 +1064,13 @@ namespace ICSharpCode.Decompiler /// is replaced with "T : unmanaged" constraints. /// [Category("C# 7.3 / VS 2017.7")] - [Description("DecompilerSettings.IsUnmanagedAttributeOnTypeParametersShouldBeReplacedWithUnmanagedConstraints")] + [Description("DecompilerSettings." + + "IsUnmanagedAttributeOnTypeParametersShouldBeReplacedWithUnmanagedConstraints")] public bool IntroduceUnmanagedConstraint { get { return introduceUnmanagedConstraint; } set { - if (introduceUnmanagedConstraint != value) { + if (introduceUnmanagedConstraint != value) + { introduceUnmanagedConstraint = value; OnPropertyChanged(); } @@ -1019,7 +1087,8 @@ namespace ICSharpCode.Decompiler public bool StackAllocInitializers { get { return stackAllocInitializers; } set { - if (stackAllocInitializers != value) { + if (stackAllocInitializers != value) + { stackAllocInitializers = value; OnPropertyChanged(); } @@ -1036,7 +1105,8 @@ namespace ICSharpCode.Decompiler public bool PatternBasedFixedStatement { get { return patternBasedFixedStatement; } set { - if (patternBasedFixedStatement != value) { + if (patternBasedFixedStatement != value) + { patternBasedFixedStatement = value; OnPropertyChanged(); } @@ -1054,7 +1124,8 @@ namespace ICSharpCode.Decompiler public bool TupleTypes { get { return tupleTypes; } set { - if (tupleTypes != value) { + if (tupleTypes != value) + { tupleTypes = value; OnPropertyChanged(); } @@ -1071,7 +1142,8 @@ namespace ICSharpCode.Decompiler public bool ThrowExpressions { get { return throwExpressions; } set { - if (throwExpressions != value) { + if (throwExpressions != value) + { throwExpressions = value; OnPropertyChanged(); } @@ -1089,7 +1161,8 @@ namespace ICSharpCode.Decompiler public bool TupleConversions { get { return tupleConversions; } set { - if (tupleConversions != value) { + if (tupleConversions != value) + { tupleConversions = value; OnPropertyChanged(); } @@ -1106,13 +1179,14 @@ namespace ICSharpCode.Decompiler public bool TupleComparisons { get { return tupleComparisons; } set { - if (tupleComparisons != value) { + if (tupleComparisons != value) + { tupleComparisons = value; OnPropertyChanged(); } } } - + bool namedArguments = true; /// @@ -1123,7 +1197,8 @@ namespace ICSharpCode.Decompiler public bool NamedArguments { get { return namedArguments; } set { - if (namedArguments != value) { + if (namedArguments != value) + { namedArguments = value; OnPropertyChanged(); } @@ -1140,7 +1215,8 @@ namespace ICSharpCode.Decompiler public bool NonTrailingNamedArguments { get { return nonTrailingNamedArguments; } set { - if (nonTrailingNamedArguments != value) { + if (nonTrailingNamedArguments != value) + { nonTrailingNamedArguments = value; OnPropertyChanged(); } @@ -1157,7 +1233,8 @@ namespace ICSharpCode.Decompiler public bool OptionalArguments { get { return optionalArguments; } set { - if (optionalArguments != value) { + if (optionalArguments != value) + { optionalArguments = value; OnPropertyChanged(); } @@ -1174,7 +1251,8 @@ namespace ICSharpCode.Decompiler public bool LocalFunctions { get { return localFunctions; } set { - if (localFunctions != value) { + if (localFunctions != value) + { localFunctions = value; OnPropertyChanged(); } @@ -1191,7 +1269,8 @@ namespace ICSharpCode.Decompiler public bool Deconstruction { get { return deconstruction; } set { - if (deconstruction != value) { + if (deconstruction != value) + { deconstruction = value; OnPropertyChanged(); } @@ -1208,7 +1287,8 @@ namespace ICSharpCode.Decompiler public bool StaticLocalFunctions { get { return staticLocalFunctions; } set { - if (staticLocalFunctions != value) { + if (staticLocalFunctions != value) + { staticLocalFunctions = value; OnPropertyChanged(); } @@ -1225,7 +1305,8 @@ namespace ICSharpCode.Decompiler public bool Ranges { get { return ranges; } set { - if (ranges != value) { + if (ranges != value) + { ranges = value; OnPropertyChanged(); } @@ -1242,7 +1323,8 @@ namespace ICSharpCode.Decompiler public bool NullableReferenceTypes { get { return nullableReferenceTypes; } set { - if (nullableReferenceTypes != value) { + if (nullableReferenceTypes != value) + { nullableReferenceTypes = value; OnPropertyChanged(); } @@ -1257,7 +1339,8 @@ namespace ICSharpCode.Decompiler public bool ShowDebugInfo { get { return showDebugInfo; } set { - if (showDebugInfo != value) { + if (showDebugInfo != value) + { showDebugInfo = value; OnPropertyChanged(); } @@ -1268,14 +1351,16 @@ namespace ICSharpCode.Decompiler bool assumeArrayLengthFitsIntoInt32 = true; /// - /// Gets/Sets whether the decompiler can assume that 'ldlen; conv.i4.ovf' does not throw an overflow exception. + /// Gets/Sets whether the decompiler can assume that 'ldlen; conv.i4.ovf' + /// does not throw an overflow exception. /// [Category("DecompilerSettings.VBSpecificOptions")] [Browsable(false)] public bool AssumeArrayLengthFitsIntoInt32 { get { return assumeArrayLengthFitsIntoInt32; } set { - if (assumeArrayLengthFitsIntoInt32 != value) { + if (assumeArrayLengthFitsIntoInt32 != value) + { assumeArrayLengthFitsIntoInt32 = value; OnPropertyChanged(); } @@ -1292,7 +1377,8 @@ namespace ICSharpCode.Decompiler public bool IntroduceIncrementAndDecrement { get { return introduceIncrementAndDecrement; } set { - if (introduceIncrementAndDecrement != value) { + if (introduceIncrementAndDecrement != value) + { introduceIncrementAndDecrement = value; OnPropertyChanged(); } @@ -1309,7 +1395,8 @@ namespace ICSharpCode.Decompiler public bool MakeAssignmentExpressions { get { return makeAssignmentExpressions; } set { - if (makeAssignmentExpressions != value) { + if (makeAssignmentExpressions != value) + { makeAssignmentExpressions = value; OnPropertyChanged(); } @@ -1326,7 +1413,8 @@ namespace ICSharpCode.Decompiler public bool RemoveDeadCode { get { return removeDeadCode; } set { - if (removeDeadCode != value) { + if (removeDeadCode != value) + { removeDeadCode = value; OnPropertyChanged(); } @@ -1340,7 +1428,8 @@ namespace ICSharpCode.Decompiler public bool RemoveDeadStores { get { return removeDeadStores; } set { - if (removeDeadStores != value) { + if (removeDeadStores != value) + { removeDeadStores = value; OnPropertyChanged(); } @@ -1356,7 +1445,8 @@ namespace ICSharpCode.Decompiler public bool LoadInMemory { get { return loadInMemory; } set { - if (loadInMemory != value) { + if (loadInMemory != value) + { loadInMemory = value; OnPropertyChanged(); } @@ -1369,7 +1459,8 @@ namespace ICSharpCode.Decompiler public bool ThrowOnAssemblyResolveErrors { get { return throwOnAssemblyResolveErrors; } set { - if (throwOnAssemblyResolveErrors != value) { + if (throwOnAssemblyResolveErrors != value) + { throwOnAssemblyResolveErrors = value; OnPropertyChanged(); } @@ -1383,7 +1474,8 @@ namespace ICSharpCode.Decompiler public bool ApplyWindowsRuntimeProjections { get { return applyWindowsRuntimeProjections; } set { - if (applyWindowsRuntimeProjections != value) { + if (applyWindowsRuntimeProjections != value) + { applyWindowsRuntimeProjections = value; OnPropertyChanged(); } @@ -1402,7 +1494,8 @@ namespace ICSharpCode.Decompiler public bool ForStatement { get { return forStatement; } set { - if (forStatement != value) { + if (forStatement != value) + { forStatement = value; OnPropertyChanged(); } @@ -1419,7 +1512,8 @@ namespace ICSharpCode.Decompiler public bool DoWhileStatement { get { return doWhileStatement; } set { - if (doWhileStatement != value) { + if (doWhileStatement != value) + { doWhileStatement = value; OnPropertyChanged(); } @@ -1429,14 +1523,16 @@ namespace ICSharpCode.Decompiler bool separateLocalVariableDeclarations = false; /// - /// Gets/sets whether the decompiler should separate local variable declarations from their initialization. + /// Gets/sets whether the decompiler should separate local variable declarations + /// from their initialization. /// [Category("DecompilerSettings.Other")] [Description("DecompilerSettings.SeparateLocalVariableDeclarations")] public bool SeparateLocalVariableDeclarations { get { return separateLocalVariableDeclarations; } set { - if (separateLocalVariableDeclarations != value) { + if (separateLocalVariableDeclarations != value) + { separateLocalVariableDeclarations = value; OnPropertyChanged(); } @@ -1454,7 +1550,8 @@ namespace ICSharpCode.Decompiler public bool UseSdkStyleProjectFormat { get { return useSdkStyleProjectFormat; } set { - if (useSdkStyleProjectFormat != value) { + if (useSdkStyleProjectFormat != value) + { useSdkStyleProjectFormat = value; OnPropertyChanged(); } @@ -1472,7 +1569,8 @@ namespace ICSharpCode.Decompiler public bool AggressiveScalarReplacementOfAggregates { get { return aggressiveScalarReplacementOfAggregates; } set { - if (aggressiveScalarReplacementOfAggregates != value) { + if (aggressiveScalarReplacementOfAggregates != value) + { aggressiveScalarReplacementOfAggregates = value; OnPropertyChanged(); } @@ -1491,7 +1589,8 @@ namespace ICSharpCode.Decompiler public bool AggressiveInlining { get { return aggressiveInlining; } set { - if (aggressiveInlining != value) { + if (aggressiveInlining != value) + { aggressiveInlining = value; OnPropertyChanged(); } @@ -1503,7 +1602,8 @@ namespace ICSharpCode.Decompiler [Browsable(false)] public CSharpFormattingOptions CSharpFormattingOptions { get { - if (csharpFormattingOptions == null) { + if (csharpFormattingOptions == null) + { csharpFormattingOptions = FormattingOptionsFactory.CreateAllman(); csharpFormattingOptions.IndentSwitchBody = false; csharpFormattingOptions.ArrayInitializerWrapping = Wrapping.WrapAlways; @@ -1513,7 +1613,8 @@ namespace ICSharpCode.Decompiler set { if (value == null) throw new ArgumentNullException(); - if (csharpFormattingOptions != value) { + if (csharpFormattingOptions != value) + { csharpFormattingOptions = value; OnPropertyChanged(); } @@ -1524,7 +1625,8 @@ namespace ICSharpCode.Decompiler protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { - if (PropertyChanged != null) { + if (PropertyChanged != null) + { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index f498c6f78..b20dfeb75 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -21,9 +21,11 @@ using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; using System.Text; + using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; + using SRM = System.Reflection.Metadata; namespace ICSharpCode.Decompiler.Disassembler @@ -54,7 +56,7 @@ namespace ICSharpCode.Decompiler.Disassembler { return string.Format("IL_{0:x4}", offset); } - + public static string OffsetToString(long offset) { return string.Format("IL_{0:x4}", offset); @@ -76,12 +78,14 @@ namespace ICSharpCode.Decompiler.Disassembler WriteOffsetReference(writer, exceptionHandler.TryOffset + exceptionHandler.TryLength); writer.Write(' '); writer.Write(exceptionHandler.Kind.ToString().ToLowerInvariant()); - if (exceptionHandler.FilterOffset != -1) { + if (exceptionHandler.FilterOffset != -1) + { writer.Write(' '); WriteOffsetReference(writer, exceptionHandler.FilterOffset); writer.Write(" handler "); } - if (!exceptionHandler.CatchType.IsNil) { + if (!exceptionHandler.CatchType.IsNil) + { writer.Write(' '); exceptionHandler.CatchType.WriteTo(module, writer, context); } @@ -108,11 +112,13 @@ namespace ICSharpCode.Decompiler.Disassembler { if (string.IsNullOrEmpty(identifier)) return false; - if (!(char.IsLetter(identifier[0]) || IsValidIdentifierCharacter(identifier[0]))) { + if (!(char.IsLetter(identifier[0]) || IsValidIdentifierCharacter(identifier[0]))) + { // As a special case, .ctor and .cctor are valid despite starting with a dot return identifier == ".ctor" || identifier == ".cctor"; } - for (int i = 1; i < identifier.Length; i++) { + for (int i = 1; i < identifier.Length; i++) + { if (!(char.IsLetterOrDigit(identifier[i]) || IsValidIdentifierCharacter(identifier[i]) || identifier[i] == '.')) return false; } @@ -121,9 +127,12 @@ namespace ICSharpCode.Decompiler.Disassembler public static string Escape(string identifier) { - if (IsValidIdentifier(identifier) && !Metadata.ILOpCodeExtensions.ILKeywords.Contains(identifier)) { + if (IsValidIdentifier(identifier) && !Metadata.ILOpCodeExtensions.ILKeywords.Contains(identifier)) + { return identifier; - } else { + } + else + { // The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence, // but we follow Microsoft's ILDasm and use \'. return "'" + EscapeString(identifier).Replace("'", "\\'") + "'"; @@ -137,16 +146,23 @@ namespace ICSharpCode.Decompiler.Disassembler var parameters = methodDefinition.GetParameters().Select(p => metadata.GetParameter(p)).ToArray(); var signatureHeader = signature.Header; int index = sequence; - if (signatureHeader.IsInstance && signature.ParameterTypes.Length == parameters.Length) { + if (signatureHeader.IsInstance && signature.ParameterTypes.Length == parameters.Length) + { index--; } - if (index < 0 || index >= parameters.Length) { + if (index < 0 || index >= parameters.Length) + { writer.WriteLocalReference(sequence.ToString(), "param_" + index); - } else { + } + else + { var param = parameters[index]; - if (param.Name.IsNil) { + if (param.Name.IsNil) + { writer.WriteLocalReference(sequence.ToString(), "param_" + index); - } else { + } + else + { writer.WriteLocalReference(Escape(metadata.GetString(param.Name)), "param_" + index); } } @@ -163,17 +179,28 @@ namespace ICSharpCode.Decompiler.Disassembler throw new ArgumentNullException(nameof(operand)); string s = operand as string; - if (s != null) { + if (s != null) + { WriteOperand(writer, s); - } else if (operand is char) { + } + else if (operand is char) + { writer.Write(((int)(char)operand).ToString()); - } else if (operand is float) { + } + else if (operand is float) + { WriteOperand(writer, (float)operand); - } else if (operand is double) { + } + else if (operand is double) + { WriteOperand(writer, (double)operand); - } else if (operand is bool) { + } + else if (operand is bool) + { writer.Write((bool)operand ? "true" : "false"); - } else { + } + else + { s = ToInvariantCultureString(operand); writer.Write(s); } @@ -186,44 +213,58 @@ namespace ICSharpCode.Decompiler.Disassembler public static void WriteOperand(ITextOutput writer, float val) { - if (val == 0) { - if (1 / val == float.NegativeInfinity) { + if (val == 0) + { + if (1 / val == float.NegativeInfinity) + { // negative zero is a special case writer.Write('-'); } writer.Write("0.0"); - } else if (float.IsInfinity(val) || float.IsNaN(val)) { + } + else if (float.IsInfinity(val) || float.IsNaN(val)) + { byte[] data = BitConverter.GetBytes(val); writer.Write('('); - for (int i = 0; i < data.Length; i++) { + for (int i = 0; i < data.Length; i++) + { if (i > 0) writer.Write(' '); writer.Write(data[i].ToString("X2")); } writer.Write(')'); - } else { + } + else + { writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture)); } } public static void WriteOperand(ITextOutput writer, double val) { - if (val == 0) { - if (1 / val == double.NegativeInfinity) { + if (val == 0) + { + if (1 / val == double.NegativeInfinity) + { // negative zero is a special case writer.Write('-'); } writer.Write("0.0"); - } else if (double.IsInfinity(val) || double.IsNaN(val)) { + } + else if (double.IsInfinity(val) || double.IsNaN(val)) + { byte[] data = BitConverter.GetBytes(val); writer.Write('('); - for (int i = 0; i < data.Length; i++) { + for (int i = 0; i < data.Length; i++) + { if (i > 0) writer.Write(' '); writer.Write(data[i].ToString("X2")); } writer.Write(')'); - } else { + } + else + { writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture)); } } @@ -238,8 +279,10 @@ namespace ICSharpCode.Decompiler.Disassembler public static string EscapeString(string str) { StringBuilder sb = new StringBuilder(); - foreach (char ch in str) { - switch (ch) { + foreach (char ch in str) + { + switch (ch) + { case '"': sb.Append("\\\""); break; @@ -272,9 +315,12 @@ namespace ICSharpCode.Decompiler.Disassembler break; default: // print control characters and uncommon white spaces as numbers - if (char.IsControl(ch) || char.IsSurrogate(ch) || (char.IsWhiteSpace(ch) && ch != ' ')) { + if (char.IsControl(ch) || char.IsSurrogate(ch) || (char.IsWhiteSpace(ch) && ch != ' ')) + { sb.Append("\\u" + ((int)ch).ToString("x4")); - } else { + } + else + { sb.Append(ch); } break; @@ -284,7 +330,8 @@ namespace ICSharpCode.Decompiler.Disassembler } public static string PrimitiveTypeName(string fullName) { - switch (fullName) { + switch (fullName) + { case "System.SByte": return "int8"; case "System.Int16": diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs index 7954ab2b5..7191f389f 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerSignatureTypeProvider.cs @@ -20,8 +20,8 @@ using System; using System.Collections.Immutable; using System.Reflection.Metadata; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.IL; +using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.Disassembler { @@ -44,12 +44,15 @@ namespace ICSharpCode.Decompiler.Disassembler var syntaxForElementTypes = syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature; elementType(syntaxForElementTypes); output.Write('['); - for (int i = 0; i < shape.Rank; i++) { + for (int i = 0; i < shape.Rank; i++) + { if (i > 0) output.Write(", "); - if (i < shape.LowerBounds.Length || i < shape.Sizes.Length) { + if (i < shape.LowerBounds.Length || i < shape.Sizes.Length) + { int lower = 0; - if (i < shape.LowerBounds.Length) { + if (i < shape.LowerBounds.Length) + { lower = shape.LowerBounds[i]; output.Write(lower.ToString()); } @@ -77,7 +80,8 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write("method "); signature.ReturnType(syntax); output.Write(" *("); - for (int i = 0; i < signature.ParameterTypes.Length; i++) { + for (int i = 0; i < signature.ParameterTypes.Length; i++) + { if (i > 0) output.Write(", "); signature.ParameterTypes[i](syntax); @@ -92,7 +96,8 @@ namespace ICSharpCode.Decompiler.Disassembler var syntaxForElementTypes = syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature; genericType(syntaxForElementTypes); output.Write('<'); - for (int i = 0; i < typeArguments.Length; i++) { + for (int i = 0; i < typeArguments.Length; i++) + { if (i > 0) output.Write(", "); typeArguments[i](syntaxForElementTypes); @@ -121,7 +126,8 @@ namespace ICSharpCode.Decompiler.Disassembler { if (paramRef.IsNil || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) output.Write(index.ToString()); - else { + else + { var param = metadata.GetGenericParameter(paramRef); if (param.Name.IsNil) output.Write(param.Index.ToString()); @@ -164,7 +170,8 @@ namespace ICSharpCode.Decompiler.Disassembler public Action GetPrimitiveType(PrimitiveTypeCode typeCode) { - switch (typeCode) { + switch (typeCode) + { case PrimitiveTypeCode.SByte: return syntax => output.Write("int8"); case PrimitiveTypeCode.Int16: @@ -219,7 +226,8 @@ namespace ICSharpCode.Decompiler.Disassembler public Action GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) { return syntax => { - switch (rawTypeKind) { + switch (rawTypeKind) + { case 0x00: break; case 0x11: @@ -238,7 +246,8 @@ namespace ICSharpCode.Decompiler.Disassembler public Action GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) { return syntax => { - switch (rawTypeKind) { + switch (rawTypeKind) + { case 0x00: break; case 0x11: diff --git a/ICSharpCode.Decompiler/Disassembler/ILParser.cs b/ICSharpCode.Decompiler/Disassembler/ILParser.cs index 5e7191cc8..4cb364790 100644 --- a/ICSharpCode.Decompiler/Disassembler/ILParser.cs +++ b/ICSharpCode.Decompiler/Disassembler/ILParser.cs @@ -19,6 +19,7 @@ using System; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.Disassembler @@ -33,7 +34,8 @@ namespace ICSharpCode.Decompiler.Disassembler public static void SkipOperand(this ref BlobReader blob, ILOpCode opCode) { - switch (opCode.GetOperandType()) { + switch (opCode.GetOperandType()) + { // 64-bit case OperandType.I8: case OperandType.R: @@ -90,7 +92,8 @@ namespace ICSharpCode.Decompiler.Disassembler public static int DecodeIndex(this ref BlobReader blob, ILOpCode opCode) { - switch (opCode.GetOperandType()) { + switch (opCode.GetOperandType()) + { case OperandType.ShortVariable: return blob.ReadByte(); case OperandType.Variable: diff --git a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs index 3a4057850..96900d561 100644 --- a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs +++ b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; @@ -91,7 +92,8 @@ namespace ICSharpCode.Decompiler.Disassembler : this(module, handle, genericContext, ILStructureType.Root, 0, body.GetILReader().Length) { // Build the tree of exception structures: - for (int i = 0; i < body.ExceptionRegions.Length; i++) { + for (int i = 0; i < body.ExceptionRegions.Length; i++) + { ExceptionRegion eh = body.ExceptionRegions[i]; if (!body.ExceptionRegions.Take(i).Any(oldEh => oldEh.TryOffset == eh.TryOffset && oldEh.TryLength == eh.TryLength)) AddNestedStructure(new ILStructure(module, handle, genericContext, ILStructureType.Try, eh.TryOffset, eh.TryOffset + eh.TryLength, eh)); @@ -102,10 +104,12 @@ namespace ICSharpCode.Decompiler.Disassembler // Very simple loop detection: look for backward branches (var allBranches, var isAfterUnconditionalBranch) = FindAllBranches(body.GetILReader()); // We go through the branches in reverse so that we find the biggest possible loop boundary first (think loops with "continue;") - for (int i = allBranches.Count - 1; i >= 0; i--) { + for (int i = allBranches.Count - 1; i >= 0; i--) + { int loopEnd = allBranches[i].Source.End; int loopStart = allBranches[i].Target; - if (loopStart < loopEnd) { + if (loopStart < loopEnd) + { // We found a backward branch. This is a potential loop. // Check that is has only one entry point: int entryPoint = -1; @@ -113,11 +117,14 @@ namespace ICSharpCode.Decompiler.Disassembler // entry point is first instruction in loop if prev inst isn't an unconditional branch if (loopStart > 0 && !isAfterUnconditionalBranch[loopStart]) entryPoint = allBranches[i].Target; - + bool multipleEntryPoints = false; - foreach (var branch in allBranches) { - if (branch.Source.Start < loopStart || branch.Source.Start >= loopEnd) { - if (loopStart <= branch.Target && branch.Target < loopEnd) { + foreach (var branch in allBranches) + { + if (branch.Source.Start < loopStart || branch.Source.Start >= loopEnd) + { + if (loopStart <= branch.Target && branch.Target < loopEnd) + { // jump from outside the loop into the loop if (entryPoint < 0) entryPoint = branch.Target; @@ -126,7 +133,8 @@ namespace ICSharpCode.Decompiler.Disassembler } } } - if (!multipleEntryPoints) { + if (!multipleEntryPoints) + { AddNestedStructure(new ILStructure(module, handle, genericContext, ILStructureType.Loop, loopStart, loopEnd, entryPoint)); } } @@ -166,21 +174,28 @@ namespace ICSharpCode.Decompiler.Disassembler // use <= for end-offset comparisons because both end and EndOffset are exclusive Debug.Assert(StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= EndOffset); - foreach (ILStructure child in this.Children) { - if (child.StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= child.EndOffset) { + foreach (ILStructure child in this.Children) + { + if (child.StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= child.EndOffset) + { return child.AddNestedStructure(newStructure); - } else if (!(child.EndOffset <= newStructure.StartOffset || newStructure.EndOffset <= child.StartOffset)) { + } + else if (!(child.EndOffset <= newStructure.StartOffset || newStructure.EndOffset <= child.StartOffset)) + { // child and newStructure overlap - if (!(newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset)) { + if (!(newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset)) + { // Invalid nesting, can't build a tree. -> Don't add the new structure. return false; } } } // Move existing structures into the new structure: - for (int i = 0; i < this.Children.Count; i++) { + for (int i = 0; i < this.Children.Count; i++) + { ILStructure child = this.Children[i]; - if (newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset) { + if (newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset) + { this.Children.RemoveAt(i--); newStructure.Children.Add(child); } @@ -218,11 +233,13 @@ namespace ICSharpCode.Decompiler.Disassembler var bitset = new BitSet(body.Length + 1); body.Reset(); int target; - while (body.RemainingBytes > 0) { + while (body.RemainingBytes > 0) + { var offset = body.Offset; int endOffset; var thisOpCode = body.DecodeOpCode(); - switch (thisOpCode.GetOperandType()) { + switch (thisOpCode.GetOperandType()) + { case OperandType.BrTarget: case OperandType.ShortBrTarget: target = ILParser.DecodeBranchTarget(ref body, thisOpCode); @@ -246,7 +263,8 @@ namespace ICSharpCode.Decompiler.Disassembler static bool IsUnconditionalBranch(ILOpCode opCode) { - switch (opCode) { + switch (opCode) + { case ILOpCode.Br: case ILOpCode.Br_s: case ILOpCode.Ret: @@ -275,7 +293,8 @@ namespace ICSharpCode.Decompiler.Disassembler public ILStructure GetInnermost(int offset) { Debug.Assert(StartOffset <= offset && offset < EndOffset); - foreach (ILStructure child in this.Children) { + foreach (ILStructure child in this.Children) + { if (child.StartOffset <= offset && offset < child.EndOffset) return child.GetInnermost(offset); } diff --git a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs index 2a669e692..6403a231f 100644 --- a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs @@ -22,6 +22,7 @@ using System.Collections.Immutable; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Threading; + using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; @@ -87,16 +88,20 @@ namespace ICSharpCode.Decompiler.Disassembler // start writing IL code output.WriteLine("// Method begins at RVA 0x{0:x4}", methodDefinition.RelativeVirtualAddress); - if (methodDefinition.RelativeVirtualAddress == 0) { + if (methodDefinition.RelativeVirtualAddress == 0) + { output.WriteLine("// Code size {0} (0x{0:x})", 0); output.WriteLine(".maxstack {0}", 0); output.WriteLine(); return; } MethodBodyBlock body; - try { + try + { body = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress); - } catch (BadImageFormatException ex) { + } + catch (BadImageFormatException ex) + { output.WriteLine("// {0}", ex.Message); return; } @@ -113,13 +118,17 @@ namespace ICSharpCode.Decompiler.Disassembler sequencePoints = DebugInfo?.GetSequencePoints(handle) ?? EmptyList.Instance; nextSequencePointIndex = 0; - if (DetectControlStructure && blob.Length > 0) { + if (DetectControlStructure && blob.Length > 0) + { blob.Reset(); HashSet branchTargets = GetBranchTargets(blob); blob.Reset(); WriteStructureBody(new ILStructure(module, handle, genericContext, body), branchTargets, ref blob); - } else { - while (blob.RemainingBytes > 0) { + } + else + { + while (blob.RemainingBytes > 0) + { cancellationToken.ThrowIfCancellationRequested(); WriteInstruction(output, metadata, handle, ref blob); } @@ -138,24 +147,32 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(" init"); var blob = metadata.GetStandaloneSignature(body.LocalSignature); var signature = ImmutableArray>.Empty; - try { - if (blob.GetKind() == StandaloneSignatureKind.LocalVariables) { + try + { + if (blob.GetKind() == StandaloneSignatureKind.LocalVariables) + { signature = blob.DecodeLocalSignature(signatureDecoder, genericContext); - } else { + } + else + { output.Write(" /* wrong signature kind */"); } - } catch (BadImageFormatException ex) { + } + catch (BadImageFormatException ex) + { output.Write($" /* {ex.Message} */"); } output.Write(' '); output.WriteLine("("); output.Indent(); int index = 0; - foreach (var v in signature) { + foreach (var v in signature) + { output.WriteLocalReference("[" + index + "]", "loc_" + index, isDefinition: true); output.Write(' '); v(ILNameSyntax.TypeName); - if (DebugInfo != null && DebugInfo.TryGetName(method, index, out var name)) { + if (DebugInfo != null && DebugInfo.TryGetName(method, index, out var name)) + { output.Write(" " + DisassemblerHelpers.Escape(name)); } if (index + 1 < signature.Length) @@ -174,9 +191,11 @@ namespace ICSharpCode.Decompiler.Disassembler genericContext = new GenericContext(handle, module); signatureDecoder = new DisassemblerSignatureTypeProvider(module, output); var handlers = body.ExceptionRegions; - if (!handlers.IsEmpty) { + if (!handlers.IsEmpty) + { output.WriteLine(); - foreach (var eh in handlers) { + foreach (var eh in handlers) + { eh.WriteTo(module, genericContext, output); output.WriteLine(); } @@ -186,13 +205,19 @@ namespace ICSharpCode.Decompiler.Disassembler HashSet GetBranchTargets(BlobReader blob) { HashSet branchTargets = new HashSet(); - while (blob.RemainingBytes > 0) { + while (blob.RemainingBytes > 0) + { var opCode = ILParser.DecodeOpCode(ref blob); - if (opCode == ILOpCode.Switch) { + if (opCode == ILOpCode.Switch) + { branchTargets.UnionWith(ILParser.DecodeSwitchTargets(ref blob)); - } else if (opCode.IsBranch()) { + } + else if (opCode.IsBranch()) + { branchTargets.Add(ILParser.DecodeBranchTarget(ref blob, opCode)); - } else { + } + else + { ILParser.SkipOperand(ref blob, opCode); } } @@ -201,10 +226,12 @@ namespace ICSharpCode.Decompiler.Disassembler void WriteStructureHeader(ILStructure s) { - switch (s.Type) { + switch (s.Type) + { case ILStructureType.Loop: output.Write("// loop start"); - if (s.LoopEntryPointOffset >= 0) { + if (s.LoopEntryPointOffset >= 0) + { output.Write(" (head: "); DisassemblerHelpers.WriteOffsetReference(output, s.LoopEntryPointOffset); output.Write(')'); @@ -216,11 +243,13 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine("{"); break; case ILStructureType.Handler: - switch (s.ExceptionHandler.Kind) { + switch (s.ExceptionHandler.Kind) + { case ExceptionRegionKind.Catch: case ExceptionRegionKind.Filter: output.Write("catch"); - if (!s.ExceptionHandler.CatchType.IsNil) { + if (!s.ExceptionHandler.CatchType.IsNil) + { output.Write(' '); s.ExceptionHandler.CatchType.WriteTo(s.Module, output, s.GenericContext, ILNameSyntax.TypeName); } @@ -252,16 +281,21 @@ namespace ICSharpCode.Decompiler.Disassembler bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; - while (body.RemainingBytes > 0 && body.Offset < s.EndOffset) { + while (body.RemainingBytes > 0 && body.Offset < s.EndOffset) + { cancellationToken.ThrowIfCancellationRequested(); int offset = body.Offset; - if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { + if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) + { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(child, branchTargets, ref body); WriteStructureFooter(child); - } else { - if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { + } + else + { + if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) + { output.WriteLine(); // put an empty line after branches, and in front of branch targets } var currentOpCode = ILParser.DecodeOpCode(ref body); @@ -280,7 +314,8 @@ namespace ICSharpCode.Decompiler.Disassembler void WriteStructureFooter(ILStructure s) { output.Unindent(); - switch (s.Type) { + switch (s.Type) + { case ILStructureType.Loop: output.WriteLine("// end loop"); break; @@ -301,16 +336,22 @@ namespace ICSharpCode.Decompiler.Disassembler protected virtual void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodDefinition, ref BlobReader blob) { int offset = blob.Offset; - if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count) { + if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count) + { var sp = sequencePoints[nextSequencePointIndex]; - if (sp.Offset <= offset) { + if (sp.Offset <= offset) + { output.Write("// sequence point: "); - if (sp.Offset != offset) { + if (sp.Offset != offset) + { output.Write("!! at " + DisassemblerHelpers.OffsetToString(sp.Offset) + " !!"); } - if (sp.IsHidden) { + if (sp.IsHidden) + { output.WriteLine("hidden"); - } else { + } + else + { output.WriteLine($"(line {sp.StartLine}, col {sp.StartColumn}) to (line {sp.EndLine}, col {sp.EndColumn}) in {sp.DocumentUrl}"); } nextSequencePointIndex++; @@ -319,9 +360,11 @@ namespace ICSharpCode.Decompiler.Disassembler ILOpCode opCode = ILParser.DecodeOpCode(ref blob); output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true); output.Write(": "); - if (opCode.IsDefined()) { + if (opCode.IsDefined()) + { WriteOpCode(opCode); - switch (opCode.GetOperandType()) { + switch (opCode.GetOperandType()) + { case OperandType.BrTarget: case OperandType.ShortBrTarget: output.Write(' '); @@ -335,9 +378,12 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(' '); int metadataToken = blob.ReadInt32(); EntityHandle? handle = MetadataTokenHelpers.TryAsEntityHandle(metadataToken); - try { + try + { handle?.WriteTo(module, output, genericContext); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { handle = null; } WriteMetadataToken(handle, metadataToken, spaceBefore: true); @@ -346,9 +392,11 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(' '); metadataToken = blob.ReadInt32(); handle = MetadataTokenHelpers.TryAsEntityHandle(metadataToken); - switch (handle?.Kind) { + switch (handle?.Kind) + { case HandleKind.MemberReference: - switch (metadata.GetMemberReference((MemberReferenceHandle)handle).GetKind()) { + switch (metadata.GetMemberReference((MemberReferenceHandle)handle).GetKind()) + { case MemberReferenceKind.Method: output.Write("method "); break; @@ -364,9 +412,12 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write("method "); break; } - try { + try + { handle?.WriteTo(module, output, genericContext); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { handle = null; } WriteMetadataToken(handle, metadataToken, spaceBefore: true); @@ -396,14 +447,18 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(' '); UserStringHandle? userString; string text; - try { + try + { userString = MetadataTokens.UserStringHandle(metadataToken); text = metadata.GetUserString(userString.Value); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { userString = null; text = null; } - if (userString != null) { + if (userString != null) + { DisassemblerHelpers.WriteOperand(output, text); } WriteMetadataToken(userString, metadataToken, spaceBefore: true); @@ -411,7 +466,8 @@ namespace ICSharpCode.Decompiler.Disassembler case OperandType.Switch: int[] targets = ILParser.DecodeSwitchTargets(ref blob); output.Write(" ("); - for (int i = 0; i < targets.Length; i++) { + for (int i = 0; i < targets.Length; i++) + { if (i > 0) output.Write(", "); output.WriteLocalReference($"IL_{targets[i]:x4}", targets[i]); @@ -421,32 +477,43 @@ namespace ICSharpCode.Decompiler.Disassembler case OperandType.Variable: output.Write(' '); int index = blob.ReadUInt16(); - if (opCode == ILOpCode.Ldloc || opCode == ILOpCode.Ldloca || opCode == ILOpCode.Stloc) { + if (opCode == ILOpCode.Ldloc || opCode == ILOpCode.Ldloca || opCode == ILOpCode.Stloc) + { DisassemblerHelpers.WriteVariableReference(output, metadata, methodDefinition, index); - } else { + } + else + { DisassemblerHelpers.WriteParameterReference(output, metadata, methodDefinition, index); } break; case OperandType.ShortVariable: output.Write(' '); index = blob.ReadByte(); - if (opCode == ILOpCode.Ldloc_s || opCode == ILOpCode.Ldloca_s || opCode == ILOpCode.Stloc_s) { + if (opCode == ILOpCode.Ldloc_s || opCode == ILOpCode.Ldloca_s || opCode == ILOpCode.Stloc_s) + { DisassemblerHelpers.WriteVariableReference(output, metadata, methodDefinition, index); - } else { + } + else + { DisassemblerHelpers.WriteParameterReference(output, metadata, methodDefinition, index); } break; } - } else { + } + else + { ushort opCodeValue = (ushort)opCode; - if (opCodeValue > 0xFF) { + if (opCodeValue > 0xFF) + { // split 16-bit value into two emitbyte directives output.WriteLine($".emitbyte 0x{(byte)(opCodeValue >> 8):x}"); // add label output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset + 1), offset + 1, isDefinition: true); output.Write(": "); output.Write($".emitbyte 0x{(byte)(opCodeValue & 0xFF):x}"); - } else { + } + else + { output.Write($".emitbyte 0x{(byte)opCodeValue:x}"); } } @@ -457,7 +524,8 @@ namespace ICSharpCode.Decompiler.Disassembler { var opCodeInfo = new OpCodeInfo(opCode, opCode.GetDisplayName()); string index; - switch (opCode) { + switch (opCode) + { case ILOpCode.Ldarg_0: case ILOpCode.Ldarg_1: case ILOpCode.Ldarg_2: diff --git a/ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs b/ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs index 987687ed6..931bc671d 100644 --- a/ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs +++ b/ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.Disassembler @@ -64,7 +65,8 @@ namespace ICSharpCode.Decompiler.Disassembler get { if (encodedName != null) return encodedName; - switch (Name) { + switch (Name) + { case "constrained.": encodedName = "Constrained"; return encodedName; @@ -86,14 +88,20 @@ namespace ICSharpCode.Decompiler.Disassembler } string text = ""; bool toUpperCase = true; - foreach (var ch in Name) { - if (ch == '.') { + foreach (var ch in Name) + { + if (ch == '.') + { text += '_'; toUpperCase = true; - } else if (toUpperCase) { + } + else if (toUpperCase) + { text += char.ToUpperInvariant(ch); toUpperCase = false; - } else { + } + else + { text += ch; } } diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index da34d08a7..ba73ac8a2 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -25,9 +25,9 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Threading; -using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.DebugInfo; +using ICSharpCode.Decompiler.IL; +using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.Disassembler { @@ -172,10 +172,12 @@ namespace ICSharpCode.Decompiler.Disassembler if (isCompilerControlled) output.Write("privatescope "); - if ((methodDefinition.Attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl) { + if ((methodDefinition.Attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl) + { output.Write("pinvokeimpl"); var info = methodDefinition.GetImport(); - if (!info.Module.IsNil) { + if (!info.Module.IsNil) + { var moduleRef = metadata.GetModuleReference(info.Module); output.Write("(\"" + DisassemblerHelpers.EscapeString(metadata.GetString(moduleRef.Name)) + "\""); @@ -185,7 +187,8 @@ namespace ICSharpCode.Decompiler.Disassembler if ((info.Attributes & MethodImportAttributes.ExactSpelling) == MethodImportAttributes.ExactSpelling) output.Write(" nomangle"); - switch (info.Attributes & MethodImportAttributes.CharSetMask) { + switch (info.Attributes & MethodImportAttributes.CharSetMask) + { case MethodImportAttributes.CharSetAnsi: output.Write(" ansi"); break; @@ -200,7 +203,8 @@ namespace ICSharpCode.Decompiler.Disassembler if ((info.Attributes & MethodImportAttributes.SetLastError) == MethodImportAttributes.SetLastError) output.Write(" lasterr"); - switch (info.Attributes & MethodImportAttributes.CallingConventionMask) { + switch (info.Attributes & MethodImportAttributes.CallingConventionMask) + { case MethodImportAttributes.CallingConventionCDecl: output.Write(" cdecl"); break; @@ -227,12 +231,16 @@ namespace ICSharpCode.Decompiler.Disassembler output.Indent(); var declaringType = methodDefinition.GetDeclaringType(); MethodSignature>? signature; - try { + try + { var signatureProvider = new DisassemblerSignatureTypeProvider(module, output); signature = methodDefinition.DecodeSignature(signatureProvider, genericContext); - if (signature.Value.Header.HasExplicitThis) { + if (signature.Value.Header.HasExplicitThis) + { output.Write("instance explicit "); - } else if (signature.Value.Header.IsInstance) { + } + else if (signature.Value.Header.IsInstance) + { output.Write("instance "); } @@ -241,26 +249,34 @@ namespace ICSharpCode.Decompiler.Disassembler //return type signature.Value.ReturnType(ILNameSyntax.Signature); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { signature = null; output.Write(""); } output.Write(' '); var parameters = methodDefinition.GetParameters(); - if (parameters.Count > 0) { + if (parameters.Count > 0) + { var firstParam = metadata.GetParameter(parameters.First()); - if (firstParam.SequenceNumber == 0) { + if (firstParam.SequenceNumber == 0) + { var marshallingDesc = firstParam.GetMarshallingDescriptor(); - if (!marshallingDesc.IsNil) { + if (!marshallingDesc.IsNil) + { WriteMarshalInfo(metadata.GetBlobReader(marshallingDesc)); } } } - if (isCompilerControlled) { + if (isCompilerControlled) + { output.Write(DisassemblerHelpers.Escape(metadata.GetString(methodDefinition.Name) + "$PST" + MetadataTokens.GetToken(handle).ToString("X8"))); - } else { + } + else + { output.Write(DisassemblerHelpers.Escape(metadata.GetString(methodDefinition.Name))); } @@ -268,7 +284,8 @@ namespace ICSharpCode.Decompiler.Disassembler //( params ) output.Write(" ("); - if (signature?.ParameterTypes.Length > 0) { + if (signature?.ParameterTypes.Length > 0) + { output.WriteLine(); output.Indent(); WriteParameters(metadata, parameters, signature.Value); @@ -288,21 +305,29 @@ namespace ICSharpCode.Decompiler.Disassembler internal static void WriteMetadataToken(ITextOutput output, PEFile module, Handle? handle, int metadataToken, bool spaceAfter, bool spaceBefore, bool showMetadataTokens, bool base10) { - if (showMetadataTokens || handle == null) { - if (spaceBefore) { + if (showMetadataTokens || handle == null) + { + if (spaceBefore) + { output.Write(' '); } output.Write("/* "); - if (base10) { + if (base10) + { output.WriteReference(module, handle.GetValueOrDefault(), metadataToken.ToString(), "metadata"); - } else { + } + else + { output.WriteReference(module, handle.GetValueOrDefault(), metadataToken.ToString("X8"), "metadata"); } output.Write(" */"); - if (spaceAfter) { + if (spaceAfter) + { output.Write(' '); } - } else if (spaceBefore && spaceAfter) { + } + else if (spaceBefore && spaceAfter) + { output.Write(' '); } } @@ -314,22 +339,26 @@ namespace ICSharpCode.Decompiler.Disassembler OpenBlock(defaultCollapsed: isInType); WriteAttributes(module, methodDefinition.GetCustomAttributes()); - foreach (var h in handle.GetMethodImplementations(metadata)) { + foreach (var h in handle.GetMethodImplementations(metadata)) + { var impl = metadata.GetMethodImplementation(h); output.Write(".override method "); impl.MethodDeclaration.WriteTo(module, output, genericContext); output.WriteLine(); } - foreach (var p in methodDefinition.GetGenericParameters()) { + foreach (var p in methodDefinition.GetGenericParameters()) + { WriteGenericParameterAttributes(module, genericContext, p); } - foreach (var p in methodDefinition.GetParameters()) { + foreach (var p in methodDefinition.GetParameters()) + { WriteParameterAttributes(module, p); } WriteSecurityDeclarations(module, methodDefinition.GetDeclarativeSecurityAttributes()); - if (methodDefinition.HasBody()) { + if (methodDefinition.HasBody()) + { methodBodyDisassembler.Disassemble(module, handle); } var declaringType = metadata.GetTypeDefinition(methodDefinition.GetDeclaringType()); @@ -341,10 +370,12 @@ namespace ICSharpCode.Decompiler.Disassembler { if (secDeclProvider.Count == 0) return; - foreach (var h in secDeclProvider) { + foreach (var h in secDeclProvider) + { output.Write(".permissionset "); var secdecl = module.Metadata.GetDeclarativeSecurityAttribute(h); - switch ((ushort)secdecl.Action) { + switch ((ushort)secdecl.Action) + { case 1: // DeclarativeSecurityAction.Request output.Write("request"); break; @@ -395,11 +426,14 @@ namespace ICSharpCode.Decompiler.Disassembler break; } var blob = module.Metadata.GetBlobReader(secdecl.PermissionSet); - if (AssemblyResolver == null) { + if (AssemblyResolver == null) + { output.Write(" = "); WriteBlob(blob); output.WriteLine(); - } else if ((char)blob.ReadByte() != '.') { + } + else if ((char)blob.ReadByte() != '.') + { blob.Reset(); output.WriteLine(); output.Indent(); @@ -407,12 +441,17 @@ namespace ICSharpCode.Decompiler.Disassembler WriteBlob(blob); output.WriteLine(); output.Unindent(); - } else { + } + else + { var outputWithRollback = new TextOutputWithRollback(output); - try { + try + { TryDecodeSecurityDeclaration(outputWithRollback, blob, module); outputWithRollback.Commit(); - } catch (Exception ex) when (ex is BadImageFormatException || ex is EnumUnderlyingTypeResolveException) { + } + catch (Exception ex) when (ex is BadImageFormatException || ex is EnumUnderlyingTypeResolveException) + { blob.Reset(); output.Write(" = "); WriteBlob(blob); @@ -491,14 +530,18 @@ namespace ICSharpCode.Decompiler.Disassembler // if we deal with an assembly-qualified name, resolve the assembly if (nameParts.Length == 2) containingModule = resolver.Resolve(AssemblyNameReference.Parse(nameParts[1])); - if (containingModule != null) { + if (containingModule != null) + { // try to find the type in the assembly typeDefHandle = FindType(containingModule, typeNameParts); - } else { + } + else + { // just fully-qualified name, try current assembly typeDefHandle = FindType(module, typeNameParts); containingModule = module; - if (typeDefHandle.IsNil && TryResolveMscorlib(out var mscorlib)) { + if (typeDefHandle.IsNil && TryResolveMscorlib(out var mscorlib)) + { // otherwise try mscorlib typeDefHandle = FindType(mscorlib, typeNameParts); containingModule = mscorlib; @@ -513,25 +556,34 @@ namespace ICSharpCode.Decompiler.Disassembler var currentNamespace = metadata.GetNamespaceDefinitionRoot(); ImmutableArray typeDefinitions = default; - for (int i = 0; i < name.Length; i++) { + for (int i = 0; i < name.Length; i++) + { string identifier = name[i]; - if (!typeDefinitions.IsDefault) { + if (!typeDefinitions.IsDefault) + { restart: - foreach (var type in typeDefinitions) { + foreach (var type in typeDefinitions) + { var typeDef = metadata.GetTypeDefinition(type); var currentTypeName = metadata.GetString(typeDef.Name); - if (identifier == currentTypeName) { + if (identifier == currentTypeName) + { if (i + 1 == name.Length) return type; typeDefinitions = typeDef.GetNestedTypes(); goto restart; } } - } else { + } + else + { var next = currentNamespace.NamespaceDefinitions.FirstOrDefault(ns => metadata.StringComparer.Equals(metadata.GetNamespaceDefinition(ns).Name, identifier)); - if (!next.IsNil) { + if (!next.IsNil) + { currentNamespace = metadata.GetNamespaceDefinition(next); - } else { + } + else + { typeDefinitions = currentNamespace.TypeDefinitions; i--; } @@ -557,11 +609,13 @@ namespace ICSharpCode.Decompiler.Disassembler bool TryResolveMscorlib(out PEFile mscorlib) { mscorlib = null; - if (this.mscorlib != null) { + if (this.mscorlib != null) + { mscorlib = this.mscorlib; return true; } - if (resolver == null) { + if (resolver == null) + { return false; } this.mscorlib = mscorlib = resolver.Resolve(AssemblyNameReference.Parse("mscorlib")); @@ -576,18 +630,23 @@ namespace ICSharpCode.Decompiler.Disassembler string currentAssemblyName = null; string currentFullAssemblyName = null; - if (module.Metadata.IsAssembly) { + if (module.Metadata.IsAssembly) + { currentAssemblyName = module.Metadata.GetString(module.Metadata.GetAssemblyDefinition().Name); currentFullAssemblyName = module.Metadata.GetFullAssemblyName(); } - int count = blob.ReadCompressedInteger(); - for (int i = 0; i < count; i++) { + int count = blob.ReadCompressedInteger(); + for (int i = 0; i < count; i++) + { var fullTypeName = blob.ReadSerializedString(); string[] nameParts = fullTypeName.Split(new[] { ", " }, StringSplitOptions.None); - if (nameParts.Length < 2 || nameParts[1] == currentAssemblyName) { + if (nameParts.Length < 2 || nameParts[1] == currentAssemblyName) + { output.Write("class "); output.Write(DisassemblerHelpers.Escape(fullTypeName)); - } else { + } + else + { output.Write('['); output.Write(nameParts[1]); output.Write(']'); @@ -601,13 +660,16 @@ namespace ICSharpCode.Decompiler.Disassembler var decoder = new CustomAttributeDecoder<(PrimitiveTypeCode Code, string Name)>(new SecurityDeclarationDecoder(output, AssemblyResolver, module), module.Metadata, provideBoxingTypeInfo: true); var arguments = decoder.DecodeNamedArguments(ref blob, argCount); - if (argCount > 0) { + if (argCount > 0) + { output.WriteLine(); output.Indent(); } - foreach (var argument in arguments) { - switch (argument.Kind) { + foreach (var argument in arguments) + { + switch (argument.Kind) + { case CustomAttributeNamedArgumentKind.Field: output.Write("field "); break; @@ -623,7 +685,8 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(); } - if (argCount > 0) { + if (argCount > 0) + { output.Unindent(); } @@ -633,18 +696,21 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(','); output.WriteLine(); } - + output.Unindent(); output.WriteLine("}"); } void WriteValue(ITextOutput output, (PrimitiveTypeCode Code, string Name) type, object value) { - if (value is CustomAttributeTypedArgument<(PrimitiveTypeCode, string)> boxedValue) { + if (value is CustomAttributeTypedArgument<(PrimitiveTypeCode, string)> boxedValue) + { output.Write("object("); WriteValue(output, boxedValue.Type, boxedValue.Value); output.Write(")"); - } else if (value is ImmutableArray> arrayValue) { + } + else if (value is ImmutableArray> arrayValue) + { string elementType = type.Name != null && !type.Name.StartsWith("enum ", StringComparison.Ordinal) ? type.Name.Remove(type.Name.Length - 2) : PrimitiveTypeCodeToString(type.Code); @@ -653,17 +719,24 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(arrayValue.Length.ToString()); output.Write("]("); bool first = true; - foreach (var item in arrayValue) { - if (!first) output.Write(" "); - if (item.Value is CustomAttributeTypedArgument<(PrimitiveTypeCode, string)> boxedItem) { + foreach (var item in arrayValue) + { + if (!first) + output.Write(" "); + if (item.Value is CustomAttributeTypedArgument<(PrimitiveTypeCode, string)> boxedItem) + { WriteValue(output, boxedItem.Type, boxedItem.Value); - } else { + } + else + { WriteSimpleValue(output, item.Value, elementType); } first = false; } output.Write(")"); - } else { + } + else + { string typeName = type.Name != null && !type.Name.StartsWith("enum ", StringComparison.Ordinal) ? type.Name : PrimitiveTypeCodeToString(type.Code); @@ -676,15 +749,19 @@ namespace ICSharpCode.Decompiler.Disassembler private static void WriteSimpleValue(ITextOutput output, object value, string typeName) { - switch (typeName) { + switch (typeName) + { case "string": output.Write("'" + DisassemblerHelpers.EscapeString(value.ToString()).Replace("'", "\'") + "'"); break; case "type": var info = ((PrimitiveTypeCode Code, string Name))value; - if (info.Name.StartsWith("enum ", StringComparison.Ordinal)) { + if (info.Name.StartsWith("enum ", StringComparison.Ordinal)) + { output.Write(info.Name.Substring(5)); - } else { + } + else + { output.Write(info.Name); } break; @@ -696,7 +773,8 @@ namespace ICSharpCode.Decompiler.Disassembler static string PrimitiveTypeCodeToString(PrimitiveTypeCode typeCode) { - switch (typeCode) { + switch (typeCode) + { case PrimitiveTypeCode.Boolean: return "bool"; case PrimitiveTypeCode.Byte: @@ -743,7 +821,8 @@ namespace ICSharpCode.Decompiler.Disassembler void WriteNativeType(ref BlobReader blob) { byte type; - switch (type = blob.ReadByte()) { + switch (type = blob.ReadByte()) + { case 0x66: // None case 0x50: // Max break; @@ -799,10 +878,12 @@ namespace ICSharpCode.Decompiler.Disassembler int sizeParameterIndex = blob.TryReadCompressedInteger(out int value) ? value : -1; int size = blob.TryReadCompressedInteger(out value) ? value : -1; int sizeParameterMultiplier = blob.TryReadCompressedInteger(out value) ? value : -1; - if (size >= 0) { + if (size >= 0) + { output.Write(size.ToString()); } - if (sizeParameterIndex >= 0 && sizeParameterMultiplier != 0) { + if (sizeParameterIndex >= 0 && sizeParameterMultiplier != 0) + { output.Write(" + "); output.Write(sizeParameterIndex.ToString()); } @@ -837,9 +918,11 @@ namespace ICSharpCode.Decompiler.Disassembler break; case 0x1d: // SafeArray output.Write("safearray "); - if (blob.RemainingBytes > 0) { + if (blob.RemainingBytes > 0) + { byte elementType = blob.ReadByte(); - switch (elementType) { + switch (elementType) + { case 0: // None break; case 2: // I2 @@ -908,7 +991,8 @@ namespace ICSharpCode.Decompiler.Disassembler case 0x1e: // FixedArray output.Write("fixed array"); output.Write("[{0}]", blob.TryReadCompressedInteger(out value) ? value : 0); - if (blob.RemainingBytes > 0) { + if (blob.RemainingBytes > 0) + { output.Write(' '); WriteNativeType(ref blob); } @@ -942,7 +1026,8 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write("custom(\"{0}\", \"{1}\"", DisassemblerHelpers.EscapeString(managedType), DisassemblerHelpers.EscapeString(cookie)); - if (guid != Guid.Empty || !string.IsNullOrEmpty(unmanagedType)) { + if (guid != Guid.Empty || !string.IsNullOrEmpty(unmanagedType)) + { output.Write(", \"{0}\", \"{1}\"", guid.ToString(), DisassemblerHelpers.EscapeString(unmanagedType)); } output.Write(')'); @@ -962,14 +1047,18 @@ namespace ICSharpCode.Decompiler.Disassembler int i = 0; int offset = signature.Header.IsInstance ? 1 : 0; - foreach (var h in parameters) { + foreach (var h in parameters) + { var p = metadata.GetParameter(h); // skip return type parameter handle - if (p.SequenceNumber == 0) continue; + if (p.SequenceNumber == 0) + continue; // fill gaps in parameter list - while (i < p.SequenceNumber - 1) { - if (i > 0) { + while (i < p.SequenceNumber - 1) + { + if (i > 0) + { output.Write(','); output.WriteLine(); } @@ -980,7 +1069,8 @@ namespace ICSharpCode.Decompiler.Disassembler } // separator - if (i > 0) { + if (i > 0) + { output.Write(','); output.WriteLine(); } @@ -995,7 +1085,8 @@ namespace ICSharpCode.Decompiler.Disassembler signature.ParameterTypes[i](ILNameSyntax.Signature); output.Write(' '); var md = p.GetMarshallingDescriptor(); - if (!md.IsNil) { + if (!md.IsNil) + { WriteMarshalInfo(metadata.GetBlobReader(md)); } output.WriteLocalReference(DisassemblerHelpers.Escape(metadata.GetString(p.Name)), "param_" + (i + offset), isDefinition: true); @@ -1003,8 +1094,10 @@ namespace ICSharpCode.Decompiler.Disassembler } // add remaining parameter types as unnamed parameters - while (i < signature.RequiredParameterCount) { - if (i > 0) { + while (i < signature.RequiredParameterCount) + { + if (i > 0) + { output.Write(','); output.WriteLine(); } @@ -1021,16 +1114,19 @@ namespace ICSharpCode.Decompiler.Disassembler { var metadata = module.Metadata; var p = metadata.GetGenericParameter(handle); - if (p.GetCustomAttributes().Count > 0) { + if (p.GetCustomAttributes().Count > 0) + { output.Write(".param type {0}", metadata.GetString(p.Name)); output.WriteLine(); output.Indent(); WriteAttributes(module, p.GetCustomAttributes()); output.Unindent(); } - foreach (var constraintHandle in p.GetConstraints()) { + foreach (var constraintHandle in p.GetConstraints()) + { var constraint = metadata.GetGenericParameterConstraint(constraintHandle); - if (constraint.GetCustomAttributes().Count > 0) { + if (constraint.GetCustomAttributes().Count > 0) + { output.Write(".param constraint {0}, ", metadata.GetString(p.Name)); constraint.Type.WriteTo(module, output, context, ILNameSyntax.TypeName); output.WriteLine(); @@ -1048,7 +1144,8 @@ namespace ICSharpCode.Decompiler.Disassembler if (p.GetDefaultValue().IsNil && p.GetCustomAttributes().Count == 0) return; output.Write(".param [{0}]", p.SequenceNumber); - if (!p.GetDefaultValue().IsNil) { + if (!p.GetDefaultValue().IsNil) + { output.Write(" = "); WriteConstant(metadata, metadata.GetConstant(p.GetDefaultValue())); } @@ -1060,32 +1157,44 @@ namespace ICSharpCode.Decompiler.Disassembler void WriteConstant(MetadataReader metadata, Constant constant) { - switch (constant.TypeCode) { + switch (constant.TypeCode) + { case ConstantTypeCode.NullReference: output.Write("nullref"); break; default: var blob = metadata.GetBlobReader(constant.Value); object value; - try { + try + { value = blob.ReadConstant(constant.TypeCode); - } catch (ArgumentOutOfRangeException) { + } + catch (ArgumentOutOfRangeException) + { output.Write($"/* Constant with invalid typecode: {constant.TypeCode} */"); return; } - if (value is string) { + if (value is string) + { DisassemblerHelpers.WriteOperand(output, value); - } else { + } + else + { string typeName = DisassemblerHelpers.PrimitiveTypeName(value.GetType().FullName); output.Write(typeName); output.Write('('); float? cf = value as float?; double? cd = value as double?; - if (cf.HasValue && (float.IsNaN(cf.Value) || float.IsInfinity(cf.Value))) { + if (cf.HasValue && (float.IsNaN(cf.Value) || float.IsInfinity(cf.Value))) + { output.Write("0x{0:x8}", BitConverter.ToInt32(BitConverter.GetBytes(cf.Value), 0)); - } else if (cd.HasValue && (double.IsNaN(cd.Value) || double.IsInfinity(cd.Value))) { + } + else if (cd.HasValue && (double.IsNaN(cd.Value) || double.IsInfinity(cd.Value))) + { output.Write("0x{0:x16}", BitConverter.DoubleToInt64Bits(cd.Value)); - } else { + } + else + { DisassemblerHelpers.WriteOperand(output, value); } output.Write(')'); @@ -1121,33 +1230,47 @@ namespace ICSharpCode.Decompiler.Disassembler char sectionPrefix = DisassembleFieldHeaderInternal(module, handle, metadata, fieldDefinition); output.WriteLine(); var attributes = fieldDefinition.GetCustomAttributes(); - if (attributes.Count > 0) { + if (attributes.Count > 0) + { output.MarkFoldStart(); WriteAttributes(module, fieldDefinition.GetCustomAttributes()); output.MarkFoldEnd(); } - if (fieldDefinition.HasFlag(FieldAttributes.HasFieldRVA)) { + if (fieldDefinition.HasFlag(FieldAttributes.HasFieldRVA)) + { // Field data as specified in II.16.3.1 of ECMA-335 6th edition int rva = fieldDefinition.GetRelativeVirtualAddress(); int sectionIndex = module.Reader.PEHeaders.GetContainingSectionIndex(rva); - if (sectionIndex < 0) { + if (sectionIndex < 0) + { output.WriteLine($"// RVA {rva:X8} invalid (not in any section)"); - } else { + } + else + { BlobReader initVal; - try { + try + { initVal = fieldDefinition.GetInitialValue(module.Reader, null); - } catch (BadImageFormatException ex) { + } + catch (BadImageFormatException ex) + { initVal = default; output.WriteLine("// .data {2}_{0:X8} = {1}", fieldDefinition.GetRelativeVirtualAddress(), ex.Message, sectionPrefix); } - if (initVal.Length > 0) { + if (initVal.Length > 0) + { var sectionHeader = module.Reader.PEHeaders.SectionHeaders[sectionIndex]; output.Write(".data "); - if (sectionHeader.Name == ".text") { + if (sectionHeader.Name == ".text") + { output.Write("cil "); - } else if (sectionHeader.Name == ".tls") { + } + else if (sectionHeader.Name == ".tls") + { output.Write("tls "); - } else if (sectionHeader.Name != ".data") { + } + else if (sectionHeader.Name != ".data") + { output.Write($"/* {sectionHeader.Name} */ "); } output.Write($"{sectionPrefix}_{rva:X8} = bytearray "); @@ -1171,7 +1294,8 @@ namespace ICSharpCode.Decompiler.Disassembler WriteMetadataToken(output, module, handle, MetadataTokens.GetToken(handle), spaceAfter: true, spaceBefore: true, ShowMetadataTokens, ShowMetadataTokensInBase10); int offset = fieldDefinition.GetOffset(); - if (offset > -1) { + if (offset > -1) + { output.Write("[" + offset + "] "); } WriteEnum(fieldDefinition.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility); @@ -1181,7 +1305,8 @@ namespace ICSharpCode.Decompiler.Disassembler var signature = fieldDefinition.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new GenericContext(fieldDefinition.GetDeclaringType(), module)); var marshallingDescriptor = fieldDefinition.GetMarshallingDescriptor(); - if (!marshallingDescriptor.IsNil) { + if (!marshallingDescriptor.IsNil) + { WriteMarshalInfo(metadata.GetBlobReader(marshallingDescriptor)); } @@ -1190,14 +1315,16 @@ namespace ICSharpCode.Decompiler.Disassembler var fieldName = metadata.GetString(fieldDefinition.Name); output.Write(DisassemblerHelpers.Escape(fieldName)); char sectionPrefix = 'D'; - if (fieldDefinition.HasFlag(FieldAttributes.HasFieldRVA)) { + if (fieldDefinition.HasFlag(FieldAttributes.HasFieldRVA)) + { int rva = fieldDefinition.GetRelativeVirtualAddress(); sectionPrefix = GetRVASectionPrefix(module.Reader.PEHeaders, rva); output.Write(" at {1}_{0:X8}", rva, sectionPrefix); } var defaultValue = fieldDefinition.GetDefaultValue(); - if (!defaultValue.IsNil) { + if (!defaultValue.IsNil) + { output.Write(" = "); WriteConstant(metadata, metadata.GetConstant(defaultValue)); } @@ -1211,7 +1338,8 @@ namespace ICSharpCode.Decompiler.Disassembler if (sectionIndex < 0) return 'D'; var sectionHeader = headers.SectionHeaders[sectionIndex]; - switch (sectionHeader.Name) { + switch (sectionHeader.Name) + { case ".tls": return 'T'; case ".text": @@ -1239,7 +1367,8 @@ namespace ICSharpCode.Decompiler.Disassembler WriteAttributes(module, propertyDefinition.GetCustomAttributes()); WriteNestedMethod(".get", module, accessors.Getter); WriteNestedMethod(".set", module, accessors.Setter); - foreach (var method in accessors.Others) { + foreach (var method in accessors.Others) + { WriteNestedMethod(".other", module, method); } CloseBlock(); @@ -1269,7 +1398,8 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(DisassemblerHelpers.Escape(metadata.GetString(propertyDefinition.Name))); output.Write('('); - if (signature.ParameterTypes.Length > 0) { + if (signature.ParameterTypes.Length > 0) + { var parameters = metadata.GetMethodDefinition(accessors.GetAny()).GetParameters(); int parametersCount = accessors.Getter.IsNil ? parameters.Count - 1 : parameters.Count; @@ -1310,7 +1440,8 @@ namespace ICSharpCode.Decompiler.Disassembler WriteNestedMethod(".addon", module, accessors.Adder); WriteNestedMethod(".removeon", module, accessors.Remover); WriteNestedMethod(".fire", module, accessors.Raiser); - foreach (var method in accessors.Others) { + foreach (var method in accessors.Others) + { WriteNestedMethod(".other", module, method); } CloseBlock(); @@ -1326,11 +1457,16 @@ namespace ICSharpCode.Decompiler.Disassembler private void DisassembleEventHeaderInternal(PEFile module, EventDefinitionHandle handle, EventDefinition eventDefinition, EventAccessors accessors) { TypeDefinitionHandle declaringType; - if (!accessors.Adder.IsNil) { + if (!accessors.Adder.IsNil) + { declaringType = module.Metadata.GetMethodDefinition(accessors.Adder).GetDeclaringType(); - } else if (!accessors.Remover.IsNil) { + } + else if (!accessors.Remover.IsNil) + { declaringType = module.Metadata.GetMethodDefinition(accessors.Remover).GetDeclaringType(); - } else { + } + else + { declaringType = module.Metadata.GetMethodDefinition(accessors.Raiser).GetDeclaringType(); } output.WriteReference(module, handle, ".event", isDefinition: true); @@ -1339,7 +1475,8 @@ namespace ICSharpCode.Decompiler.Disassembler WriteFlags(eventDefinition.Attributes, eventAttributes); var provider = new DisassemblerSignatureTypeProvider(module, output); Action signature; - switch (eventDefinition.Type.Kind) { + switch (eventDefinition.Type.Kind) + { case HandleKind.TypeDefinition: signature = provider.GetTypeFromDefinition(module.Metadata, (TypeDefinitionHandle)eventDefinition.Type, 0); break; @@ -1402,10 +1539,12 @@ namespace ICSharpCode.Decompiler.Disassembler DisassembleTypeHeaderInternal(module, type, typeDefinition, genericContext); var interfaces = typeDefinition.GetInterfaceImplementations(); - if (interfaces.Count > 0) { + if (interfaces.Count > 0) + { output.Indent(); bool first = true; - foreach (var i in interfaces) { + foreach (var i in interfaces) + { if (!first) output.WriteLine(","); if (first) @@ -1427,19 +1566,23 @@ namespace ICSharpCode.Decompiler.Disassembler isInType = true; WriteAttributes(module, typeDefinition.GetCustomAttributes()); WriteSecurityDeclarations(module, typeDefinition.GetDeclarativeSecurityAttributes()); - foreach (var tp in typeDefinition.GetGenericParameters()) { + foreach (var tp in typeDefinition.GetGenericParameters()) + { WriteGenericParameterAttributes(module, genericContext, tp); } var layout = typeDefinition.GetLayout(); - if (!layout.IsDefault) { + if (!layout.IsDefault) + { output.WriteLine(".pack {0}", layout.PackingSize); output.WriteLine(".size {0}", layout.Size); output.WriteLine(); } var nestedTypes = typeDefinition.GetNestedTypes(); - if (!nestedTypes.IsEmpty) { + if (!nestedTypes.IsEmpty) + { output.WriteLine("// Nested Types"); - foreach (var nestedType in nestedTypes) { + foreach (var nestedType in nestedTypes) + { cancellationToken.ThrowIfCancellationRequested(); DisassembleType(module, nestedType); output.WriteLine(); @@ -1447,27 +1590,33 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(); } var fields = typeDefinition.GetFields(); - if (fields.Any()) { + if (fields.Any()) + { output.WriteLine("// Fields"); - foreach (var field in fields) { + foreach (var field in fields) + { cancellationToken.ThrowIfCancellationRequested(); DisassembleField(module, field); } output.WriteLine(); } var methods = typeDefinition.GetMethods(); - if (methods.Any()) { + if (methods.Any()) + { output.WriteLine("// Methods"); - foreach (var m in methods) { + foreach (var m in methods) + { cancellationToken.ThrowIfCancellationRequested(); DisassembleMethod(module, m); output.WriteLine(); } } var events = typeDefinition.GetEvents(); - if (events.Any()) { + if (events.Any()) + { output.WriteLine("// Events"); - foreach (var ev in events) { + foreach (var ev in events) + { cancellationToken.ThrowIfCancellationRequested(); DisassembleEvent(module, ev); output.WriteLine(); @@ -1475,9 +1624,11 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(); } var properties = typeDefinition.GetProperties(); - if (properties.Any()) { + if (properties.Any()) + { output.WriteLine("// Properties"); - foreach (var prop in properties) { + foreach (var prop in properties) + { cancellationToken.ThrowIfCancellationRequested(); DisassembleProperty(module, prop); } @@ -1498,8 +1649,9 @@ namespace ICSharpCode.Decompiler.Disassembler { output.WriteReference(module, handle, ".class", isDefinition: true); WriteMetadataToken(output, module, handle, MetadataTokens.GetToken(handle), - spaceAfter: true, spaceBefore: true, ShowMetadataTokens, ShowMetadataTokensInBase10); if ((typeDefinition.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface) - output.Write("interface "); + spaceAfter: true, spaceBefore: true, ShowMetadataTokens, ShowMetadataTokensInBase10); + if ((typeDefinition.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface) + output.Write("interface "); WriteEnum(typeDefinition.Attributes & TypeAttributes.VisibilityMask, typeVisibility); WriteEnum(typeDefinition.Attributes & TypeAttributes.LayoutMask, typeLayout); WriteEnum(typeDefinition.Attributes & TypeAttributes.StringFormatMask, typeStringFormat); @@ -1512,7 +1664,8 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(); EntityHandle baseType = typeDefinition.GetBaseTypeOrNil(); - if (!baseType.IsNil) { + if (!baseType.IsNil) + { output.Indent(); output.Write("extends "); baseType.WriteTo(module, output, genericContext, ILNameSyntax.TypeName); @@ -1523,25 +1676,33 @@ namespace ICSharpCode.Decompiler.Disassembler void WriteTypeParameters(ITextOutput output, PEFile module, GenericContext context, GenericParameterHandleCollection p) { - if (p.Count > 0) { + if (p.Count > 0) + { output.Write('<'); var metadata = module.Metadata; - for (int i = 0; i < p.Count; i++) { + for (int i = 0; i < p.Count; i++) + { if (i > 0) output.Write(", "); var gp = metadata.GetGenericParameter(p[i]); - if ((gp.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == GenericParameterAttributes.ReferenceTypeConstraint) { + if ((gp.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == GenericParameterAttributes.ReferenceTypeConstraint) + { output.Write("class "); - } else if ((gp.Attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) == GenericParameterAttributes.NotNullableValueTypeConstraint) { + } + else if ((gp.Attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) == GenericParameterAttributes.NotNullableValueTypeConstraint) + { output.Write("valuetype "); } - if ((gp.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) == GenericParameterAttributes.DefaultConstructorConstraint) { + if ((gp.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) == GenericParameterAttributes.DefaultConstructorConstraint) + { output.Write(".ctor "); } var constraints = gp.GetConstraints(); - if (constraints.Count > 0) { + if (constraints.Count > 0) + { output.Write('('); - for (int j = 0; j < constraints.Count; j++) { + for (int j = 0; j < constraints.Count; j++) + { if (j > 0) output.Write(", "); var constraint = metadata.GetGenericParameterConstraint(constraints[j]); @@ -1549,9 +1710,12 @@ namespace ICSharpCode.Decompiler.Disassembler } output.Write(") "); } - if ((gp.Attributes & GenericParameterAttributes.Contravariant) == GenericParameterAttributes.Contravariant) { + if ((gp.Attributes & GenericParameterAttributes.Contravariant) == GenericParameterAttributes.Contravariant) + { output.Write('-'); - } else if ((gp.Attributes & GenericParameterAttributes.Covariant) == GenericParameterAttributes.Covariant) { + } + else if ((gp.Attributes & GenericParameterAttributes.Covariant) == GenericParameterAttributes.Covariant) + { output.Write('+'); } output.Write(DisassemblerHelpers.Escape(metadata.GetString(gp.Name))); @@ -1565,11 +1729,13 @@ namespace ICSharpCode.Decompiler.Disassembler void WriteAttributes(PEFile module, CustomAttributeHandleCollection attributes) { var metadata = module.Metadata; - foreach (CustomAttributeHandle a in attributes) { + foreach (CustomAttributeHandle a in attributes) + { output.Write(".custom "); var attr = metadata.GetCustomAttribute(a); attr.Constructor.WriteTo(module, output, GenericContext.Empty); - if (!attr.Value.IsNil) { + if (!attr.Value.IsNil) + { output.Write(" = "); WriteBlob(attr.Value, metadata); } @@ -1588,10 +1754,14 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write("("); output.Indent(); - for (int i = 0; i < reader.Length; i++) { - if (i % 16 == 0 && i < reader.Length - 1) { + for (int i = 0; i < reader.Length; i++) + { + if (i % 16 == 0 && i < reader.Length - 1) + { output.WriteLine(); - } else { + } + else + { output.Write(' '); } output.Write(reader.ReadByte().ToString("x2")); @@ -1624,9 +1794,11 @@ namespace ICSharpCode.Decompiler.Disassembler { long val = Convert.ToInt64(flags); long tested = 0; - foreach (var pair in flagNames) { + foreach (var pair in flagNames) + { tested |= pair.Key; - if ((val & pair.Key) != 0 && pair.Value != null) { + if ((val & pair.Key) != 0 && pair.Value != null) + { output.Write(pair.Value); output.Write(' '); } @@ -1638,16 +1810,20 @@ namespace ICSharpCode.Decompiler.Disassembler void WriteEnum(T enumValue, EnumNameCollection enumNames) where T : struct { long val = Convert.ToInt64(enumValue); - foreach (var pair in enumNames) { - if (pair.Key == val) { - if (pair.Value != null) { + foreach (var pair in enumNames) + { + if (pair.Key == val) + { + if (pair.Value != null) + { output.Write(pair.Value); output.Write(' '); } return; } } - if (val != 0) { + if (val != 0) + { output.Write("flag({0:x4})", val); output.Write(' '); } @@ -1677,18 +1853,21 @@ namespace ICSharpCode.Decompiler.Disassembler public void DisassembleNamespace(string nameSpace, PEFile module, IEnumerable types) { - if (!string.IsNullOrEmpty(nameSpace)) { + if (!string.IsNullOrEmpty(nameSpace)) + { output.Write(".namespace " + DisassemblerHelpers.Escape(nameSpace)); OpenBlock(false); } bool oldIsInType = isInType; isInType = true; - foreach (var td in types) { + foreach (var td in types) + { cancellationToken.ThrowIfCancellationRequested(); DisassembleType(module, td); output.WriteLine(); } - if (!string.IsNullOrEmpty(nameSpace)) { + if (!string.IsNullOrEmpty(nameSpace)) + { CloseBlock(); isInType = oldIsInType; } @@ -1697,7 +1876,8 @@ namespace ICSharpCode.Decompiler.Disassembler public void WriteAssemblyHeader(PEFile module) { var metadata = module.Metadata; - if (!metadata.IsAssembly) return; + if (!metadata.IsAssembly) + return; output.Write(".assembly "); var asm = metadata.GetAssemblyDefinition(); if ((asm.Flags & AssemblyFlags.WindowsRuntime) == AssemblyFlags.WindowsRuntime) @@ -1706,19 +1886,22 @@ namespace ICSharpCode.Decompiler.Disassembler OpenBlock(false); WriteAttributes(module, asm.GetCustomAttributes()); WriteSecurityDeclarations(module, asm.GetDeclarativeSecurityAttributes()); - if (!asm.PublicKey.IsNil) { + if (!asm.PublicKey.IsNil) + { output.Write(".publickey = "); WriteBlob(asm.PublicKey, metadata); output.WriteLine(); } - if (asm.HashAlgorithm != AssemblyHashAlgorithm.None) { + if (asm.HashAlgorithm != AssemblyHashAlgorithm.None) + { output.Write(".hash algorithm 0x{0:x8}", (int)asm.HashAlgorithm); if (asm.HashAlgorithm == AssemblyHashAlgorithm.Sha1) output.Write(" // SHA1"); output.WriteLine(); } Version v = asm.Version; - if (v != null) { + if (v != null) + { output.WriteLine(".ver {0}:{1}:{2}:{3}", v.Major, v.Minor, v.Build, v.Revision); } CloseBlock(); @@ -1726,23 +1909,27 @@ namespace ICSharpCode.Decompiler.Disassembler public void WriteAssemblyReferences(MetadataReader metadata) { - foreach (var m in metadata.GetModuleReferences()) { + foreach (var m in metadata.GetModuleReferences()) + { var mref = metadata.GetModuleReference(m); output.WriteLine(".module extern {0}", DisassemblerHelpers.Escape(metadata.GetString(mref.Name))); } - foreach (var a in metadata.AssemblyReferences) { + foreach (var a in metadata.AssemblyReferences) + { var aref = metadata.GetAssemblyReference(a); output.Write(".assembly extern "); if ((aref.Flags & AssemblyFlags.WindowsRuntime) == AssemblyFlags.WindowsRuntime) output.Write("windowsruntime "); output.Write(DisassemblerHelpers.Escape(metadata.GetString(aref.Name))); OpenBlock(false); - if (!aref.PublicKeyOrToken.IsNil) { + if (!aref.PublicKeyOrToken.IsNil) + { output.Write(".publickeytoken = "); WriteBlob(aref.PublicKeyOrToken, metadata); output.WriteLine(); } - if (aref.Version != null) { + if (aref.Version != null) + { output.WriteLine(".ver {0}:{1}:{2}:{3}", aref.Version.Major, aref.Version.Minor, aref.Version.Build, aref.Version.Revision); } CloseBlock(); @@ -1755,21 +1942,24 @@ namespace ICSharpCode.Decompiler.Disassembler void WriteExportedType(ExportedType exportedType) { - if (!exportedType.Namespace.IsNil) { + if (!exportedType.Namespace.IsNil) + { output.Write(DisassemblerHelpers.Escape(metadata.GetString(exportedType.Namespace))); output.Write('.'); } output.Write(DisassemblerHelpers.Escape(metadata.GetString(exportedType.Name))); } - foreach (var et in metadata.ExportedTypes) { + foreach (var et in metadata.ExportedTypes) + { var exportedType = metadata.GetExportedType(et); output.Write(".class extern "); if (exportedType.IsForwarder) output.Write("forwarder "); WriteExportedType(exportedType); OpenBlock(false); - switch (exportedType.Implementation.Kind) { + switch (exportedType.Implementation.Kind) + { case HandleKind.AssemblyFile: var file = metadata.GetAssemblyFile((AssemblyFileHandle)exportedType.Implementation); output.WriteLine(".file {0}", metadata.GetString(file.Name)); @@ -1780,11 +1970,15 @@ namespace ICSharpCode.Decompiler.Disassembler case HandleKind.ExportedType: output.Write(".class extern "); var declaringType = metadata.GetExportedType((ExportedTypeHandle)exportedType.Implementation); - while (true) { + while (true) + { WriteExportedType(declaringType); - if (declaringType.Implementation.Kind == HandleKind.ExportedType) { + if (declaringType.Implementation.Kind == HandleKind.ExportedType) + { declaringType = metadata.GetExportedType((ExportedTypeHandle)declaringType.Implementation); - } else { + } + else + { break; } } @@ -1804,7 +1998,8 @@ namespace ICSharpCode.Decompiler.Disassembler var moduleDefinition = metadata.GetModuleDefinition(); output.WriteLine(".module {0}", metadata.GetString(moduleDefinition.Name)); - if (!skipMVID) { + if (!skipMVID) + { output.WriteLine("// MVID: {0}", metadata.GetGuid(moduleDefinition.Mvid).ToString("B").ToUpperInvariant()); } @@ -1820,7 +2015,8 @@ namespace ICSharpCode.Decompiler.Disassembler public void WriteModuleContents(PEFile module) { - foreach (var handle in module.Metadata.GetTopLevelTypeDefinitions()) { + foreach (var handle in module.Metadata.GetTopLevelTypeDefinitions()) + { DisassembleType(module, handle); output.WriteLine(); } diff --git a/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs b/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs index 46b11db6c..ce8cc84f5 100644 --- a/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs +++ b/ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs @@ -19,6 +19,7 @@ using System; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -36,26 +37,29 @@ namespace ICSharpCode.Decompiler.Documentation { readonly string typeName; readonly int typeParameterCount; - + public GetPotentiallyNestedClassTypeReference(string typeName, int typeParameterCount) { this.typeName = typeName; this.typeParameterCount = typeParameterCount; } - + public IType Resolve(ITypeResolveContext context) { string[] parts = typeName.Split('.'); - var assemblies = new [] { context.CurrentModule }.Concat(context.Compilation.Modules); - for (int i = parts.Length - 1; i >= 0; i--) { + var assemblies = new[] { context.CurrentModule }.Concat(context.Compilation.Modules); + for (int i = parts.Length - 1; i >= 0; i--) + { string ns = string.Join(".", parts, 0, i); string name = parts[i]; int topLevelTPC = (i == parts.Length - 1 ? typeParameterCount : 0); - foreach (var asm in assemblies) { + foreach (var asm in assemblies) + { if (asm == null) continue; ITypeDefinition typeDef = asm.GetTypeDefinition(new TopLevelTypeName(ns, name, topLevelTPC)); - for (int j = i + 1; j < parts.Length && typeDef != null; j++) { + for (int j = i + 1; j < parts.Length && typeDef != null; j++) + { int tpc = (j == parts.Length - 1 ? typeParameterCount : 0); typeDef = typeDef.NestedTypes.FirstOrDefault(n => n.Name == parts[j] && n.TypeParameterCount == tpc); } @@ -67,7 +71,7 @@ namespace ICSharpCode.Decompiler.Documentation if (idx < 0) return new UnknownType("", typeName, typeParameterCount); // give back a guessed namespace/type name - return new UnknownType(typeName.Substring(0, idx), typeName.Substring(idx + 1), typeParameterCount); + return new UnknownType(typeName.Substring(0, idx), typeName.Substring(idx + 1), typeParameterCount); } /// @@ -78,14 +82,16 @@ namespace ICSharpCode.Decompiler.Documentation public EntityHandle ResolveInPEFile(PEFile module) { string[] parts = typeName.Split('.'); - for (int i = parts.Length - 1; i >= 0; i--) { + for (int i = parts.Length - 1; i >= 0; i--) + { string ns = string.Join(".", parts, 0, i); string name = parts[i]; int topLevelTPC = (i == parts.Length - 1 ? typeParameterCount : 0); var topLevelName = new TopLevelTypeName(ns, name, topLevelTPC); var typeHandle = module.GetTypeDefinition(topLevelName); - for (int j = i + 1; j < parts.Length && !typeHandle.IsNil; j++) { + for (int j = i + 1; j < parts.Length && !typeHandle.IsNil; j++) + { int tpc = (j == parts.Length - 1 ? typeParameterCount : 0); var typeDef = module.Metadata.GetTypeDefinition(typeHandle); string lookupName = parts[j] + (tpc > 0 ? "`" + tpc : ""); @@ -95,7 +101,8 @@ namespace ICSharpCode.Decompiler.Documentation if (!typeHandle.IsNil) return typeHandle; FullTypeName typeName = topLevelName; - for (int j = i + 1; j < parts.Length; j++) { + for (int j = i + 1; j < parts.Length; j++) + { int tpc = (j == parts.Length - 1 ? typeParameterCount : 0); typeName = typeName.NestedType(parts[j], tpc); } diff --git a/ICSharpCode.Decompiler/Documentation/IdStringMemberReference.cs b/ICSharpCode.Decompiler/Documentation/IdStringMemberReference.cs index 2b9c6b447..3b0ad8bdc 100644 --- a/ICSharpCode.Decompiler/Documentation/IdStringMemberReference.cs +++ b/ICSharpCode.Decompiler/Documentation/IdStringMemberReference.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Documentation @@ -27,17 +28,18 @@ namespace ICSharpCode.Decompiler.Documentation readonly ITypeReference declaringTypeReference; readonly char memberType; readonly string memberIdString; - + public IdStringMemberReference(ITypeReference declaringTypeReference, char memberType, string memberIdString) { this.declaringTypeReference = declaringTypeReference; this.memberType = memberType; this.memberIdString = memberIdString; } - + bool CanMatch(IMember member) { - switch (member.SymbolKind) { + switch (member.SymbolKind) + { case SymbolKind.Field: return memberType == 'F'; case SymbolKind.Property: @@ -54,15 +56,16 @@ namespace ICSharpCode.Decompiler.Documentation throw new NotSupportedException(member.SymbolKind.ToString()); } } - + public ITypeReference DeclaringTypeReference { get { return declaringTypeReference; } } - + public IMember Resolve(ITypeResolveContext context) { IType declaringType = declaringTypeReference.Resolve(context); - foreach (var member in declaringType.GetMembers(CanMatch, GetMemberOptions.IgnoreInheritedMembers)) { + foreach (var member in declaringType.GetMembers(CanMatch, GetMemberOptions.IgnoreInheritedMembers)) + { if (IdStringProvider.GetIdString(member) == memberIdString) return member; } diff --git a/ICSharpCode.Decompiler/Documentation/IdStringProvider.cs b/ICSharpCode.Decompiler/Documentation/IdStringProvider.cs index 29d4e596b..75470a24d 100644 --- a/ICSharpCode.Decompiler/Documentation/IdStringProvider.cs +++ b/ICSharpCode.Decompiler/Documentation/IdStringProvider.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -38,7 +39,8 @@ namespace ICSharpCode.Decompiler.Documentation public static string GetIdString(this IEntity entity) { StringBuilder b = new StringBuilder(); - switch (entity.SymbolKind) { + switch (entity.SymbolKind) + { case SymbolKind.TypeDefinition: b.Append("T:"); AppendTypeName(b, (ITypeDefinition)entity, false); @@ -58,31 +60,38 @@ namespace ICSharpCode.Decompiler.Documentation break; } IMember member = (IMember)entity; - if (member.DeclaringType != null) { + if (member.DeclaringType != null) + { AppendTypeName(b, member.DeclaringType, false); b.Append('.'); } - if (member.IsExplicitInterfaceImplementation && member.Name.IndexOf('.') < 0 && member.ExplicitlyImplementedInterfaceMembers.Count() == 1) { + if (member.IsExplicitInterfaceImplementation && member.Name.IndexOf('.') < 0 && member.ExplicitlyImplementedInterfaceMembers.Count() == 1) + { AppendTypeName(b, member.ExplicitlyImplementedInterfaceMembers.First().DeclaringType, true); b.Append('#'); } b.Append(member.Name.Replace('.', '#').Replace('<', '{').Replace('>', '}')); IMethod method = member as IMethod; - if (method != null && method.TypeParameters.Count > 0) { + 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) { + 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(','); + for (int i = 0; i < parameters.Count; i++) + { + if (i > 0) + b.Append(','); AppendTypeName(b, parameters[i].Type, false); } b.Append(')'); } - if (member.SymbolKind == SymbolKind.Operator && (member.Name == "op_Implicit" || member.Name == "op_Explicit")) { + if (member.SymbolKind == SymbolKind.Operator && (member.Name == "op_Implicit" || member.Name == "op_Explicit")) + { b.Append('~'); AppendTypeName(b, member.ReturnType, false); } @@ -102,15 +111,19 @@ namespace ICSharpCode.Decompiler.Documentation static void AppendTypeName(StringBuilder b, IType type, bool explicitInterfaceImpl) { - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.Dynamic: b.Append(explicitInterfaceImpl ? "System#Object" : "System.Object"); break; case TypeKind.TypeParameter: ITypeParameter tp = (ITypeParameter)type; - if (explicitInterfaceImpl) { + if (explicitInterfaceImpl) + { b.Append(tp.Name); - } else { + } + else + { b.Append('`'); if (tp.OwnerType == SymbolKind.Method) b.Append('`'); @@ -121,8 +134,10 @@ namespace ICSharpCode.Decompiler.Documentation ArrayType array = (ArrayType)type; AppendTypeName(b, array.ElementType, explicitInterfaceImpl); b.Append('['); - if (array.Dimensions > 1) { - for (int i = 0; i < array.Dimensions; i++) { + if (array.Dimensions > 1) + { + for (int i = 0; i < array.Dimensions; i++) + { if (i > 0) b.Append(explicitInterfaceImpl ? '@' : ','); if (!explicitInterfaceImpl) @@ -141,12 +156,15 @@ namespace ICSharpCode.Decompiler.Documentation break; default: IType declType = type.DeclaringType; - if (declType != null) { + if (declType != null) + { AppendTypeName(b, declType, explicitInterfaceImpl); b.Append(explicitInterfaceImpl ? '#' : '.'); b.Append(type.Name); AppendTypeParameters(b, type, declType.TypeParameterCount, explicitInterfaceImpl); - } else { + } + else + { if (explicitInterfaceImpl) b.Append(type.FullName.Replace('.', '#')); else @@ -160,18 +178,23 @@ namespace ICSharpCode.Decompiler.Documentation static void AppendTypeParameters(StringBuilder b, IType type, int outerTypeParameterCount, bool explicitInterfaceImpl) { int tpc = type.TypeParameterCount - outerTypeParameterCount; - if (tpc > 0) { + if (tpc > 0) + { ParameterizedType pt = type as ParameterizedType; - if (pt != null) { + if (pt != null) + { b.Append('{'); var ta = pt.TypeArguments; - for (int i = outerTypeParameterCount; i < ta.Count; i++) { + for (int i = outerTypeParameterCount; i < ta.Count; i++) + { if (i > outerTypeParameterCount) b.Append(explicitInterfaceImpl ? '@' : ','); AppendTypeName(b, ta[i], explicitInterfaceImpl); } b.Append('}'); - } else { + } + else + { b.Append('`'); b.Append(tpc); } @@ -211,11 +234,11 @@ namespace ICSharpCode.Decompiler.Documentation ITypeReference typeReference = ParseTypeName(typeName, ref pos); if (pos != typeName.Length) throw new ReflectionNameParseException(pos, "Expected end of type name"); -// string memberName = memberIDString.Substring(dotPos + 1, parenPos - (dotPos + 1)); -// pos = memberName.LastIndexOf("``"); -// if (pos > 0) -// memberName = memberName.Substring(0, pos); -// memberName = memberName.Replace('#', '.'); + // string memberName = memberIDString.Substring(dotPos + 1, parenPos - (dotPos + 1)); + // pos = memberName.LastIndexOf("``"); + // if (pos > 0) + // memberName = memberName.Substring(0, pos); + // memberName = memberName.Replace('#', '.'); return new IdStringMemberReference(typeReference, typeChar, memberIdString); } #endregion @@ -254,7 +277,8 @@ namespace ICSharpCode.Decompiler.Documentation static bool IsIDStringSpecialCharacter(char c) { - switch (c) { + switch (c) + { case ':': case '{': case '}': @@ -278,40 +302,51 @@ namespace ICSharpCode.Decompiler.Documentation if (pos == typeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); ITypeReference result; - if (reflectionTypeName[pos] == '`') { + if (reflectionTypeName[pos] == '`') + { // type parameter reference pos++; if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); - if (reflectionTypeName[pos] == '`') { + if (reflectionTypeName[pos] == '`') + { // method type parameter reference pos++; int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos); result = TypeParameterReference.Create(SymbolKind.Method, index); - } else { + } + else + { // class type parameter reference int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos); result = TypeParameterReference.Create(SymbolKind.TypeDefinition, index); } - } else { + } + else + { // not a type parameter reference: read the actual type name List typeArguments = new List(); string typeNameWithoutSuffix = ReadTypeName(typeName, ref pos, true, out int typeParameterCount, typeArguments); result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount); - while (pos < typeName.Length && typeName[pos] == '.') { + while (pos < typeName.Length && typeName[pos] == '.') + { pos++; string nestedTypeName = ReadTypeName(typeName, ref pos, false, out typeParameterCount, typeArguments); result = new NestedTypeReference(result, nestedTypeName, typeParameterCount); } - if (typeArguments.Count > 0) { + if (typeArguments.Count > 0) + { result = new ParameterizedTypeReference(result, typeArguments); } } - while (pos < typeName.Length) { - switch (typeName[pos]) { + while (pos < typeName.Length) + { + switch (typeName[pos]) + { case '[': int dimensions = 1; - do { + do + { pos++; if (pos == typeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); @@ -345,13 +380,17 @@ namespace ICSharpCode.Decompiler.Documentation string shortTypeName = typeName.Substring(startPos, pos - startPos); // read type arguments: typeParameterCount = 0; - if (pos < typeName.Length && typeName[pos] == '`') { + if (pos < typeName.Length && typeName[pos] == '`') + { // unbound generic type pos++; typeParameterCount = ReflectionHelper.ReadTypeParameterCount(typeName, ref pos); - } else if (pos < typeName.Length && typeName[pos] == '{') { + } + else if (pos < typeName.Length && typeName[pos] == '{') + { // bound generic type - do { + do + { pos++; typeArguments.Add(ParseTypeName(typeName, ref pos)); typeParameterCount++; @@ -380,9 +419,12 @@ namespace ICSharpCode.Decompiler.Documentation throw new ArgumentNullException(nameof(idString)); if (context == null) throw new ArgumentNullException(nameof(context)); - if (idString.StartsWith("T:", StringComparison.Ordinal)) { + if (idString.StartsWith("T:", StringComparison.Ordinal)) + { return ParseTypeName(idString.Substring(2)).Resolve(context).GetDefinition(); - } else { + } + else + { return ParseMemberIdString(idString).Resolve(context); } } diff --git a/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs b/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs index b10b15975..b922beeef 100644 --- a/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs +++ b/ICSharpCode.Decompiler/Documentation/XmlDocLoader.cs @@ -20,6 +20,7 @@ using System; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.Documentation @@ -31,7 +32,7 @@ namespace ICSharpCode.Decompiler.Documentation { static readonly Lazy mscorlibDocumentation = new Lazy(LoadMscorlibDocumentation); static readonly ConditionalWeakTable cache = new ConditionalWeakTable(); - + static XmlDocumentationProvider LoadMscorlibDocumentation() { string xmlDocFile = FindXmlDocumentation("mscorlib.dll", TargetRuntime.Net_4_0) @@ -41,25 +42,31 @@ namespace ICSharpCode.Decompiler.Documentation else return null; } - + public static XmlDocumentationProvider MscorlibDocumentation { get { return mscorlibDocumentation.Value; } } - + public static XmlDocumentationProvider LoadDocumentation(PEFile module) { if (module == null) throw new ArgumentNullException(nameof(module)); - lock (cache) { - if (!cache.TryGetValue(module, out XmlDocumentationProvider xmlDoc)) { + lock (cache) + { + if (!cache.TryGetValue(module, out XmlDocumentationProvider xmlDoc)) + { string xmlDocFile = LookupLocalizedXmlDoc(module.FileName); - if (xmlDocFile == null) { + if (xmlDocFile == null) + { xmlDocFile = FindXmlDocumentation(Path.GetFileName(module.FileName), module.GetRuntime()); } - if (xmlDocFile != null) { + if (xmlDocFile != null) + { xmlDoc = new XmlDocumentationProvider(xmlDocFile); cache.Add(module, xmlDoc); - } else { + } + else + { cache.Add(module, null); // add missing documentation files as well xmlDoc = null; } @@ -67,14 +74,15 @@ namespace ICSharpCode.Decompiler.Documentation return xmlDoc; } } - + static readonly string referenceAssembliesPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Reference Assemblies\Microsoft\\Framework"); static readonly string frameworkPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"Microsoft.NET\Framework"); - + static string FindXmlDocumentation(string assemblyFileName, TargetRuntime runtime) { string fileName; - switch (runtime) { + switch (runtime) + { case TargetRuntime.Net_1_0: fileName = LookupLocalizedXmlDoc(Path.Combine(frameworkPath, "v1.0.3705", assemblyFileName)); break; @@ -95,34 +103,38 @@ namespace ICSharpCode.Decompiler.Documentation } return fileName; } - + static string LookupLocalizedXmlDoc(string fileName) { if (string.IsNullOrEmpty(fileName)) return null; - + string xmlFileName = Path.ChangeExtension(fileName, ".xml"); string currentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName; string localizedXmlDocFile = GetLocalizedName(xmlFileName, currentCulture); - + Debug.WriteLine("Try find XMLDoc @" + localizedXmlDocFile); - if (File.Exists(localizedXmlDocFile)) { + if (File.Exists(localizedXmlDocFile)) + { return localizedXmlDocFile; } Debug.WriteLine("Try find XMLDoc @" + xmlFileName); - if (File.Exists(xmlFileName)) { + if (File.Exists(xmlFileName)) + { return xmlFileName; } - if (currentCulture != "en") { + if (currentCulture != "en") + { string englishXmlDocFile = GetLocalizedName(xmlFileName, "en"); Debug.WriteLine("Try find XMLDoc @" + englishXmlDocFile); - if (File.Exists(englishXmlDocFile)) { + if (File.Exists(englishXmlDocFile)) + { return englishXmlDocFile; } } return null; } - + static string GetLocalizedName(string fileName, string language) { string localizedXmlDocFile = Path.GetDirectoryName(fileName); diff --git a/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs b/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs index 3b8b0f21e..61948f6ca 100644 --- a/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs +++ b/ICSharpCode.Decompiler/Documentation/XmlDocumentationElement.cs @@ -22,6 +22,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml.Linq; + using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -89,12 +90,16 @@ namespace ICSharpCode.Decompiler.Documentation /// public IEntity ReferencedEntity { get { - if (!referencedEntityInitialized) { + if (!referencedEntityInitialized) + { string cref = GetAttribute("cref"); - try { + try + { if (!string.IsNullOrEmpty(cref) && crefResolver != null) referencedEntity = crefResolver(cref); - } catch { + } + catch + { referencedEntity = null; } referencedEntityInitialized = true; @@ -132,7 +137,8 @@ namespace ICSharpCode.Decompiler.Documentation /// public string TextContent { get { - if (textContent == null) { + if (textContent == null) + { StringBuilder b = new StringBuilder(); foreach (var child in this.Children) b.Append(child.TextContent); @@ -165,38 +171,52 @@ namespace ICSharpCode.Decompiler.Documentation static List CreateElements(IEnumerable childObjects, IEntity declaringEntity, Func crefResolver, int nestingLevel) { List list = new List(); - foreach (var child in childObjects) { + foreach (var child in childObjects) + { var childText = child as XText; var childTag = child as XCData; var childElement = child as XElement; - if (childText != null) { + if (childText != null) + { list.Add(new XmlDocumentationElement(childText.Value, declaringEntity)); - } else if (childTag != null) { + } + else if (childTag != null) + { list.Add(new XmlDocumentationElement(childTag.Value, declaringEntity)); - } else if (childElement != null) { - if (nestingLevel < 5 && childElement.Name == "inheritdoc") { + } + else if (childElement != null) + { + if (nestingLevel < 5 && childElement.Name == "inheritdoc") + { string cref = childElement.Attribute("cref").Value; IEntity inheritedFrom = null; string inheritedDocumentation = null; - if (cref != null) { + if (cref != null) + { inheritedFrom = crefResolver(cref); if (inheritedFrom != null) inheritedDocumentation = inheritedFrom.GetDocumentation(); - } else { - foreach (IMember baseMember in InheritanceHelper.GetBaseMembers((IMember)declaringEntity, includeImplementedInterfaces: true)) { + } + else + { + foreach (IMember baseMember in InheritanceHelper.GetBaseMembers((IMember)declaringEntity, includeImplementedInterfaces: true)) + { inheritedDocumentation = baseMember.GetDocumentation(); - if (inheritedDocumentation != null) { + if (inheritedDocumentation != null) + { inheritedFrom = baseMember; break; } } } - if (inheritedDocumentation != null) { + if (inheritedDocumentation != null) + { var doc = XDocument.Parse(inheritedDocumentation); // XPath filter not yet implemented - if (childElement.Parent == null && childElement.Attribute("select").Value == null) { + if (childElement.Parent == null && childElement.Attribute("select").Value == null) + { // Inheriting documentation at the root level List doNotInherit = new List(); doNotInherit.Add("overloads"); @@ -212,18 +232,22 @@ namespace ICSharpCode.Decompiler.Documentation list.AddRange(CreateElements(inheritedChildren, inheritedFrom, crefResolver, nestingLevel + 1)); } } - } else { + } + else + { list.Add(new XmlDocumentationElement(childElement, declaringEntity, crefResolver) { nestingLevel = nestingLevel }); } } } - if (list.Count > 0 && list[0].IsTextNode) { + if (list.Count > 0 && list[0].IsTextNode) + { if (string.IsNullOrWhiteSpace(list[0].textContent)) list.RemoveAt(0); else list[0].textContent = list[0].textContent.TrimStart(); } - if (list.Count > 0 && list[list.Count - 1].IsTextNode) { + if (list.Count > 0 && list[list.Count - 1].IsTextNode) + { if (string.IsNullOrWhiteSpace(list[list.Count - 1].textContent)) list.RemoveAt(list.Count - 1); else diff --git a/ICSharpCode.Decompiler/Documentation/XmlDocumentationProvider.cs b/ICSharpCode.Decompiler/Documentation/XmlDocumentationProvider.cs index fb2e02834..b28d2f6ef 100644 --- a/ICSharpCode.Decompiler/Documentation/XmlDocumentationProvider.cs +++ b/ICSharpCode.Decompiler/Documentation/XmlDocumentationProvider.cs @@ -23,6 +23,7 @@ using System.IO; using System.Runtime.Serialization; using System.Text; using System.Xml; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -58,18 +59,20 @@ namespace ICSharpCode.Decompiler.Documentation { readonly KeyValuePair[] entries; int pos; - + public XmlDocumentationCache(int size = 50) { if (size <= 0) throw new ArgumentOutOfRangeException(nameof(size), size, "Value must be positive"); this.entries = new KeyValuePair[size]; } - + internal bool TryGet(string key, out string value) { - foreach (var pair in entries) { - if (pair.Key == key) { + foreach (var pair in entries) + { + if (pair.Key == key) + { value = pair.Value; return true; } @@ -77,7 +80,7 @@ namespace ICSharpCode.Decompiler.Documentation value = null; return false; } - + internal void Add(string key, string value) { entries[pos++] = new KeyValuePair(key, value); @@ -86,7 +89,7 @@ namespace ICSharpCode.Decompiler.Documentation } } #endregion - + [Serializable] struct IndexEntry : IComparable { @@ -94,31 +97,31 @@ namespace ICSharpCode.Decompiler.Documentation /// Hash code of the documentation tag /// internal readonly int HashCode; - + /// /// Position in the .xml file where the documentation starts /// internal readonly int PositionInFile; - + internal IndexEntry(int hashCode, int positionInFile) { this.HashCode = hashCode; this.PositionInFile = positionInFile; } - + public int CompareTo(IndexEntry other) { return this.HashCode.CompareTo(other.HashCode); } } - + [NonSerialized] XmlDocumentationCache cache = new XmlDocumentationCache(); - + readonly string fileName; readonly Encoding encoding; volatile IndexEntry[] index; // SORTED array of index entries - + #region Constructor / Redirection support /// /// Creates a new XmlDocumentationProvider. @@ -130,21 +133,29 @@ namespace ICSharpCode.Decompiler.Documentation { if (fileName == null) throw new ArgumentNullException(nameof(fileName)); - - using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { - using (XmlTextReader xmlReader = new XmlTextReader(fs)) { + + 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"))) { + if (string.IsNullOrEmpty(xmlReader.GetAttribute("redirect"))) + { this.fileName = fileName; this.encoding = xmlReader.Encoding; ReadXmlDoc(xmlReader); - } else { + } + else + { string redirectionTarget = GetRedirectionTarget(fileName, xmlReader.GetAttribute("redirect")); - if (redirectionTarget != null) { + 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)) { + using (FileStream redirectedFs = new FileStream(redirectionTarget, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) + { + using (XmlTextReader redirectedXmlReader = new XmlTextReader(redirectedFs)) + { redirectedXmlReader.XmlResolver = null; // no DTD resolving redirectedXmlReader.MoveToContent(); this.fileName = redirectionTarget; @@ -152,29 +163,31 @@ namespace ICSharpCode.Decompiler.Documentation ReadXmlDoc(redirectedXmlReader); } } - } else { + } + else + { throw new XmlException("XmlDoc " + fileName + " is redirecting to " + xmlReader.GetAttribute("redirect") + ", but that file was not found."); } } } } } - + static string GetRedirectionTarget(string xmlFileName, string target) { string programFilesDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); programFilesDir = AppendDirectorySeparator(programFilesDir); - + string corSysDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(); corSysDir = AppendDirectorySeparator(corSysDir); - - var fileName = target.Replace ("%PROGRAMFILESDIR%", programFilesDir) - .Replace ("%CORSYSDIR%", corSysDir); - if (!Path.IsPathRooted (fileName)) - fileName = Path.Combine (Path.GetDirectoryName (xmlFileName), fileName); + + var fileName = target.Replace("%PROGRAMFILESDIR%", programFilesDir) + .Replace("%CORSYSDIR%", corSysDir); + if (!Path.IsPathRooted(fileName)) + fileName = Path.Combine(Path.GetDirectoryName(xmlFileName), fileName); return LookupLocalizedXmlDoc(fileName); } - + static string AppendDirectorySeparator(string dir) { if (dir.EndsWith("\\", StringComparison.Ordinal) || dir.EndsWith("/", StringComparison.Ordinal)) @@ -182,7 +195,7 @@ namespace ICSharpCode.Decompiler.Documentation else return dir + Path.DirectorySeparatorChar; } - + /// /// Given the assembly file name, looks up the XML documentation file name. /// Returns null if no XML documentation file is found. @@ -192,25 +205,29 @@ namespace ICSharpCode.Decompiler.Documentation string xmlFileName = Path.ChangeExtension(fileName, ".xml"); string currentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName; string localizedXmlDocFile = GetLocalizedName(xmlFileName, currentCulture); - + Debug.WriteLine("Try find XMLDoc @" + localizedXmlDocFile); - if (File.Exists(localizedXmlDocFile)) { + if (File.Exists(localizedXmlDocFile)) + { return localizedXmlDocFile; } Debug.WriteLine("Try find XMLDoc @" + xmlFileName); - if (File.Exists(xmlFileName)) { + if (File.Exists(xmlFileName)) + { return xmlFileName; } - if (currentCulture != "en") { + if (currentCulture != "en") + { string englishXmlDocFile = GetLocalizedName(xmlFileName, "en"); Debug.WriteLine("Try find XMLDoc @" + englishXmlDocFile); - if (File.Exists(englishXmlDocFile)) { + if (File.Exists(englishXmlDocFile)) + { return englishXmlDocFile; } } return null; } - + static string GetLocalizedName(string fileName, string language) { string localizedXmlDocFile = Path.GetDirectoryName(fileName); @@ -219,18 +236,22 @@ namespace ICSharpCode.Decompiler.Documentation return localizedXmlDocFile; } #endregion - + #region Load / Create Index void ReadXmlDoc(XmlTextReader reader) { //lastWriteDate = File.GetLastWriteTimeUtc(fileName); // Open up a second file stream for the line<->position mapping - using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { + using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) + { LinePositionMapper linePosMapper = new LinePositionMapper(fs, encoding); List indexList = new List(); - while (reader.Read()) { - if (reader.IsStartElement()) { - switch (reader.LocalName) { + while (reader.Read()) + { + if (reader.IsStartElement()) + { + switch (reader.LocalName) + { case "members": ReadMembersSection(reader, linePosMapper, indexList); break; @@ -241,35 +262,37 @@ namespace ICSharpCode.Decompiler.Documentation this.index = indexList.ToArray(); // volatile write } } - + sealed class LinePositionMapper { readonly FileStream fs; readonly Decoder decoder; int currentLine = 1; char prevChar = '\0'; - + // buffers for use with Decoder: byte[] input = new byte[1]; char[] output = new char[1]; - + public LinePositionMapper(FileStream fs, Encoding encoding) { this.decoder = encoding.GetDecoder(); this.fs = fs; } - + public int GetPositionForLine(int line) { Debug.Assert(line >= currentLine); - while (line > currentLine) { + while (line > currentLine) + { int b = fs.ReadByte(); if (b < 0) throw new EndOfStreamException(); input[0] = (byte)b; decoder.Convert(input, 0, 1, output, 0, 1, false, out int bytesUsed, out int charsUsed, out _); Debug.Assert(bytesUsed == 1); - if (charsUsed == 1) { + if (charsUsed == 1) + { if ((prevChar != '\r' && output[0] == '\n') || output[0] == '\r') currentLine++; prevChar = output[0]; @@ -278,18 +301,22 @@ namespace ICSharpCode.Decompiler.Documentation return checked((int)fs.Position); } } - + static void ReadMembersSection(XmlTextReader reader, LinePositionMapper linePosMapper, List indexList) { - while (reader.Read()) { - switch (reader.NodeType) { + while (reader.Read()) + { + switch (reader.NodeType) + { case XmlNodeType.EndElement: - if (reader.LocalName == "members") { + if (reader.LocalName == "members") + { return; } break; case XmlNodeType.Element: - if (reader.LocalName == "member") { + if (reader.LocalName == "member") + { int pos = linePosMapper.GetPositionForLine(reader.LineNumber) + Math.Max(reader.LinePosition - 2, 0); string memberAttr = reader.GetAttribute("name"); if (memberAttr != null) @@ -300,7 +327,7 @@ namespace ICSharpCode.Decompiler.Documentation } } } - + /// /// Hash algorithm used for the index. /// This is a custom implementation so that old index files work correctly @@ -309,16 +336,18 @@ namespace ICSharpCode.Decompiler.Documentation /// static int GetHashCode(string key) { - unchecked { + unchecked + { int h = 0; - foreach (char c in key) { + foreach (char c in key) + { h = (h << 5) - h + c; } return h; } } #endregion - + #region GetDocumentation /// /// Get the documentation for the member with the specified documentation key. @@ -344,31 +373,40 @@ namespace ICSharpCode.Decompiler.Documentation { int hashcode = GetHashCode(key); var index = this.index; // read volatile field - // index is sorted, so we can use binary search + // index is sorted, so we can use binary search int m = Array.BinarySearch(index, new IndexEntry(hashcode, 0)); if (m < 0) return null; // correct hash code found. // possibly there are multiple items with the same hash, so go to the first. - while (--m >= 0 && index[m].HashCode == hashcode); + while (--m >= 0 && index[m].HashCode == hashcode) + ; // m is now 1 before the first item with the correct hash - + XmlDocumentationCache cache = this.cache; - lock (cache) { - if (!cache.TryGet(key, out string val)) { - try { + lock (cache) + { + if (!cache.TryGet(key, out string val)) + { + try + { // go through all items that have the correct hash - while (++m < index.Length && index[m].HashCode == hashcode) { + while (++m < index.Length && index[m].HashCode == hashcode) + { val = LoadDocumentation(key, index[m].PositionInFile); if (val != null) break; } // cache the result (even if it is null) cache.Add(key, val); - } catch (IOException) { + } + catch (IOException) + { // may happen if the documentation file was deleted/is inaccessible/changed (EndOfStreamException) return allowReload ? ReloadAndGetDocumentation(key) : null; - } catch (XmlException) { + } + catch (XmlException) + { // may happen if the documentation file was changed so that the file position no longer starts on a valid XML element return allowReload ? ReloadAndGetDocumentation(key) : null; } @@ -376,44 +414,58 @@ namespace ICSharpCode.Decompiler.Documentation return val; } } - + string ReloadAndGetDocumentation(string key) { - try { + try + { // Reload the index - using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { - using (XmlTextReader xmlReader = new XmlTextReader(fs)) { + 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(); ReadXmlDoc(xmlReader); } } - } catch (IOException) { + } + catch (IOException) + { // Ignore errors on reload; IEntity.Documentation callers aren't prepared to handle exceptions this.index = Empty.Array; // clear index to avoid future load attempts return null; - } catch (XmlException) { + } + catch (XmlException) + { this.index = Empty.Array; // clear index to avoid future load attempts return null; } return GetDocumentation(key, allowReload: false); // prevent infinite reload loops } #endregion - + #region Load / Read XML string LoadDocumentation(string key, int positionInFile) { - using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { + using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) + { fs.Position = positionInFile; var context = new XmlParserContext(null, null, null, XmlSpace.None) { Encoding = encoding }; - using (XmlTextReader r = new XmlTextReader(fs, XmlNodeType.Element, context)) { + using (XmlTextReader r = new XmlTextReader(fs, XmlNodeType.Element, context)) + { r.XmlResolver = null; // no DTD resolving - while (r.Read()) { - if (r.NodeType == XmlNodeType.Element) { + while (r.Read()) + { + if (r.NodeType == XmlNodeType.Element) + { string memberAttr = r.GetAttribute("name"); - if (memberAttr == key) { + if (memberAttr == key) + { return r.ReadInnerXml(); - } else { + } + else + { return null; } } @@ -423,7 +475,7 @@ namespace ICSharpCode.Decompiler.Documentation } } #endregion - + public virtual void OnDeserialization(object sender) { cache = new XmlDocumentationCache(); diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs index f0a72bf20..91c7f364d 100644 --- a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs +++ b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.FlowAnalysis @@ -33,58 +34,58 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// User index, can be used to look up additional information in an array. /// public int UserIndex; - + /// /// User data. /// public object UserData; - + /// /// Visited flag, used in various algorithms. /// public bool Visited; - + /// /// Gets the node index in a post-order traversal of the control flow graph, starting at the /// entry point. This field gets computed by dominance analysis. /// public int PostOrderNumber; - + /// /// Gets whether this node is reachable. Requires that dominance is computed! /// public bool IsReachable { get { return DominatorTreeChildren != null; } } - + /// /// Gets the immediate dominator (the parent in the dominator tree). /// Null if dominance has not been calculated; or if the node is unreachable. /// public ControlFlowNode ImmediateDominator { get; internal set; } - + /// /// List of children in the dominator tree. /// Null if dominance has not been calculated; or if the node is unreachable. /// public List DominatorTreeChildren { get; internal set; } - + /// /// List of incoming control flow edges. /// public readonly List Predecessors = new List(); - + /// /// List of outgoing control flow edges. /// public readonly List Successors = new List(); - + public void AddEdgeTo(ControlFlowNode target) { this.Successors.Add(target); target.Predecessors.Add(this); } - + public void TraversePreOrder(Func> children, Action visitAction) { if (Visited) @@ -94,7 +95,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis foreach (ControlFlowNode t in children(this)) t.TraversePreOrder(children, visitAction); } - + public void TraversePostOrder(Func> children, Action visitAction) { if (Visited) @@ -104,7 +105,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis t.TraversePostOrder(children, visitAction); visitAction(this); } - + /// /// Gets whether this dominates . /// @@ -112,7 +113,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis { // TODO: this can be made O(1) by numbering the dominator tree ControlFlowNode tmp = node; - while (tmp != null) { + while (tmp != null) + { if (tmp == this) return true; tmp = tmp.ImmediateDominator; @@ -123,7 +125,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis #if DEBUG internal static GraphVizGraph ExportGraph(IReadOnlyList nodes, Func labelFunc = null) { - if (labelFunc == null) { + if (labelFunc == null) + { labelFunc = node => { var block = node.UserData as IL.Block; return block != null ? block.Label : node.UserData?.ToString(); @@ -131,17 +134,21 @@ namespace ICSharpCode.Decompiler.FlowAnalysis } GraphVizGraph g = new GraphVizGraph(); GraphVizNode[] n = new GraphVizNode[nodes.Count]; - for (int i = 0; i < n.Length; i++) { + for (int i = 0; i < n.Length; i++) + { n[i] = new GraphVizNode(nodes[i].UserIndex); n[i].shape = "box"; n[i].label = labelFunc(nodes[i]); g.AddNode(n[i]); } - foreach (var source in nodes) { - foreach (var target in source.Successors) { + foreach (var source in nodes) + { + foreach (var target in source.Successors) + { g.AddEdge(new GraphVizEdge(source.UserIndex, target.UserIndex)); } - if (source.ImmediateDominator != null) { + if (source.ImmediateDominator != null) + { g.AddEdge( new GraphVizEdge(source.ImmediateDominator.UserIndex, source.UserIndex) { color = "green" diff --git a/ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs b/ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs index ed5d01918..eb1f41d54 100644 --- a/ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs +++ b/ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; + using ICSharpCode.Decompiler.IL; namespace ICSharpCode.Decompiler.FlowAnalysis @@ -39,7 +40,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// method calls on the type parameter, but that struct must consist only of a readonly field /// referencing some mutable object, to ensure the type parameter behaves as it if was a mutable reference type. /// - public interface IDataFlowState where Self: IDataFlowState + public interface IDataFlowState where Self : IDataFlowState { /// /// Gets whether this state is "less than" (or equal to) another state. @@ -62,7 +63,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// return !this.isReachable || otherState.isReachable; /// bool LessThanOrEqual(Self otherState); - + /// /// Creates a new object with a copy of the state. /// @@ -76,7 +77,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// return new MyState(this.isReachable); /// Self Clone(); - + /// /// Replace the contents of this state object with a copy of those in . /// @@ -92,7 +93,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// this.isReachable = newContent.isReachable; /// void ReplaceWith(Self newContent); - + /// /// Join the incomingState into this state. /// @@ -122,7 +123,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// this.isReachable &= finallyState.isReachable; /// void TriggerFinally(Self finallyState); - + /// /// Gets whether this is the bottom state. /// @@ -144,7 +145,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// return !this.isReachable; /// bool IsBottom { get; } - + /// /// Equivalent to this.ReplaceWith(bottomState), but may be implemented more efficiently. /// @@ -159,7 +160,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// void ReplaceWithBottom(); } - + /// /// Generic base class for forward data flow analyses. /// @@ -177,20 +178,20 @@ namespace ICSharpCode.Decompiler.FlowAnalysis // and gets mutated as we traverse the ILAst. // b) the input state for each control flow node // These also gets mutated as the analysis learns about new control flow edges. - + /// /// The bottom state. /// Must not be mutated. /// State bottomState; - + /// /// Current state. /// /// Caution: any state object assigned to this member gets mutated as the visitor traverses the ILAst! /// protected State state; - + /// /// Combined state of all possible exceptional control flow paths in the current try block. /// Serves as input state for catch blocks. @@ -201,9 +202,9 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// /// protected State currentStateOnException; - + bool initialized; - + /// /// Initializes the DataFlowVisitor. /// This method must be called once before any Visit()-methods can be called. @@ -225,23 +226,27 @@ namespace ICSharpCode.Decompiler.FlowAnalysis this.stateOnNullableRewrap = bottomState.Clone(); this.currentStateOnException = state.Clone(); } - - #if DEBUG + +#if DEBUG // For debugging, capture the input + output state at every instruction. readonly Dictionary debugInputState = new Dictionary(); readonly Dictionary debugOutputState = new Dictionary(); - + void DebugPoint(Dictionary debugDict, ILInstruction inst) { - #if DEBUG +#if DEBUG Debug.Assert(initialized, "Initialize() was not called"); - if (debugDict.TryGetValue(inst, out State previousState)) { + if (debugDict.TryGetValue(inst, out State previousState)) + { Debug.Assert(previousState.LessThanOrEqual(state)); previousState.JoinWith(state); - } else { + } + else + { // limit the number of tracked instructions to make memory usage in debug builds less horrible - if (debugDict.Count < 1000) { + if (debugDict.Count < 1000) + { debugDict.Add(inst, state.Clone()); } } @@ -249,49 +254,51 @@ namespace ICSharpCode.Decompiler.FlowAnalysis // currentStateOnException should be all states within the try block joined together // -> state should already have been joined into currentStateOnException. Debug.Assert(state.LessThanOrEqual(currentStateOnException)); - #endif +#endif } - #endif - +#endif + [Conditional("DEBUG")] protected void DebugStartPoint(ILInstruction inst) { - #if DEBUG +#if DEBUG DebugPoint(debugInputState, inst); - #endif +#endif } - + [Conditional("DEBUG")] protected void DebugEndPoint(ILInstruction inst) { - #if DEBUG +#if DEBUG DebugPoint(debugOutputState, inst); - #endif +#endif } - + /// /// Derived classes may add to this set of flags to ensure they don't forget to override an interesting method. /// protected InstructionFlags flagsRequiringManualImpl = InstructionFlags.ControlFlow | InstructionFlags.MayBranch | InstructionFlags.MayUnwrapNull | InstructionFlags.EndPointUnreachable; - + protected sealed override void Default(ILInstruction inst) { DebugStartPoint(inst); // This method assumes normal control flow and no branches. - if ((inst.DirectFlags & flagsRequiringManualImpl) != 0) { + if ((inst.DirectFlags & flagsRequiringManualImpl) != 0) + { throw new NotImplementedException(GetType().Name + " is missing implementation for " + inst.GetType().Name); } - + // Since this instruction has normal control flow, we can evaluate our children left-to-right. - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { child.AcceptVisitor(this); Debug.Assert(state.IsBottom || !child.HasFlag(InstructionFlags.EndPointUnreachable), "Unreachable code must be in the bottom state."); } - + DebugEndPoint(inst); } - + /// /// Handle control flow when the current instruction throws an exception: /// joins the current state into the "exception state" of the current try block. @@ -311,7 +318,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis { currentStateOnException.JoinWith(state); } - + /// /// Replace the current state with the bottom state. /// @@ -319,7 +326,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis { state.ReplaceWithBottom(); } - + /// /// Holds the state for incoming branches. /// @@ -327,7 +334,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// Only used for blocks in block containers; not for inline blocks. /// readonly Dictionary stateOnBranch = new Dictionary(); - + /// /// Holds the state at the block container end-point. (=state for incoming 'leave' instructions) /// @@ -343,21 +350,24 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// State GetBlockInputState(Block block) { - if (stateOnBranch.TryGetValue(block, out State s)) { + if (stateOnBranch.TryGetValue(block, out State s)) + { return s; - } else { + } + else + { s = bottomState.Clone(); stateOnBranch.Add(block, s); return s; } } - + /// /// For each block container, stores the set of blocks (via Block.ChildIndex) /// that had their incoming state changed and were not processed yet. /// readonly Dictionary> workLists = new Dictionary>(); - + protected internal override void VisitBlockContainer(BlockContainer container) { DebugStartPoint(container); @@ -365,13 +375,14 @@ namespace ICSharpCode.Decompiler.FlowAnalysis // register work list so that branches within this container can add to it workLists.Add(container, worklist); var stateOnEntry = GetBlockInputState(container.EntryPoint); - if (!state.LessThanOrEqual(stateOnEntry)) { + if (!state.LessThanOrEqual(stateOnEntry)) + { // If we have new information for the container's entry point, // add the container entry point to the work list. stateOnEntry.JoinWith(state); worklist.Add(0); } - + // To handle loops, we need to analyze the loop body before we can know the state for the loop backedge, // but we need to know the input state for the loop body (to which the backedge state contributes) // before we can analyze the loop body. @@ -379,16 +390,20 @@ namespace ICSharpCode.Decompiler.FlowAnalysis // To make it terminate reasonably quickly, we need to process the control flow nodes in the correct order: // reverse post-order. We use a SortedSet for this, and assume that the block indices used in the SortedSet // are ordered appropriately. The caller can use BlockContainer.SortBlocks() for this. - while (worklist.Count > 0) { + while (worklist.Count > 0) + { int blockIndex = worklist.Min; worklist.Remove(blockIndex); Block block = container.Blocks[blockIndex]; state.ReplaceWith(stateOnBranch[block]); block.AcceptVisitor(this); } - if (stateOnLeave.TryGetValue(container, out State stateOnExit)) { + if (stateOnLeave.TryGetValue(container, out State stateOnExit)) + { state.ReplaceWith(stateOnExit); - } else { + } + else + { MarkUnreachable(); } DebugEndPoint(container); @@ -399,10 +414,13 @@ namespace ICSharpCode.Decompiler.FlowAnalysis protected internal override void VisitBranch(Branch inst) { - if (inst.TriggersFinallyBlock) { + if (inst.TriggersFinallyBlock) + { Debug.Assert(state.LessThanOrEqual(currentStateOnException)); branchesTriggeringFinally.Add((inst, state.Clone())); - } else { + } + else + { MergeBranchStateIntoTargetBlock(inst, state); } MarkUnreachable(); @@ -412,21 +430,25 @@ namespace ICSharpCode.Decompiler.FlowAnalysis { var targetBlock = inst.TargetBlock; var targetState = GetBlockInputState(targetBlock); - if (!branchState.LessThanOrEqual(targetState)) { + if (!branchState.LessThanOrEqual(targetState)) + { targetState.JoinWith(branchState); BlockContainer container = (BlockContainer)targetBlock.Parent; workLists[container].Add(targetBlock.ChildIndex); } } - + protected internal override void VisitLeave(Leave inst) { inst.Value.AcceptVisitor(this); - if (inst.TriggersFinallyBlock) { + if (inst.TriggersFinallyBlock) + { Debug.Assert(state.LessThanOrEqual(currentStateOnException)); branchesTriggeringFinally.Add((inst, state.Clone())); - } else { + } + else + { MergeBranchStateIntoStateOnLeave(inst, state); } MarkUnreachable(); @@ -434,9 +456,12 @@ namespace ICSharpCode.Decompiler.FlowAnalysis void MergeBranchStateIntoStateOnLeave(Leave inst, State branchState) { - if (stateOnLeave.TryGetValue(inst.TargetContainer, out State targetState)) { + if (stateOnLeave.TryGetValue(inst.TargetContainer, out State targetState)) + { targetState.JoinWith(branchState); - } else { + } + else + { stateOnLeave.Add(inst.TargetContainer, branchState.Clone()); } // Note: We don't have to put the block container onto the work queue, @@ -449,22 +474,22 @@ namespace ICSharpCode.Decompiler.FlowAnalysis inst.Argument.AcceptVisitor(this); MarkUnreachable(); } - + protected internal override void VisitRethrow(Rethrow inst) { MarkUnreachable(); } - + protected internal override void VisitInvalidBranch(InvalidBranch inst) { MarkUnreachable(); } - + /// /// Stores the stateOnException per try instruction. /// readonly Dictionary stateOnException = new Dictionary(); - + /// /// Visits the TryBlock. /// @@ -473,9 +498,12 @@ namespace ICSharpCode.Decompiler.FlowAnalysis protected State HandleTryBlock(TryInstruction inst) { State oldStateOnException = currentStateOnException; - if (stateOnException.TryGetValue(inst, out State newStateOnException)) { + if (stateOnException.TryGetValue(inst, out State newStateOnException)) + { newStateOnException.JoinWith(state); - } else { + } + else + { newStateOnException = state.Clone(); stateOnException.Add(inst, newStateOnException); } @@ -484,7 +512,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis inst.TryBlock.AcceptVisitor(this); // swap back to the old object instance currentStateOnException = oldStateOnException; - + // No matter what kind of try-instruction this is, it's possible // that an async exception is thrown immediately in the handler block, // so propagate the state: @@ -494,13 +522,14 @@ namespace ICSharpCode.Decompiler.FlowAnalysis // does not influence the 'stateOnException' dict return newStateOnException.Clone(); } - + protected internal override void VisitTryCatch(TryCatch inst) { DebugStartPoint(inst); State onException = HandleTryBlock(inst); State endpoint = state.Clone(); - foreach (var handler in inst.Handlers) { + foreach (var handler in inst.Handlers) + { state.ReplaceWith(onException); BeginTryCatchHandler(handler); handler.Filter.AcceptVisitor(this); @@ -509,18 +538,18 @@ namespace ICSharpCode.Decompiler.FlowAnalysis // (but it's also possible that the filter didn't get executed at all // because the exception type doesn't match) onException.JoinWith(state); - + handler.Body.AcceptVisitor(this); endpoint.JoinWith(state); } state = endpoint; DebugEndPoint(inst); } - + protected virtual void BeginTryCatchHandler(TryCatchHandler inst) { } - + /// /// TryCatchHandler is handled directly in VisitTryCatch /// @@ -559,19 +588,26 @@ namespace ICSharpCode.Decompiler.FlowAnalysis void ProcessBranchesLeavingTryFinally(TryFinally tryFinally, int branchesTriggeringFinallyOldCount) { int outPos = branchesTriggeringFinallyOldCount; - for (int i = branchesTriggeringFinallyOldCount; i < branchesTriggeringFinally.Count; ++i) { + for (int i = branchesTriggeringFinallyOldCount; i < branchesTriggeringFinally.Count; ++i) + { var (branch, stateOnBranch) = branchesTriggeringFinally[i]; Debug.Assert(((ILInstruction)branch).IsDescendantOf(tryFinally)); Debug.Assert(tryFinally.IsDescendantOf(branch.TargetContainer)); stateOnBranch.TriggerFinally(state); bool triggersAnotherFinally = Branch.GetExecutesFinallyBlock(tryFinally, branch.TargetContainer); - if (triggersAnotherFinally) { + if (triggersAnotherFinally) + { branchesTriggeringFinally[outPos++] = (branch, stateOnBranch); - } else { + } + else + { // Merge state into target block. - if (branch is Leave leave) { + if (branch is Leave leave) + { MergeBranchStateIntoStateOnLeave((Leave)branch, stateOnBranch); - } else { + } + else + { MergeBranchStateIntoTargetBlock((Branch)branch, stateOnBranch); } } @@ -595,7 +631,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis state = onSuccess; DebugEndPoint(inst); } - + protected internal override void VisitIfInstruction(IfInstruction inst) { DebugStartPoint(inst); @@ -623,7 +659,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// (State OnTrue, State OnFalse) EvaluateCondition(ILInstruction inst) { - if (inst is IfInstruction ifInst) { + if (inst is IfInstruction ifInst) + { // 'if (a?b:c)' or similar. // This also includes conditions that are logic.not, logic.and, logic.or. DebugStartPoint(ifInst); @@ -640,15 +677,24 @@ namespace ICSharpCode.Decompiler.FlowAnalysis DebugEndPoint(ifInst); return (onTrue, onFalse); - } else if (inst is LdcI4 constant) { - if (constant.Value == 0) { + } + else if (inst is LdcI4 constant) + { + if (constant.Value == 0) + { return (bottomState.Clone(), state); - } else { + } + else + { return (state, bottomState.Clone()); } - } else if (inst is MatchInstruction match) { + } + else if (inst is MatchInstruction match) + { return EvaluateMatch(match); - } else { + } + else + { // other kind of condition inst.AcceptVisitor(this); return (state, state.Clone()); @@ -679,11 +725,13 @@ namespace ICSharpCode.Decompiler.FlowAnalysis DebugStartPoint(inst); inst.TestedOperand.AcceptVisitor(this); State onFalse = state.Clone(); - if (!inst.CheckNotNull && !inst.CheckType) { + if (!inst.CheckNotNull && !inst.CheckType) + { onFalse.ReplaceWithBottom(); } HandleMatchStore(inst); - foreach (var subPattern in inst.SubPatterns) { + foreach (var subPattern in inst.SubPatterns) + { var (subTrue, subFalse) = EvaluateCondition(subPattern); onFalse.JoinWith(subFalse); state = subTrue; @@ -751,7 +799,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis State beforeSections = state.Clone(); inst.Sections[0].AcceptVisitor(this); State afterSections = state.Clone(); - for (int i = 1; i < inst.Sections.Count; ++i) { + for (int i = 1; i < inst.Sections.Count; ++i) + { state.ReplaceWith(beforeSections); inst.Sections[i].AcceptVisitor(this); afterSections.JoinWith(state); @@ -759,7 +808,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis state = afterSections; DebugEndPoint(inst); } - + protected internal override void VisitYieldReturn(YieldReturn inst) { DebugStartPoint(inst); diff --git a/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs b/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs index 726cef1f7..c12175f0b 100644 --- a/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs +++ b/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs @@ -16,13 +16,14 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System.Diagnostics; -using ICSharpCode.Decompiler.IL; -using ICSharpCode.Decompiler.Util; -using System.Threading; using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; + +using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.FlowAnalysis { @@ -55,7 +56,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis this.bits = new BitSet(variableCount); this.bits.Set(0, variableCount); } - + private State(BitSet bits) { this.bits = bits; @@ -123,7 +124,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis readonly Dictionary stateOfLocalFunctionUse = new Dictionary(); readonly HashSet localFunctionsNeedingAnalysis = new HashSet(); - + public DefiniteAssignmentVisitor(ILFunction scope, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -133,36 +134,38 @@ namespace ICSharpCode.Decompiler.FlowAnalysis base.flagsRequiringManualImpl |= InstructionFlags.MayReadLocals | InstructionFlags.MayWriteLocals; Initialize(new State(scope.Variables.Count)); } - + public bool IsPotentiallyUsedUninitialized(ILVariable v) { Debug.Assert(v.Function == scope); return variablesWithUninitializedUsage[v.IndexInFunction]; } - + void HandleStore(ILVariable v) { cancellationToken.ThrowIfCancellationRequested(); - if (v.Function == scope) { + if (v.Function == scope) + { // Mark the variable as initialized: state.MarkVariableInitialized(v.IndexInFunction); // Note that this gets called even if the store is in unreachable code, // but that's OK because bottomState.MarkVariableInitialized() has no effect. - + // After the state change, we have to call // PropagateStateOnException() = currentStateOnException.JoinWith(state); // but because MarkVariableInitialized() only clears a bit, // this is guaranteed to be a no-op. } } - + void EnsureInitialized(ILVariable v) { - if (v.Function == scope && state.IsPotentiallyUninitialized(v.IndexInFunction)) { + if (v.Function == scope && state.IsPotentiallyUninitialized(v.IndexInFunction)) + { variablesWithUninitializedUsage.Set(v.IndexInFunction); } } - + protected internal override void VisitStLoc(StLoc inst) { inst.Value.AcceptVisitor(this); @@ -179,19 +182,19 @@ namespace ICSharpCode.Decompiler.FlowAnalysis HandleStore(inst.Variable); base.BeginTryCatchHandler(inst); } - + protected internal override void VisitPinnedRegion(PinnedRegion inst) { inst.Init.AcceptVisitor(this); HandleStore(inst.Variable); inst.Body.AcceptVisitor(this); } - + protected internal override void VisitLdLoc(LdLoc inst) { EnsureInitialized(inst.Variable); } - + protected internal override void VisitLdLoca(LdLoca inst) { // A variable needs to be initialized before we can take it by reference. @@ -233,9 +236,11 @@ namespace ICSharpCode.Decompiler.FlowAnalysis // Because we might discover additional points of use within the local functions, // we use a fixed-point iteration. bool changed; - do { + do + { changed = false; - foreach (var nestedFunction in inst.LocalFunctions) { + foreach (var nestedFunction in inst.LocalFunctions) + { if (!localFunctionsNeedingAnalysis.Contains(nestedFunction.ReducedMethod)) continue; localFunctionsNeedingAnalysis.Remove(nestedFunction.ReducedMethod); @@ -255,19 +260,26 @@ namespace ICSharpCode.Decompiler.FlowAnalysis { DebugStartPoint(call); bool hasOutArgs = false; - foreach (var arg in call.Arguments) { - if (arg.MatchLdLoca(out var v) && call.GetParameter(arg.ChildIndex)?.IsOut == true) { + foreach (var arg in call.Arguments) + { + if (arg.MatchLdLoca(out var v) && call.GetParameter(arg.ChildIndex)?.IsOut == true) + { // Visiting ldloca would require the variable to be initialized, // but we don't need out arguments to be initialized. hasOutArgs = true; - } else { + } + else + { arg.AcceptVisitor(this); } } // Mark out arguments as initialized, but only after the whole call: - if (hasOutArgs) { - foreach (var arg in call.Arguments) { - if (arg.MatchLdLoca(out var v) && call.GetParameter(arg.ChildIndex)?.IsOut == true) { + if (hasOutArgs) + { + foreach (var arg in call.Arguments) + { + if (arg.MatchLdLoca(out var v) && call.GetParameter(arg.ChildIndex)?.IsOut == true) + { HandleStore(v); } } @@ -282,13 +294,18 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// void HandleLocalFunctionUse(IMethod method) { - if (method.IsLocalFunction) { - if (stateOfLocalFunctionUse.TryGetValue(method, out var stateOnEntry)) { - if (!state.LessThanOrEqual(stateOnEntry)) { + if (method.IsLocalFunction) + { + if (stateOfLocalFunctionUse.TryGetValue(method, out var stateOnEntry)) + { + if (!state.LessThanOrEqual(stateOnEntry)) + { stateOnEntry.JoinWith(state); localFunctionsNeedingAnalysis.Add(method); } - } else { + } + else + { stateOfLocalFunctionUse.Add(method, state.Clone()); localFunctionsNeedingAnalysis.Add(method); } diff --git a/ICSharpCode.Decompiler/FlowAnalysis/Dominance.cs b/ICSharpCode.Decompiler/FlowAnalysis/Dominance.cs index bc7c90fa7..815b92046 100644 --- a/ICSharpCode.Decompiler/FlowAnalysis/Dominance.cs +++ b/ICSharpCode.Decompiler/FlowAnalysis/Dominance.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.FlowAnalysis @@ -44,31 +45,36 @@ namespace ICSharpCode.Decompiler.FlowAnalysis { // A Simple, Fast Dominance Algorithm // Keith D. Cooper, Timothy J. Harvey and Ken Kennedy - + var nodes = new List(); entryPoint.TraversePostOrder(n => n.Successors, nodes.Add); Debug.Assert(nodes.Last() == entryPoint); - for (int i = 0; i < nodes.Count; i++) { + for (int i = 0; i < nodes.Count; i++) + { nodes[i].PostOrderNumber = i; } - + // For the purpose of this algorithm, make the entry point its own dominator. // We'll reset it back to null at the end of this function. entryPoint.ImmediateDominator = entryPoint; bool changed; - do { + do + { changed = false; - + cancellationToken.ThrowIfCancellationRequested(); - + // For all nodes b except the entry point (in reverse post-order) - for (int i = nodes.Count - 2; i >= 0; i--) { + for (int i = nodes.Count - 2; i >= 0; i--) + { ControlFlowNode b = nodes[i]; // Compute new immediate dominator: ControlFlowNode newIdom = null; - foreach (var p in b.Predecessors) { + foreach (var p in b.Predecessors) + { // Ignore predecessors that were not processed yet - if (p.ImmediateDominator != null) { + if (p.ImmediateDominator != null) + { if (newIdom == null) newIdom = p; else @@ -77,19 +83,22 @@ namespace ICSharpCode.Decompiler.FlowAnalysis } // The reverse post-order ensures at least one of our predecessors was processed. Debug.Assert(newIdom != null); - if (newIdom != b.ImmediateDominator) { + if (newIdom != b.ImmediateDominator) + { b.ImmediateDominator = newIdom; changed = true; } } - } while(changed); + } while (changed); // Create dominator tree for all reachable nodes: - foreach (ControlFlowNode node in nodes) { + foreach (ControlFlowNode node in nodes) + { if (node.ImmediateDominator != null) node.DominatorTreeChildren = new List(); } entryPoint.ImmediateDominator = null; - foreach (ControlFlowNode node in nodes) { + foreach (ControlFlowNode node in nodes) + { // Create list of children in dominator tree if (node.ImmediateDominator != null) node.ImmediateDominator.DominatorTreeChildren.Add(node); @@ -97,7 +106,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis node.Visited = false; } } - + /// /// Returns the common ancestor of a and b in the dominator tree. /// @@ -105,7 +114,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// public static ControlFlowNode FindCommonDominator(ControlFlowNode a, ControlFlowNode b) { - while (a != b) { + while (a != b) + { while (a.PostOrderNumber < b.PostOrderNumber) a = a.ImmediateDominator; while (b.PostOrderNumber < a.PostOrderNumber) @@ -113,7 +123,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis } return a; } - + /// /// Computes a BitSet where /// result[i] == true iff cfg[i] is reachable and there is some node that is @@ -128,19 +138,24 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// public static BitSet MarkNodesWithReachableExits(ControlFlowNode[] cfg) { - #if DEBUG - for (int i = 0; i < cfg.Length; i++) { +#if DEBUG + for (int i = 0; i < cfg.Length; i++) + { Debug.Assert(cfg[i].UserIndex == i); } - #endif +#endif BitSet nonEmpty = new BitSet(cfg.Length); - foreach (var j in cfg) { + foreach (var j in cfg) + { // If j is a join-point (more than one incoming edge): // `j.IsReachable && j.ImmediateDominator == null` is the root node, which counts as an extra incoming edge - if (j.IsReachable && (j.Predecessors.Count >= 2 || (j.Predecessors.Count >= 1 && j.ImmediateDominator == null))) { + if (j.IsReachable && (j.Predecessors.Count >= 2 || (j.Predecessors.Count >= 1 && j.ImmediateDominator == null))) + { // Add j to frontier of all predecessors and their dominators up to j's immediate dominator. - foreach (var p in j.Predecessors) { - for (var runner = p; runner != j.ImmediateDominator && runner != j && runner != null; runner = runner.ImmediateDominator) { + foreach (var p in j.Predecessors) + { + for (var runner = p; runner != j.ImmediateDominator && runner != j && runner != null; runner = runner.ImmediateDominator) + { nonEmpty.Set(runner.UserIndex); } } diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs b/ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs index 08bf2e4f2..6b4013c0f 100644 --- a/ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs +++ b/ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs @@ -20,9 +20,10 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Threading; + using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Util; -using System.Threading; namespace ICSharpCode.Decompiler.FlowAnalysis { @@ -104,34 +105,34 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// The bottom state has all bits unset. /// readonly BitSet bits; - + public State(BitSet bits) { this.bits = bits; } - + public bool LessThanOrEqual(State otherState) { return bits.IsSubsetOf(otherState.bits); } - + public State Clone() { return new State(bits.Clone()); } - + public void ReplaceWith(State newContent) { bits.ReplaceWith(newContent.bits); } - + public void JoinWith(State incomingState) { // When control flow is joined together, we can simply union our bitsets. // (a store is reachable iff it is reachable through either incoming path) bits.UnionWith(incomingState.bits); } - + public void TriggerFinally(State finallyState) { // Some cases to consider: @@ -148,26 +149,27 @@ namespace ICSharpCode.Decompiler.FlowAnalysis // try-block was unreachable, so let's so at least that. // (note that in principle we could just AND the reachable and uninitialized bits, // but we don't have a good solution for the normal store bits) - if (IsReachable) { + if (IsReachable) + { ReplaceWith(finallyState); } } - + public bool IsBottom { get { return !bits[ReachableBit]; } } - + public void ReplaceWithBottom() { // We need to clear all bits, not just ReachableBit, so that // the bottom state behaves as expected in joins. bits.ClearAll(); } - + public bool IsReachable { get { return bits[ReachableBit]; } } - + /// /// Clears all store bits between startStoreIndex (incl.) and endStoreIndex (excl.) /// @@ -177,25 +179,25 @@ namespace ICSharpCode.Decompiler.FlowAnalysis Debug.Assert(endStoreIndex >= startStoreIndex); bits.Clear(startStoreIndex, endStoreIndex); } - + public bool IsReachingStore(int storeIndex) { return bits[storeIndex]; } - + public void SetStore(int storeIndex) { Debug.Assert(storeIndex >= FirstStoreIndex); bits.Set(storeIndex); } } - + /// /// To distinguish unreachable from reachable states, we use the first bit in the bitset to store the 'reachable bit'. /// If this bit is set, the state is reachable, and the remaining bits /// const int ReachableBit = 0; - + /// /// Because bit number 0 is the ReachableBit, we start counting store indices at 1. /// @@ -209,7 +211,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// The function being analyzed. /// protected readonly ILFunction scope; - + /// /// All stores for all variables in the scope. /// @@ -217,7 +219,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// Invariant: state.bits.Length == allStores.Length. /// readonly ILInstruction[] allStores; - + /// /// Maps instructions appearing in allStores to their index. /// @@ -226,7 +228,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// Does not contain UninitializedVariable (as that special instruction has multiple store indices, one per variable) /// readonly Dictionary storeIndexMap = new Dictionary(); - + /// /// For all variables v: allStores[firstStoreIndexForVariable[v.IndexInScope]] is the UninitializedVariable entry for v. /// The next few stores (up to firstStoreIndexForVariable[v.IndexInScope + 1], exclusive) are the full list of stores for v. @@ -235,13 +237,13 @@ namespace ICSharpCode.Decompiler.FlowAnalysis /// Invariant: firstStoreIndexForVariable[scope.Variables.Count] == allStores.Length /// readonly int[] firstStoreIndexForVariable; - + /// /// analyzedVariables[v.IndexInScope] is true iff RD analysis is enabled for the variable. /// readonly BitSet analyzedVariables; #endregion - + #region Constructor /// /// Prepare reaching definitions analysis for the specified variable scope. @@ -260,7 +262,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis if (scope == null) throw new ArgumentNullException(nameof(scope)); BitSet activeVariables = new BitSet(scope.Variables.Count); - for (int vi = 0; vi < scope.Variables.Count; vi++) { + for (int vi = 0; vi < scope.Variables.Count; vi++) + { activeVariables[vi] = pred(scope.Variables[vi]); } return activeVariables; @@ -280,19 +283,22 @@ namespace ICSharpCode.Decompiler.FlowAnalysis this.scope = scope; this.analyzedVariables = analyzedVariables; base.flagsRequiringManualImpl |= InstructionFlags.MayWriteLocals; - + // Fill `allStores` and `storeIndexMap` and `firstStoreIndexForVariable`. var storesByVar = FindAllStoresByVariable(scope, analyzedVariables, cancellationToken); allStores = new ILInstruction[FirstStoreIndex + storesByVar.Sum(l => l != null ? l.Count : 0)]; firstStoreIndexForVariable = new int[scope.Variables.Count + 1]; int si = FirstStoreIndex; - for (int vi = 0; vi < storesByVar.Length; vi++) { + for (int vi = 0; vi < storesByVar.Length; vi++) + { cancellationToken.ThrowIfCancellationRequested(); firstStoreIndexForVariable[vi] = si; var stores = storesByVar[vi]; - if (stores != null) { + if (stores != null) + { int expectedStoreCount = scope.Variables[vi].StoreCount; - if (!scope.Variables[vi].HasInitialValue) { + if (!scope.Variables[vi].HasInitialValue) + { // Extra store for the uninitialized state. expectedStoreCount += 1; // Note that for variables with HasInitialValue=true, @@ -302,7 +308,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis stores.CopyTo(allStores, si); // Add all stores except for the first (representing the uninitialized state) // to storeIndexMap. - for (int i = 1; i < stores.Count; i++) { + for (int i = 1; i < stores.Count; i++) + { storeIndexMap.Add(stores[i], si + i); } si += stores.Count; @@ -310,7 +317,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis } firstStoreIndexForVariable[scope.Variables.Count] = si; Debug.Assert(si == allStores.Length); - + Initialize(CreateInitialState()); } @@ -321,22 +328,26 @@ namespace ICSharpCode.Decompiler.FlowAnalysis { // For each variable, find the list of ILInstructions storing to that variable List[] storesByVar = new List[scope.Variables.Count]; - for (int vi = 0; vi < storesByVar.Length; vi++) { + for (int vi = 0; vi < storesByVar.Length; vi++) + { if (activeVariables[vi]) storesByVar[vi] = new List { null }; } - foreach (var inst in scope.Descendants) { - if (inst.HasDirectFlag(InstructionFlags.MayWriteLocals)) { + foreach (var inst in scope.Descendants) + { + if (inst.HasDirectFlag(InstructionFlags.MayWriteLocals)) + { cancellationToken.ThrowIfCancellationRequested(); ILVariable v = ((IInstructionWithVariableOperand)inst).Variable; - if (v.Function == scope && activeVariables[v.IndexInFunction]) { + if (v.Function == scope && activeVariables[v.IndexInFunction]) + { storesByVar[v.IndexInFunction].Add(inst); } } } return storesByVar; } - + /// /// Create the initial state (reachable bit + uninit variable bits set, store bits unset). /// @@ -344,8 +355,10 @@ namespace ICSharpCode.Decompiler.FlowAnalysis { BitSet initialState = new BitSet(allStores.Length); initialState.Set(ReachableBit); - for (int vi = 0; vi < scope.Variables.Count; vi++) { - if (analyzedVariables[vi]) { + for (int vi = 0; vi < scope.Variables.Count; vi++) + { + if (analyzedVariables[vi]) + { Debug.Assert(allStores[firstStoreIndexForVariable[vi]] == null); initialState.Set(firstStoreIndexForVariable[vi]); } @@ -353,28 +366,29 @@ namespace ICSharpCode.Decompiler.FlowAnalysis return new State(initialState); } #endregion - + #region Analysis void HandleStore(ILInstruction inst, ILVariable v) { cancellationToken.ThrowIfCancellationRequested(); - if (v.Function == scope && analyzedVariables[v.IndexInFunction] && state.IsReachable) { + if (v.Function == scope && analyzedVariables[v.IndexInFunction] && state.IsReachable) + { // Clear the set of stores for this variable: state.KillStores(firstStoreIndexForVariable[v.IndexInFunction], firstStoreIndexForVariable[v.IndexInFunction + 1]); // And replace it with this store: int si = storeIndexMap[inst]; state.SetStore(si); - + // We should call PropagateStateOnException() here because we changed the state. // But that's equal to: currentStateOnException.UnionWith(state); - + // Because we're already guaranteed that state.LessThanOrEqual(currentStateOnException) // when entering HandleStore(), all we really need to do to achieve what PropagateStateOnException() does // is to add the single additional store to the exceptional state as well: currentStateOnException.SetStore(si); } } - + protected internal override void VisitStLoc(StLoc inst) { inst.Value.AcceptVisitor(this); @@ -391,19 +405,19 @@ namespace ICSharpCode.Decompiler.FlowAnalysis base.BeginTryCatchHandler(inst); HandleStore(inst, inst.Variable); } - + protected internal override void VisitPinnedRegion(PinnedRegion inst) { inst.Init.AcceptVisitor(this); HandleStore(inst, inst.Variable); inst.Body.AcceptVisitor(this); } - + public bool IsAnalyzedVariable(ILVariable v) { return v.Function == scope && analyzedVariables[v.IndexInFunction]; } - + /// /// Gets all stores to v that reach the specified state. /// @@ -413,14 +427,16 @@ namespace ICSharpCode.Decompiler.FlowAnalysis { Debug.Assert(v.Function == scope && analyzedVariables[v.IndexInFunction]); int endIndex = firstStoreIndexForVariable[v.IndexInFunction + 1]; - for (int si = firstStoreIndexForVariable[v.IndexInFunction] + 1; si < endIndex; si++) { - if (state.IsReachingStore(si)) { + for (int si = firstStoreIndexForVariable[v.IndexInFunction] + 1; si < endIndex; si++) + { + if (state.IsReachingStore(si)) + { Debug.Assert(((IInstructionWithVariableOperand)allStores[si]).Variable == v); yield return allStores[si]; } } } - + /// /// Gets whether v is potentially uninitialized in the specified state. /// diff --git a/ICSharpCode.Decompiler/IL/BlockBuilder.cs b/ICSharpCode.Decompiler/IL/BlockBuilder.cs index d1d28963f..c2e0e1796 100644 --- a/ICSharpCode.Decompiler/IL/BlockBuilder.cs +++ b/ICSharpCode.Decompiler/IL/BlockBuilder.cs @@ -23,6 +23,7 @@ using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; using System.Threading; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL @@ -37,30 +38,32 @@ namespace ICSharpCode.Decompiler.IL /// The default is false. /// public bool CreateExtendedBlocks; - + internal BlockBuilder(MethodBodyBlock body, - Dictionary variableByExceptionHandler) + Dictionary variableByExceptionHandler) { Debug.Assert(body != null); Debug.Assert(variableByExceptionHandler != null); this.body = body; this.variableByExceptionHandler = variableByExceptionHandler; } - + List tryInstructionList = new List(); Dictionary handlerContainers = new Dictionary(); - + void CreateContainerStructure() { List tryCatchList = new List(); - foreach (var eh in body.ExceptionRegions) { + foreach (var eh in body.ExceptionRegions) + { var tryRange = new Interval(eh.TryOffset, eh.TryOffset + eh.TryLength); var handlerBlock = new BlockContainer(); handlerBlock.AddILRange(new Interval(eh.HandlerOffset, eh.HandlerOffset + eh.HandlerLength)); handlerBlock.Blocks.Add(new Block()); handlerContainers.Add(handlerBlock.StartILOffset, handlerBlock); - - if (eh.Kind == ExceptionRegionKind.Fault || eh.Kind == ExceptionRegionKind.Finally) { + + if (eh.Kind == ExceptionRegionKind.Fault || eh.Kind == ExceptionRegionKind.Finally) + { var tryBlock = new BlockContainer(); tryBlock.AddILRange(tryRange); if (eh.Kind == ExceptionRegionKind.Finally) @@ -71,7 +74,8 @@ namespace ICSharpCode.Decompiler.IL } // var tryCatch = tryCatchList.FirstOrDefault(tc => tc.TryBlock.ILRanges.SingleOrDefault() == tryRange); - if (tryCatch == null) { + if (tryCatch == null) + { var tryBlock = new BlockContainer(); tryBlock.AddILRange(tryRange); tryCatch = new TryCatch(tryBlock); @@ -81,13 +85,16 @@ namespace ICSharpCode.Decompiler.IL } ILInstruction filter; - if (eh.Kind == System.Reflection.Metadata.ExceptionRegionKind.Filter) { + if (eh.Kind == System.Reflection.Metadata.ExceptionRegionKind.Filter) + { var filterBlock = new BlockContainer(expectedResultType: StackType.I4); filterBlock.AddILRange(new Interval(eh.FilterOffset, eh.HandlerOffset)); filterBlock.Blocks.Add(new Block()); handlerContainers.Add(filterBlock.StartILOffset, filterBlock); filter = filterBlock; - } else { + } + else + { filter = new LdcI4(1); } @@ -97,25 +104,27 @@ namespace ICSharpCode.Decompiler.IL tryCatch.Handlers.Add(handler); tryCatch.AddILRange(handler); } - if (tryInstructionList.Count > 0) { + if (tryInstructionList.Count > 0) + { tryInstructionList = tryInstructionList.OrderBy(tc => tc.TryBlock.StartILOffset).ThenByDescending(tc => tc.TryBlock.EndILOffset).ToList(); nextTry = tryInstructionList[0]; } } - + int currentTryIndex; TryInstruction nextTry; - + BlockContainer currentContainer; Block currentBlock; Stack containerStack = new Stack(); - + public void CreateBlocks(BlockContainer mainContainer, List instructions, BitArray incomingBranches, CancellationToken cancellationToken) { CreateContainerStructure(); mainContainer.SetILRange(new Interval(0, body.GetCodeSize())); currentContainer = mainContainer; - if (instructions.Count == 0) { + if (instructions.Count == 0) + { currentContainer.Blocks.Add(new Block { Instructions = { new InvalidBranch("Empty body found. Decompiled assembly might be a reference assembly.") @@ -124,29 +133,36 @@ namespace ICSharpCode.Decompiler.IL return; } - foreach (var inst in instructions) { + foreach (var inst in instructions) + { cancellationToken.ThrowIfCancellationRequested(); int start = inst.StartILOffset; - if (currentBlock == null || (incomingBranches[start] && !IsStackAdjustment(inst))) { + if (currentBlock == null || (incomingBranches[start] && !IsStackAdjustment(inst))) + { // Finish up the previous block FinalizeCurrentBlock(start, fallthrough: true); // Leave nested containers if necessary - while (start >= currentContainer.EndILOffset) { + while (start >= currentContainer.EndILOffset) + { currentContainer = containerStack.Pop(); currentBlock = currentContainer.Blocks.Last(); // this container is skipped (i.e. the loop will execute again) // set ILRange to the last instruction offset inside the block. - if (start >= currentContainer.EndILOffset) { + if (start >= currentContainer.EndILOffset) + { Debug.Assert(currentBlock.ILRangeIsEmpty); currentBlock.AddILRange(new Interval(currentBlock.StartILOffset, start)); } } // Enter a handler if necessary - if (handlerContainers.TryGetValue(start, out BlockContainer handlerContainer)) { + if (handlerContainers.TryGetValue(start, out BlockContainer handlerContainer)) + { containerStack.Push(currentContainer); currentContainer = handlerContainer; currentBlock = handlerContainer.EntryPoint; - } else { + } + else + { FinalizeCurrentBlock(start, fallthrough: false); // Create the new block currentBlock = new Block(); @@ -154,14 +170,15 @@ namespace ICSharpCode.Decompiler.IL } currentBlock.SetILRange(new Interval(start, start)); } - while (nextTry != null && start == nextTry.TryBlock.StartILOffset) { + while (nextTry != null && start == nextTry.TryBlock.StartILOffset) + { currentBlock.Instructions.Add(nextTry); containerStack.Push(currentContainer); currentContainer = (BlockContainer)nextTry.TryBlock; currentBlock = new Block(); currentContainer.Blocks.Add(currentBlock); currentBlock.SetILRange(new Interval(start, start)); - + nextTry = tryInstructionList.ElementAtOrDefault(++currentTryIndex); } currentBlock.Instructions.Add(inst); @@ -172,7 +189,8 @@ namespace ICSharpCode.Decompiler.IL } FinalizeCurrentBlock(mainContainer.EndILOffset, fallthrough: false); // Finish up all containers - while (containerStack.Count > 0) { + while (containerStack.Count > 0) + { currentContainer = containerStack.Pop(); currentBlock = currentContainer.Blocks.Last(); FinalizeCurrentBlock(mainContainer.EndILOffset, fallthrough: false); @@ -191,12 +209,16 @@ namespace ICSharpCode.Decompiler.IL return; Debug.Assert(currentBlock.ILRangeIsEmpty); currentBlock.SetILRange(new Interval(currentBlock.StartILOffset, currentILOffset)); - if (fallthrough) { - if (currentBlock.Instructions.LastOrDefault() is SwitchInstruction switchInst && switchInst.Sections.Last().Body.MatchNop()) { + if (fallthrough) + { + if (currentBlock.Instructions.LastOrDefault() is SwitchInstruction switchInst && switchInst.Sections.Last().Body.MatchNop()) + { // Instead of putting the default branch after the switch instruction switchInst.Sections.Last().Body = new Branch(currentILOffset); Debug.Assert(switchInst.HasFlag(InstructionFlags.EndPointUnreachable)); - } else { + } + else + { currentBlock.Instructions.Add(new Branch(currentILOffset)); } } @@ -205,12 +227,14 @@ namespace ICSharpCode.Decompiler.IL void ConnectBranches(ILInstruction inst, CancellationToken cancellationToken) { - switch (inst) { + switch (inst) + { case Branch branch: cancellationToken.ThrowIfCancellationRequested(); Debug.Assert(branch.TargetBlock == null); branch.TargetBlock = FindBranchTarget(branch.TargetILOffset); - if (branch.TargetBlock == null) { + if (branch.TargetBlock == null) + { branch.ReplaceWith(new InvalidBranch("Could not find block for branch target " + Disassembler.DisassemblerHelpers.OffsetToString(branch.TargetILOffset)).WithILRange(branch)); } @@ -218,7 +242,8 @@ namespace ICSharpCode.Decompiler.IL case Leave leave: // ret (in void method) = leave(mainContainer) // endfinally = leave(null) - if (leave.TargetContainer == null) { + if (leave.TargetContainer == null) + { // assign the finally/filter container leave.TargetContainer = containerStack.Peek(); leave.Value = ILReader.Cast(leave.Value, leave.TargetContainer.ExpectedResultType, null, leave.StartILOffset); @@ -226,10 +251,12 @@ namespace ICSharpCode.Decompiler.IL break; case BlockContainer container: containerStack.Push(container); - foreach (var block in container.Blocks) { + foreach (var block in container.Blocks) + { cancellationToken.ThrowIfCancellationRequested(); ConnectBranches(block, cancellationToken); - if (block.Instructions.Count == 0 || !block.Instructions.Last().HasFlag(InstructionFlags.EndPointUnreachable)) { + if (block.Instructions.Count == 0 || !block.Instructions.Last().HasFlag(InstructionFlags.EndPointUnreachable)) + { block.Instructions.Add(new InvalidBranch("Unexpected end of block")); } } @@ -244,8 +271,10 @@ namespace ICSharpCode.Decompiler.IL Block FindBranchTarget(int targetILOffset) { - foreach (var container in containerStack) { - foreach (var block in container.Blocks) { + foreach (var container in containerStack) + { + foreach (var block in container.Blocks) + { if (block.StartILOffset == targetILOffset) return block; } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index 3a69d5859..8955fb7ae 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -16,12 +16,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using ICSharpCode.Decompiler.CSharp; -using ICSharpCode.Decompiler.DebugInfo; -using ICSharpCode.Decompiler.IL.Transforms; -using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.TypeSystem.Implementation; -using ICSharpCode.Decompiler.Util; using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -29,6 +23,13 @@ using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; +using ICSharpCode.Decompiler.CSharp; +using ICSharpCode.Decompiler.DebugInfo; +using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.TypeSystem.Implementation; +using ICSharpCode.Decompiler.Util; + namespace ICSharpCode.Decompiler.IL.ControlFlow { /// @@ -43,7 +44,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; if (!(type.IsCompilerGenerated(metadata) || td.GetDeclaringType().IsCompilerGenerated(metadata))) return false; - foreach (var i in td.GetInterfaceImplementations()) { + foreach (var i in td.GetInterfaceImplementations()) + { var tr = metadata.GetInterfaceImplementation(i).Interface.GetFullTypeName(metadata); if (!tr.IsNested && tr.TopLevelTypeName.Namespace == "System.Runtime.CompilerServices" && tr.TopLevelTypeName.Name == "IAsyncStateMachine") return true; @@ -118,11 +120,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow moveNextLeaves.Clear(); if (!MatchTaskCreationPattern(function) && !MatchAsyncEnumeratorCreationPattern(function)) return; - try { + try + { AnalyzeMoveNext(); ValidateCatchBlock(); AnalyzeDisposeAsync(); - } catch (SymbolicAnalysisFailedException) { + } + catch (SymbolicAnalysisFailedException) + { return; } @@ -140,9 +145,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow TranslateCachedFieldsToLocals(); FinalizeInlineMoveNext(function); - if (methodType == AsyncMethodType.AsyncEnumerable || methodType == AsyncMethodType.AsyncEnumerator) { + if (methodType == AsyncMethodType.AsyncEnumerable || methodType == AsyncMethodType.AsyncEnumerator) + { ((BlockContainer)function.Body).ExpectedResultType = StackType.Void; - } else { + } + else + { ((BlockContainer)function.Body).ExpectedResultType = underlyingReturnType.GetStackType(); } @@ -161,24 +169,29 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { context.StepStartGroup("CleanUpBodyOfMoveNext", function); // Copy-propagate stack slots holding an 'ldloca': - foreach (var stloc in function.Descendants.OfType().Where(s => s.Variable.Kind == VariableKind.StackSlot && s.Variable.IsSingleDefinition && s.Value is LdLoca).ToList()) { + foreach (var stloc in function.Descendants.OfType().Where(s => s.Variable.Kind == VariableKind.StackSlot && s.Variable.IsSingleDefinition && s.Value is LdLoca).ToList()) + { CopyPropagation.Propagate(stloc, context); } // Simplify stobj(ldloca) -> stloc - foreach (var stobj in function.Descendants.OfType()) { + foreach (var stobj in function.Descendants.OfType()) + { EarlyExpressionTransforms.StObjToStLoc(stobj, context); } // Copy-propagate temporaries holding a copy of 'this'. - foreach (var stloc in function.Descendants.OfType().Where(s => s.Variable.IsSingleDefinition && s.Value.MatchLdThis()).ToList()) { + foreach (var stloc in function.Descendants.OfType().Where(s => s.Variable.IsSingleDefinition && s.Value.MatchLdThis()).ToList()) + { CopyPropagation.Propagate(stloc, context); } new RemoveDeadVariableInit().Run(function, context); - foreach (var block in function.Descendants.OfType()) { + foreach (var block in function.Descendants.OfType()) + { // Run inlining, but don't remove dead variables (they might get revived by TranslateFieldsToLocalAccess) ILInlining.InlineAllInBlock(function, block, context); - if (IsAsyncEnumerator) { + if (IsAsyncEnumerator) + { // Remove lone 'ldc.i4', those are sometimes left over after C# compiler // optimizes out stores to the state variable. block.Instructions.RemoveAll(inst => inst.OpCode == OpCode.LdcI4); @@ -221,24 +234,34 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow taskType = function.Method.ReturnType; builderType = startCall.Method.DeclaringType; FullTypeName builderTypeName; - if (builderType?.GetDefinition() is { } builderTypeDef) { + if (builderType?.GetDefinition() is { } builderTypeDef) + { builderTypeName = builderTypeDef.FullTypeName; - } else if (builderType is UnknownType unknownBuilderType) { + } + else if (builderType is UnknownType unknownBuilderType) + { builderTypeName = unknownBuilderType.FullTypeName; - } else { + } + else + { return false; } - if (taskType.IsKnownType(KnownTypeCode.Void)) { + if (taskType.IsKnownType(KnownTypeCode.Void)) + { methodType = AsyncMethodType.Void; underlyingReturnType = taskType; if (builderTypeName != new TopLevelTypeName("System.Runtime.CompilerServices", "AsyncVoidMethodBuilder")) return false; - } else if (TaskType.IsNonGenericTaskType(taskType, out var builderTypeNameFromTask)) { + } + else if (TaskType.IsNonGenericTaskType(taskType, out var builderTypeNameFromTask)) + { methodType = AsyncMethodType.Task; underlyingReturnType = context.TypeSystem.FindType(KnownTypeCode.Void); if (builderTypeNameFromTask != builderTypeName) return false; - } else if (TaskType.IsGenericTaskType(taskType, out builderTypeNameFromTask)) { + } + else if (TaskType.IsGenericTaskType(taskType, out builderTypeNameFromTask)) + { methodType = AsyncMethodType.TaskOfT; if (taskType.IsKnownType(KnownTypeCode.TaskOfT)) underlyingReturnType = TaskType.UnpackTask(context.TypeSystem, taskType); @@ -246,7 +269,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow underlyingReturnType = startCall.Method.DeclaringType.TypeArguments[0]; if (builderTypeNameFromTask != builderTypeName) return false; - } else { + } + else + { return false; } if (startCall.Arguments.Count != 2) @@ -259,18 +284,24 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; pos--; - if (loadBuilderExpr.MatchLdLocRef(out ILVariable builderVar)) { + if (loadBuilderExpr.MatchLdLocRef(out ILVariable builderVar)) + { // Check third-to-last instruction (copy of builder) // stloc builder(ldfld StateMachine::<>t__builder(ldloc stateMachine)) if (!body[pos].MatchStLoc(builderVar, out loadBuilderExpr)) return false; pos--; } - if (loadBuilderExpr.MatchLdFld(out var loadStateMachineForBuilderExpr, out builderField)) { + if (loadBuilderExpr.MatchLdFld(out var loadStateMachineForBuilderExpr, out builderField)) + { // OK, calling Start on copy of stateMachine.<>t__builder - } else if (loadBuilderExpr.MatchLdFlda(out loadStateMachineForBuilderExpr, out builderField)) { + } + else if (loadBuilderExpr.MatchLdFlda(out loadStateMachineForBuilderExpr, out builderField)) + { // OK, Roslyn 3.6 started directly calling Start without making a copy - } else { + } + else + { return false; } builderField = (IField)builderField.MemberDefinition; @@ -278,10 +309,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; // Check the last instruction (ret) - if (methodType == AsyncMethodType.Void) { + if (methodType == AsyncMethodType.Void) + { if (!body.Last().MatchLeave(blockContainer)) return false; - } else { + } + else + { // ret(call(AsyncTaskMethodBuilder::get_Task, ldflda(StateMachine::<>t__builder, ldloca(stateMachine)))) if (!body.Last().MatchReturn(out var returnValue)) return false; @@ -289,10 +323,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; ILInstruction target; IField builderField2; - if (builderType.IsReferenceType == true) { + if (builderType.IsReferenceType == true) + { if (!getTaskArgs[0].MatchLdFld(out target, out builderField2)) return false; - } else { + } + else + { if (!getTaskArgs[0].MatchLdFlda(out target, out builderField2)) return false; } @@ -327,7 +364,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow int stopPos = pos; pos = 0; - if (stateMachineType.Kind == TypeKind.Class) { + if (stateMachineType.Kind == TypeKind.Class) + { // If state machine is a class, the first instruction creates an instance: // stloc stateMachine(newobj StateMachine.ctor()) if (!body[pos].MatchStLoc(stateMachineVar, out var init)) @@ -336,17 +374,23 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; pos++; } - for (; pos < stopPos; pos++) { + for (; pos < stopPos; pos++) + { // stfld StateMachine.field(ldloca stateMachine, ldvar(param)) if (!MatchStFld(body[pos], stateMachineVar, out var field, out var fieldInit)) return false; - if (fieldInit.MatchLdLoc(out var v) && v.Kind == VariableKind.Parameter) { + if (fieldInit.MatchLdLoc(out var v) && v.Kind == VariableKind.Parameter) + { // OK, copies parameter into state machine fieldToParameterMap[field] = v; - } else if (fieldInit is LdObj ldobj && ldobj.Target.MatchLdThis()) { + } + else if (fieldInit is LdObj ldobj && ldobj.Target.MatchLdThis()) + { // stfld <>4__this(ldloc stateMachine, ldobj AsyncInStruct(ldloc this)) fieldToParameterMap[field] = ((LdLoc)ldobj.Target).Variable; - } else { + } + else + { return false; } } @@ -360,7 +404,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow static bool MatchCall(ILInstruction inst, string name, out InstructionCollection args) { if (inst is CallInstruction call && (call.OpCode == OpCode.Call || call.OpCode == OpCode.CallVirt) - && call.Method.Name == name && !call.Method.IsStatic) { + && call.Method.Name == name && !call.Method.IsStatic) + { args = call.Arguments; return args.Count > 0; } @@ -386,11 +431,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!context.Settings.AsyncEnumerator) return false; taskType = function.ReturnType; - if (taskType.IsKnownType(KnownTypeCode.IAsyncEnumeratorOfT)) { + if (taskType.IsKnownType(KnownTypeCode.IAsyncEnumeratorOfT)) + { methodType = AsyncMethodType.AsyncEnumerator; - } else if (taskType.IsKnownType(KnownTypeCode.IAsyncEnumerableOfT)) { + } + else if (taskType.IsKnownType(KnownTypeCode.IAsyncEnumerableOfT)) + { methodType = AsyncMethodType.AsyncEnumerable; - } else { + } + else + { return false; } underlyingReturnType = taskType.TypeArguments.Single(); @@ -399,24 +449,33 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (blockContainer.Blocks.Count != 1) return false; var body = blockContainer.EntryPoint; - if (body.Instructions.Count == 1) { + if (body.Instructions.Count == 1) + { // No parameters passed to enumerator (not even 'this'): // ret(newobj(...)) if (!body.Instructions[0].MatchReturn(out var newObj)) return false; - if (MatchEnumeratorCreationNewObj(newObj, context, out initialState, out stateMachineType)) { + if (MatchEnumeratorCreationNewObj(newObj, context, out initialState, out stateMachineType)) + { // HACK: the normal async/await logic expects 'initialState' to be the 'in progress' state initialState = -1; - try { + try + { AnalyzeEnumeratorCtor(((NewObj)newObj).Method, context, out builderField, out builderType, out stateField); - } catch (SymbolicAnalysisFailedException) { + } + catch (SymbolicAnalysisFailedException) + { return false; } return true; - } else { + } + else + { return false; } - } else { + } + else + { // stloc v(newobj d__0..ctor(ldc.i4 - 2)) // stfld <>4__this(ldloc v, ldloc this) @@ -429,12 +488,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; pos++; - while (MatchStFld(body.Instructions[pos], v, out var field, out var value)) { - if (value.MatchLdLoc(out var p) && p.Kind == VariableKind.Parameter) { + while (MatchStFld(body.Instructions[pos], v, out var field, out var value)) + { + if (value.MatchLdLoc(out var p) && p.Kind == VariableKind.Parameter) + { fieldToParameterMap[field] = p; - } else if (value is LdObj ldobj && ldobj.Target.MatchLdThis()) { + } + else if (value is LdObj ldobj && ldobj.Target.MatchLdThis()) + { fieldToParameterMap[field] = ((LdLoc)ldobj.Target).Variable; - } else { + } + else + { return false; } pos++; @@ -446,12 +511,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // HACK: the normal async/await logic expects 'initialState' to be the 'in progress' state initialState = -1; - try { + try + { AnalyzeEnumeratorCtor(((NewObj)newObj).Method, context, out builderField, out builderType, out stateField); - if (methodType == AsyncMethodType.AsyncEnumerable) { + if (methodType == AsyncMethodType.AsyncEnumerable) + { ResolveIEnumerableIEnumeratorFieldMapping(); } - } catch (SymbolicAnalysisFailedException) { + } + catch (SymbolicAnalysisFailedException) + { return false; } return true; @@ -485,7 +554,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow TypeDefinition td; if (type.IsNil || !type.IsCompilerGeneratedOrIsInCompilerGeneratedClass(metadata) || (td = metadata.GetTypeDefinition(type)).GetDeclaringType().IsNil) return false; - foreach (var i in td.GetInterfaceImplementations()) { + foreach (var i in td.GetInterfaceImplementations()) + { var tr = metadata.GetInterfaceImplementation(i).Interface.GetFullTypeName(metadata); if (!tr.IsNested && tr.TopLevelTypeName.Namespace == "System.Collections.Generic" && tr.TopLevelTypeName.Name == "IAsyncEnumerator" && tr.TopLevelTypeName.TypeParameterCount == 1) return true; @@ -508,16 +578,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // stfld <>t__builder(ldloc this, call Create()) // leave IL_0000 (nop) // } - foreach (var inst in body.Instructions) { + foreach (var inst in body.Instructions) + { if (inst.MatchStFld(out var target, out var field, out var value) && target.MatchLdThis() && value.MatchLdLoc(out var arg) - && arg.Kind == VariableKind.Parameter && arg.Index == 0) { + && arg.Kind == VariableKind.Parameter && arg.Index == 0) + { stateField = (IField)field.MemberDefinition; } if (inst.MatchStFld(out target, out field, out value) && target.MatchLdThis() - && value is Call call && call.Method.Name == "Create") { + && value is Call call && call.Method.Name == "Create") + { builderField = (IField)field.MemberDefinition; } } @@ -559,20 +632,26 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow bool[] blocksAnalyzed = new bool[blockContainer.Blocks.Count]; cachedStateVar = null; int pos = 0; - while (blockContainer.EntryPoint.Instructions[pos] is StLoc stloc) { + while (blockContainer.EntryPoint.Instructions[pos] is StLoc stloc) + { // stloc V_1(ldfld <>4__this(ldloc this)) if (!stloc.Value.MatchLdFld(out var target, out var field)) throw new SymbolicAnalysisFailedException(); if (!target.MatchLdThis()) throw new SymbolicAnalysisFailedException(); - if (field.MemberDefinition == stateField && cachedStateVar == null) { + if (field.MemberDefinition == stateField && cachedStateVar == null) + { // stloc(cachedState, ldfld(valuetype StateMachineStruct::<>1__state, ldloc(this))) cachedStateVar = stloc.Variable; - } else if (fieldToParameterMap.TryGetValue((IField)field.MemberDefinition, out var param)) { + } + else if (fieldToParameterMap.TryGetValue((IField)field.MemberDefinition, out var param)) + { if (!stloc.Variable.IsSingleDefinition) throw new SymbolicAnalysisFailedException(); cachedFieldToParameterMap[stloc.Variable] = param; - } else { + } + else + { throw new SymbolicAnalysisFailedException(); } pos++; @@ -585,18 +664,22 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (((BlockContainer)mainTryCatch.TryBlock).EntryPoint.Instructions[0] is StLoc initDoFinallyBodies && initDoFinallyBodies.Variable.Kind == VariableKind.Local && initDoFinallyBodies.Variable.Type.IsKnownType(KnownTypeCode.Boolean) - && initDoFinallyBodies.Value.MatchLdcI4(1)) { + && initDoFinallyBodies.Value.MatchLdcI4(1)) + { doFinallyBodies = initDoFinallyBodies.Variable; } Debug.Assert(blockContainer.Blocks[0] == blockContainer.EntryPoint); // already checked this block blocksAnalyzed[0] = true; pos = 1; - if (MatchYieldBlock(blockContainer, pos)) { + if (MatchYieldBlock(blockContainer, pos)) + { setResultYieldBlock = blockContainer.Blocks[pos]; blocksAnalyzed[pos] = true; pos++; - } else { + } + else + { setResultYieldBlock = null; } @@ -632,7 +715,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private Block CheckSetResultReturnBlock(BlockContainer blockContainer, int setResultReturnBlockIndex, bool[] blocksAnalyzed) { - if (setResultReturnBlockIndex >= blockContainer.Blocks.Count) { + if (setResultReturnBlockIndex >= blockContainer.Blocks.Count) + { // This block can be absent if the function never exits normally, // but always throws an exception/loops infinitely. resultVar = null; @@ -647,12 +731,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow throw new SymbolicAnalysisFailedException(); finalStateKnown = true; pos++; - if (pos + 2 == block.Instructions.Count && block.MatchIfAtEndOfBlock(out var condition, out var trueInst, out var falseInst)) { - if (MatchDisposeCombinedTokens(blockContainer, condition, trueInst, falseInst, blocksAnalyzed, out var setResultAndExitBlock)) { + if (pos + 2 == block.Instructions.Count && block.MatchIfAtEndOfBlock(out var condition, out var trueInst, out var falseInst)) + { + if (MatchDisposeCombinedTokens(blockContainer, condition, trueInst, falseInst, blocksAnalyzed, out var setResultAndExitBlock)) + { blocksAnalyzed[block.ChildIndex] = true; block = setResultAndExitBlock; pos = 0; - } else { + } + else + { throw new SymbolicAnalysisFailedException(); } } @@ -720,7 +808,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private void MatchHoistedLocalCleanup(Block block, ref int pos) { - while (block.Instructions[pos].MatchStFld(out var target, out _, out var value)) { + while (block.Instructions[pos].MatchStFld(out var target, out _, out var value)) + { // https://github.com/dotnet/roslyn/pull/39735 hoisted local cleanup if (!target.MatchLdThis()) throw new SymbolicAnalysisFailedException(); @@ -739,7 +828,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow throw new SymbolicAnalysisFailedException(); if (!IsBuilderOrPromiseFieldOnThis(args[0])) throw new SymbolicAnalysisFailedException(); - switch (methodType) { + switch (methodType) + { case AsyncMethodType.TaskOfT: if (args.Count != 2) throw new SymbolicAnalysisFailedException(); @@ -762,7 +852,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow break; } pos++; - if (MatchCall(block.Instructions[pos], "Complete", out args)) { + if (MatchCall(block.Instructions[pos], "Complete", out args)) + { if (!(args.Count == 1 && IsBuilderFieldOnThis(args[0]))) throw new SymbolicAnalysisFailedException(); pos++; @@ -803,20 +894,27 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // stfld <>1__state(ldloc this, ldc.i4 -2) if (!MatchStateAssignment(catchBlock.Instructions[1], out int newState)) throw new SymbolicAnalysisFailedException(); - if (finalStateKnown) { + if (finalStateKnown) + { if (newState != finalState) throw new SymbolicAnalysisFailedException(); - } else { + } + else + { finalState = newState; finalStateKnown = true; } int pos = 2; - if (pos + 2 == catchBlock.Instructions.Count && catchBlock.MatchIfAtEndOfBlock(out var condition, out var trueInst, out var falseInst)) { - if (MatchDisposeCombinedTokens(handlerContainer, condition, trueInst, falseInst, blocksAnalyzed, out var setResultAndExitBlock)) { + if (pos + 2 == catchBlock.Instructions.Count && catchBlock.MatchIfAtEndOfBlock(out var condition, out var trueInst, out var falseInst)) + { + if (MatchDisposeCombinedTokens(handlerContainer, condition, trueInst, falseInst, blocksAnalyzed, out var setResultAndExitBlock)) + { blocksAnalyzed[catchBlock.ChildIndex] = true; catchBlock = setResultAndExitBlock; pos = 0; - } else { + } + else + { throw new SymbolicAnalysisFailedException(); } } @@ -833,7 +931,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow pos++; // [optional] call Complete(ldfld <>t__builder(ldloc this)) - if (MatchCall(catchBlock.Instructions[pos], "Complete", out args)) { + if (MatchCall(catchBlock.Instructions[pos], "Complete", out args)) + { if (!(args.Count == 1 && IsBuilderFieldOnThis(args[0]))) throw new SymbolicAnalysisFailedException(); pos++; @@ -851,11 +950,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { IField field; ILInstruction target; - if (builderType.IsReferenceType == true) { + if (builderType.IsReferenceType == true) + { // ldfld(StateMachine::<>t__builder, ldloc(this)) if (!inst.MatchLdFld(out target, out field)) return false; - } else { + } + else + { // ldflda(StateMachine::<>t__builder, ldloc(this)) if (!inst.MatchLdFlda(out target, out field)) return false; @@ -865,9 +967,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow bool IsBuilderOrPromiseFieldOnThis(ILInstruction inst) { - if (methodType == AsyncMethodType.AsyncEnumerable || methodType == AsyncMethodType.AsyncEnumerator) { + if (methodType == AsyncMethodType.AsyncEnumerable || methodType == AsyncMethodType.AsyncEnumerator) + { return true; // TODO: check against uses of promise fields in other methods? - } else { + } + else + { return IsBuilderFieldOnThis(inst); } } @@ -878,7 +983,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (inst.MatchStFld(out var target, out var field, out var value) && StackSlotValue(target).MatchLdThis() && field.MemberDefinition == stateField - && StackSlotValue(value).MatchLdcI4(out newState)) { + && StackSlotValue(value).MatchLdcI4(out newState)) + { return true; } newState = 0; @@ -891,7 +997,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private void AnalyzeDisposeAsync() { disposeModeField = null; - if (!IsAsyncEnumerator) { + if (!IsAsyncEnumerator) + { return; } var disposeAsync = stateMachineType.Methods.FirstOrDefault(m => m.Name.EndsWith(".DisposeAsync", StringComparison.Ordinal)); @@ -899,7 +1006,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow throw new SymbolicAnalysisFailedException("Could not find DisposeAsync()"); var disposeAsyncHandle = (MethodDefinitionHandle)disposeAsync.MetadataToken; var function = YieldReturnDecompiler.CreateILAst(disposeAsyncHandle, context); - foreach (var store in function.Descendants) { + foreach (var store in function.Descendants) + { if (!store.MatchStFld(out var target, out var field, out var value)) continue; if (!target.MatchLdThis()) @@ -925,17 +1033,22 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow function.IsIterator = IsAsyncEnumerator; moveNextFunction.Variables.Clear(); moveNextFunction.ReleaseRef(); - foreach (var branch in function.Descendants.OfType()) { - if (branch.TargetBlock == setResultReturnBlock) { + foreach (var branch in function.Descendants.OfType()) + { + if (branch.TargetBlock == setResultReturnBlock) + { branch.ReplaceWith(new Leave((BlockContainer)function.Body, resultVar == null ? null : new LdLoc(resultVar)).WithILRange(branch)); } } - if (setResultYieldBlock != null) { + if (setResultYieldBlock != null) + { // We still might have branches to this block; and we can't quite yet get rid of it. ((BlockContainer)function.Body).Blocks.Add(setResultYieldBlock); } - foreach (var leave in function.Descendants.OfType()) { - if (leave.TargetContainer == moveNextFunction.Body) { + foreach (var leave in function.Descendants.OfType()) + { + if (leave.TargetContainer == moveNextFunction.Body) + { leave.TargetContainer = (BlockContainer)function.Body; moveNextLeaves.Add(leave); } @@ -948,19 +1061,24 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void FinalizeInlineMoveNext(ILFunction function) { context.Step("FinalizeInlineMoveNext()", function); - foreach (var leave in function.Descendants.OfType()) { - if (moveNextLeaves.Contains(leave)) { + foreach (var leave in function.Descendants.OfType()) + { + if (moveNextLeaves.Contains(leave)) + { leave.ReplaceWith(new InvalidBranch { Message = "leave MoveNext - await not detected correctly" }.WithILRange(leave)); } } // Delete dead loads of the state cache variable: - foreach (var block in function.Descendants.OfType()) { - for (int i = block.Instructions.Count - 1; i >= 0; i--) { + foreach (var block in function.Descendants.OfType()) + { + for (int i = block.Instructions.Count - 1; i >= 0; i--) + { if (block.Instructions[i].MatchStLoc(out var v, out var value) && v.IsSingleDefinition && v.LoadCount == 0 - && value.MatchLdLoc(cachedStateVar)) { + && value.MatchLdLoc(cachedStateVar)) + { block.Instructions.RemoveAt(i); } } @@ -978,7 +1096,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { context.StepStartGroup("AnalyzeStateMachine()", function); smallestAwaiterVarIndex = int.MaxValue; - foreach (var container in function.Descendants.OfType()) { + foreach (var container in function.Descendants.OfType()) + { // Use a separate state range analysis per container. var sra = new StateRangeAnalysis(StateRangeAnalysisMode.AsyncMoveNext, stateField, cachedStateVar); sra.CancellationToken = context.CancellationToken; @@ -986,48 +1105,65 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow sra.AssignStateRanges(container, LongSet.Universe); var stateToBlockMap = sra.GetBlockStateSetMapping(container); - foreach (var block in container.Blocks) { + foreach (var block in container.Blocks) + { context.CancellationToken.ThrowIfCancellationRequested(); - if (block.Instructions.Last() is Leave leave && moveNextLeaves.Contains(leave)) { + if (block.Instructions.Last() is Leave leave && moveNextLeaves.Contains(leave)) + { // This is likely an 'await' block context.Step($"AnalyzeAwaitBlock({block.StartILOffset:x4})", block); - if (AnalyzeAwaitBlock(block, out var awaiterVar, out var awaiterField, out int state, out int yieldOffset)) { + if (AnalyzeAwaitBlock(block, out var awaiterVar, out var awaiterField, out int state, out int yieldOffset)) + { block.Instructions.Add(new Await(new LdLoca(awaiterVar))); Block targetBlock = stateToBlockMap.GetOrDefault(state); - if (targetBlock != null) { + if (targetBlock != null) + { awaitDebugInfos.Add(new AsyncDebugInfo.Await(yieldOffset, targetBlock.StartILOffset)); block.Instructions.Add(new Branch(targetBlock)); - } else { + } + else + { block.Instructions.Add(new InvalidBranch("Could not find block for state " + state)); } awaitBlocks.Add(block, (awaiterVar, awaiterField)); - if (awaiterVar.Index < smallestAwaiterVarIndex) { + if (awaiterVar.Index < smallestAwaiterVarIndex) + { smallestAwaiterVarIndex = awaiterVar.Index.Value; } } - } else if (block.Instructions.Last().MatchBranch(setResultYieldBlock)) { + } + else if (block.Instructions.Last().MatchBranch(setResultYieldBlock)) + { // This is a 'yield return' in an async enumerator. context.Step($"AnalyzeYieldReturn({block.StartILOffset:x4})", block); - if (AnalyzeYieldReturn(block, out var yieldValue, out int state)) { + if (AnalyzeYieldReturn(block, out var yieldValue, out int state)) + { block.Instructions.Add(new YieldReturn(yieldValue)); Block targetBlock = stateToBlockMap.GetOrDefault(state); - if (targetBlock != null) { + if (targetBlock != null) + { block.Instructions.Add(new Branch(targetBlock)); - } else { + } + else + { block.Instructions.Add(new InvalidBranch("Could not find block for state " + state)); } - } else { + } + else + { block.Instructions.Add(new InvalidBranch("Could not detect 'yield return'")); } } TransformYieldBreak(block); } - foreach (var block in container.Blocks) { + foreach (var block in container.Blocks) + { SimplifyIfDisposeMode(block); } // Skip the state dispatcher and directly jump to the initial state var entryPoint = stateToBlockMap.GetOrDefault(initialState); - if (entryPoint != null) { + if (entryPoint != null) + { container.Blocks.Insert(0, new Block { Instructions = { new Branch(entryPoint) @@ -1059,9 +1195,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Detected a 'yield break;' context.Step($"TransformYieldBreak({block.StartILOffset:x4})", block); var breakTarget = FindYieldBreakTarget(branch.TargetBlock); - if (breakTarget is Block targetBlock) { + if (breakTarget is Block targetBlock) + { branch.TargetBlock = targetBlock; - } else { + } + else + { Debug.Assert(breakTarget is BlockContainer); branch.ReplaceWith(new Leave((BlockContainer)breakTarget).WithILRange(branch)); } @@ -1075,31 +1214,49 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // to determine the final target. var visited = new HashSet(); var evalContext = new SymbolicEvaluationContext(disposeModeField); - while (true) { - for (int i = 0; i < block.Instructions.Count; i++) { + while (true) + { + for (int i = 0; i < block.Instructions.Count; i++) + { ILInstruction inst = block.Instructions[i]; - while (inst.MatchIfInstruction(out var condition, out var trueInst, out var falseInst)) { + while (inst.MatchIfInstruction(out var condition, out var trueInst, out var falseInst)) + { var condVal = evalContext.Eval(condition).AsBool(); - if (condVal.Type == SymbolicValueType.IntegerConstant) { + if (condVal.Type == SymbolicValueType.IntegerConstant) + { inst = condVal.Constant != 0 ? trueInst : falseInst; - } else if (condVal.Type == SymbolicValueType.StateInSet) { + } + else if (condVal.Type == SymbolicValueType.StateInSet) + { inst = condVal.ValueSet.Contains(1) ? trueInst : falseInst; - } else { + } + else + { return block; } } - if (inst.MatchBranch(out var targetBlock)) { - if (visited.Add(block)) { + if (inst.MatchBranch(out var targetBlock)) + { + if (visited.Add(block)) + { block = targetBlock; break; // continue with next block - } else { + } + else + { return block; // infinite loop detected } - } else if (inst is Leave leave && leave.Value.OpCode == OpCode.Nop) { + } + else if (inst is Leave leave && leave.Value.OpCode == OpCode.Nop) + { return leave.TargetContainer; - } else if (inst.OpCode == OpCode.Nop) { + } + else if (inst.OpCode == OpCode.Nop) + { continue; // continue with next instruction in this block - } else { + } + else + { return block; } } @@ -1138,10 +1295,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow state = 0; yieldOffset = -1; int pos = block.Instructions.Count - 2; - if (pos >= 0 && doFinallyBodies != null && block.Instructions[pos] is StLoc storeDoFinallyBodies) { + if (pos >= 0 && doFinallyBodies != null && block.Instructions[pos] is StLoc storeDoFinallyBodies) + { if (!(storeDoFinallyBodies.Variable.Kind == VariableKind.Local && storeDoFinallyBodies.Variable.Type.IsKnownType(KnownTypeCode.Boolean) - && storeDoFinallyBodies.Variable.Index == doFinallyBodies.Index)) { + && storeDoFinallyBodies.Variable.Index == doFinallyBodies.Index)) + { return false; } if (!storeDoFinallyBodies.Value.MatchLdcI4(0)) @@ -1149,13 +1308,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow pos--; } - if (pos >= 0 && MatchCall(block.Instructions[pos], "AwaitUnsafeOnCompleted", out var callArgs)) { + if (pos >= 0 && MatchCall(block.Instructions[pos], "AwaitUnsafeOnCompleted", out var callArgs)) + { // call AwaitUnsafeOnCompleted(ldflda <>t__builder(ldloc this), ldloca awaiter, ldloc this) - } else if (pos >= 0 && MatchCall(block.Instructions[pos], "AwaitOnCompleted", out callArgs)) { + } + else if (pos >= 0 && MatchCall(block.Instructions[pos], "AwaitOnCompleted", out callArgs)) + { // call AwaitOnCompleted(ldflda <>t__builder(ldloc this), ldloca awaiter, ldloc this) // The C# compiler emits the non-unsafe call when the awaiter does not implement // ICriticalNotifyCompletion. - } else { + } + else + { return false; } if (callArgs.Count != 3) @@ -1164,10 +1328,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; if (!callArgs[1].MatchLdLoca(out awaiter)) return false; - if (callArgs[2].MatchLdThis()) { + if (callArgs[2].MatchLdThis()) + { // OK (if state machine is a struct) pos--; - } else if (callArgs[2].MatchLdLoca(out var tempVar)) { + } + else if (callArgs[2].MatchLdLoca(out var tempVar)) + { // Roslyn, non-optimized uses a class for the state machine. // stloc tempVar(ldloc this) // call AwaitUnsafeOnCompleted(ldflda <>t__builder](ldloc this), ldloca awaiter, ldloca tempVar) @@ -1176,7 +1343,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!tempVal.MatchLdThis()) return false; pos -= 2; - } else { + } + else + { return false; } // stfld StateMachine.<>awaiter(ldloc this, ldloc awaiter) @@ -1204,7 +1373,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; if (pos > 0 && block.Instructions[pos - 1] is StLoc stloc && stloc.Variable.Kind == VariableKind.Local && stloc.Variable.Index == cachedStateVar.Index - && StackSlotValue(stloc.Value).MatchLdcI4(state)) { + && StackSlotValue(stloc.Value).MatchLdcI4(state)) + { // also delete the assignment to cachedStateVar pos--; } @@ -1213,7 +1383,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow while (pos > 0 && block.Instructions[pos - 1] is StLoc stloc2 && stloc2.Variable.IsSingleDefinition && stloc2.Variable.LoadCount == 0 && stloc2.Variable.Kind == VariableKind.StackSlot - && SemanticHelper.IsPure(stloc2.Value.Flags)) { + && SemanticHelper.IsPure(stloc2.Value.Flags)) + { pos--; } block.Instructions.RemoveRange(pos, block.Instructions.Count - pos); @@ -1222,8 +1393,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow static ILInstruction StackSlotValue(ILInstruction inst) { - if (inst.MatchLdLoc(out var v) && v.Kind == VariableKind.StackSlot && v.IsSingleDefinition) { - if (v.StoreInstructions[0] is StLoc stloc) { + if (inst.MatchLdLoc(out var v) && v.Kind == VariableKind.StackSlot && v.IsSingleDefinition) + { + if (v.StoreInstructions[0] is StLoc stloc) + { return stloc.Value; } } @@ -1248,15 +1421,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; pos--; - if (pos >= 0 && block.Instructions[pos].MatchStLoc(cachedStateVar, out var cachedStateNewValue)) { - if (StackSlotValue(cachedStateNewValue).MatchLdcI4(newState)) { + if (pos >= 0 && block.Instructions[pos].MatchStLoc(cachedStateVar, out var cachedStateNewValue)) + { + if (StackSlotValue(cachedStateNewValue).MatchLdcI4(newState)) + { pos--; // OK, ignore V_0 store - } else { + } + else + { return false; } } - while (pos >= 0 && block.Instructions[pos] is StLoc stloc) { + while (pos >= 0 && block.Instructions[pos] is StLoc stloc) + { if (stloc.Variable.Kind != VariableKind.StackSlot) return false; if (!SemanticHelper.IsPure(stloc.Value.Flags)) @@ -1279,8 +1457,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void DetectAwaitPattern(ILFunction function) { context.StepStartGroup("DetectAwaitPattern", function); - foreach (var container in function.Descendants.OfType()) { - foreach (var block in container.Blocks) { + foreach (var container in function.Descendants.OfType()) + { + foreach (var block in container.Blocks) + { context.CancellationToken.ThrowIfCancellationRequested(); DetectAwaitPattern(block); } @@ -1322,7 +1502,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!block.Instructions.Last().MatchBranch(out var awaitBlock)) return; // condition might be inverted, swap branches: - if (condition.MatchLogicNot(out var negatedCondition)) { + if (condition.MatchLogicNot(out var negatedCondition)) + { condition = negatedCondition; ExtensionMethods.Swap(ref completedBlock, ref awaitBlock); } @@ -1360,8 +1541,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow getResultCall.ReplaceWith(awaitInst); // Remove useless reset of awaiterVar. - if (completedBlock.Instructions.ElementAtOrDefault(1) is StObj stobj) { - if (stobj.Target.MatchLdLoca(awaiterVar) && stobj.Value.OpCode == OpCode.DefaultValue) { + if (completedBlock.Instructions.ElementAtOrDefault(1) is StObj stobj) + { + if (stobj.Target.MatchLdLoca(awaiterVar) && stobj.Value.OpCode == OpCode.DefaultValue) + { completedBlock.Instructions.RemoveAt(1); } } @@ -1369,7 +1552,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow static ILInstruction UnwrapConvUnknown(ILInstruction inst) { - if (inst is Conv conv && conv.TargetType == PrimitiveType.Unknown) { + if (inst is Conv conv && conv.TargetType == PrimitiveType.Unknown) + { return conv.Argument; } return inst; @@ -1386,7 +1570,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (block.Instructions.Count < 2) return false; int pos = 0; - if (block.Instructions[pos] is StLoc stloc && stloc.Variable.IsSingleDefinition) { + if (block.Instructions[pos] is StLoc stloc && stloc.Variable.IsSingleDefinition) + { if (!block.Instructions[pos + 1].MatchStFld(out var target, out stackField, out var value)) return false; if (!target.MatchLdThis()) @@ -1409,7 +1594,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // stloc awaiterVar(ldfld awaiterField(ldloc this)) if (!block.Instructions[pos].MatchStLoc(awaiterVar, out var value)) return false; - if (value is CastClass cast && cast.Type.Equals(awaiterVar.Type)) { + if (value is CastClass cast && cast.Type.Equals(awaiterVar.Type)) + { // If the awaiter is a reference type, it might get stored in a field of type `object` // and cast back to the awaiter type in the resume block value = cast.Argument; @@ -1426,15 +1612,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (block.Instructions[pos].MatchStFld(out target, out field, out value) && target.MatchLdThis() && field.Equals(awaiterField) - && (value.OpCode == OpCode.DefaultValue || value.OpCode == OpCode.LdNull)) { + && (value.OpCode == OpCode.DefaultValue || value.OpCode == OpCode.LdNull)) + { pos++; - } else { + } + else + { // {stloc V_6(default.value System.Runtime.CompilerServices.TaskAwaiter)} // {stobj System.Runtime.CompilerServices.TaskAwaiter`1[[System.Int32]](ldflda <>u__$awaiter4(ldloc this), ldloc V_6) at IL_0163} if (block.Instructions[pos].MatchStLoc(out var variable, out value) && value.OpCode == OpCode.DefaultValue && block.Instructions[pos + 1].MatchStFld(out target, out field, out value) && field.Equals(awaiterField) - && value.MatchLdLoc(variable)) { + && value.MatchLdLoc(variable)) + { pos += 2; } } @@ -1443,17 +1633,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // stloc cachedStateVar(ldloc S_28) // stfld <>1__state(ldloc this, ldloc S_28) ILVariable m1Var = null; - if (block.Instructions[pos] is StLoc stlocM1 && stlocM1.Value.MatchLdcI4(initialState) && stlocM1.Variable.Kind == VariableKind.StackSlot) { + if (block.Instructions[pos] is StLoc stlocM1 && stlocM1.Value.MatchLdcI4(initialState) && stlocM1.Variable.Kind == VariableKind.StackSlot) + { m1Var = stlocM1.Variable; pos++; } - if (block.Instructions[pos] is StLoc stlocCachedState) { - if (stlocCachedState.Variable.Kind == VariableKind.Local && stlocCachedState.Variable.Index == cachedStateVar?.Index) { + if (block.Instructions[pos] is StLoc stlocCachedState) + { + if (stlocCachedState.Variable.Kind == VariableKind.Local && stlocCachedState.Variable.Index == cachedStateVar?.Index) + { if (stlocCachedState.Value.MatchLdLoc(m1Var) || stlocCachedState.Value.MatchLdcI4(initialState)) pos++; } } - if (block.Instructions[pos].MatchStFld(out target, out field, out value)) { + if (block.Instructions[pos].MatchStFld(out target, out field, out value)) + { if (!target.MatchLdThis()) return false; if (!field.MemberDefinition.Equals(stateField.MemberDefinition)) @@ -1461,7 +1655,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!(value.MatchLdcI4(initialState) || value.MatchLdLoc(m1Var))) return false; pos++; - } else { + } + else + { return false; } @@ -1470,7 +1666,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private bool RestoreStack(Block block, ref int pos, IField stackField) { - if (stackField == null) { + if (stackField == null) + { return true; // nothing to restore } // stloc temp(unbox.any T(ldfld <>t__stack(ldloc this))) @@ -1488,12 +1685,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; pos++; // restoring stack slots - while (block.Instructions[pos].MatchStLoc(out var v) && v.Kind == VariableKind.StackSlot) { + while (block.Instructions[pos].MatchStLoc(out var v) && v.Kind == VariableKind.StackSlot) + { pos++; } // stfld <>t__stack(ldloc this, ldnull) - if (block.Instructions[pos].MatchStFld(out target, out field, out var value)) { - if (target.MatchLdThis() && field.Equals(stackField) && value.MatchLdNull()) { + if (block.Instructions[pos].MatchStFld(out target, out field, out var value)) + { + if (target.MatchLdThis() && field.Equals(stackField) && value.MatchLdNull()) + { pos++; } } @@ -1506,17 +1706,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// private void CleanDoFinallyBodies(ILFunction function) { - if (doFinallyBodies == null) { + if (doFinallyBodies == null) + { return; // roslyn-compiled code doesn't use doFinallyBodies } context.StepStartGroup("CleanDoFinallyBodies", function); Block entryPoint = GetBodyEntryPoint(function.Body as BlockContainer); - if (entryPoint != null && entryPoint.Instructions[0].MatchStLoc(doFinallyBodies, out var value) && value.MatchLdcI4(1)) { + if (entryPoint != null && entryPoint.Instructions[0].MatchStLoc(doFinallyBodies, out var value) && value.MatchLdcI4(1)) + { // Remove initial doFinallyBodies assignment, if it wasn't already removed when // we rearranged the control flow. entryPoint.Instructions.RemoveAt(0); } - if (doFinallyBodies.StoreInstructions.Count != 0 || doFinallyBodies.AddressCount != 0) { + if (doFinallyBodies.StoreInstructions.Count != 0 || doFinallyBodies.AddressCount != 0) + { // misdetected another variable as doFinallyBodies? // reintroduce the initial store of ldc.i4(1) context.Step("Re-introduce misdetected doFinallyBodies", function); @@ -1524,10 +1727,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow new StLoc(doFinallyBodies, new LdcI4(1))); return; } - foreach (var tryFinally in function.Descendants.OfType()) { + foreach (var tryFinally in function.Descendants.OfType()) + { entryPoint = GetBodyEntryPoint(tryFinally.FinallyBlock as BlockContainer); - if (entryPoint?.Instructions[0] is IfInstruction ifInst) { - if (ifInst.Condition.MatchLogicNot(out var logicNotArg) && logicNotArg.MatchLdLoc(doFinallyBodies)) { + if (entryPoint?.Instructions[0] is IfInstruction ifInst) + { + if (ifInst.Condition.MatchLogicNot(out var logicNotArg) && logicNotArg.MatchLdLoc(doFinallyBodies)) + { context.Step("Remove if(doFinallyBodies) from try-finally", tryFinally); // condition will always be false now that we're using 'await' instructions entryPoint.Instructions.RemoveAt(0); @@ -1535,7 +1741,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } } // if there's any remaining loads (there shouldn't be), replace them with the constant 1 - foreach (LdLoc load in doFinallyBodies.LoadInstructions.ToArray()) { + foreach (LdLoc load in doFinallyBodies.LoadInstructions.ToArray()) + { load.ReplaceWith(new LdcI4(1).WithILRange(load)); } context.StepEndGroup(keepIfEmpty: true); @@ -1546,7 +1753,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (body == null) return null; Block entryPoint = body.EntryPoint; - while (entryPoint.Instructions[0].MatchBranch(out var targetBlock) && targetBlock.IncomingEdgeCount == 1 && targetBlock.Parent == body) { + while (entryPoint.Instructions[0].MatchBranch(out var targetBlock) && targetBlock.IncomingEdgeCount == 1 && targetBlock.Parent == body) + { entryPoint = targetBlock; } return entryPoint; @@ -1554,12 +1762,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void TranslateCachedFieldsToLocals() { - foreach (var (cachedVar, param) in cachedFieldToParameterMap) { + foreach (var (cachedVar, param) in cachedFieldToParameterMap) + { Debug.Assert(cachedVar.StoreCount <= 1); - foreach (var inst in cachedVar.LoadInstructions.ToArray()) { + foreach (var inst in cachedVar.LoadInstructions.ToArray()) + { inst.Variable = param; } - foreach (var inst in cachedVar.AddressInstructions.ToArray()) { + foreach (var inst in cachedVar.AddressInstructions.ToArray()) + { inst.Variable = param; } } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs index a04179144..63a02b56a 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.IL.Transforms; namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -32,7 +33,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow HashSet changedContainers = new HashSet(); // analyze all try-catch statements in the function - foreach (var tryCatch in function.Descendants.OfType().ToArray()) { + foreach (var tryCatch in function.Descendants.OfType().ToArray()) + { if (!(tryCatch.Parent?.Parent is BlockContainer container)) continue; // Detect all handlers that contain an await expression @@ -40,7 +42,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var cfg = new ControlFlowGraph(container, context.CancellationToken); if (transformableCatchBlocks.Count > 0) changedContainers.Add(container); - foreach (var result in transformableCatchBlocks) { + foreach (var result in transformableCatchBlocks) + { var node = cfg.GetNode(result.RealCatchBlockEntryPoint); context.StepStartGroup("Inline catch block with await", result.Handler); @@ -50,12 +53,17 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow context.Step("Remove jump-table entry", result.JumpTableEntry); jumpTableBlock.Instructions.RemoveAt(result.JumpTableEntry.ChildIndex); - foreach (var branch in tryCatch.Descendants.OfType()) { - if (branch.TargetBlock == jumpTableBlock) { - if (result.NextBlockOrExitContainer is BlockContainer exitContainer) { + foreach (var branch in tryCatch.Descendants.OfType()) + { + if (branch.TargetBlock == jumpTableBlock) + { + if (result.NextBlockOrExitContainer is BlockContainer exitContainer) + { context.Step("branch jumpTableBlock => leave exitContainer", branch); branch.ReplaceWith(new Leave(exitContainer)); - } else { + } + else + { context.Step("branch jumpTableBlock => branch nextBlock", branch); branch.ReplaceWith(new Branch((Block)result.NextBlockOrExitContainer)); } @@ -72,25 +80,30 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow catchBlockHead.Remove(); // Inline all blocks that are dominated by the entrypoint of the real catch block - foreach (var n in cfg.cfg) { + foreach (var n in cfg.cfg) + { if (((Block)n.UserData).Parent == result.Handler.Body) continue; - if (node.Dominates(n)) { + if (node.Dominates(n)) + { MoveBlock((Block)n.UserData, (BlockContainer)result.Handler.Body); } } // Remove unreachable pattern blocks // TODO : sanity check - if (result.NextBlockOrExitContainer is Block nextBlock && nextBlock.IncomingEdgeCount == 0) { + if (result.NextBlockOrExitContainer is Block nextBlock && nextBlock.IncomingEdgeCount == 0) + { List dependentBlocks = new List(); Block current = nextBlock; - - do { - foreach (var branch in current.Descendants.OfType()) { + + do + { + foreach (var branch in current.Descendants.OfType()) + { dependentBlocks.Add(branch.TargetBlock); } - + current.Remove(); dependentBlocks.Remove(current); current = dependentBlocks.FirstOrDefault(b => b.IncomingEdgeCount == 0); @@ -98,8 +111,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } // Remove all assignments to the common object variable that stores the exception object. - if (result.ObjectVariableStore != null) { - foreach (var load in result.ObjectVariableStore.Variable.LoadInstructions.ToArray()) { + if (result.ObjectVariableStore != null) + { + foreach (var load in result.ObjectVariableStore.Variable.LoadInstructions.ToArray()) + { if (load.Parent is CastClass cc && cc.Type == result.Handler.Variable.Type) cc.ReplaceWith(new LdLoc(result.Handler.Variable)); else @@ -129,7 +144,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { transformableCatchBlocks = new List<(int Id, TryCatchHandler Handler, Block RealCatchBlockEntryPoint, ILInstruction NextBlockOrExitContainer, IfInstruction JumpTableEntry, StLoc ObjectVariableStore)>(); catchHandlerIdentifier = null; - foreach (var handler in handlers) { + foreach (var handler in handlers) + { if (!MatchAwaitCatchHandler((BlockContainer)handler.Body, out int id, out var identifierVariable, out var realEntryPoint, out var nextBlockOrExitContainer, out var jumpTableEntry, out var objectVariableStore)) continue; if (id < 1 || (catchHandlerIdentifier != null && identifierVariable != catchHandlerIdentifier)) @@ -160,7 +176,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; if (!catchBlock.Instructions.Last().MatchBranch(out var jumpTableStartBlock)) return false; - if (catchBlock.Instructions.Count > 2 && catchBlock.Instructions[catchBlock.Instructions.Count - 3] is StLoc stloc) { + if (catchBlock.Instructions.Count > 2 && catchBlock.Instructions[catchBlock.Instructions.Count - 3] is StLoc stloc) + { objectVariableStore = stloc; } var identifierVariableAssignment = catchBlock.Instructions.SecondToLastOrDefault(); @@ -171,37 +188,51 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // if (comp(identifierVariable == id)) br realEntryPoint // br jumpTableEntryBlock ILVariable identifierVariableCopy; - if (jumpTableStartBlock.Instructions.Count == 3) { + if (jumpTableStartBlock.Instructions.Count == 3) + { if (!jumpTableStartBlock.Instructions[0].MatchStLoc(out identifierVariableCopy, out var identifierVariableLoad) || !identifierVariableLoad.MatchLdLoc(identifierVariable)) return false; - } else if (jumpTableStartBlock.Instructions.Count == 2) { + } + else if (jumpTableStartBlock.Instructions.Count == 2) + { identifierVariableCopy = identifierVariable; - } else return false; + } + else + return false; var jumpTableEntryBlock = jumpTableStartBlock; - do { + do + { if (!(jumpTableEntryBlock.Instructions.SecondToLastOrDefault() is IfInstruction ifInst)) return false; ILInstruction lastInst = jumpTableEntryBlock.Instructions.Last(); - if (ifInst.Condition.MatchCompEquals(out var left, out var right)) { + if (ifInst.Condition.MatchCompEquals(out var left, out var right)) + { if (!ifInst.TrueInst.MatchBranch(out realEntryPoint)) return false; - if (!lastInst.MatchBranch(out jumpTableEntryBlock)) { + if (!lastInst.MatchBranch(out jumpTableEntryBlock)) + { if (!lastInst.MatchLeave((BlockContainer)lastInst.Parent.Parent)) return false; } - } else if (ifInst.Condition.MatchCompNotEquals(out left, out right)) { + } + else if (ifInst.Condition.MatchCompNotEquals(out left, out right)) + { if (!lastInst.MatchBranch(out realEntryPoint)) return false; - if (!ifInst.TrueInst.MatchBranch(out jumpTableEntryBlock)) { + if (!ifInst.TrueInst.MatchBranch(out jumpTableEntryBlock)) + { if (!ifInst.TrueInst.MatchLeave((BlockContainer)lastInst.Parent.Parent)) return false; } - } else { + } + else + { return false; } if (!left.MatchLdLoc(identifierVariableCopy)) return false; - if (right.MatchLdcI4(id)) { + if (right.MatchLdcI4(id)) + { nextBlockOrExitContainer = jumpTableEntryBlock ?? lastInst.Parent.Parent; jumpTableEntry = ifInst; return true; diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs index c0e616765..265dda66e 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -33,7 +34,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow HashSet changedContainers = new HashSet(); // analyze all try-catch statements in the function - foreach (var tryCatch in function.Descendants.OfType().ToArray()) { + foreach (var tryCatch in function.Descendants.OfType().ToArray()) + { if (!(tryCatch.Parent?.Parent is BlockContainer container)) continue; // await in finally uses a single catch block with catch-type object @@ -44,7 +46,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var block = catchBlockContainer.EntryPoint; if (block.Instructions.Count < 2 || !block.Instructions[0].MatchStLoc(out var globalCopyVar, out var value) || !value.MatchLdLoc(tryCatch.Handlers[0].Variable)) continue; - if (block.Instructions.Count == 3) { + if (block.Instructions.Count == 3) + { if (!block.Instructions[1].MatchStLoc(out var globalCopyVarTemp, out value) || !value.MatchLdLoc(globalCopyVar)) continue; globalCopyVar = globalCopyVarTemp; @@ -70,7 +73,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void TraverseDominatorTree(ControlFlowNode node) { - if (entryPointOfFinallyNode != node) { + if (entryPointOfFinallyNode != node) + { if (entryPointOfFinallyNode.Dominates(node)) additionalBlocksInFinally.Add((Block)node.UserData); else @@ -80,7 +84,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (node == exitOfFinallyNode) return; - foreach (var child in node.DominatorTreeChildren) { + foreach (var child in node.DominatorTreeChildren) + { TraverseDominatorTree(child); } } @@ -90,7 +95,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow context.Step("Inline finally block with await", tryCatch.Handlers[0]); - foreach (var blockToRemove in blocksToRemove) { + foreach (var blockToRemove in blocksToRemove) + { blockToRemove.Remove(); } var finallyContainer = new BlockContainer(); @@ -99,16 +105,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow afterFinally.Instructions.RemoveAt(0); changedContainers.Add(container); var outer = BlockContainer.FindClosestContainer(container.Parent); - if (outer != null) changedContainers.Add(outer); + if (outer != null) + changedContainers.Add(outer); finallyContainer.Blocks.Add(entryPointOfFinally); finallyContainer.AddILRange(entryPointOfFinally); exitOfFinally.Instructions.RemoveRange(tempStore.ChildIndex, 3); exitOfFinally.Instructions.Add(new Leave(finallyContainer)); - foreach (var branchToFinally in container.Descendants.OfType()) { + foreach (var branchToFinally in container.Descendants.OfType()) + { if (branchToFinally.TargetBlock == entryPointOfFinally) branchToFinally.ReplaceWith(new Branch(afterFinally)); } - foreach (var newBlock in additionalBlocksInFinally) { + foreach (var newBlock in additionalBlocksInFinally) + { newBlock.Remove(); finallyContainer.Blocks.Add(newBlock); finallyContainer.AddILRange(newBlock); @@ -203,15 +212,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (afterFinally.Instructions.Count < 2) return false; ILVariable globalCopyVarSplitted; - switch (afterFinally.Instructions[0]) { + switch (afterFinally.Instructions[0]) + { case IfInstruction ifInst: - if (ifInst.Condition.MatchCompEquals(out var load, out var ldone) && ldone.MatchLdcI4(1) && load.MatchLdLoc(out var variable)) { + if (ifInst.Condition.MatchCompEquals(out var load, out var ldone) && ldone.MatchLdcI4(1) && load.MatchLdLoc(out var variable)) + { if (!ifInst.TrueInst.MatchBranch(out var targetBlock)) return false; blocksToRemove.Add(afterFinally); afterFinally = targetBlock; return true; - } else if (ifInst.Condition.MatchCompNotEquals(out load, out ldone) && ldone.MatchLdcI4(1) && load.MatchLdLoc(out variable)) { + } + else if (ifInst.Condition.MatchCompNotEquals(out load, out ldone) && ldone.MatchLdcI4(1) && load.MatchLdLoc(out variable)) + { if (!afterFinally.Instructions[1].MatchBranch(out var targetBlock)) return false; blocksToRemove.Add(afterFinally); diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs index 26863e0bb..764130eaa 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Util; @@ -70,7 +71,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Because this transform runs at the beginning of the block transforms, // we know that `block` is still a (non-extended) basic block. - + // Previous-to-last instruction might have conditional control flow, // usually an IfInstruction with a branch: if (block.Instructions.SecondToLastOrDefault() is IfInstruction ifInst) @@ -84,7 +85,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// private void HandleIfInstruction(Block block, IfInstruction ifInst) { - while (InlineTrueBranch(block, ifInst) || InlineExitBranch(block)) { + while (InlineTrueBranch(block, ifInst) || InlineExitBranch(block)) + { PickBetterBlockExit(block, ifInst); MergeCommonBranches(block, ifInst); SwapEmptyThen(ifInst); @@ -103,10 +105,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// private bool InlineTrueBranch(Block block, IfInstruction ifInst) { - if (!CanInline(ifInst.TrueInst)) { - if (block.Instructions.SecondToLastOrDefault() == ifInst && ifInst.FalseInst.MatchNop()) { + if (!CanInline(ifInst.TrueInst)) + { + if (block.Instructions.SecondToLastOrDefault() == ifInst && ifInst.FalseInst.MatchNop()) + { var exitInst = block.Instructions.Last(); - if (DetectExitPoints.CompatibleExitInstruction(ifInst.TrueInst, exitInst)) { + if (DetectExitPoints.CompatibleExitInstruction(ifInst.TrueInst, exitInst)) + { // if (...) exitInst; exitInst; context.Step("Use empty block as then-branch", ifInst.TrueInst); ifInst.TrueInst = new Nop().WithILRange(ifInst.TrueInst); @@ -128,7 +133,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return true; } - + /// /// ...; br nextBlock; /// -> @@ -159,8 +164,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private bool CanInline(ILInstruction exitInst) { if (exitInst is Branch branch - && branch.TargetBlock.Parent == currentContainer - && branch.TargetBlock.IncomingEdgeCount == 1) { + && branch.TargetBlock.Parent == currentContainer + && branch.TargetBlock.IncomingEdgeCount == 1) + { // if the incoming edge count is 1, then this must be the sole branch, and dominance is already ensured Debug.Assert(cfgNode.Dominates(context.ControlFlowGraph.GetNode(branch.TargetBlock))); // can't have "final instructions" in control flow blocks @@ -189,16 +195,17 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var elseExits = new List(); int falseInstIndex = block.Instructions.IndexOf(ifInst) + 1; AddExits(block, falseInstIndex, elseExits); - + var commonExits = elseExits.Where(e1 => thenExits.Any(e2 => DetectExitPoints.CompatibleExitInstruction(e1, e2))); // find the common exit with the highest block exit priority ILInstruction commonExit = null; - foreach (var exit in commonExits) { + foreach (var exit in commonExits) + { if (commonExit == null || CompareBlockExitPriority(exit, commonExit) > 0) commonExit = exit; } - + if (commonExit == null) return; @@ -208,22 +215,23 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var blockExit = block.Instructions.Last(); if (CompareBlockExitPriority(blockExit, commonExit, true) > 0 && !WillShortCircuit(block, ifInst, commonExit)) return; - + // could improve performance by directly implementing the || short-circuit when WillShortCircuit // currently the same general sequence of transformations introduces both operators - context.StepStartGroup("Merge common branches "+commonExit, ifInst); + context.StepStartGroup("Merge common branches " + commonExit, ifInst); ProduceExit(ifInst.TrueInst, 0, commonExit); ProduceExit(block, falseInstIndex, commonExit); - + // if (...) { ...; blockExit; } ...; blockExit; // -> if (...) { ...; blockExit; } else { ... } blockExit; - if (ifInst != block.Instructions.SecondToLastOrDefault()) { + if (ifInst != block.Instructions.SecondToLastOrDefault()) + { context.Step("Embed else-block for goto removal", ifInst); Debug.Assert(IsEmpty(ifInst.FalseInst)); ifInst.FalseInst = ExtractBlock(block, block.Instructions.IndexOf(ifInst) + 1, block.Instructions.Count - 1); } - + // if (...) { ...; goto blockExit; } blockExit; // -> if (...) { ... } blockExit; // OR @@ -237,7 +245,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow context.StepEndGroup(); } - + /// /// Finds all exits which could be brought to the block root via inversion /// @@ -247,8 +255,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return; exits.Add(exitInst); - if (searchInst is Block block) { - for (int i = startIndex; i < block.Instructions.Count; i++) { + if (searchInst is Block block) + { + for (int i = startIndex; i < block.Instructions.Count; i++) + { if (block.Instructions[i] is IfInstruction ifInst) AddExits(ifInst.TrueInst, 0, exits); } @@ -290,9 +300,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (DetectExitPoints.CompatibleExitInstruction(exitInst, targetExit)) return true; - if (searchInst is Block block) { - for (int i = startIndex; i < block.Instructions.Count; i++) { - if (block.Instructions[i] is IfInstruction ifInst && ProduceExit(ifInst.TrueInst, 0, targetExit)) { + if (searchInst is Block block) + { + for (int i = startIndex; i < block.Instructions.Count; i++) + { + if (block.Instructions[i] is IfInstruction ifInst && ProduceExit(ifInst.TrueInst, 0, targetExit)) + { InvertIf(block, ifInst); Debug.Assert(DetectExitPoints.CompatibleExitInstruction(GetExit(block), targetExit)); return true; @@ -327,12 +340,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // find the host if statement var elseIfInst = elseExit; - while (elseIfInst.Parent != block) { + while (elseIfInst.Parent != block) + { elseIfInst = elseIfInst.Parent; } - - return block.Instructions.IndexOf(elseIfInst) == block.Instructions.IndexOf(ifInst) + 1 - && ThenInstIsSingleExit(elseIfInst); + + return block.Instructions.IndexOf(elseIfInst) == block.Instructions.IndexOf(ifInst) + 1 + && ThenInstIsSingleExit(elseIfInst); } private void InvertIf(Block block, IfInstruction ifInst) => InvertIf(block, ifInst, context); @@ -350,32 +364,38 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow internal static void InvertIf(Block block, IfInstruction ifInst, ILTransformContext context) { Debug.Assert(ifInst.Parent == block); - + //assert then block terminates var trueExitInst = GetExit(ifInst.TrueInst); var exitInst = GetExit(block); context.Step($"InvertIf at IL_{ifInst.StartILOffset:x4}", ifInst); - + //if the then block terminates, else blocks are redundant, and should not exist Debug.Assert(IsEmpty(ifInst.FalseInst)); //save a copy var thenInst = ifInst.TrueInst; - if (ifInst != block.Instructions.SecondToLastOrDefault()) { + if (ifInst != block.Instructions.SecondToLastOrDefault()) + { // extract "else...; exit". // Note that this will only extract instructions that were previously inlined from another block // (via InlineExitBranch), so the instructions are already fully-transformed. // So it's OK to move them into a nested block again (which hides them from the following block transforms). ifInst.TrueInst = ExtractBlock(block, block.Instructions.IndexOf(ifInst) + 1, block.Instructions.Count); - } else { + } + else + { block.Instructions.RemoveAt(block.Instructions.Count - 1); ifInst.TrueInst = exitInst; } - if (thenInst is Block thenBlock) { + if (thenInst is Block thenBlock) + { block.Instructions.AddRange(thenBlock.Instructions); - } else { + } + else + { block.Instructions.Add(thenInst); } @@ -407,11 +427,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// private void IntroduceShortCircuit(IfInstruction ifInst) { - if (IsEmpty(ifInst.FalseInst) - && ifInst.TrueInst is Block trueBlock + if (IsEmpty(ifInst.FalseInst) + && ifInst.TrueInst is Block trueBlock && trueBlock.Instructions.Count == 1 && trueBlock.FinalInstruction is Nop - && trueBlock.Instructions[0].MatchIfInstruction(out var nestedCondition, out var nestedTrueInst)) { + && trueBlock.Instructions[0].MatchIfInstruction(out var nestedCondition, out var nestedTrueInst)) + { context.Step("Combine 'if (cond1 && cond2)' in then-branch", ifInst); ifInst.Condition = IfInstruction.LogicAnd(ifInst.Condition, nestedCondition); ifInst.TrueInst = nestedTrueInst; @@ -441,7 +462,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { // some compilers merge the leave instructions for different arguments using stack variables // these get split and inlined, but the ILRange of the value remains a better indicator of the actual location - if (inst is Leave leave && !leave.Value.MatchNop()) { + if (inst is Leave leave && !leave.Value.MatchNop()) + { isEmpty = leave.Value.ILRangeIsEmpty; return leave.Value.StartILOffset; } @@ -459,12 +481,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private void PickBetterBlockExit(Block block, IfInstruction ifInst) { var exitInst = GetExit(block); - if (IsEmpty(ifInst.FalseInst) - && TryGetExit(ifInst.TrueInst, out var trueExitInst) - && CompareBlockExitPriority(trueExitInst, exitInst) > 0) + if (IsEmpty(ifInst.FalseInst) + && TryGetExit(ifInst.TrueInst, out var trueExitInst) + && CompareBlockExitPriority(trueExitInst, exitInst) > 0) InvertIf(block, ifInst); } - + /// /// Compares two exit instructions for block exit priority /// A higher priority exit should be kept as the last instruction in a block @@ -492,14 +514,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (isKeyword1 != isKeyword2) return isKeyword1 ? -1 : 1; - - if (isKeyword1) { + + if (isKeyword1) + { //for keywords - if (currentContainer.Kind == ContainerKind.Switch) { + if (currentContainer.Kind == ContainerKind.Switch) + { // breaks have highest priority in a switch if ((keyword1 == Keyword.Break) != (keyword2 == Keyword.Break)) return keyword1 == Keyword.Break ? 1 : -1; - } else { + } + else + { // breaks have lowest priority if ((keyword1 == Keyword.Break) != (keyword2 == Keyword.Break)) return keyword1 == Keyword.Break ? -1 : 1; @@ -508,15 +534,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if ((keyword1 == Keyword.Continue) != (keyword2 == Keyword.Continue)) return keyword1 == Keyword.Continue ? 1 : -1; } - } else {// for non-keywords (only Branch or Leave) - // branches have lower priority than non-keyword leaves + } + else + {// for non-keywords (only Branch or Leave) + // branches have lower priority than non-keyword leaves bool isBranch1 = exit1 is Branch; bool isBranch2 = exit2 is Branch; if (isBranch1 != isBranch2) return isBranch1 ? -1 : 1; // two leaves that both want end of block priority - if (exit1.MatchLeave(out var container1) && exit2.MatchLeave(out var container2) && container1 != container2) { + if (exit1.MatchLeave(out var container1) && exit2.MatchLeave(out var container2) && container1 != container2) + { // choose the outer one return container2.IsDescendantOf(container1) ? 1 : -1; } @@ -524,7 +553,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (strongly) return 0; - + // prefer arranging stuff in IL order if (exit1.MatchBranch(out var block1) && exit2.MatchBranch(out var block2)) return block1.StartILOffset.CompareTo(block2.StartILOffset); @@ -532,7 +561,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // use the IL offsets of the arguments of leave instructions instead of the leaves themselves if possible if (exit1.MatchLeave(out var _, out var arg1) && exit2.MatchLeave(out var _, out var arg2)) return arg1.StartILOffset.CompareTo(arg2.StartILOffset); - + return exit1.StartILOffset.CompareTo(exit2.StartILOffset); } @@ -545,19 +574,23 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private bool IsKeywordExit(ILInstruction exitInst, out Keyword keyword) { keyword = Keyword.Other; - switch (exitInst) { + switch (exitInst) + { case Branch branch: - if (IsContinueBlock(branch.TargetContainer, branch.TargetBlock)) { + if (IsContinueBlock(branch.TargetContainer, branch.TargetBlock)) + { keyword = Keyword.Continue; return true; } return false; case Leave leave: - if (leave.IsLeavingFunction) { + if (leave.IsLeavingFunction) + { keyword = Keyword.Return; return true; } - if (leave.TargetContainer.Kind != ContainerKind.Normal) { + if (leave.TargetContainer.Kind != ContainerKind.Normal) + { keyword = Keyword.Break; return true; } @@ -576,11 +609,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (inst is Block block && block.Instructions.Count > 0) inst = block.Instructions.Last(); - if (inst.HasFlag(InstructionFlags.EndPointUnreachable)) { + if (inst.HasFlag(InstructionFlags.EndPointUnreachable)) + { exitInst = inst; return true; } - + exitInst = null; return false; } @@ -601,7 +635,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// /// Returns true if inst is Nop or a Block with no instructions. /// - private static bool IsEmpty(ILInstruction inst) => + private static bool IsEmpty(ILInstruction inst) => inst is Nop || inst is Block block && block.Instructions.Count == 0 && block.FinalInstruction is Nop; /// @@ -615,7 +649,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; // increment blocks have exactly 2 incoming edges - if (container.EntryPoint.IncomingEdgeCount == 2) { + if (container.EntryPoint.IncomingEdgeCount == 2) + { var forIncrement = HighLevelLoopTransform.GetIncrementBlock(container, container.EntryPoint); if (forIncrement != null) return block == forIncrement; @@ -630,7 +665,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow internal static Block ExtractBlock(Block block, int startIndex, int endIndex) { var extractedBlock = new Block(); - for (int i = startIndex; i < endIndex; i++) { + for (int i = startIndex; i < endIndex; i++) + { var inst = block.Instructions[i]; extractedBlock.Instructions.Add(inst); extractedBlock.AddILRange(inst); diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowGraph.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowGraph.cs index a5f006100..a4cecb709 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowGraph.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowGraph.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; + using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.Util; @@ -65,7 +66,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow this.container = container; this.cfg = new ControlFlowNode[container.Blocks.Count]; this.nodeHasDirectExitOutOfContainer = new BitSet(cfg.Length); - for (int i = 0; i < cfg.Length; i++) { + for (int i = 0; i < cfg.Length; i++) + { Block block = container.Blocks[i]; cfg[i] = new ControlFlowNode { UserIndex = i, UserData = block }; dict.Add(block, cfg[i]); @@ -79,30 +81,41 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void CreateEdges(CancellationToken cancellationToken) { - for (int i = 0; i < container.Blocks.Count; i++) { + for (int i = 0; i < container.Blocks.Count; i++) + { cancellationToken.ThrowIfCancellationRequested(); var block = container.Blocks[i]; var sourceNode = cfg[i]; - foreach (var node in block.Descendants) { - if (node is Branch branch) { - if (branch.TargetBlock.Parent == container) { + foreach (var node in block.Descendants) + { + if (node is Branch branch) + { + if (branch.TargetBlock.Parent == container) + { sourceNode.AddEdgeTo(cfg[container.Blocks.IndexOf(branch.TargetBlock)]); - } else if (branch.TargetBlock.IsDescendantOf(container)) { + } + else if (branch.TargetBlock.IsDescendantOf(container)) + { // Internal control flow within a nested container. - } else { + } + else + { // Branch out of this container into a parent container. // Like return statements and exceptional exits, // we ignore this for the CFG and the dominance calculation. // However, it's relevant for HasReachableExit(). nodeHasDirectExitOutOfContainer.Set(i); } - } else if (node is Leave leave && !leave.TargetContainer.IsDescendantOf(block)) { + } + else if (node is Leave leave && !leave.TargetContainer.IsDescendantOf(block)) + { // Leave instructions (like other exits out of the container) // are ignored for the CFG and dominance, // but is relevant for HasReachableExit(). // However, a 'leave' that exits the whole function represents a return, // and is not considered a reachable exit. - if (!leave.IsLeavingFunction) { + if (!leave.IsLeavingFunction) + { nodeHasDirectExitOutOfContainer.Set(i); } } @@ -115,12 +128,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Also mark the nodes that exit the block container altogether. // Invariant: leaving[n.UserIndex] == true implies leaving[n.ImmediateDominator.UserIndex] == true var leaving = new BitSet(cfg.Length); - foreach (var node in cfg) { + foreach (var node in cfg) + { if (leaving[node.UserIndex]) continue; - if (nodeHasDirectExitOutOfContainer[node.UserIndex]) { - for (ControlFlowNode p = node; p != null; p = p.ImmediateDominator) { - if (leaving[p.UserIndex]) { + if (nodeHasDirectExitOutOfContainer[node.UserIndex]) + { + for (ControlFlowNode p = node; p != null; p = p.ImmediateDominator) + { + if (leaving[p.UserIndex]) + { // we can stop marking when we've reached an already-marked node break; } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs index 59e4387f7..c813d3465 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -42,7 +43,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow public void Run(ILFunction function, ILTransformContext context) { - foreach (var block in function.Descendants.OfType()) { + foreach (var block in function.Descendants.OfType()) + { context.CancellationToken.ThrowIfCancellationRequested(); RemoveNopInstructions(block); @@ -60,8 +62,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private static void RemoveNopInstructions(Block block) { // Move ILRanges of special nop instructions to the previous non-nop instruction. - for (int i = block.Instructions.Count - 1; i > 0; i--) { - if (block.Instructions[i] is Nop nop && nop.Kind == NopKind.Pop) { + for (int i = block.Instructions.Count - 1; i > 0; i--) + { + if (block.Instructions[i] is Nop nop && nop.Kind == NopKind.Pop) + { block.Instructions[i - 1].AddILRange(nop); } } @@ -76,13 +80,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Previously copy propagation did this; // ideally the ILReader would already do this, // for now do this here (even though it's not control-flow related). - for (int i = block.Instructions.Count - 1; i >= 0; i--) { - if (block.Instructions[i] is StLoc stloc && stloc.Variable.IsSingleDefinition && stloc.Variable.LoadCount == 0 && stloc.Variable.Kind == VariableKind.StackSlot) { + for (int i = block.Instructions.Count - 1; i >= 0; i--) + { + if (block.Instructions[i] is StLoc stloc && stloc.Variable.IsSingleDefinition && stloc.Variable.LoadCount == 0 && stloc.Variable.Kind == VariableKind.StackSlot) + { context.Step($"Remove dead stack store {stloc.Variable.Name}", stloc); - if (aggressive ? SemanticHelper.IsPure(stloc.Value.Flags) : IsSimple(stloc.Value)) { + if (aggressive ? SemanticHelper.IsPure(stloc.Value.Flags) : IsSimple(stloc.Value)) + { Debug.Assert(SemanticHelper.IsPure(stloc.Value.Flags)); block.Instructions.RemoveAt(i++); - } else { + } + else + { stloc.Value.AddILRange(stloc); stloc.ReplaceWith(stloc.Value); } @@ -91,7 +100,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow bool IsSimple(ILInstruction inst) { - switch (inst.OpCode) { + switch (inst.OpCode) + { case OpCode.LdLoc: case OpCode.LdStr: // C# 1.0 compiler sometimes emits redundant ldstr in switch-on-string pattern return true; @@ -110,10 +120,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // (where 'v' has no other uses) // Simplify these to a simple `ret()` so that they match the release build version. // - if (block.Instructions.Count == 2 && block.Instructions[1].MatchReturn(out ILInstruction value)) { + if (block.Instructions.Count == 2 && block.Instructions[1].MatchReturn(out ILInstruction value)) + { var ret = (Leave)block.Instructions[1]; if (value.MatchLdLoc(out ILVariable v) - && v.IsSingleDefinition && v.LoadCount == 1 && block.Instructions[0].MatchStLoc(v, out ILInstruction inst)) { + && v.IsSingleDefinition && v.LoadCount == 1 && block.Instructions[0].MatchStLoc(v, out ILInstruction inst)) + { context.Step("Inline variable in return block", block); inst.AddILRange(ret.Value); inst.AddILRange(block.Instructions[0]); @@ -122,17 +134,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } } } - + void SimplifyBranchChains(ILFunction function, ILTransformContext context) { List<(BlockContainer, Block)> blocksToAdd = new List<(BlockContainer, Block)>(); HashSet visitedBlocks = new HashSet(); - foreach (var branch in function.Descendants.OfType()) { + foreach (var branch in function.Descendants.OfType()) + { // Resolve chained branches to the final target: var targetBlock = branch.TargetBlock; visitedBlocks.Clear(); - while (targetBlock.Instructions.Count == 1 && targetBlock.Instructions[0].OpCode == OpCode.Branch) { - if (!visitedBlocks.Add(targetBlock)) { + while (targetBlock.Instructions.Count == 1 && targetBlock.Instructions[0].OpCode == OpCode.Branch) + { + if (!visitedBlocks.Add(targetBlock)) + { // prevent infinite loop when branch chain is cyclic break; } @@ -144,12 +159,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow targetBlock.Instructions.Clear(); // mark the block for deletion targetBlock = branch.TargetBlock; } - if (IsBranchToReturnBlock(branch)) { - if (aggressivelyDuplicateReturnBlocks) { + if (IsBranchToReturnBlock(branch)) + { + if (aggressivelyDuplicateReturnBlocks) + { // Replace branches to 'return blocks' with the return instruction context.Step("Replace branch to return with return", branch); branch.ReplaceWith(targetBlock.Instructions[0].Clone()); - } else if (branch.TargetContainer != branch.Ancestors.OfType().First()) { + } + else if (branch.TargetContainer != branch.Ancestors.OfType().First()) + { // We don't want to always inline the return directly, because this // might force us to place the return within a loop, when it's better // placed outside. @@ -162,7 +181,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow blocksToAdd.Add((localContainer, blockCopy)); branch.TargetBlock = blockCopy; } - } else if (targetBlock.Instructions.Count == 1 && targetBlock.Instructions[0] is Leave leave && leave.Value.MatchNop()) { + } + else if (targetBlock.Instructions.Count == 1 && targetBlock.Instructions[0] is Leave leave && leave.Value.MatchNop()) + { context.Step("Replace branch to leave with leave", branch); // Replace branches to 'leave' instruction with the leave instruction var leave2 = leave.Clone(); @@ -173,18 +194,22 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (targetBlock.IncomingEdgeCount == 0) targetBlock.Instructions.Clear(); // mark the block for deletion } - foreach (var (container, block) in blocksToAdd) { + foreach (var (container, block) in blocksToAdd) + { container.Blocks.Add(block); } } - + void CleanUpEmptyBlocks(ILFunction function, ILTransformContext context) { - foreach (var container in function.Descendants.OfType()) { - foreach (var block in container.Blocks) { + foreach (var container in function.Descendants.OfType()) + { + foreach (var block in container.Blocks) + { if (block.Instructions.Count == 0) continue; // block is already marked for deletion - while (CombineBlockWithNextBlock(container, block, context)) { + while (CombineBlockWithNextBlock(container, block, context)) + { // repeat combining blocks until it is no longer possible // (this loop terminates because a block is deleted in every iteration) } @@ -204,8 +229,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!value.MatchLdLoc(out var returnVar)) return false; var container = branch.TargetContainer; - for (ILInstruction inst = branch; inst != container; inst = inst.Parent) { - if (inst.Parent is TryFinally tryFinally && inst.SlotInfo == TryFinally.TryBlockSlot) { + for (ILInstruction inst = branch; inst != container; inst = inst.Parent) + { + if (inst.Parent is TryFinally tryFinally && inst.SlotInfo == TryFinally.TryBlockSlot) + { // The branch will trigger the finally block. // Moving the return block into the try is only possible if the finally block doesn't touch the return variable. if (returnVar.IsUsedWithin(tryFinally.FinallyBlock)) @@ -214,7 +241,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } return true; } - + static bool CombineBlockWithNextBlock(BlockContainer container, Block block, ILTransformContext context) { Debug.Assert(container == block.Parent); @@ -229,7 +256,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; // don't inline block into itself context.Step("CombineBlockWithNextBlock", br); var targetBlock = br.TargetBlock; - if (targetBlock.StartILOffset < block.StartILOffset && IsDeadTrueStore(block)) { + if (targetBlock.StartILOffset < block.StartILOffset && IsDeadTrueStore(block)) + { // The C# compiler generates a dead store for the condition of while (true) loops. block.Instructions.RemoveRange(block.Instructions.Count - 3, 2); } @@ -248,7 +276,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// private static bool IsDeadTrueStore(Block block) { - if (block.Instructions.Count < 3) return false; + if (block.Instructions.Count < 3) + return false; if (!(block.Instructions.SecondToLastOrDefault() is StLoc deadStore && block.Instructions[block.Instructions.Count - 3] is StLoc tempStore)) return false; if (!(deadStore.Variable.LoadCount == 0 && deadStore.Variable.AddressCount == 0)) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs index 793dedb3a..d5994794e 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -59,7 +60,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow public void Run(ILFunction function, ILTransformContext context) { this.context = context; - foreach (var container in function.Descendants.OfType()) { + foreach (var container in function.Descendants.OfType()) + { context.CancellationToken.ThrowIfCancellationRequested(); DetectNullSafeArrayToPointerOrCustomRefPin(container); SplitBlocksAtWritesToPinnedLocals(container); @@ -68,14 +70,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow container.Blocks.RemoveAll(b => b.Instructions.Count == 0); // remove dummy blocks } // Sometimes there's leftover writes to the original pinned locals - foreach (var block in function.Descendants.OfType()) { + foreach (var block in function.Descendants.OfType()) + { context.CancellationToken.ThrowIfCancellationRequested(); - for (int i = 0; i < block.Instructions.Count; i++) { + for (int i = 0; i < block.Instructions.Count; i++) + { var stloc = block.Instructions[i] as StLoc; - if (stloc != null && stloc.Variable.Kind == VariableKind.PinnedLocal && stloc.Variable.LoadCount == 0 && stloc.Variable.AddressCount == 0) { - if (SemanticHelper.IsPure(stloc.Value.Flags)) { + if (stloc != null && stloc.Variable.Kind == VariableKind.PinnedLocal && stloc.Variable.LoadCount == 0 && stloc.Variable.AddressCount == 0) + { + if (SemanticHelper.IsPure(stloc.Value.Flags)) + { block.Instructions.RemoveAt(i--); - } else { + } + else + { stloc.ReplaceWith(stloc.Value); } } @@ -90,16 +98,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// void SplitBlocksAtWritesToPinnedLocals(BlockContainer container) { - for (int i = 0; i < container.Blocks.Count; i++) { + for (int i = 0; i < container.Blocks.Count; i++) + { var block = container.Blocks[i]; - for (int j = 0; j < block.Instructions.Count - 1; j++) { + for (int j = 0; j < block.Instructions.Count - 1; j++) + { var inst = block.Instructions[j]; - if (inst.MatchStLoc(out ILVariable v, out var value) && v.Kind == VariableKind.PinnedLocal) { - if (block.Instructions[j + 1].OpCode != OpCode.Branch) { + if (inst.MatchStLoc(out ILVariable v, out var value) && v.Kind == VariableKind.PinnedLocal) + { + if (block.Instructions[j + 1].OpCode != OpCode.Branch) + { // split block after j: context.Step("Split block after pinned local write", inst); var newBlock = new Block(); - for (int k = j + 1; k < block.Instructions.Count; k++) { + for (int k = j + 1; k < block.Instructions.Count; k++) + { newBlock.Instructions.Add(block.Instructions[k]); } newBlock.AddILRange(newBlock.Instructions[0]); @@ -109,18 +122,22 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } // in case of re-pinning (e.g. C++/CLI assignment to pin_ptr variable), // it's possible for the new value to be dependent on the old. - if (v.IsUsedWithin(value)) { + if (v.IsUsedWithin(value)) + { // In this case, we need to un-inline the uses of the pinned local // so that they are split off into the block prior to the pinned local write var temp = context.Function.RegisterVariable(VariableKind.StackSlot, v.Type); block.Instructions.Insert(j++, new StLoc(temp, new LdLoc(v))); - foreach (var descendant in value.Descendants) { - if (descendant.MatchLdLoc(v)) { + foreach (var descendant in value.Descendants) + { + if (descendant.MatchLdLoc(v)) + { descendant.ReplaceWith(new LdLoc(temp).WithILRange(descendant)); } } } - if (j > 0) { + if (j > 0) + { // split block before j: context.Step("Split block before pinned local write", inst); var newBlock = new Block(); @@ -140,24 +157,32 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void DetectNullSafeArrayToPointerOrCustomRefPin(BlockContainer container) { bool modified = false; - for (int i = 0; i < container.Blocks.Count; i++) { + for (int i = 0; i < container.Blocks.Count; i++) + { var block = container.Blocks[i]; - if (IsNullSafeArrayToPointerPattern(block, out ILVariable v, out ILVariable p, out Block targetBlock)) { + if (IsNullSafeArrayToPointerPattern(block, out ILVariable v, out ILVariable p, out Block targetBlock)) + { context.Step("NullSafeArrayToPointerPattern", block); ILInstruction arrayToPointer = new GetPinnableReference(new LdLoc(v), null); - if (p.StackType != StackType.Ref) { + if (p.StackType != StackType.Ref) + { arrayToPointer = new Conv(arrayToPointer, p.StackType.ToPrimitiveType(), false, Sign.None); } block.Instructions[block.Instructions.Count - 2] = new StLoc(p, arrayToPointer) .WithILRange(block.Instructions[block.Instructions.Count - 2]); ((Branch)block.Instructions.Last()).TargetBlock = targetBlock; modified = true; - } else if (IsCustomRefPinPattern(block, out ILInstruction ldlocMem, out var callGPR, out v, out var stlocPtr, out targetBlock)) { + } + else if (IsCustomRefPinPattern(block, out ILInstruction ldlocMem, out var callGPR, out v, out var stlocPtr, out targetBlock)) + { context.Step("CustomRefPinPattern", block); ILInstruction gpr; - if (context.Settings.PatternBasedFixedStatement) { + if (context.Settings.PatternBasedFixedStatement) + { gpr = new GetPinnableReference(ldlocMem, callGPR.Method); - } else { + } + else + { gpr = new IfInstruction( condition: new Comp(ComparisonKind.Inequality, Sign.None, ldlocMem, new LdNull()), trueInst: callGPR, @@ -171,7 +196,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow modified = true; } } - if (modified) { + if (modified) + { container.Blocks.RemoveAll(b => b.IncomingEdgeCount == 0); // remove blocks made unreachable } } @@ -301,11 +327,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!(condition != null && condition.Kind == ComparisonKind.Equality && condition.Left.MatchLdLoc(out v) && condition.Right.MatchLdNull())) return false; bool usingPreviousVar = false; - if (v.Kind == VariableKind.StackSlot) { + if (v.Kind == VariableKind.StackSlot) + { // If the variable is a stack slot, that might be due to an inline assignment, // so check the previous instruction: var previous = block.Instructions.ElementAtOrDefault(block.Instructions.Count - 3) as StLoc; - if (previous != null && previous.Value.MatchLdLoc(v)) { + if (previous != null && previous.Value.MatchLdLoc(v)) + { // stloc V(ldloc S) // if (comp(ldloc S == ldnull)) ... v = previous.Variable; @@ -340,16 +368,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!block.Instructions[0].MatchIfInstruction(out ILInstruction condition, out ILInstruction trueInst)) return false; condition = condition.UnwrapConv(ConversionKind.Truncate); - if (condition.MatchLdLen(StackType.I, out ILInstruction array)) { + if (condition.MatchLdLen(StackType.I, out ILInstruction array)) + { // OK - } else if (condition is CallInstruction call && call.Method.Name == "get_Length") { + } + else if (condition is CallInstruction call && call.Method.Name == "get_Length") + { // Used instead of ldlen for multi-dimensional arrays if (!call.Method.DeclaringType.IsKnownType(KnownTypeCode.Array)) return false; if (call.Arguments.Count != 1) return false; array = call.Arguments[0]; - } else { + } + else + { return false; } if (!array.MatchLdLoc(v)) @@ -373,16 +406,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; if (!block.Instructions[0].MatchStLoc(out var p2, out ILInstruction value)) return false; - if (p != p2) { + if (p != p2) + { // If the pointer is unused, the variable P might have been split. - if (p.LoadCount == 0 && p.AddressCount == 0 && p2.LoadCount == 0 && p2.AddressCount == 0) { + if (p.LoadCount == 0 && p.AddressCount == 0 && p2.LoadCount == 0 && p2.AddressCount == 0) + { if (!ILVariableEqualityComparer.Instance.Equals(p, p2)) return false; - } else { + } + else + { return false; } } - if (v.Kind == VariableKind.PinnedLocal) { + if (v.Kind == VariableKind.PinnedLocal) + { value = value.UnwrapConv(ConversionKind.StopGCTracking); } if (!(value is LdElema ldelema)) @@ -420,15 +458,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (stLoc == null || stLoc.Variable.Kind != VariableKind.PinnedLocal) return false; // stLoc is a store to a pinned local. - if (IsNullOrZero(stLoc.Value)) { + if (IsNullOrZero(stLoc.Value)) + { return false; // ignore unpin instructions } // stLoc is a store that starts a new pinned region context.StepStartGroup($"DetectPinnedRegion {stLoc.Variable.Name}", block); - try { + try + { return CreatePinnedRegion(block, stLoc); - } finally { + } + finally + { context.StepEndGroup(keepIfEmpty: true); } } @@ -440,26 +482,35 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow int[] reachedEdgesPerBlock = new int[sourceContainer.Blocks.Count]; Queue workList = new Queue(); Block entryBlock = ((Branch)block.Instructions.Last()).TargetBlock; - if (entryBlock.Parent != sourceContainer) { + if (entryBlock.Parent != sourceContainer) + { // we didn't find a single block to be added to the pinned region return false; } - if (entryBlock.Instructions[0].MatchStLoc(stLoc.Variable, out _)) { + if (entryBlock.Instructions[0].MatchStLoc(stLoc.Variable, out _)) + { // pinned region has empty body - } else { + } + else + { reachedEdgesPerBlock[entryBlock.ChildIndex]++; workList.Enqueue(entryBlock); } - while (workList.Count > 0) { + while (workList.Count > 0) + { Block workItem = workList.Dequeue(); - foreach (var branch in workItem.Descendants.OfType()) { - if (branch.TargetBlock.Parent == sourceContainer) { - if (branch.TargetBlock.Instructions[0].MatchStLoc(stLoc.Variable, out _)) { + foreach (var branch in workItem.Descendants.OfType()) + { + if (branch.TargetBlock.Parent == sourceContainer) + { + if (branch.TargetBlock.Instructions[0].MatchStLoc(stLoc.Variable, out _)) + { // Found unpin instruction continue; } Debug.Assert(branch.TargetBlock != block); - if (reachedEdgesPerBlock[branch.TargetBlock.ChildIndex]++ == 0) { + if (reachedEdgesPerBlock[branch.TargetBlock.ChildIndex]++ == 0) + { // detected first edge to that block: add block as work item workList.Enqueue(branch.TargetBlock); } @@ -470,8 +521,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Validate that all uses of a block consistently are inside or outside the pinned region. // (we cannot do this anymore after we start moving blocks around) bool cloneBlocks = false; - for (int i = 0; i < sourceContainer.Blocks.Count; i++) { - if (reachedEdgesPerBlock[i] != 0 && reachedEdgesPerBlock[i] != sourceContainer.Blocks[i].IncomingEdgeCount) { + for (int i = 0; i < sourceContainer.Blocks.Count; i++) + { + if (reachedEdgesPerBlock[i] != 0 && reachedEdgesPerBlock[i] != sourceContainer.Blocks[i].IncomingEdgeCount) + { // Don't abort in this case, we still need to somehow represent the pinned variable with a fixed statement. // We'll duplicate the code so that it can be both inside and outside the pinned region. cloneBlocks = true; @@ -482,32 +535,39 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow context.Step("CreatePinnedRegion", block); BlockContainer body = new BlockContainer(); Block[] clonedBlocks = cloneBlocks ? new Block[sourceContainer.Blocks.Count] : null; - for (int i = 0; i < sourceContainer.Blocks.Count; i++) { - if (reachedEdgesPerBlock[i] > 0) { + for (int i = 0; i < sourceContainer.Blocks.Count; i++) + { + if (reachedEdgesPerBlock[i] > 0) + { var innerBlock = sourceContainer.Blocks[i]; - if (cloneBlocks) { + if (cloneBlocks) + { innerBlock = (Block)innerBlock.Clone(); clonedBlocks[i] = innerBlock; } Branch br = innerBlock.Instructions.LastOrDefault() as Branch; if (br != null && br.TargetBlock.IncomingEdgeCount == 1 - && br.TargetContainer == sourceContainer && reachedEdgesPerBlock[br.TargetBlock.ChildIndex] == 0) { + && br.TargetContainer == sourceContainer && reachedEdgesPerBlock[br.TargetBlock.ChildIndex] == 0) + { // branch that leaves body. // The target block should have an instruction that resets the pin; delete that instruction: StLoc unpin = br.TargetBlock.Instructions.First() as StLoc; - if (unpin != null && unpin.Variable == stLoc.Variable && IsNullOrZero(unpin.Value)) { + if (unpin != null && unpin.Variable == stLoc.Variable && IsNullOrZero(unpin.Value)) + { br.TargetBlock.Instructions.RemoveAt(0); } } body.Blocks.Add(innerBlock); // move block into body - if (!cloneBlocks) { + if (!cloneBlocks) + { sourceContainer.Blocks[i] = new Block(); // replace with dummy block // we'll delete the dummy block later } } } - if (body.Blocks.Count == 0) { + if (body.Blocks.Count == 0) + { // empty body, the entryBlock itself doesn't belong into the pinned region Debug.Assert(reachedEdgesPerBlock[entryBlock.ChildIndex] == 0); var bodyBlock = new Block(); @@ -520,12 +580,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow stLoc.ReplaceWith(pinnedRegion); block.Instructions.RemoveAt(block.Instructions.Count - 1); // remove branch into body - if (cloneBlocks) { + if (cloneBlocks) + { // Adjust branches between cloned blocks. - foreach (var branch in body.Descendants.OfType()) { - if (branch.TargetContainer == sourceContainer) { + foreach (var branch in body.Descendants.OfType()) + { + if (branch.TargetContainer == sourceContainer) + { int i = branch.TargetBlock.ChildIndex; - if (clonedBlocks[i] != null) { + if (clonedBlocks[i] != null) + { branch.TargetBlock = clonedBlocks[i]; } } @@ -533,13 +597,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Replace unreachable blocks in sourceContainer with dummy blocks: bool[] isAlive = new bool[sourceContainer.Blocks.Count]; List duplicatedBlockStartOffsets = new List(); - foreach (var remainingBlock in sourceContainer.TopologicalSort(deleteUnreachableBlocks: true)) { + foreach (var remainingBlock in sourceContainer.TopologicalSort(deleteUnreachableBlocks: true)) + { isAlive[remainingBlock.ChildIndex] = true; - if (clonedBlocks[remainingBlock.ChildIndex] != null) { + if (clonedBlocks[remainingBlock.ChildIndex] != null) + { duplicatedBlockStartOffsets.Add(remainingBlock.StartILOffset); } } - for (int i = 0; i < isAlive.Length; i++) { + for (int i = 0; i < isAlive.Length; i++) + { if (!isAlive[i]) sourceContainer.Blocks[i] = new Block(); } @@ -558,7 +625,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow static bool IsNullOrZero(ILInstruction inst) { - while (inst is Conv conv) { + while (inst is Conv conv) + { inst = conv.Argument; } return inst.MatchLdcI4(0) || inst.MatchLdNull(); @@ -572,13 +640,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// void ProcessPinnedRegion(PinnedRegion pinnedRegion) { - if (pinnedRegion.Variable.Type.Kind == TypeKind.ByReference) { + if (pinnedRegion.Variable.Type.Kind == TypeKind.ByReference) + { // C# doesn't support a "by reference" variable, so replace it with a native pointer context.Step("Replace pinned ref-local with native pointer", pinnedRegion); ILVariable oldVar = pinnedRegion.Variable; IType elementType = ((ByReferenceType)oldVar.Type).ElementType; if (elementType.Kind == TypeKind.Pointer && pinnedRegion.Init.MatchLdFlda(out _, out var field) - && ((PointerType)elementType).ElementType.Equals(field.Type)) { + && ((PointerType)elementType).ElementType.Equals(field.Type)) + { // Roslyn 2.6 (C# 7.2) uses type "int*&" for the pinned local referring to a // fixed field of type "int". // Remove the extra level of indirection. @@ -593,11 +663,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow oldVar.Function.Variables.Add(newVar); ReplacePinnedVar(oldVar, newVar, pinnedRegion); UseExistingVariableForPinnedRegion(pinnedRegion); - } else if (pinnedRegion.Variable.Type.Kind == TypeKind.Array) { + } + else if (pinnedRegion.Variable.Type.Kind == TypeKind.Array) + { context.Step("Replace pinned array with native pointer", pinnedRegion); MoveArrayToPointerToPinnedRegionInit(pinnedRegion); UseExistingVariableForPinnedRegion(pinnedRegion); - } else if (pinnedRegion.Variable.Type.IsKnownType(KnownTypeCode.String)) { + } + else if (pinnedRegion.Variable.Type.IsKnownType(KnownTypeCode.String)) + { // fixing a string HandleStringToPointer(pinnedRegion); } @@ -607,7 +681,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow DetectPinnedRegion(block); body.Blocks.RemoveAll(b => b.Instructions.Count == 0); // remove dummy blocks body.SetILRange(body.EntryPoint); - if (pinnedRegion.Variable.Kind != VariableKind.PinnedRegionLocal) { + if (pinnedRegion.Variable.Kind != VariableKind.PinnedRegionLocal) + { Debug.Assert(pinnedRegion.Variable.Kind == VariableKind.PinnedLocal); pinnedRegion.Variable.Kind = VariableKind.PinnedRegionLocal; } @@ -620,8 +695,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow Debug.Assert(pinnedRegion.Variable.Type.Kind == TypeKind.Array); // Find the single load of the variable within the pinnedRegion: LdLoc ldloc = null; - foreach (var inst in pinnedRegion.Descendants.OfType()) { - if (inst.Variable == pinnedRegion.Variable && inst != pinnedRegion) { + foreach (var inst in pinnedRegion.Descendants.OfType()) + { + if (inst.Variable == pinnedRegion.Variable && inst != pinnedRegion) + { if (ldloc != null) return; // more than 1 variable access ldloc = inst as LdLoc; @@ -652,28 +729,35 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void ReplacePinnedVar(ILVariable oldVar, ILVariable newVar, ILInstruction inst) { Debug.Assert(newVar.StackType == StackType.I); - if (inst is Conv conv && conv.Kind == ConversionKind.StopGCTracking && conv.Argument.MatchLdLoc(oldVar) && conv.ResultType == newVar.StackType) { + if (inst is Conv conv && conv.Kind == ConversionKind.StopGCTracking && conv.Argument.MatchLdLoc(oldVar) && conv.ResultType == newVar.StackType) + { // conv ref->i (ldloc oldVar) // => ldloc newVar conv.AddILRange(conv.Argument); conv.ReplaceWith(new LdLoc(newVar).WithILRange(conv)); return; } - if (inst is IInstructionWithVariableOperand iwvo && iwvo.Variable == oldVar) { + if (inst is IInstructionWithVariableOperand iwvo && iwvo.Variable == oldVar) + { iwvo.Variable = newVar; - if (inst is StLoc stloc && oldVar.Type.Kind == TypeKind.ByReference) { + if (inst is StLoc stloc && oldVar.Type.Kind == TypeKind.ByReference) + { stloc.Value = new Conv(stloc.Value, PrimitiveType.I, false, Sign.None); } - if ((inst is LdLoc || inst is StLoc) && !IsSlotAcceptingBothManagedAndUnmanagedPointers(inst.SlotInfo) && oldVar.StackType != StackType.I) { + if ((inst is LdLoc || inst is StLoc) && !IsSlotAcceptingBothManagedAndUnmanagedPointers(inst.SlotInfo) && oldVar.StackType != StackType.I) + { // wrap inst in Conv, so that the stack types match up var children = inst.Parent.Children; children[inst.ChildIndex] = new Conv(inst, oldVar.StackType.ToPrimitiveType(), false, Sign.None); } - } else if (inst.MatchLdStr(out var val) && val == "Is this ILSpy?") { + } + else if (inst.MatchLdStr(out var val) && val == "Is this ILSpy?") + { inst.ReplaceWith(new LdStr("This is ILSpy!")); // easter egg ;) return; } - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { ReplacePinnedVar(oldVar, newVar, child); } } @@ -704,9 +788,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // if (comp(ldloc nativeVar == conv i4->i (ldc.i4 0))) br targetBlock // br adjustOffsetToStringData ILVariable newVar; - if (!body.EntryPoint.Instructions[0].MatchStLoc(out ILVariable nativeVar, out ILInstruction initInst)) { + if (!body.EntryPoint.Instructions[0].MatchStLoc(out ILVariable nativeVar, out ILInstruction initInst)) + { // potentially a special case with legacy csc and an unused pinned variable: - if (pinnedRegion.Variable.AddressCount == 0 && pinnedRegion.Variable.LoadCount == 0) { + if (pinnedRegion.Variable.AddressCount == 0 && pinnedRegion.Variable.LoadCount == 0) + { var charPtr = new PointerType(context.TypeSystem.FindType(KnownTypeCode.Char)); newVar = new ILVariable(VariableKind.PinnedRegionLocal, charPtr, pinnedRegion.Variable.Index); newVar.Name = pinnedRegion.Variable.Name; @@ -717,7 +803,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } return; } - if (body.EntryPoint.Instructions.Count != 3) { + if (body.EntryPoint.Instructions.Count != 3) + { return; } @@ -733,14 +820,17 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow && IsOffsetToStringDataBlock(adjustOffsetToStringData, nativeVar, targetBlock))) return; context.Step("Handle pinned string (with adjustOffsetToStringData)", pinnedRegion); - if (targetBlock.Parent == body) { + if (targetBlock.Parent == body) + { // remove old entry point body.Blocks.RemoveAt(0); body.Blocks.RemoveAt(adjustOffsetToStringData.ChildIndex); // make targetBlock the new entry point body.Blocks.RemoveAt(targetBlock.ChildIndex); body.Blocks.Insert(0, targetBlock); - } else { + } + else + { // pinned region has empty body, immediately jumps to targetBlock which is outside body.Blocks[0].Instructions.Clear(); body.Blocks.RemoveRange(1, body.Blocks.Count - 1); @@ -755,17 +845,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (nativeVar.Kind == VariableKind.StackSlot && nativeVar.LoadCount == 1 && body.EntryPoint.Instructions[0].MatchStLoc(out otherVar, out otherVarInit) && otherVarInit.MatchLdLoc(nativeVar) - && otherVar.IsSingleDefinition) { + && otherVar.IsSingleDefinition) + { body.EntryPoint.Instructions.RemoveAt(0); nativeVar = otherVar; } - if (nativeVar.Kind == VariableKind.Local) { + if (nativeVar.Kind == VariableKind.Local) + { newVar = new ILVariable(VariableKind.PinnedRegionLocal, nativeVar.Type, nativeVar.Index); newVar.Name = nativeVar.Name; newVar.HasGeneratedName = nativeVar.HasGeneratedName; nativeVar.Function.Variables.Add(newVar); ReplacePinnedVar(nativeVar, newVar, pinnedRegion); - } else { + } + else + { newVar = nativeVar; } ReplacePinnedVar(pinnedRegion.Variable, newVar, pinnedRegion); @@ -778,18 +872,23 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (block.Instructions.Count != 2) return false; ILInstruction value; - if (nativeVar.IsSingleDefinition && nativeVar.LoadCount == 2) { + if (nativeVar.IsSingleDefinition && nativeVar.LoadCount == 2) + { // If there are no loads (except for the two in the string-to-pointer pattern), // then we might have split nativeVar: if (!block.Instructions[0].MatchStLoc(out var otherVar, out value)) return false; if (!(otherVar.IsSingleDefinition && otherVar.LoadCount == 0)) return false; - } else if (nativeVar.StoreCount == 2) { + } + else if (nativeVar.StoreCount == 2) + { // normal case with non-split variable if (!block.Instructions[0].MatchStLoc(nativeVar, out value)) return false; - } else { + } + else + { return false; } if (!value.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out ILInstruction left, out ILInstruction right)) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ExitPoints.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ExitPoints.cs index 4d7401978..fd76f3a27 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ExitPoints.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ExitPoints.cs @@ -17,10 +17,11 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using System.Diagnostics; -using ICSharpCode.Decompiler.IL.Transforms; using System.Threading; -using System.Collections.Generic; + +using ICSharpCode.Decompiler.IL.Transforms; namespace ICSharpCode.Decompiler.IL.ControlFlow { @@ -67,13 +68,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow internal static ILInstruction GetExit(ILInstruction inst) { SlotInfo slot = inst.SlotInfo; - if (slot == Block.InstructionSlot) { + if (slot == Block.InstructionSlot) + { Block block = (Block)inst.Parent; return block.Instructions.ElementAtOrDefault(inst.ChildIndex + 1) ?? ExitNotYetDetermined; - } else if (slot == TryInstruction.TryBlockSlot - || slot == TryCatchHandler.BodySlot - || slot == TryCatch.HandlerSlot - || slot == PinnedRegion.BodySlot) + } + else if (slot == TryInstruction.TryBlockSlot + || slot == TryCatchHandler.BodySlot + || slot == TryCatch.HandlerSlot + || slot == PinnedRegion.BodySlot) { return GetExit(inst.Parent); } @@ -88,7 +91,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { if (exit1 == null || exit2 == null || exit1.OpCode != exit2.OpCode) return false; - switch (exit1.OpCode) { + switch (exit1.OpCode) + { case OpCode.Branch: Branch br1 = (Branch)exit1; Branch br2 = (Branch)exit2; @@ -130,8 +134,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // It's possible that there are unreachable code blocks which we only // detect as such during exit point detection. // Clean them up. - foreach (var block in blocksPotentiallyMadeUnreachable) { - if (block.IncomingEdgeCount == 0 || block.IncomingEdgeCount == 1 && IsInfiniteLoop(block)) { + foreach (var block in blocksPotentiallyMadeUnreachable) + { + if (block.IncomingEdgeCount == 0 || block.IncomingEdgeCount == 1 && IsInfiniteLoop(block)) + { block.Remove(); } } @@ -150,7 +156,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow foreach (var child in inst.Children) child.AcceptVisitor(this); } - + protected internal override void VisitBlockContainer(BlockContainer container) { var oldExit = currentExit; @@ -161,11 +167,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow currentContainer = container; potentialExits = (thisExit == ExitNotYetDetermined ? new List() : null); base.VisitBlockContainer(container); - if (thisExit == ExitNotYetDetermined && potentialExits.Count > 0) { + if (thisExit == ExitNotYetDetermined && potentialExits.Count > 0) + { // This transform determined an exit point. currentExit = ChooseExit(potentialExits); - foreach (var exit in potentialExits) { - if (CompatibleExitInstruction(currentExit, exit)) { + foreach (var exit in potentialExits) + { + if (CompatibleExitInstruction(currentExit, exit)) + { exit.ReplaceWith(new Leave(currentContainer).WithILRange(exit)); } } @@ -176,18 +185,24 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow while (inst.Parent.OpCode != OpCode.Block) inst = inst.Parent; Block block = (Block)inst.Parent; - if (block.HasFlag(InstructionFlags.EndPointUnreachable)) { + if (block.HasFlag(InstructionFlags.EndPointUnreachable)) + { // Special case: despite replacing the exits with leave(currentContainer), // we still have an unreachable endpoint. // The appended currentExit instruction would not be reachable! // This happens in test case ExceptionHandling.ThrowInFinally() - if (currentExit is Branch b) { + if (currentExit is Branch b) + { blocksPotentiallyMadeUnreachable.Add(b.TargetBlock); } - } else { + } + else + { block.Instructions.Add(currentExit); } - } else { + } + else + { Debug.Assert(thisExit == currentExit); } currentExit = oldExit; @@ -198,8 +213,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow static ILInstruction ChooseExit(List potentialExits) { ILInstruction first = potentialExits[0]; - if (first is Leave l && l.IsLeavingFunction) { - for (int i = 1; i < potentialExits.Count; i++) { + if (first is Leave l && l.IsLeavingFunction) + { + for (int i = 1; i < potentialExits.Count; i++) + { var exit = potentialExits[i]; if (!(exit is Leave l2 && l2.IsLeavingFunction)) return exit; @@ -212,37 +229,46 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { cancellationToken.ThrowIfCancellationRequested(); // Don't use foreach loop, because the children might add to the block - for (int i = 0; i < block.Instructions.Count; i++) { + for (int i = 0; i < block.Instructions.Count; i++) + { block.Instructions[i].AcceptVisitor(this); } } void HandleExit(ILInstruction inst) { - if (currentExit == ExitNotYetDetermined && CanIntroduceAsExit(inst)) { + if (currentExit == ExitNotYetDetermined && CanIntroduceAsExit(inst)) + { potentialExits.Add(inst); - } else if (CompatibleExitInstruction(inst, currentExit)) { + } + else if (CompatibleExitInstruction(inst, currentExit)) + { inst.ReplaceWith(new Leave(currentContainer).WithILRange(inst)); } } private bool CanIntroduceAsExit(ILInstruction inst) { - if (currentContainer.LeaveCount > 0) { + if (currentContainer.LeaveCount > 0) + { // if we're re-running on a block container that already has an exit, // we can't introduce any additional exits return false; } - if (inst is Leave l && l.IsLeavingFunction) { + if (inst is Leave l && l.IsLeavingFunction) + { return canIntroduceExitForReturn; - } else { + } + else + { return true; } } protected internal override void VisitBranch(Branch inst) { - if (!inst.TargetBlock.IsDescendantOf(currentContainer)) { + if (!inst.TargetBlock.IsDescendantOf(currentContainer)) + { HandleExit(inst); } } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs index 36632f739..d8f2be9be 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Util; @@ -39,7 +40,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow public class LoopDetection : IBlockTransform { BlockTransformContext context; - + /// Block container corresponding to the current cfg. BlockContainer currentBlockContainer; @@ -51,7 +52,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// Used when isSwitch == true, to determine appropriate exit points within loops /// private SwitchDetection.LoopContext loopContext; - + /// /// Check whether 'block' is a loop head; and construct a loop instruction /// (nested BlockContainer) if it is. @@ -67,7 +68,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Because this is a post-order block transform, we can assume that // any nested loops within this loop have already been constructed. - if (block.Instructions.Last() is SwitchInstruction switchInst) { + if (block.Instructions.Last() is SwitchInstruction switchInst) + { // Switch instructions support "break;" just like loops DetectSwitchBody(block, switchInst); } @@ -77,8 +79,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow Debug.Assert(!TreeTraversal.PreOrder(h, n => n.DominatorTreeChildren).Any(n => n.Visited)); List loop = null; - foreach (var t in h.Predecessors) { - if (h.Dominates(t)) { + foreach (var t in h.Predecessors) + { + if (h.Dominates(t)) + { // h->t is a back edge, and h is a loop header // Add the natural loop of t->h to the loop. @@ -88,7 +92,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // that includes the back edge and has no predecessors outside the set // except for the predecessor of the header. - if (loop == null) { + if (loop == null) + { loop = new List(); loop.Add(h); // Mark loop header as visited so that the pre-order traversal @@ -98,7 +103,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow t.TraversePreOrder(n => n.Predecessors, loop.Add); } } - if (loop != null) { + if (loop != null) + { var headBlock = (Block)h.UserData; context.Step($"Construct loop with head {headBlock.Label}", headBlock); // loop now is the union of all natural loops with loop head h. @@ -112,7 +118,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // (if the loop doesn't contain nested loops, this is a topological sort) loop.Sort((a, b) => b.PostOrderNumber.CompareTo(a.PostOrderNumber)); Debug.Assert(loop[0] == h); - foreach (var node in loop) { + foreach (var node in loop) + { node.Visited = false; // reset visited flag so that we can find outer loops Debug.Assert(h.Dominates(node), "The loop body must be dominated by the loop head"); } @@ -135,22 +142,26 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// void IncludeNestedContainers(List loop) { - for (int i = 0; i < loop.Count; i++) { + for (int i = 0; i < loop.Count; i++) + { IncludeBlock((Block)loop[i].UserData); } void IncludeBlock(Block block) { - foreach (var nestedContainer in block.Instructions.OfType()) { + foreach (var nestedContainer in block.Instructions.OfType()) + { // Just in case the block has multiple nested containers (e.g. due to loop and switch), // also check the entry point: IncludeBlock(nestedContainer.EntryPoint); // Use normal processing for all non-entry-point blocks // (the entry-point itself doesn't have a CFG node, because it's newly created by this transform) - for (int i = 1; i < nestedContainer.Blocks.Count; i++) { + for (int i = 1; i < nestedContainer.Blocks.Count; i++) + { var node = context.ControlFlowGraph.GetNode(nestedContainer.Blocks[i]); Debug.Assert(loop[0].Dominates(node)); - if (!node.Visited) { + if (!node.Visited) + { node.Visited = true; loop.Add(node); // note: this block will be re-visited when the "i < loop.Count" @@ -241,26 +252,33 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { exitPoint = FindExitPoint(loopHead, loop); Debug.Assert(!loop.Contains(exitPoint), "Cannot pick an exit point that is part of the natural loop"); - if (exitPoint != null) { + if (exitPoint != null) + { // Either we are in case 1 and just picked an exit that maximizes the amount of code // outside the loop, or we are in case 2 and found an exit point via post-dominance. // Note that if exitPoint == NoExitPoint, we end up adding all dominated blocks to the loop. var ep = exitPoint; - foreach (var node in TreeTraversal.PreOrder(loopHead, n => DominatorTreeChildren(n, ep))) { - if (!node.Visited) { + foreach (var node in TreeTraversal.PreOrder(loopHead, n => DominatorTreeChildren(n, ep))) + { + if (!node.Visited) + { node.Visited = true; loop.Add(node); } } // The loop/switch can only be entered through the entry point. - if (isSwitch) { + if (isSwitch) + { // In the case of a switch, false positives in the "continue;" detection logic // can lead to falsely excludes some blocks from the body. // Fix that by including all predecessors of included blocks. Debug.Assert(loop[0] == loopHead); - for (int i = 1; i < loop.Count; i++) { - foreach (var p in loop[i].Predecessors) { - if (!p.Visited) { + for (int i = 1; i < loop.Count; i++) + { + foreach (var p in loop[i].Predecessors) + { + if (!p.Visited) + { p.Visited = true; loop.Add(p); } @@ -268,7 +286,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } } Debug.Assert(loop.All(n => n == loopHead || n.Predecessors.All(p => p.Visited))); - } else { + } + else + { // We are in case 2, but could not find a suitable exit point. // Heuristically try to minimize the number of exit points // (but we'll always end up with more than 1 exit and will require goto statements). @@ -294,15 +314,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow internal ControlFlowNode FindExitPoint(ControlFlowNode loopHead, IReadOnlyList naturalLoop) { bool hasReachableExit = HasReachableExit(loopHead); - if (!hasReachableExit) { + if (!hasReachableExit) + { // Case 1: // There are no nodes n so that loopHead dominates a predecessor of n but not n itself // -> we could build a loop with zero exit points. - if (IsPossibleForeachLoop((Block)loopHead.UserData, out var exitBranch)) { - if (exitBranch != null) { + if (IsPossibleForeachLoop((Block)loopHead.UserData, out var exitBranch)) + { + if (exitBranch != null) + { // let's see if the target of the exit branch is a suitable exit point var cfgNode = loopHead.Successors.FirstOrDefault(n => n.UserData == exitBranch.TargetBlock); - if (cfgNode != null && loopHead.Dominates(cfgNode) && !context.ControlFlowGraph.HasReachableExit(cfgNode)) { + if (cfgNode != null && loopHead.Dominates(cfgNode) && !context.ControlFlowGraph.HasReachableExit(cfgNode)) + { return cfgNode; } } @@ -311,11 +335,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow ControlFlowNode exitPoint = null; int exitPointILOffset = -1; ConsiderReturnAsExitPoint((Block)loopHead.UserData, ref exitPoint, ref exitPointILOffset); - foreach (var node in loopHead.DominatorTreeChildren) { + foreach (var node in loopHead.DominatorTreeChildren) + { PickExitPoint(node, ref exitPoint, ref exitPointILOffset); } return exitPoint; - } else { + } + else + { // Case 2: // We need to pick our exit point so that all paths from the loop head // to the reachable exits run through that exit point. @@ -325,9 +352,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow //ControlFlowNode.ExportGraph(revCfg).Show("rev"); ControlFlowNode commonAncestor = revCfg[loopHead.UserIndex]; Debug.Assert(commonAncestor.IsReachable); - foreach (ControlFlowNode cfgNode in naturalLoop) { + foreach (ControlFlowNode cfgNode in naturalLoop) + { ControlFlowNode revNode = revCfg[cfgNode.UserIndex]; - if (revNode.IsReachable) { + if (revNode.IsReachable) + { commonAncestor = Dominance.FindCommonDominator(commonAncestor, revNode); } } @@ -335,12 +364,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // However, this doesn't mean that 'commonAncestor' is valid as an exit point. // We walk up the post-dominator tree until we've got a valid exit point: ControlFlowNode exitPoint; - while (commonAncestor.UserIndex >= 0) { + while (commonAncestor.UserIndex >= 0) + { exitPoint = cfg[commonAncestor.UserIndex]; Debug.Assert(exitPoint.Visited == naturalLoop.Contains(exitPoint)); // It's possible that 'commonAncestor' is itself part of the natural loop. // If so, it's not a valid exit point. - if (!exitPoint.Visited && ValidateExitPoint(loopHead, exitPoint)) { + if (!exitPoint.Visited && ValidateExitPoint(loopHead, exitPoint)) + { // we found an exit point return exitPoint; } @@ -387,16 +418,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow bool IsValid(ControlFlowNode node) { - if (!cfg.HasReachableExit(node)) { + if (!cfg.HasReachableExit(node)) + { // Optimization: if the dominance frontier is empty, we don't need // to check every node. return true; } - foreach (var succ in node.Successors) { + foreach (var succ in node.Successors) + { if (loopHead != succ && loopHead.Dominates(succ) && !exitPoint.Dominates(succ)) return false; } - foreach (var child in node.DominatorTreeChildren) { + foreach (var child in node.DominatorTreeChildren) + { if (!IsValid(child)) return false; } @@ -412,12 +446,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow bool HasReachableExit(ControlFlowNode node) => isSwitch ? loopContext.GetBreakTargets(node).Any() : context.ControlFlowGraph.HasReachableExit(node); - + /// /// Returns the children in a loop dominator tree, with an optional exit point /// Avoids returning continue statements when analysing switches (because increment blocks can be dominated) /// - IEnumerable DominatorTreeChildren(ControlFlowNode n, ControlFlowNode exitPoint) => + IEnumerable DominatorTreeChildren(ControlFlowNode n, ControlFlowNode exitPoint) => n.DominatorTreeChildren.Where(c => c != exitPoint && (!isSwitch || !loopContext.MatchContinue(c))); /// @@ -456,24 +490,27 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // moving almost all of the code into the loop. } ConsiderReturnAsExitPoint(block, ref exitPoint, ref exitPointILOffset); - foreach (var child in node.DominatorTreeChildren) { + foreach (var child in node.DominatorTreeChildren) + { PickExitPoint(child, ref exitPoint, ref exitPointILOffset); } } - + private static void ConsiderReturnAsExitPoint(Block block, ref ControlFlowNode exitPoint, ref int exitPointILOffset) { // It's possible that the real exit point of the loop is a "return;" that has been combined (by ControlFlowSimplification) // with the condition block. if (!block.MatchIfAtEndOfBlock(out _, out var trueInst, out var falseInst)) return; - if (trueInst.StartILOffset > exitPointILOffset && trueInst is Leave { IsLeavingFunction: true, Value: Nop _ }) { + if (trueInst.StartILOffset > exitPointILOffset && trueInst is Leave { IsLeavingFunction: true, Value: Nop _ }) + { // By using NoExitPoint, everything (including the "return;") becomes part of the loop body // Then DetectExitPoint will move the "return;" out of the loop body. exitPoint = NoExitPoint; exitPointILOffset = trueInst.StartILOffset; } - if (falseInst.StartILOffset > exitPointILOffset && falseInst is Leave { IsLeavingFunction: true, Value: Nop _ }) { + if (falseInst.StartILOffset > exitPointILOffset && falseInst is Leave { IsLeavingFunction: true, Value: Nop _ }) + { exitPoint = NoExitPoint; exitPointILOffset = falseInst.StartILOffset; } @@ -499,26 +536,32 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { ControlFlowNode[] cfg = context.ControlFlowGraph.cfg; ControlFlowNode[] rev = new ControlFlowNode[cfg.Length + 1]; - for (int i = 0; i < cfg.Length; i++) { + for (int i = 0; i < cfg.Length; i++) + { rev[i] = new ControlFlowNode { UserIndex = i, UserData = cfg[i].UserData }; } ControlFlowNode nodeTreatedAsExitNode = null; bool multipleNodesTreatedAsExitNodes = false; ControlFlowNode exitNode = new ControlFlowNode { UserIndex = -1 }; rev[cfg.Length] = exitNode; - for (int i = 0; i < cfg.Length; i++) { + for (int i = 0; i < cfg.Length; i++) + { if (!loopHead.Dominates(cfg[i]) || isSwitch && cfg[i] != loopHead && loopContext.MatchContinue(cfg[i])) continue; // Add reverse edges for all edges in cfg - foreach (var succ in cfg[i].Successors) { + foreach (var succ in cfg[i].Successors) + { // edges to outer loops still count as exits (labelled continue not implemented) if (isSwitch && loopContext.MatchContinue(succ, 1)) continue; - if (loopHead.Dominates(succ)) { + if (loopHead.Dominates(succ)) + { rev[succ.UserIndex].AddEdgeTo(rev[i]); - } else { + } + else + { if (nodeTreatedAsExitNode == null) nodeTreatedAsExitNode = succ; if (nodeTreatedAsExitNode != succ) @@ -526,7 +569,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow exitNode.AddEdgeTo(rev[i]); } } - if (context.ControlFlowGraph.HasDirectExitOutOfContainer(cfg[i])) { + if (context.ControlFlowGraph.HasDirectExitOutOfContainer(cfg[i])) + { exitNode.AddEdgeTo(rev[i]); } } @@ -551,7 +595,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!loopHead.Instructions[0].MatchIfInstruction(out var condition, out var trueInst)) return false; var falseInst = loopHead.Instructions[1]; - while (condition.MatchLogicNot(out var arg)) { + while (condition.MatchLogicNot(out var arg)) + { condition = arg; ExtensionMethods.Swap(ref trueInst, ref falseInst); } @@ -563,7 +608,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Check that loopHead is entry-point of try-block: Block entryPoint = container.EntryPoint; - while (entryPoint.IncomingEdgeCount == 1 && entryPoint.Instructions.Count == 1 && entryPoint.Instructions[0].MatchBranch(out var targetBlock)) { + while (entryPoint.IncomingEdgeCount == 1 && entryPoint.Instructions.Count == 1 && entryPoint.Instructions[0].MatchBranch(out var targetBlock)) + { // skip blocks that only branch to another block entryPoint = targetBlock; } @@ -590,7 +636,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void ExtendLoopHeuristic(ControlFlowNode loopHead, List loop, ControlFlowNode candidate) { Debug.Assert(candidate.Visited == loop.Contains(candidate)); - if (!candidate.Visited) { + if (!candidate.Visited) + { // This node not yet part of the loop, but might be added List additionalNodes = new List(); // Find additionalNodes nodes and mark them as visited. @@ -606,13 +653,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Measure number of added and removed exit points int removedExitPoints = additionalNodes.Count(IsExitPoint); int addedExitPoints = newExitPoints.Count(n => !IsExitPoint(n)); - if (removedExitPoints > addedExitPoints) { + if (removedExitPoints > addedExitPoints) + { // We can reduce the number of exit points by adding the candidate node to the loop. candidate.TraversePreOrder(n => n.Predecessors, loop.Add); } } // Pre-order traversal of dominator tree - foreach (var node in candidate.DominatorTreeChildren) { + foreach (var node in candidate.DominatorTreeChildren) + { ExtendLoopHeuristic(loopHead, loop, node); } } @@ -624,7 +673,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { if (node.Visited) return false; // nodes in the loop are not exit points - foreach (var pred in node.Predecessors) { + foreach (var pred in node.Predecessors) + { if (pred.Visited) return true; } @@ -655,10 +705,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow MoveBlocksIntoContainer(loop, loopContainer); // Rewrite branches within the loop from oldEntryPoint to newEntryPoint: - foreach (var branch in loopContainer.Descendants.OfType()) { - if (branch.TargetBlock == oldEntryPoint) { + foreach (var branch in loopContainer.Descendants.OfType()) + { + if (branch.TargetBlock == oldEntryPoint) + { branch.TargetBlock = newEntryPoint; - } else if (branch.TargetBlock == exitTargetBlock) { + } + else if (branch.TargetBlock == exitTargetBlock) + { branch.ReplaceWith(new Leave(loopContainer).WithILRange(branch)); } } @@ -668,19 +722,22 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { // Move other blocks into the loop body: they're all dominated by the loop header, // and thus cannot be the target of branch instructions outside the loop. - for (int i = 1; i < loop.Count; i++) { + for (int i = 1; i < loop.Count; i++) + { Block block = (Block)loop[i].UserData; // some blocks might already be in use by nested loops that were detected earlier; // don't move those (they'll be implicitly moved when the block containing the // nested loop container is moved). - if (block.Parent == currentBlockContainer) { + if (block.Parent == currentBlockContainer) + { Debug.Assert(block.ChildIndex != 0); int oldChildIndex = block.ChildIndex; loopContainer.Blocks.Add(block); currentBlockContainer.Blocks.SwapRemoveAt(oldChildIndex); } } - for (int i = 1; i < loop.Count; i++) { + for (int i = 1; i < loop.Count; i++) + { // Verify that we moved all loop blocks into the loop container. // If we wanted to move any blocks already in use by a nested loop, // this means we check that the whole nested loop got moved. @@ -703,13 +760,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow nodesInSwitch.Add(h); h.Visited = true; ExtendLoop(h, nodesInSwitch, out var exitPoint); - if (exitPoint != null && h.Dominates(exitPoint) && exitPoint.Predecessors.Count == 1 && !HasReachableExit(exitPoint)) { + if (exitPoint != null && h.Dominates(exitPoint) && exitPoint.Predecessors.Count == 1 && !HasReachableExit(exitPoint)) + { // If the exit point is reachable from just one single "break;", // it's better to move the code into the switch. // (unlike loops which should not be nested unless necessary, // nesting switches makes it clearer in which cases a piece of code is reachable) nodesInSwitch.AddRange(TreeTraversal.PreOrder(exitPoint, p => p.DominatorTreeChildren)); - foreach (var node in nodesInSwitch) { + foreach (var node in nodesInSwitch) + { node.Visited = true; } exitPoint = null; @@ -720,7 +779,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // (if the loop doesn't contain nested loops, this is a topological sort) nodesInSwitch.Sort((a, b) => b.PostOrderNumber.CompareTo(a.PostOrderNumber)); Debug.Assert(nodesInSwitch[0] == h); - foreach (var node in nodesInSwitch) { + foreach (var node in nodesInSwitch) + { node.Visited = false; // reset visited flag so that we can find outer loops Debug.Assert(h.Dominates(node), "The switch body must be dominated by the switch head"); } @@ -733,16 +793,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow block.Instructions[block.Instructions.Count - 1] = switchContainer; Block exitTargetBlock = (Block)exitPoint?.UserData; - if (exitTargetBlock != null) { + if (exitTargetBlock != null) + { block.Instructions.Add(new Branch(exitTargetBlock)); } - + switchContainer.AddILRange(newEntryPoint); MoveBlocksIntoContainer(nodesInSwitch, switchContainer); // Rewrite branches within the loop from oldEntryPoint to newEntryPoint: - foreach (var branch in switchContainer.Descendants.OfType()) { - if (branch.TargetBlock == exitTargetBlock) { + foreach (var branch in switchContainer.Descendants.OfType()) + { + if (branch.TargetBlock == exitTargetBlock) + { branch.ReplaceWith(new Leave(switchContainer).WithILRange(branch)); } } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/StateRangeAnalysis.cs b/ICSharpCode.Decompiler/IL/ControlFlow/StateRangeAnalysis.cs index 9ef815526..982706107 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/StateRangeAnalysis.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/StateRangeAnalysis.cs @@ -16,8 +16,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.Util; using System; using System.Collections.Generic; using System.Diagnostics; @@ -26,6 +24,9 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Util; + namespace ICSharpCode.Decompiler.IL.ControlFlow { enum StateRangeAnalysisMode @@ -65,7 +66,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { this.mode = mode; this.stateField = stateField; - if (mode == StateRangeAnalysisMode.IteratorDispose) { + if (mode == StateRangeAnalysisMode.IteratorDispose) + { finallyMethodToStateRange = new Dictionary(); } @@ -86,7 +88,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var sra = new StateRangeAnalysis(mode, stateField); sra.doFinallyBodies = this.doFinallyBodies; sra.skipFinallyBodies = this.skipFinallyBodies; - foreach (var v in this.evalContext.StateVariables) { + foreach (var v in this.evalContext.StateVariables) + { sra.evalContext.AddStateVariable(v); } return sra; @@ -104,13 +107,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow public LongSet AssignStateRanges(ILInstruction inst, LongSet stateRange) { CancellationToken.ThrowIfCancellationRequested(); - switch (inst) { + switch (inst) + { case BlockContainer blockContainer: AddStateRange(blockContainer.EntryPoint, stateRange); - foreach (var block in blockContainer.Blocks) { + foreach (var block in blockContainer.Blocks) + { // We assume that there are no jumps to blocks already processed. // TODO: is SortBlocks() guaranteeing this, even if the user code has loops? - if (ranges.TryGetValue(block, out stateRange)) { + if (ranges.TryGetValue(block, out stateRange)) + { AssignStateRanges(block, stateRange); } } @@ -118,7 +124,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // return LongSet.Empty. return LongSet.Empty; case Block block: - foreach (var instInBlock in block.Instructions) { + foreach (var instInBlock in block.Instructions) + { if (stateRange.IsEmpty) break; var oldStateRange = stateRange; @@ -141,7 +148,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (val.Type != SymbolicValueType.State) goto default; List exitIntervals = new List(); - foreach (var section in switchInst.Sections) { + foreach (var section in switchInst.Sections) + { // switch (state + Constant) // matches 'case VALUE:' // iff (state + Constant == value) @@ -154,7 +162,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return new LongSet(exitIntervals); case IfInstruction ifInst: val = evalContext.Eval(ifInst.Condition).AsBool(); - if (val.Type != SymbolicValueType.StateInSet) { + if (val.Type != SymbolicValueType.StateInSet) + { goto default; } LongSet trueRanges = val.ValueSet; @@ -173,10 +182,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return stateRange; case StLoc stloc: val = evalContext.Eval(stloc.Value); - if (val.Type == SymbolicValueType.State && val.Constant == 0) { + if (val.Type == SymbolicValueType.State && val.Constant == 0) + { evalContext.AddStateVariable(stloc.Variable); return stateRange; - } else { + } + else + { goto default; // user code } case Call call when mode == StateRangeAnalysisMode.IteratorDispose: @@ -186,20 +198,23 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow finallyMethodToStateRange.Add((IMethod)call.Method.MemberDefinition, stateRange); return LongSet.Empty; // return Empty since we executed user code (the finally method) case StObj stobj when mode == StateRangeAnalysisMode.IteratorMoveNext: + { + if (stobj.MatchStFld(out var target, out var field, out var value) + && target.MatchLdThis() && field.MemberDefinition == stateField && value.MatchLdcI4(-1)) { - if (stobj.MatchStFld(out var target, out var field, out var value) - && target.MatchLdThis() && field.MemberDefinition == stateField && value.MatchLdcI4(-1)) - { - // Mono resets the state field during MoveNext(); - // don't consider this user code. - return stateRange; - } else { - goto default; - } + // Mono resets the state field during MoveNext(); + // don't consider this user code. + return stateRange; } + else + { + goto default; + } + } default: // User code - abort analysis - if (mode == StateRangeAnalysisMode.IteratorDispose && !(inst is Leave l && l.IsLeavingFunction)) { + if (mode == StateRangeAnalysisMode.IteratorDispose && !(inst is Leave l && l.IsLeavingFunction)) + { throw new SymbolicAnalysisFailedException("Unexpected instruction in Iterator.Dispose()"); } return LongSet.Empty; @@ -228,13 +243,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow IEnumerable<(LongSet, Block)> GetMapping() { // First, consider container exits: - foreach (var (block, states) in ranges) { + foreach (var (block, states) in ranges) + { if (block.Parent != container) yield return (states, block); } // Then blocks within the container: - foreach (var block in container.Blocks.Reverse()) { - if (ranges.TryGetValue(block, out var states)) { + foreach (var block in container.Blocks.Reverse()) + { + if (ranges.TryGetValue(block, out var states)) + { yield return (states, block); } } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs index bc9b39b77..61b015af1 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs @@ -1,9 +1,10 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; -using System; -using System.Linq; namespace ICSharpCode.Decompiler.IL.ControlFlow { @@ -56,7 +57,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// Blocks that can be deleted if the tail of the initial block is replaced with a switch instruction. /// public readonly List InnerBlocks = new List(); - + public Block RootBlock { get; private set; } /// @@ -97,13 +98,17 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// If false, analyze the whole block. bool AnalyzeBlock(Block block, LongSet inputValues, bool tailOnly = false) { - if (block.Instructions.Count == 0) { + if (block.Instructions.Count == 0) + { // might happen if the block was already marked for deletion in SwitchDetection return false; } - if (tailOnly) { + if (tailOnly) + { Debug.Assert(block == RootBlock); - } else { + } + else + { Debug.Assert(switchVar != null); // switchVar should always be determined by the top-level call if (block.IncomingEdgeCount != 1 || block == RootBlock) return false; // for now, let's only consider if-structures that form a tree @@ -114,40 +119,54 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (block.Instructions.Count >= 2 && block.Instructions[block.Instructions.Count - 2].MatchIfInstruction(out var condition, out var trueInst) && AnalyzeCondition(condition, out trueValues) - ) { + ) + { if (!(tailOnly || block.Instructions.Count == 2)) return false; trueValues = trueValues.IntersectWith(inputValues); if (trueValues.SetEquals(inputValues) || trueValues.IsEmpty) return false; Block trueBlock; - if (trueInst.MatchBranch(out trueBlock) && AnalyzeBlock(trueBlock, trueValues)) { + if (trueInst.MatchBranch(out trueBlock) && AnalyzeBlock(trueBlock, trueValues)) + { // OK, true block was further analyzed. InnerBlocks.Add(trueBlock); - } else { + } + else + { // Create switch section for trueInst. AddSection(trueValues, trueInst); } - } else if (block.Instructions.Last() is SwitchInstruction switchInst) { + } + else if (block.Instructions.Last() is SwitchInstruction switchInst) + { if (!(tailOnly || block.Instructions.Count == 1)) return false; - if (AnalyzeSwitch(switchInst, inputValues)) { + if (AnalyzeSwitch(switchInst, inputValues)) + { ContainsILSwitch = true; // OK return true; - } else { // switch analysis failed (e.g. switchVar mismatch) + } + else + { // switch analysis failed (e.g. switchVar mismatch) return false; } - } else { // unknown inst + } + else + { // unknown inst return false; } var remainingValues = inputValues.ExceptWith(trueValues); ILInstruction falseInst = block.Instructions.Last(); Block falseBlock; - if (falseInst.MatchBranch(out falseBlock) && AnalyzeBlock(falseBlock, remainingValues)) { + if (falseInst.MatchBranch(out falseBlock) && AnalyzeBlock(falseBlock, remainingValues)) + { // OK, false block was further analyzed. InnerBlocks.Add(falseBlock); - } else { + } + else + { // Create switch section for falseInst. AddSection(remainingValues, falseInst); } @@ -158,13 +177,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { Debug.Assert(!inst.IsLifted); long offset; - if (MatchSwitchVar(inst.Value)) { + if (MatchSwitchVar(inst.Value)) + { offset = 0; - } else if (inst.Value is BinaryNumericInstruction bop) { + } + else if (inst.Value is BinaryNumericInstruction bop) + { if (bop.CheckForOverflow) return false; - if (MatchSwitchVar(bop.Left) && bop.Right.MatchLdcI(out long val)) { - switch (bop.Operator) { + if (MatchSwitchVar(bop.Left) && bop.Right.MatchLdcI(out long val)) + { + switch (bop.Operator) + { case BinaryNumericOperator.Add: offset = unchecked(-val); break; @@ -174,25 +198,33 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow default: // unknown bop.Operator return false; } - } else { // unknown bop.Left + } + else + { // unknown bop.Left return false; } - } else { // unknown inst.Value + } + else + { // unknown inst.Value return false; } - foreach (var section in inst.Sections) { + foreach (var section in inst.Sections) + { var matchValues = section.Labels.AddOffset(offset).IntersectWith(inputValues); if (!AllowUnreachableCases && matchValues.IsEmpty) return false; - if (matchValues.Count() > 1 && section.Body.MatchBranch(out var targetBlock) && AnalyzeBlock(targetBlock, matchValues)) { + if (matchValues.Count() > 1 && section.Body.MatchBranch(out var targetBlock) && AnalyzeBlock(targetBlock, matchValues)) + { InnerBlocks.Add(targetBlock); - } else { + } + else + { AddSection(matchValues, section.Body); } } return true; } - + /// /// Adds a new section to the Sections list. /// @@ -201,30 +233,42 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// void AddSection(LongSet values, ILInstruction inst) { - if (values.IsEmpty) { + if (values.IsEmpty) + { return; } - if (inst.MatchBranch(out Block targetBlock)) { - if (targetBlockToSectionIndex.TryGetValue(targetBlock, out int index)) { + if (inst.MatchBranch(out Block targetBlock)) + { + if (targetBlockToSectionIndex.TryGetValue(targetBlock, out int index)) + { Sections[index] = new KeyValuePair( Sections[index].Key.UnionWith(values), inst ); - } else { + } + else + { targetBlockToSectionIndex.Add(targetBlock, Sections.Count); Sections.Add(new KeyValuePair(values, inst)); } - } else if (inst.MatchLeave(out BlockContainer targetContainer)) { - if (targetContainerToSectionIndex.TryGetValue(targetContainer, out int index)) { + } + else if (inst.MatchLeave(out BlockContainer targetContainer)) + { + if (targetContainerToSectionIndex.TryGetValue(targetContainer, out int index)) + { Sections[index] = new KeyValuePair( Sections[index].Key.UnionWith(values), inst ); - } else { + } + else + { targetContainerToSectionIndex.Add(targetContainer, Sections.Count); Sections.Add(new KeyValuePair(values, inst)); } - } else { + } + else + { Sections.Add(new KeyValuePair(values, inst)); } } @@ -257,21 +301,28 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// private bool AnalyzeCondition(ILInstruction condition, out LongSet trueValues) { - if (condition is Comp comp && MatchSwitchVar(comp.Left, out var sub) && comp.Right.MatchLdcI(out long val)) { + if (condition is Comp comp && MatchSwitchVar(comp.Left, out var sub) && comp.Right.MatchLdcI(out long val)) + { // if (comp((V - sub) OP val)) trueValues = MakeSetWhereComparisonIsTrue(comp.Kind, val, comp.Sign); trueValues = trueValues.AddOffset(sub); return true; - } else if (MatchSwitchVar(condition)) { + } + else if (MatchSwitchVar(condition)) + { // if (ldloc V) --> branch for all values except 0 trueValues = new LongSet(0).Invert(); return true; - } else if (condition.MatchLogicNot(out ILInstruction arg)) { + } + else if (condition.MatchLogicNot(out ILInstruction arg)) + { // if (logic.not(X)) --> branch for all values where if (X) does not branch bool res = AnalyzeCondition(arg, out LongSet falseValues); trueValues = falseValues.Invert(); return res; - } else { + } + else + { trueValues = LongSet.Empty; return false; } @@ -282,7 +333,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// internal static LongSet MakeSetWhereComparisonIsTrue(ComparisonKind kind, long val, Sign sign) { - switch (kind) { + switch (kind) + { case ComparisonKind.Equality: return new LongSet(val); case ComparisonKind.Inequality: @@ -302,16 +354,22 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private static LongSet MakeGreaterThanOrEqualSet(long val, Sign sign) { - if (sign == Sign.Signed) { + if (sign == Sign.Signed) + { return new LongSet(LongInterval.Inclusive(val, long.MaxValue)); - } else { + } + else + { Debug.Assert(sign == Sign.Unsigned); - if (val >= 0) { + if (val >= 0) + { // The range val to ulong.MaxValue expressed with signed longs // is not a single contiguous range, but two ranges: return new LongSet(LongInterval.Inclusive(val, long.MaxValue)) .UnionWith(new LongSet(new LongInterval(long.MinValue, 0))); - } else { + } + else + { return new LongSet(new LongInterval(val, 0)); } } @@ -319,13 +377,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private static LongSet MakeLessThanOrEqualSet(long val, Sign sign) { - if (sign == Sign.Signed) { + if (sign == Sign.Signed) + { return new LongSet(LongInterval.Inclusive(long.MinValue, val)); - } else { + } + else + { Debug.Assert(sign == Sign.Unsigned); - if (val >= 0) { + if (val >= 0) + { return new LongSet(LongInterval.Inclusive(0, val)); - } else { + } + else + { // The range 0 to (ulong)val expressed with signed longs // is not a single contiguous range, but two ranges: return new LongSet(LongInterval.Inclusive(0, long.MaxValue)) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs index aaaf64bec..2e2f2e3c6 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs @@ -16,15 +16,16 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using ICSharpCode.Decompiler.IL.Transforms; using System; using System.Collections.Generic; -using System.Linq; using System.Diagnostics; +using System.Linq; + +using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.FlowAnalysis; -using ICSharpCode.Decompiler.Util; +using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.CSharp.Transforms; +using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL.ControlFlow { @@ -89,30 +90,32 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return loopHead; // match for loop increment block - if (pred.Successors.Count == 1) { - if (HighLevelLoopTransform.MatchIncrementBlock((Block)pred.UserData, out var target) &&target == loopHead.UserData) + if (pred.Successors.Count == 1) + { + if (HighLevelLoopTransform.MatchIncrementBlock((Block)pred.UserData, out var target) && target == loopHead.UserData) return pred; } // match do-while condition - if (pred.Successors.Count <= 2) { + if (pred.Successors.Count <= 2) + { if (HighLevelLoopTransform.MatchDoWhileConditionBlock((Block)pred.UserData, out var t1, out var t2) && - (t1 == loopHead.UserData || t2 == loopHead.UserData)) + (t1 == loopHead.UserData || t2 == loopHead.UserData)) return pred; } return loopHead; } - + public bool MatchContinue(ControlFlowNode node) => MatchContinue(node, out var _); - public bool MatchContinue(ControlFlowNode node, int depth) => + public bool MatchContinue(ControlFlowNode node, int depth) => MatchContinue(node, out int _depth) && depth == _depth; public bool MatchContinue(ControlFlowNode node, out int depth) => continueDepth.TryGetValue(node, out depth); public int GetContinueDepth(ControlFlowNode node) => MatchContinue(node, out var depth) ? depth : 0; - + /// /// Lists all potential targets for break; statements from a domination tree, /// assuming the domination tree must be exited via either break; or continue; @@ -123,7 +126,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// Note that node will be returned once for each outgoing edge. /// Labelled continue statements (depth > 1) are counted as break targets /// - internal IEnumerable GetBreakTargets(ControlFlowNode dominator) => + internal IEnumerable GetBreakTargets(ControlFlowNode dominator) => TreeTraversal.PreOrder(dominator, n => n.DominatorTreeChildren.Where(c => !MatchContinue(c))) .SelectMany(n => n.Successors) .Where(n => !dominator.Dominates(n) && !MatchContinue(n, 1)); @@ -135,16 +138,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow analysis.AllowUnreachableCases = context.Settings.RemoveDeadCode; - foreach (var container in function.Descendants.OfType()) { + foreach (var container in function.Descendants.OfType()) + { currentContainer = container; controlFlowGraph = null; bool blockContainerNeedsCleanup = false; - foreach (var block in container.Blocks) { + foreach (var block in container.Blocks) + { context.CancellationToken.ThrowIfCancellationRequested(); ProcessBlock(block, ref blockContainerNeedsCleanup); } - if (blockContainerNeedsCleanup) { + if (blockContainerNeedsCleanup) + { Debug.Assert(container.Blocks.All(b => b.Instructions.Count != 0 || b.IncomingEdgeCount == 0)); // if the original code has an unreachable switch-like condition @@ -161,33 +167,40 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void ProcessBlock(Block block, ref bool blockContainerNeedsCleanup) { bool analysisSuccess = analysis.AnalyzeBlock(block); - if (analysisSuccess && UseCSharpSwitch(out _)) { + if (analysisSuccess && UseCSharpSwitch(out _)) + { // complex multi-block switch that can be combined into a single SwitchInstruction ILInstruction switchValue = new LdLoc(analysis.SwitchVariable); Debug.Assert(switchValue.ResultType.IsIntegerType() || switchValue.ResultType == StackType.Unknown); - if (!(switchValue.ResultType == StackType.I4 || switchValue.ResultType == StackType.I8)) { + if (!(switchValue.ResultType == StackType.I4 || switchValue.ResultType == StackType.I8)) + { // switchValue must have a result type of either I4 or I8 switchValue = new Conv(switchValue, PrimitiveType.I8, false, Sign.Signed); } var sw = new SwitchInstruction(switchValue); - foreach (var section in analysis.Sections) { + foreach (var section in analysis.Sections) + { sw.Sections.Add(new SwitchSection { Labels = section.Key, Body = section.Value }); } - if (block.Instructions.Last() is SwitchInstruction) { + if (block.Instructions.Last() is SwitchInstruction) + { // we'll replace the switch - } else { + } + else + { Debug.Assert(block.Instructions.SecondToLastOrDefault() is IfInstruction); // Remove branch/leave after if; it's getting moved into a section. block.Instructions.RemoveAt(block.Instructions.Count - 1); } sw.AddILRange(block.Instructions[block.Instructions.Count - 1]); block.Instructions[block.Instructions.Count - 1] = sw; - + // mark all inner blocks that were converted to the switch statement for deletion - foreach (var innerBlock in analysis.InnerBlocks) { + foreach (var innerBlock in analysis.InnerBlocks) + { Debug.Assert(innerBlock.Parent == block.Parent); Debug.Assert(innerBlock != ((BlockContainer)block.Parent).EntryPoint); innerBlock.Instructions.Clear(); @@ -196,7 +209,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow controlFlowGraph = null; // control flow graph is no-longer valid blockContainerNeedsCleanup = true; SortSwitchSections(sw); - } else { + } + else + { // 2nd pass of SimplifySwitchInstruction (after duplicating return blocks), // (1st pass was in ControlFlowSimplification) SimplifySwitchInstruction(block, context); @@ -218,12 +233,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var dict = new Dictionary(); // branch target -> switch section sw.Sections.RemoveAll( section => { - if (section.Body.MatchBranch(out Block target)) { - if (dict.TryGetValue(target, out SwitchSection primarySection)) { + if (section.Body.MatchBranch(out Block target)) + { + if (dict.TryGetValue(target, out SwitchSection primarySection)) + { primarySection.Labels = primarySection.Labels.UnionWith(section.Labels); primarySection.HasNullLabel |= section.HasNullLabel; return true; // remove this section - } else { + } + else + { dict.Add(target, section); } } @@ -244,11 +263,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow static void AdjustLabels(SwitchInstruction sw, ILTransformContext context) { - if (sw.Value is BinaryNumericInstruction bop && !bop.CheckForOverflow && bop.Right.MatchLdcI(out long val)) { + if (sw.Value is BinaryNumericInstruction bop && !bop.CheckForOverflow && bop.Right.MatchLdcI(out long val)) + { // Move offset into labels: context.Step("Move offset into switch labels", bop); long offset; - switch (bop.Operator) { + switch (bop.Operator) + { case BinaryNumericOperator.Add: offset = unchecked(-val); break; @@ -259,7 +280,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return; } sw.Value = bop.Left; - foreach (var section in sw.Sections) { + foreach (var section in sw.Sections) + { section.Labels = section.Labels.AddOffset(offset); } } @@ -272,18 +294,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// private bool UseCSharpSwitch(out KeyValuePair defaultSection) { - if (!analysis.InnerBlocks.Any()) { + if (!analysis.InnerBlocks.Any()) + { defaultSection = default; return false; } defaultSection = analysis.Sections.FirstOrDefault(s => s.Key.Count() > MaxValuesPerSection); - if (defaultSection.Value == null) { + if (defaultSection.Value == null) + { // no default section found? // This should never happen, as we'd need 2^64/MaxValuesPerSection sections to hit this case... return false; } var defaultSectionKey = defaultSection.Key; - if (analysis.Sections.Any(s => !s.Key.SetEquals(defaultSectionKey) && s.Key.Count() > MaxValuesPerSection)) { + if (analysis.Sections.Any(s => !s.Key.SetEquals(defaultSectionKey) && s.Key.Count() > MaxValuesPerSection)) + { // Only the default section is allowed to have tons of keys. // C# doesn't support "case 1 to 100000000", and we don't want to generate // gigabytes of case labels. @@ -293,13 +318,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // good enough indicator that the surrounding code also forms a switch statement if (analysis.ContainsILSwitch || MatchRoslynSwitchOnString()) return true; - + // heuristic to determine if a block would be better represented as an if statement rather than switch int ifCount = analysis.InnerBlocks.Count + 1; int intervalCount = analysis.Sections.Where(s => !s.Key.SetEquals(defaultSectionKey)).Sum(s => s.Key.Intervals.Length); if (ifCount < intervalCount) return false; - + (var flowNodes, var caseNodes) = AnalyzeControlFlow(); // don't create switch statements with only one non-default label when the corresponding condition tree is flat @@ -307,7 +332,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // for example, a loop condition: while (c == '\n' || c == '\r') if (analysis.Sections.Count == 2 && IsSingleCondition(flowNodes, caseNodes)) return false; - + // if there is no ILSwitch, there's still many control flow patterns that // match a switch statement but were originally just regular if statements, // and converting them to switches results in poor quality code with goto statements @@ -345,7 +370,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { if (controlFlowGraph == null) controlFlowGraph = new ControlFlowGraph(currentContainer, context.CancellationToken); - + var switchHead = controlFlowGraph.GetNode(analysis.RootBlock); loopContext = new LoopContext(controlFlowGraph, switchHead); @@ -354,11 +379,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // grab the control flow nodes for blocks targetted by each section var caseNodes = new List(); - foreach (var s in analysis.Sections) { - if (!s.Value.MatchBranch(out var block)) + foreach (var s in analysis.Sections) + { + if (!s.Value.MatchBranch(out var block)) continue; - if (block.Parent == currentContainer) { + if (block.Parent == currentContainer) + { var node = controlFlowGraph.GetNode(block); if (!loopContext.MatchContinue(node)) caseNodes.Add(node); @@ -385,7 +412,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow breakBlock = null; if (externalCases.Count > 1) return true; // cannot have more than one break case without gotos - + // check that case nodes flow through a single point var breakTargets = caseNodes.Except(externalCases).SelectMany(n => loopContext.GetBreakTargets(n)).ToHashSet(); @@ -393,8 +420,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // if there are none, then the external case (if any) can be the break target if (breakTargets.Count != 1) return breakTargets.Count > 1; - - breakBlock = (Block) breakTargets.Single().UserData; + + breakBlock = (Block)breakTargets.Single().UserData; // external case must consist of a single "break;" return externalCases.Count == 1 && breakBlock != externalCases.Single().UserData; @@ -408,18 +435,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { if (analysis.RootBlock.IncomingEdgeCount != 1) return; - + // if (comp(logic.not(call get_HasValue(ldloca nullableVar))) br NullCase // br RootBlock var nullableBlock = (Block)controlFlowGraph.GetNode(analysis.RootBlock).Predecessors.SingleOrDefault()?.UserData; if (nullableBlock == null || - nullableBlock.Instructions.Count < 2 || - !nullableBlock.Instructions.Last().MatchBranch(analysis.RootBlock) || - !nullableBlock.Instructions.SecondToLastOrDefault().MatchIfInstruction(out var cond, out var trueInst) || - !cond.MatchLogicNot(out var getHasValue) || - !NullableLiftingTransform.MatchHasValueCall(getHasValue, out ILInstruction nullableInst)) + nullableBlock.Instructions.Count < 2 || + !nullableBlock.Instructions.Last().MatchBranch(analysis.RootBlock) || + !nullableBlock.Instructions.SecondToLastOrDefault().MatchIfInstruction(out var cond, out var trueInst) || + !cond.MatchLogicNot(out var getHasValue) || + !NullableLiftingTransform.MatchHasValueCall(getHasValue, out ILInstruction nullableInst)) return; - + // could check that nullableInst is ldloc or ldloca and that the switch variable matches a GetValueOrDefault // but the effect of adding an incorrect block to the flowBlock list would only be disasterous if it branched directly // to a candidate case block @@ -486,15 +513,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // search down the tree, marking nodes as visited while they continue the current condition var n = rootNode; - while (n.Successors.Count > 0 && (n == rootNode || IsFlowNode(n))) { - if (n.Successors.Count == 1) { + while (n.Successors.Count > 0 && (n == rootNode || IsFlowNode(n))) + { + if (n.Successors.Count == 1) + { // if there is more than one case node, then a flow node with only one successor is not part of the initial condition if (caseNodes.Count > 1) break; - + n = n.Successors[0]; } - else { // 2 successors + else + { // 2 successors if (IsShortCircuit(n, 0)) n = n.Successors[0]; else if (IsShortCircuit(n, 1)) @@ -502,7 +532,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow else break; } - + n.Visited = true; if (loopContext.MatchContinue(n)) break; diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/SymbolicExecution.cs b/ICSharpCode.Decompiler/IL/ControlFlow/SymbolicExecution.cs index 9d406f3aa..4bd88cade 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/SymbolicExecution.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/SymbolicExecution.cs @@ -16,14 +16,15 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.Util; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Util; + namespace ICSharpCode.Decompiler.IL.ControlFlow { /// @@ -81,7 +82,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow public SymbolicValue AsBool() { - if (Type == SymbolicValueType.State) { + if (Type == SymbolicValueType.State) + { // convert state integer to bool: // if (state + c) = if (state + c != 0) = if (state != -c) return new SymbolicValue(SymbolicValueType.StateInSet, new LongSet(unchecked(-Constant)).Invert()); @@ -109,14 +111,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!stateVariables.Contains(v)) stateVariables.Add(v); } - + public IEnumerable StateVariables { get => stateVariables; } static readonly SymbolicValue Failed = new SymbolicValue(SymbolicValueType.Unknown); public SymbolicValue Eval(ILInstruction inst) { - if (inst is BinaryNumericInstruction bni && bni.Operator == BinaryNumericOperator.Sub && !bni.CheckForOverflow) { + if (inst is BinaryNumericInstruction bni && bni.Operator == BinaryNumericOperator.Sub && !bni.CheckForOverflow) + { var left = Eval(bni.Left); var right = Eval(bni.Right); if (left.Type != SymbolicValueType.State && left.Type != SymbolicValueType.IntegerConstant) @@ -124,45 +127,65 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (right.Type != SymbolicValueType.IntegerConstant) return Failed; return new SymbolicValue(left.Type, unchecked(left.Constant - right.Constant)); - } else if (inst.MatchLdFld(out var target, out var field)) { + } + else if (inst.MatchLdFld(out var target, out var field)) + { if (Eval(target).Type != SymbolicValueType.This) return Failed; if (field.MemberDefinition != stateField) return Failed; return new SymbolicValue(SymbolicValueType.State); - } else if (inst.MatchLdLoc(out var loadedVariable)) { + } + else if (inst.MatchLdLoc(out var loadedVariable)) + { if (stateVariables.Contains(loadedVariable)) return new SymbolicValue(SymbolicValueType.State); else if (loadedVariable.Kind == VariableKind.Parameter && loadedVariable.Index < 0) return new SymbolicValue(SymbolicValueType.This); else return Failed; - } else if (inst.MatchLdcI4(out var value)) { + } + else if (inst.MatchLdcI4(out var value)) + { return new SymbolicValue(SymbolicValueType.IntegerConstant, value); - } else if (inst is Comp comp) { + } + else if (inst is Comp comp) + { var left = Eval(comp.Left); var right = Eval(comp.Right); - if (left.Type == SymbolicValueType.State && right.Type == SymbolicValueType.IntegerConstant) { + if (left.Type == SymbolicValueType.State && right.Type == SymbolicValueType.IntegerConstant) + { // bool: (state + left.Constant == right.Constant) LongSet trueSums = SwitchAnalysis.MakeSetWhereComparisonIsTrue(comp.Kind, right.Constant, comp.Sign); // symbolic value is true iff trueSums.Contains(state + left.Constant) LongSet trueStates = trueSums.AddOffset(unchecked(-left.Constant)); // symbolic value is true iff trueStates.Contains(state) return new SymbolicValue(SymbolicValueType.StateInSet, trueStates); - } else if (left.Type == SymbolicValueType.StateInSet && right.Type == SymbolicValueType.IntegerConstant) { - if (comp.Kind == ComparisonKind.Equality && right.Constant == 0) { + } + else if (left.Type == SymbolicValueType.StateInSet && right.Type == SymbolicValueType.IntegerConstant) + { + if (comp.Kind == ComparisonKind.Equality && right.Constant == 0) + { // comp((x in set) == 0) ==> x not in set return new SymbolicValue(SymbolicValueType.StateInSet, left.ValueSet.Invert()); - } else if (comp.Kind == ComparisonKind.Inequality && right.Constant != 0) { + } + else if (comp.Kind == ComparisonKind.Inequality && right.Constant != 0) + { // comp((x in set) != 0) => x in set return new SymbolicValue(SymbolicValueType.StateInSet, left.ValueSet); - } else { + } + else + { return Failed; } - } else { + } + else + { return Failed; } - } else { + } + else + { return Failed; } } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs index ca6314a74..fc98e4b43 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs @@ -16,16 +16,17 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using ICSharpCode.Decompiler.CSharp; -using ICSharpCode.Decompiler.IL.Transforms; -using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.Util; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; +using ICSharpCode.Decompiler.CSharp; +using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Util; + namespace ICSharpCode.Decompiler.IL.ControlFlow { public class YieldReturnDecompiler : IILTransform @@ -88,7 +89,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// and the decompiled code of the finally method body. /// readonly Dictionary decompiledFinallyMethods = new Dictionary(); - + /// /// Temporary stores for 'yield break'. /// @@ -126,13 +127,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!MatchEnumeratorCreationPattern(function)) return; BlockContainer newBody; - try { + try + { AnalyzeCtor(); AnalyzeCurrentProperty(); ResolveIEnumerableIEnumeratorFieldMapping(); ConstructExceptionTable(); newBody = AnalyzeMoveNext(function); - } catch (SymbolicAnalysisFailedException) { + } + catch (SymbolicAnalysisFailedException) + { return; } @@ -146,15 +150,18 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow PrintFinallyMethodStateRanges(newBody); // Add state machine field meta-data to parameter ILVariables. - foreach (var (f, p) in fieldToParameterMap) { + foreach (var (f, p) in fieldToParameterMap) + { p.StateMachineField = f; } context.Step("Delete unreachable blocks", function); - if (isCompiledWithMono) { + if (isCompiledWithMono) + { // mono has try-finally inline (like async on MS); we also need to sort nested blocks: - foreach (var nestedContainer in newBody.Blocks.SelectMany(c => c.Descendants).OfType()) { + foreach (var nestedContainer in newBody.Blocks.SelectMany(c => c.Descendants).OfType()) + { nestedContainer.SortBlocks(deleteUnreachableBlocks: true); } // We need to clean up nested blocks before the main block, so that edges from unreachable code @@ -165,7 +172,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow newBody.SortBlocks(deleteUnreachableBlocks: true); function.CheckInvariant(ILPhase.Normal); - if (!isCompiledWithMono) { + if (!isCompiledWithMono) + { DecompileFinallyBlocks(); ReconstructTryFinallyBlocks(function); } @@ -176,19 +184,25 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow CleanSkipFinallyBodies(function); // On mono, we still need to remove traces of the state variable(s): - if (isCompiledWithMono) { - if (fieldToParameterMap.TryGetValue(stateField, out var stateVar)) { + if (isCompiledWithMono) + { + if (fieldToParameterMap.TryGetValue(stateField, out var stateVar)) + { returnStores.AddRange(stateVar.StoreInstructions.OfType()); } - foreach (var cachedStateVar in cachedStateVars) { + foreach (var cachedStateVar in cachedStateVars) + { returnStores.AddRange(cachedStateVar.StoreInstructions.OfType()); } } - if (returnStores.Count > 0) { + if (returnStores.Count > 0) + { context.Step("Remove temporaries", function); - foreach (var store in returnStores) { - if (store.Variable.LoadCount == 0 && store.Variable.AddressCount == 0 && store.Parent is Block block) { + foreach (var store in returnStores) + { + if (store.Variable.LoadCount == 0 && store.Variable.AddressCount == 0 && store.Parent is Block block) + { Debug.Assert(SemanticHelper.IsPure(store.Value.Flags)); block.Instructions.Remove(store); } @@ -205,22 +219,29 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow bool MatchEnumeratorCreationPattern(ILFunction function) { Block body = SingleBlock(function.Body); - if (body == null || body.Instructions.Count == 0) { + if (body == null || body.Instructions.Count == 0) + { return false; } ILInstruction newObj; - if (body.Instructions.Count == 1) { + if (body.Instructions.Count == 1) + { // No parameters passed to enumerator (not even 'this'): // ret(newobj(...)) if (!body.Instructions[0].MatchReturn(out newObj)) return false; - if (MatchEnumeratorCreationNewObj(newObj)) { + if (MatchEnumeratorCreationNewObj(newObj)) + { return true; - } else if (MatchMonoEnumeratorCreationNewObj(newObj)) { + } + else if (MatchMonoEnumeratorCreationNewObj(newObj)) + { isCompiledWithMono = true; return true; - } else { + } + else + { return false; } } @@ -233,41 +254,55 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // stloc(var_1, newobj(..)) if (!body.Instructions[pos].MatchStLoc(out var var1, out newObj)) return false; - if (MatchEnumeratorCreationNewObj(newObj)) { + if (MatchEnumeratorCreationNewObj(newObj)) + { pos++; // OK isCompiledWithMono = false; - } else if (MatchMonoEnumeratorCreationNewObj(newObj)) { + } + else if (MatchMonoEnumeratorCreationNewObj(newObj)) + { pos++; isCompiledWithMono = true; - } else { + } + else + { return false; } - - for (; pos < body.Instructions.Count; pos++) { + + for (; pos < body.Instructions.Count; pos++) + { // stfld(..., ldloc(var_1), ldloc(parameter)) // or (in structs): stfld(..., ldloc(var_1), ldobj(ldloc(this))) if (!body.Instructions[pos].MatchStFld(out var ldloc, out var storedField, out var value)) break; - if (!ldloc.MatchLdLoc(var1)) { + if (!ldloc.MatchLdLoc(var1)) + { return false; } - if (value.MatchLdLoc(out var parameter) && parameter.Kind == VariableKind.Parameter) { + if (value.MatchLdLoc(out var parameter) && parameter.Kind == VariableKind.Parameter) + { fieldToParameterMap[(IField)storedField.MemberDefinition] = parameter; - } else if (value is LdObj ldobj && ldobj.Target.MatchLdThis()) { + } + else if (value is LdObj ldobj && ldobj.Target.MatchLdThis()) + { // copy of 'this' in struct fieldToParameterMap[(IField)storedField.MemberDefinition] = ((LdLoc)ldobj.Target).Variable; - } else { + } + else + { return false; } } // In debug builds, the compiler may copy the var1 into another variable (var2) before returning it. if (body.Instructions[pos].MatchStLoc(out var var2, out var ldlocForStloc2) - && ldlocForStloc2.MatchLdLoc(var1)) { + && ldlocForStloc2.MatchLdLoc(var1)) + { // stloc(var_2, ldloc(var_1)) pos++; } - if (isCompiledWithMono) { + if (isCompiledWithMono) + { // Mono initializes the state field separately: // (but not if it's left at the default value 0) if (body.Instructions[pos].MatchStFld(out var target, out var field, out var value) @@ -280,10 +315,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } } if (body.Instructions[pos].MatchReturn(out var retVal) - && retVal.MatchLdLoc(var2 ?? var1)) { + && retVal.MatchLdLoc(var2 ?? var1)) + { // ret(ldloc(var_2)) return true; - } else { + } + else + { return false; } } @@ -294,7 +332,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow internal static Block SingleBlock(ILInstruction body) { var block = body as Block; - if (body is BlockContainer blockContainer && blockContainer.Blocks.Count == 1) { + if (body is BlockContainer blockContainer && blockContainer.Blocks.Count == 1) + { block = blockContainer.Blocks.Single() as Block; } return block; @@ -309,7 +348,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow out enumeratorCtor, out enumeratorType); } - internal static bool MatchEnumeratorCreationNewObj(ILInstruction inst, + internal static bool MatchEnumeratorCreationNewObj(ILInstruction inst, MetadataReader metadata, TypeDefinitionHandle currentType, out MethodDefinitionHandle enumeratorCtor, out TypeDefinitionHandle enumeratorType) { @@ -350,7 +389,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow TypeDefinition td; if (type.IsNil || !type.IsCompilerGeneratedOrIsInCompilerGeneratedClass(metadata) || (td = metadata.GetTypeDefinition(type)).GetDeclaringType().IsNil) return false; - foreach (var i in td.GetInterfaceImplementations()) { + foreach (var i in td.GetInterfaceImplementations()) + { var tr = metadata.GetInterfaceImplementation(i).Interface.GetFullTypeName(metadata); if (!tr.IsNested && tr.TopLevelTypeName.Namespace == "System.Collections" && tr.TopLevelTypeName.Name == "IEnumerator") return true; @@ -368,11 +408,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow Block body = SingleBlock(CreateILAst(enumeratorCtor, context).Body); if (body == null) throw new SymbolicAnalysisFailedException("Missing enumeratorCtor.Body"); - foreach (var inst in body.Instructions) { + foreach (var inst in body.Instructions) + { if (inst.MatchStFld(out var target, out var field, out var value) && target.MatchLdThis() && value.MatchLdLoc(out var arg) - && arg.Kind == VariableKind.Parameter && arg.Index == 0) { + && arg.Kind == VariableKind.Parameter && arg.Index == 0) + { stateField = (IField)field.MemberDefinition; } } @@ -422,15 +464,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow Block body = SingleBlock(CreateILAst(getCurrentMethod, context).Body); if (body == null) throw new SymbolicAnalysisFailedException(); - if (body.Instructions.Count == 1) { + if (body.Instructions.Count == 1) + { // release builds directly return the current field // ret(ldfld F(ldloc(this))) if (body.Instructions[0].MatchReturn(out var retVal) && retVal.MatchLdFld(out var target, out var field) - && target.MatchLdThis()) { + && target.MatchLdThis()) + { currentField = (IField)field.MemberDefinition; } - } else if (body.Instructions.Count == 2) { + } + else if (body.Instructions.Count == 2) + { // debug builds store the return value in a temporary // stloc V = ldfld F(ldloc(this)) // ret(ldloc V) @@ -438,7 +484,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow && ldfld.MatchLdFld(out var target, out var field) && target.MatchLdThis() && body.Instructions[1].MatchReturn(out var retVal) - && retVal.MatchLdLoc(v)) { + && retVal.MatchLdLoc(v)) + { currentField = (IField)field.MemberDefinition; } } @@ -462,12 +509,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (getEnumeratorMethod.IsNil) return; // no mappings (maybe it's just an IEnumerator implementation?) var function = CreateILAst(getEnumeratorMethod, context); - foreach (var block in function.Descendants.OfType()) { - foreach (var inst in block.Instructions) { + foreach (var block in function.Descendants.OfType()) + { + foreach (var inst in block.Instructions) + { // storeTarget.storeField = this.loadField; if (inst.MatchStFld(out var storeTarget, out var storeField, out var storeValue) && storeValue.MatchLdFld(out var loadTarget, out var loadField) - && loadTarget.MatchLdThis()) { + && loadTarget.MatchLdThis()) + { storeField = (IField)storeField.MemberDefinition; loadField = (IField)loadField.MemberDefinition; if (fieldToParameterMap.TryGetValue(loadField, out var mappedParameter)) @@ -483,17 +533,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void ConstructExceptionTable() { - if (isCompiledWithMono) { + if (isCompiledWithMono) + { disposeMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => metadata.GetString(metadata.GetMethodDefinition(m).Name) == "Dispose"); var function = CreateILAst(disposeMethod, context); BlockContainer body = (BlockContainer)function.Body; - for (var i = 0; (i < body.EntryPoint.Instructions.Count) && !(body.EntryPoint.Instructions[i] is Branch); i++) { + for (var i = 0; (i < body.EntryPoint.Instructions.Count) && !(body.EntryPoint.Instructions[i] is Branch); i++) + { if (body.EntryPoint.Instructions[i] is StObj stobj && stobj.MatchStFld(out var target, out var field, out var value) && target.MatchLdThis() && field.Type.IsKnownType(KnownTypeCode.Boolean) - && value.MatchLdcI4(1)) { + && value.MatchLdcI4(1)) + { disposingField = (IField)field.MemberDefinition; break; } @@ -501,7 +554,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // On mono, we don't need to analyse Dispose() to reconstruct the try-finally structure. finallyMethodToStateRange = default; - } else { + } + else + { // Non-Mono: analyze try-finally structure in Dispose() disposeMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => metadata.GetString(metadata.GetMethodDefinition(m).Name) == "System.IDisposable.Dispose"); var function = CreateILAst(disposeMethod, context); @@ -510,13 +565,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow finallyMethodToStateRange = rangeAnalysis.finallyMethodToStateRange; } } - + [Conditional("DEBUG")] void PrintFinallyMethodStateRanges(BlockContainer bc) { if (finallyMethodToStateRange == null) return; - foreach (var (method, stateRange) in finallyMethodToStateRange) { + foreach (var (method, stateRange) in finallyMethodToStateRange) + { bc.Blocks[0].Instructions.Insert(0, new Nop { Comment = method.Name + " in " + stateRange }); @@ -537,12 +593,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Copy-propagate temporaries holding a copy of 'this'. // This is necessary because the old (pre-Roslyn) C# compiler likes to store 'this' in temporary variables. - foreach (var stloc in moveNextFunction.Descendants.OfType().Where(s => s.Variable.IsSingleDefinition && s.Value.MatchLdThis()).ToList()) { + foreach (var stloc in moveNextFunction.Descendants.OfType().Where(s => s.Variable.IsSingleDefinition && s.Value.MatchLdThis()).ToList()) + { CopyPropagation.Propagate(stloc, context); } var body = (BlockContainer)moveNextFunction.Body; - if (body.Blocks.Count == 1 && body.Blocks[0].Instructions.Count == 1 && body.Blocks[0].Instructions[0] is TryFault tryFault) { + if (body.Blocks.Count == 1 && body.Blocks[0].Instructions.Count == 1 && body.Blocks[0].Instructions[0] is TryFault tryFault) + { body = (BlockContainer)tryFault.TryBlock; var faultBlockContainer = tryFault.FaultBlock as BlockContainer; if (faultBlockContainer?.Blocks.Count != 1) @@ -553,32 +611,42 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow && call.Method.MetadataToken == disposeMethod && call.Arguments.Count == 1 && call.Arguments[0].MatchLdThis() - && faultBlock.Instructions[1].MatchLeave(faultBlockContainer))) { + && faultBlock.Instructions[1].MatchLeave(faultBlockContainer))) + { throw new SymbolicAnalysisFailedException("Unexpected fault block contents in MoveNext()"); } } - if (stateField == null) { + if (stateField == null) + { // With mono-compiled state machines, it's possible that we haven't discovered the state field // yet because the compiler let it be implicitly initialized to 0. // In this case, we must discover it from the first instruction in MoveNext(): if (body.EntryPoint.Instructions[0] is StLoc stloc && stloc.Value.MatchLdFld(out var target, out var field) - && target.MatchLdThis() && field.Type.IsKnownType(KnownTypeCode.Int32)) { + && target.MatchLdThis() && field.Type.IsKnownType(KnownTypeCode.Int32)) + { stateField = (IField)field.MemberDefinition; - } else { + } + else + { throw new SymbolicAnalysisFailedException("Could not find state field."); } } skipFinallyBodies = null; - if (isCompiledWithMono) { + if (isCompiledWithMono) + { // Mono uses skipFinallyBodies; find out which variable that is: - foreach (var tryFinally in body.Descendants.OfType()) { - if ((tryFinally.FinallyBlock as BlockContainer)?.EntryPoint.Instructions[0] is IfInstruction ifInst) { - if (ifInst.Condition.MatchLogicNot(out var arg) && arg.MatchLdLoc(out var v) && v.Type.IsKnownType(KnownTypeCode.Boolean)) { + foreach (var tryFinally in body.Descendants.OfType()) + { + if ((tryFinally.FinallyBlock as BlockContainer)?.EntryPoint.Instructions[0] is IfInstruction ifInst) + { + if (ifInst.Condition.MatchLogicNot(out var arg) && arg.MatchLdLoc(out var v) && v.Type.IsKnownType(KnownTypeCode.Boolean)) + { bool isInitializedInEntryBlock = false; - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) + { if (body.EntryPoint.Instructions.ElementAtOrDefault(i) is StLoc stloc && stloc.Variable == v && stloc.Value.MatchLdcI4(0)) { @@ -586,7 +654,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow break; } } - if (isInitializedInEntryBlock) { + if (isInitializedInEntryBlock) + { skipFinallyBodies = v; break; } @@ -621,25 +690,34 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // at the beginning of MoveNext(). Undo this optimization. context.StepStartGroup("PropagateCopiesOfFields"); var mutableFields = body.Descendants.OfType().Where(ldflda => ldflda.Parent.OpCode != OpCode.LdObj).Select(ldflda => ldflda.Field).ToHashSet(); - for (int i = 0; i < body.EntryPoint.Instructions.Count; i++) { + for (int i = 0; i < body.EntryPoint.Instructions.Count; i++) + { if (body.EntryPoint.Instructions[i] is StLoc store && store.Variable.IsSingleDefinition && store.Value is LdObj ldobj && ldobj.Target is LdFlda ldflda && ldflda.Target.MatchLdThis()) { - if (!mutableFields.Contains(ldflda.Field)) { + if (!mutableFields.Contains(ldflda.Field)) + { // perform copy propagation: (unlike CopyPropagation.Propagate(), copy the ldobj arguments as well) - foreach (var expr in store.Variable.LoadInstructions.ToArray()) { + foreach (var expr in store.Variable.LoadInstructions.ToArray()) + { expr.ReplaceWith(store.Value.Clone()); } body.EntryPoint.Instructions.RemoveAt(i--); - } else if (ldflda.Field.MemberDefinition == stateField.MemberDefinition) { + } + else if (ldflda.Field.MemberDefinition == stateField.MemberDefinition) + { continue; - } else { + } + else + { break; // unsupported: load of mutable field (other than state field) } - } else { + } + else + { break; // unknown instruction } } @@ -671,41 +749,54 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var blockStateMap = rangeAnalysis.GetBlockStateSetMapping(oldBody); BlockContainer newBody = new BlockContainer().WithILRange(oldBody); // create all new blocks so that they can be referenced by gotos - for (int blockIndex = 0; blockIndex < oldBody.Blocks.Count; blockIndex++) { + for (int blockIndex = 0; blockIndex < oldBody.Blocks.Count; blockIndex++) + { newBody.Blocks.Add(new Block().WithILRange(oldBody.Blocks[blockIndex])); } // convert contents of blocks - for (int i = 0; i < oldBody.Blocks.Count; i++) { + for (int i = 0; i < oldBody.Blocks.Count; i++) + { var oldBlock = oldBody.Blocks[i]; var newBlock = newBody.Blocks[i]; - foreach (var oldInst in oldBlock.Instructions) { + foreach (var oldInst in oldBlock.Instructions) + { context.CancellationToken.ThrowIfCancellationRequested(); - if (oldInst.MatchStFld(out var target, out var field, out var value) && target.MatchLdThis()) { - if (field.MemberDefinition.Equals(stateField)) { - if (value.MatchLdcI4(out int newState)) { + if (oldInst.MatchStFld(out var target, out var field, out var value) && target.MatchLdThis()) + { + if (field.MemberDefinition.Equals(stateField)) + { + if (value.MatchLdcI4(out int newState)) + { // On state change, break up the block: // (this allows us to consider each block individually for try-finally reconstruction) newBlock = SplitBlock(newBlock, oldInst); // We keep the state-changing instruction around (as first instruction of the new block) // for reconstructing the try-finallys. - } else { + } + else + { newBlock.Instructions.Add(new InvalidExpression("Assigned non-constant to iterator.state field").WithILRange(oldInst)); continue; // don't copy over this instruction, but continue with the basic block } - } else if (field.MemberDefinition.Equals(currentField)) { + } + else if (field.MemberDefinition.Equals(currentField)) + { // create yield return newBlock.Instructions.Add(new YieldReturn(value).WithILRange(oldInst)); ConvertBranchAfterYieldReturn(newBlock, oldBlock, oldInst.ChildIndex + 1); break; // we're done with this basic block } - } else if (oldInst is Call call && call.Arguments.Count == 1 && call.Arguments[0].MatchLdThis() - && finallyMethodToStateRange.ContainsKey((IMethod)call.Method.MemberDefinition)) + } + else if (oldInst is Call call && call.Arguments.Count == 1 && call.Arguments[0].MatchLdThis() + && finallyMethodToStateRange.ContainsKey((IMethod)call.Method.MemberDefinition)) { // Break up the basic block on a call to a finally method // (this allows us to consider each block individually for try-finally reconstruction) newBlock = SplitBlock(newBlock, oldInst); - } else if (oldInst is TryFinally tryFinally && isCompiledWithMono) { + } + else if (oldInst is TryFinally tryFinally && isCompiledWithMono) + { // with mono, we have to recurse into try-finally blocks var oldTryBlock = (BlockContainer)tryFinally.TryBlock; var sra = rangeAnalysis.CreateNestedAnalysis(); @@ -731,7 +822,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void ConvertBranchAfterYieldReturn(Block newBlock, Block oldBlock, int pos) { Block targetBlock; - if (isCompiledWithMono && disposingField != null) { + if (isCompiledWithMono && disposingField != null) + { // Mono skips over the state assignment if 'this.disposing' is set: // ... // stfld $current(ldloc this, yield-expr) @@ -752,7 +844,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow && condition.MatchLdFld(out var condTarget, out var condField) && condTarget.MatchLdThis() && condField.MemberDefinition.Equals(disposingField) && oldBlock.Instructions[pos + 1].MatchBranch(out targetBlock) - && targetBlock.Parent == oldBlock.Parent) { + && targetBlock.Parent == oldBlock.Parent) + { // Keep looking at the target block: oldBlock = targetBlock; pos = 0; @@ -762,19 +855,25 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (oldBlock.Instructions[pos].MatchStFld(out var target, out var field, out var value) && target.MatchLdThis() && field.MemberDefinition == stateField - && value.MatchLdcI4(out int newState)) { + && value.MatchLdcI4(out int newState)) + { pos++; - } else { + } + else + { newBlock.Instructions.Add(new InvalidBranch("Unable to find new state assignment for yield return")); return; } // Mono may have 'br setSkipFinallyBodies' here, so follow the branch - if (oldBlock.Instructions[pos].MatchBranch(out targetBlock) && targetBlock.Parent == oldBlock.Parent) { + if (oldBlock.Instructions[pos].MatchBranch(out targetBlock) && targetBlock.Parent == oldBlock.Parent) + { oldBlock = targetBlock; pos = 0; } - if (oldBlock.Instructions[pos].MatchStLoc(skipFinallyBodies, out value)) { - if (!value.MatchLdcI4(1)) { + if (oldBlock.Instructions[pos].MatchStLoc(skipFinallyBodies, out value)) + { + if (!value.MatchLdcI4(1)) + { newBlock.Instructions.Add(new InvalidExpression { ExpectedResultType = StackType.Void, Message = "Unexpected assignment to skipFinallyBodies" @@ -783,12 +882,17 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow pos++; } - if (oldBlock.Instructions[pos].MatchReturn(out var retVal) && retVal.MatchLdcI4(1)) { + if (oldBlock.Instructions[pos].MatchReturn(out var retVal) && retVal.MatchLdcI4(1)) + { // OK, found return directly after state assignment - } else if (oldBlock.Instructions[pos].MatchBranch(out targetBlock) - && targetBlock.Instructions[0].MatchReturn(out retVal) && retVal.MatchLdcI4(1)) { + } + else if (oldBlock.Instructions[pos].MatchBranch(out targetBlock) + && targetBlock.Instructions[0].MatchReturn(out retVal) && retVal.MatchLdcI4(1)) + { // OK, jump to common return block (e.g. on Mono) - } else { + } + else + { newBlock.Instructions.Add(new InvalidBranch("Unable to find 'return true' for yield return")); return; } @@ -797,7 +901,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow Block SplitBlock(Block newBlock, ILInstruction oldInst) { - if (newBlock.Instructions.Count > 0) { + if (newBlock.Instructions.Count > 0) + { var newBlock2 = new Block(); newBlock2.AddILRange(new Interval(oldInst.StartILOffset, oldInst.StartILOffset)); newBody.Blocks.Add(newBlock2); @@ -810,26 +915,32 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow ILInstruction MakeGoTo(int v) { Block targetBlock = blockStateMap.GetOrDefault(v); - if (targetBlock != null) { + if (targetBlock != null) + { if (targetBlock.Parent == oldBody) return new Branch(newBody.Blocks[targetBlock.ChildIndex]); else return new Branch(targetBlock); - } else { + } + else + { return new InvalidBranch("Could not find block for state " + v); } } void UpdateBranchTargets(ILInstruction inst) { - switch (inst) { + switch (inst) + { case Branch branch: - if (branch.TargetContainer == oldBody) { + if (branch.TargetContainer == oldBody) + { branch.TargetBlock = newBody.Blocks[branch.TargetBlock.ChildIndex]; } break; case Leave leave: - if (leave.MatchReturn(out var value)) { + if (leave.MatchReturn(out var value)) + { bool validYieldBreak = value.MatchLdcI4(0); if (value.MatchLdLoc(out var v) && (v.Kind == VariableKind.Local || v.Kind == VariableKind.StackSlot) @@ -838,20 +949,27 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow validYieldBreak = true; returnStores.AddRange(v.StoreInstructions.Cast()); } - if (validYieldBreak) { + if (validYieldBreak) + { // yield break leave.ReplaceWith(new Leave(newBody).WithILRange(leave)); - } else { + } + else + { leave.ReplaceWith(new InvalidBranch("Unexpected return in MoveNext()").WithILRange(leave)); } - } else { - if (leave.TargetContainer == oldBody) { + } + else + { + if (leave.TargetContainer == oldBody) + { leave.TargetContainer = newBody; } } break; } - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { UpdateBranchTargets(child); } } @@ -864,11 +982,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// internal static void TranslateFieldsToLocalAccess(ILFunction function, ILInstruction inst, Dictionary fieldToVariableMap, bool isCompiledWithMono = false) { - if (inst is LdFlda ldflda && ldflda.Target.MatchLdThis()) { + if (inst is LdFlda ldflda && ldflda.Target.MatchLdThis()) + { var fieldDef = (IField)ldflda.Field.MemberDefinition; - if (!fieldToVariableMap.TryGetValue(fieldDef, out var v)) { + if (!fieldToVariableMap.TryGetValue(fieldDef, out var v)) + { string name = null; - if (!string.IsNullOrEmpty(fieldDef.Name) && fieldDef.Name[0] == '<') { + if (!string.IsNullOrEmpty(fieldDef.Name) && fieldDef.Name[0] == '<') + { int pos = fieldDef.Name.IndexOf('>'); if (pos > 1) name = fieldDef.Name.Substring(1, pos - 1); @@ -878,24 +999,35 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow v.StateMachineField = ldflda.Field; fieldToVariableMap.Add(fieldDef, v); } - if (v.StackType == StackType.Ref) { + if (v.StackType == StackType.Ref) + { Debug.Assert(v.Kind == VariableKind.Parameter && v.Index < 0); // this pointer inst.ReplaceWith(new LdLoc(v).WithILRange(inst)); - } else { + } + else + { inst.ReplaceWith(new LdLoca(v).WithILRange(inst)); } - } else if (!isCompiledWithMono && inst.MatchLdThis()) { + } + else if (!isCompiledWithMono && inst.MatchLdThis()) + { inst.ReplaceWith(new InvalidExpression("stateMachine") { ExpectedResultType = inst.ResultType }.WithILRange(inst)); - } else { - foreach (var child in inst.Children) { + } + else + { + foreach (var child in inst.Children) + { TranslateFieldsToLocalAccess(function, child, fieldToVariableMap, isCompiledWithMono); } - if (inst is LdObj ldobj && ldobj.Target is LdLoca ldloca && ldloca.Variable.StateMachineField != null) { + if (inst is LdObj ldobj && ldobj.Target is LdLoca ldloca && ldloca.Variable.StateMachineField != null) + { LdLoc ldloc = new LdLoc(ldloca.Variable); ldloc.AddILRange(ldobj); ldloc.AddILRange(ldloca); inst.ReplaceWith(ldloc); - } else if (inst is StObj stobj && stobj.Target is LdLoca ldloca2 && ldloca2.Variable.StateMachineField != null) { + } + else if (inst is StObj stobj && stobj.Target is LdLoca ldloca2 && ldloca2.Variable.StateMachineField != null) + { StLoc stloc = new StLoc(ldloca2.Variable, stobj.Value); stloc.AddILRange(stobj); stloc.AddILRange(ldloca2); @@ -908,11 +1040,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow #region DecompileFinallyBlocks void DecompileFinallyBlocks() { - foreach (var method in finallyMethodToStateRange.Keys) { + foreach (var method in finallyMethodToStateRange.Keys) + { var function = CreateILAst((MethodDefinitionHandle)method.MetadataToken, context); var body = (BlockContainer)function.Body; var newState = GetNewState(body.EntryPoint); - if (newState != null) { + if (newState != null) + { body.EntryPoint.Instructions.RemoveAt(0); } function.ReleaseRef(); // make body reusable outside of function @@ -944,16 +1078,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var stateToContainer = new Dictionary(); stateToContainer.Add(-1, newBody); // First, analyse the newBody: for each block, determine the active state number. - foreach (var block in newBody.Blocks) { + foreach (var block in newBody.Blocks) + { context.CancellationToken.ThrowIfCancellationRequested(); int oldState = blockState[block.ChildIndex]; BlockContainer container; // new container for the block - if (GetNewState(block) is int newState) { + if (GetNewState(block) is int newState) + { // OK, state change // Remove the state-changing instruction block.Instructions.RemoveAt(0); - if (!stateToContainer.TryGetValue(newState, out container)) { + if (!stateToContainer.TryGetValue(newState, out container)) + { // First time we see this state. // This means we just found the entry point of a try block. CreateTryBlock(block, newState); @@ -964,13 +1101,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // we can use stateToContainer[oldState] as parent. container = stateToContainer[oldState]; } - } else { + } + else + { // Because newBody is topologically sorted we because we just removed unreachable code, // we can assume that blockState[] was already set for this block. newState = oldState; container = stateToContainer[oldState]; } - if (container != newBody) { + if (container != newBody) + { // Move the block into the container. container.Blocks.Add(block); // Keep the stale reference in newBody.Blocks for now, to avoid @@ -981,12 +1121,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow block.Instructions.Insert(0, new Nop { Comment = "state == " + newState }); #endif // Propagate newState to successor blocks - foreach (var branch in block.Descendants.OfType()) { - if (branch.TargetBlock.Parent == newBody) { + foreach (var branch in block.Descendants.OfType()) + { + if (branch.TargetBlock.Parent == newBody) + { int stateAfterBranch = newState; if (Block.GetPredecessor(branch) is Call call && call.Arguments.Count == 1 && call.Arguments[0].MatchLdThis() - && call.Method.Name == "System.IDisposable.Dispose") { + && call.Method.Name == "System.IDisposable.Dispose") + { // pre-roslyn compiles "yield break;" into "Dispose(); goto return_false;", // so convert the dispose call into a state transition to the final state stateAfterBranch = -1; @@ -1002,7 +1145,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow void CreateTryBlock(Block block, int state) { var finallyMethod = FindFinallyMethod(state); - if (finallyMethod != null) { + if (finallyMethod != null) + { // remove the method so that it doesn't cause ambiguity when processing nested try-finally blocks finallyMethodToStateRange.Remove(finallyMethod); } @@ -1016,16 +1160,21 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow stateToContainer.Add(state, tryBlockContainer); ILInstruction finallyBlock; - if (finallyMethod == null) { + if (finallyMethod == null) + { finallyBlock = new InvalidBranch($"Could not find finallyMethod for state={state}.\n" + $"Possibly this method is affected by a C# compiler bug that causes the finally body\n" + $"not to run in case of an exception or early 'break;' out of a loop consuming this iterable."); - } else if (decompiledFinallyMethods.TryGetValue(finallyMethod, out var decompiledMethod)) { + } + else if (decompiledFinallyMethods.TryGetValue(finallyMethod, out var decompiledMethod)) + { finallyBlock = decompiledMethod.function.Body; var vars = decompiledMethod.function.Variables.ToArray(); decompiledMethod.function.Variables.Clear(); iteratorFunction.Variables.AddRange(vars); - } else { + } + else + { finallyBlock = new InvalidBranch("Missing decompiledFinallyMethod"); } @@ -1036,8 +1185,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow IMethod FindFinallyMethod(int state) { IMethod foundMethod = null; - foreach (var (method, stateRange) in finallyMethodToStateRange) { - if (stateRange.Contains(state)) { + foreach (var (method, stateRange) in finallyMethodToStateRange) + { + if (stateRange.Contains(state)) + { if (foundMethod == null) foundMethod = method; else @@ -1057,9 +1208,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow && value.MatchLdcI4(out int newState)) { return newState; - } else if (block.Instructions[0] is Call call - && call.Arguments.Count == 1 && call.Arguments[0].MatchLdThis() - && decompiledFinallyMethods.TryGetValue((IMethod)call.Method.MemberDefinition, out var finallyMethod)) + } + else if (block.Instructions[0] is Call call + && call.Arguments.Count == 1 && call.Arguments[0].MatchLdThis() + && decompiledFinallyMethods.TryGetValue((IMethod)call.Method.MemberDefinition, out var finallyMethod)) { return finallyMethod.outerState; } @@ -1073,21 +1225,26 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// private void CleanSkipFinallyBodies(ILFunction function) { - if (skipFinallyBodies == null) { + if (skipFinallyBodies == null) + { return; // only mono-compiled code uses skipFinallyBodies } context.StepStartGroup("CleanSkipFinallyBodies", function); Block entryPoint = AsyncAwaitDecompiler.GetBodyEntryPoint(function.Body as BlockContainer); - if (skipFinallyBodies.StoreInstructions.Count != 0 || skipFinallyBodies.AddressCount != 0) { + if (skipFinallyBodies.StoreInstructions.Count != 0 || skipFinallyBodies.AddressCount != 0) + { // misdetected another variable as doFinallyBodies? // Fortunately removing the initial store of 0 is harmless, as we // default-initialize the variable on uninit uses return; } - foreach (var tryFinally in function.Descendants.OfType()) { + foreach (var tryFinally in function.Descendants.OfType()) + { entryPoint = AsyncAwaitDecompiler.GetBodyEntryPoint(tryFinally.FinallyBlock as BlockContainer); - if (entryPoint?.Instructions[0] is IfInstruction ifInst) { - if (ifInst.Condition.MatchLogicNot(out var logicNotArg) && logicNotArg.MatchLdLoc(skipFinallyBodies)) { + if (entryPoint?.Instructions[0] is IfInstruction ifInst) + { + if (ifInst.Condition.MatchLogicNot(out var logicNotArg) && logicNotArg.MatchLdLoc(skipFinallyBodies)) + { context.Step("Remove if (skipFinallyBodies) from try-finally", tryFinally); // condition will always be true now that we're using 'yield' instructions entryPoint.Instructions[0] = ifInst.TrueInst; diff --git a/ICSharpCode.Decompiler/IL/ILAstWritingOptions.cs b/ICSharpCode.Decompiler/IL/ILAstWritingOptions.cs index 617024eb7..90c7aaca8 100644 --- a/ICSharpCode.Decompiler/IL/ILAstWritingOptions.cs +++ b/ICSharpCode.Decompiler/IL/ILAstWritingOptions.cs @@ -34,7 +34,8 @@ namespace ICSharpCode.Decompiler.IL public bool UseLogicOperationSugar { get { return useLogicOperationSugar; } set { - if (useLogicOperationSugar != value) { + if (useLogicOperationSugar != value) + { useLogicOperationSugar = value; OnPropertyChanged(); } @@ -47,7 +48,8 @@ namespace ICSharpCode.Decompiler.IL public bool UseFieldSugar { get { return useFieldSugar; } set { - if (useFieldSugar != value) { + if (useFieldSugar != value) + { useFieldSugar = value; OnPropertyChanged(); } @@ -60,7 +62,8 @@ namespace ICSharpCode.Decompiler.IL public bool ShowILRanges { get { return showILRanges; } set { - if (showILRanges != value) { + if (showILRanges != value) + { showILRanges = value; OnPropertyChanged(); } @@ -73,7 +76,8 @@ namespace ICSharpCode.Decompiler.IL public bool ShowChildIndexInBlock { get { return showChildIndexInBlock; } set { - if (showChildIndexInBlock != value) { + if (showChildIndexInBlock != value) + { showChildIndexInBlock = value; OnPropertyChanged(); } diff --git a/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs b/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs index 32310150c..6f6ec269f 100644 --- a/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs +++ b/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index c85375d2d..2f015c77e 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -22,15 +22,17 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using System.Threading; using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Threading; + +using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; + using ArrayType = ICSharpCode.Decompiler.TypeSystem.ArrayType; using ByReferenceType = ICSharpCode.Decompiler.TypeSystem.ByReferenceType; using PinnedType = ICSharpCode.Decompiler.TypeSystem.Implementation.PinnedType; -using ICSharpCode.Decompiler.Disassembler; -using System.Reflection.Metadata.Ecma335; namespace ICSharpCode.Decompiler.IL { @@ -97,10 +99,13 @@ namespace ICSharpCode.Decompiler.IL if (methodDefinitionHandle.IsNil) throw new ArgumentException("methodDefinitionHandle.IsNil"); this.method = module.GetDefinition(methodDefinitionHandle); - if (genericContext.ClassTypeParameters == null && genericContext.MethodTypeParameters == null) { + if (genericContext.ClassTypeParameters == null && genericContext.MethodTypeParameters == null) + { // no generic context specified: use the method's own type parameters genericContext = new GenericContext(method); - } else { + } + else + { // generic context specified, so specialize the method for it: this.method = this.method.Specialize(genericContext.ToSubstitution()); } @@ -113,8 +118,10 @@ namespace ICSharpCode.Decompiler.IL this.methodReturnStackType = method.ReturnType.GetStackType(); InitParameterVariables(); localVariables = InitLocalVariables(); - if (body.LocalVariablesInitialized) { - foreach (var v in localVariables) { + if (body.LocalVariablesInitialized) + { + foreach (var v in localVariables) + { v.HasInitialValue = true; } } @@ -128,7 +135,8 @@ namespace ICSharpCode.Decompiler.IL EntityHandle ReadAndDecodeMetadataToken() { int token = reader.ReadInt32(); - if (token <= 0) { + if (token <= 0) + { // SRM uses negative tokens as "virtual tokens" and can get confused // if we manually create them. // Row-IDs < 1 are always invalid. @@ -163,14 +171,18 @@ namespace ICSharpCode.Decompiler.IL if (body.LocalSignature.IsNil) return Empty.Array; ImmutableArray variableTypes; - try { + try + { variableTypes = module.DecodeLocalSignature(body.LocalSignature, genericContext); - } catch (BadImageFormatException ex) { + } + catch (BadImageFormatException ex) + { Warnings.Add("Error decoding local variables: " + ex.Message); variableTypes = ImmutableArray.Empty; } var localVariables = new ILVariable[variableTypes.Length]; - foreach (var (index, type) in variableTypes.WithIndex()) { + foreach (var (index, type) in variableTypes.WithIndex()) + { localVariables[index] = CreateILVariable(index, type); } return localVariables; @@ -186,10 +198,12 @@ namespace ICSharpCode.Decompiler.IL parameterVariables = new ILVariable[popCount]; int paramIndex = 0; int offset = 0; - if (!method.IsStatic) { + if (!method.IsStatic) + { offset = 1; IType declaringType = method.DeclaringType; - if (declaringType.IsUnbound()) { + if (declaringType.IsUnbound()) + { // If method is a definition (and not specialized), the declaring type is also just a definition, // and needs to be converted into a normally usable type. declaringType = new ParameterizedType(declaringType, declaringType.TypeParameters); @@ -198,7 +212,8 @@ namespace ICSharpCode.Decompiler.IL ilVar.IsRefReadOnly = method.ThisIsRefReadOnly; parameterVariables[paramIndex++] = ilVar; } - while (paramIndex < parameterVariables.Length) { + while (paramIndex < parameterVariables.Length) + { IParameter parameter = method.Parameters[paramIndex - offset]; ILVariable ilVar = CreateILVariable(paramIndex - offset, parameter.Type, parameter.Name); ilVar.IsRefReadOnly = parameter.IsIn; @@ -211,20 +226,28 @@ namespace ICSharpCode.Decompiler.IL ILVariable CreateILVariable(int index, IType type) { VariableKind kind; - if (type.SkipModifiers() is PinnedType pinned) { + if (type.SkipModifiers() is PinnedType pinned) + { kind = VariableKind.PinnedLocal; type = pinned.ElementType; - } else { + } + else + { kind = VariableKind.Local; } ILVariable ilVar = new ILVariable(kind, type, index); - if (!UseDebugSymbols || DebugInfo == null || !DebugInfo.TryGetName((MethodDefinitionHandle)method.MetadataToken, index, out string name)) { + if (!UseDebugSymbols || DebugInfo == null || !DebugInfo.TryGetName((MethodDefinitionHandle)method.MetadataToken, index, out string name)) + { ilVar.Name = "V_" + index; ilVar.HasGeneratedName = true; - } else if (string.IsNullOrWhiteSpace(name)) { + } + else if (string.IsNullOrWhiteSpace(name)) + { ilVar.Name = "V_" + index; ilVar.HasGeneratedName = true; - } else { + } + else + { ilVar.Name = name; } return ilVar; @@ -234,7 +257,8 @@ namespace ICSharpCode.Decompiler.IL { Debug.Assert(!parameterType.IsUnbound()); ITypeDefinition def = parameterType.GetDefinition(); - if (def != null && index < 0 && def.IsReferenceType == false) { + if (def != null && index < 0 && def.IsReferenceType == false) + { parameterType = new ByReferenceType(parameterType); } var ilVar = new ILVariable(VariableKind.Parameter, parameterType, index); @@ -247,7 +271,7 @@ namespace ICSharpCode.Decompiler.IL ilVar.Name = name; return ilVar; } - + /// /// Warn when invalid IL is detected. /// ILSpy should be able to handle invalid IL; but this method can be helpful for debugging the ILReader, @@ -260,39 +284,53 @@ namespace ICSharpCode.Decompiler.IL ImmutableStack MergeStacks(ImmutableStack a, ImmutableStack b) { - if (CheckStackCompatibleWithoutAdjustments(a, b)) { + if (CheckStackCompatibleWithoutAdjustments(a, b)) + { // We only need to union the input variables, but can // otherwise re-use the existing stack. ImmutableStack output = a; - while (!a.IsEmpty && !b.IsEmpty) { + while (!a.IsEmpty && !b.IsEmpty) + { Debug.Assert(a.Peek().StackType == b.Peek().StackType); unionFind.Merge(a.Peek(), b.Peek()); a = a.Pop(); b = b.Pop(); } return output; - } else if (a.Count() != b.Count()) { + } + else if (a.Count() != b.Count()) + { // Let's not try to merge mismatched stacks. Warn("Incompatible stack heights: " + a.Count() + " vs " + b.Count()); return a; - } else { + } + else + { // The more complex case where the stacks don't match exactly. var output = new List(); - while (!a.IsEmpty && !b.IsEmpty) { + while (!a.IsEmpty && !b.IsEmpty) + { var varA = a.Peek(); var varB = b.Peek(); - if (varA.StackType == varB.StackType) { + if (varA.StackType == varB.StackType) + { unionFind.Merge(varA, varB); output.Add(varA); - } else { - if (!IsValidTypeStackTypeMerge(varA.StackType, varB.StackType)) { + } + else + { + if (!IsValidTypeStackTypeMerge(varA.StackType, varB.StackType)) + { Warn("Incompatible stack types: " + varA.StackType + " vs " + varB.StackType); } - if (varA.StackType > varB.StackType) { + if (varA.StackType > varB.StackType) + { output.Add(varA); // every store to varB should also store to varA stackMismatchPairs.Add((varB, varA)); - } else { + } + else + { output.Add(varB); // every store to varA should also store to varB stackMismatchPairs.Add((varA, varB)); @@ -309,7 +347,8 @@ namespace ICSharpCode.Decompiler.IL static bool CheckStackCompatibleWithoutAdjustments(ImmutableStack a, ImmutableStack b) { - while (!a.IsEmpty && !b.IsEmpty) { + while (!a.IsEmpty && !b.IsEmpty) + { if (a.Peek().StackType != b.Peek().StackType) return false; a = a.Pop(); @@ -339,21 +378,26 @@ namespace ICSharpCode.Decompiler.IL /// void StoreStackForOffset(int offset, ref ImmutableStack stack) { - if (stackByOffset.TryGetValue(offset, out var existing)) { + if (stackByOffset.TryGetValue(offset, out var existing)) + { stack = MergeStacks(existing, stack); if (stack != existing) stackByOffset[offset] = stack; - } else { + } + else + { stackByOffset.Add(offset, stack); } } - + void ReadInstructions(CancellationToken cancellationToken) { // Fill isBranchTarget and branchStackDict based on exception handlers - foreach (var eh in body.ExceptionRegions) { + foreach (var eh in body.ExceptionRegions) + { ImmutableStack ehStack = null; - if (eh.Kind == ExceptionRegionKind.Catch) { + if (eh.Kind == ExceptionRegionKind.Catch) + { var catchType = module.ResolveType(eh.CatchType, genericContext); var v = new ILVariable(VariableKind.ExceptionStackSlot, catchType, eh.HandlerOffset) { Name = "E_" + eh.HandlerOffset, @@ -361,37 +405,47 @@ namespace ICSharpCode.Decompiler.IL }; variableByExceptionHandler.Add(eh, v); ehStack = ImmutableStack.Create(v); - } else if (eh.Kind == ExceptionRegionKind.Filter) { + } + else if (eh.Kind == ExceptionRegionKind.Filter) + { var v = new ILVariable(VariableKind.ExceptionStackSlot, compilation.FindType(KnownTypeCode.Object), eh.HandlerOffset) { Name = "E_" + eh.HandlerOffset, HasGeneratedName = true }; variableByExceptionHandler.Add(eh, v); ehStack = ImmutableStack.Create(v); - } else { + } + else + { ehStack = ImmutableStack.Empty; } - if (eh.FilterOffset != -1) { + if (eh.FilterOffset != -1) + { isBranchTarget[eh.FilterOffset] = true; StoreStackForOffset(eh.FilterOffset, ref ehStack); } - if (eh.HandlerOffset != -1) { + if (eh.HandlerOffset != -1) + { isBranchTarget[eh.HandlerOffset] = true; StoreStackForOffset(eh.HandlerOffset, ref ehStack); } } reader.Reset(); - while (reader.RemainingBytes > 0) { + while (reader.RemainingBytes > 0) + { cancellationToken.ThrowIfCancellationRequested(); int start = reader.Offset; StoreStackForOffset(start, ref currentStack); currentInstructionStart = start; bool startedWithEmptyStack = currentStack.IsEmpty; ILInstruction decodedInstruction; - try { + try + { decodedInstruction = DecodeInstruction(); - } catch (BadImageFormatException ex) { + } + catch (BadImageFormatException ex) + { decodedInstruction = new InvalidBranch(ex.Message); } if (decodedInstruction.ResultType == StackType.Unknown && decodedInstruction.OpCode != OpCode.InvalidBranch && UnpackPush(decodedInstruction).OpCode != OpCode.InvalidExpression) @@ -401,19 +455,23 @@ namespace ICSharpCode.Decompiler.IL decodedInstruction.AddILRange(new Interval(start, end)); UnpackPush(decodedInstruction).AddILRange(decodedInstruction); instructionBuilder.Add(decodedInstruction); - if (decodedInstruction.HasDirectFlag(InstructionFlags.EndPointUnreachable)) { - if (!stackByOffset.TryGetValue(end, out currentStack)) { + if (decodedInstruction.HasDirectFlag(InstructionFlags.EndPointUnreachable)) + { + if (!stackByOffset.TryGetValue(end, out currentStack)) + { currentStack = ImmutableStack.Empty; } } - if (IsSequencePointInstruction(decodedInstruction) || startedWithEmptyStack) { + if (IsSequencePointInstruction(decodedInstruction) || startedWithEmptyStack) + { this.SequencePointCandidates.Add(decodedInstruction.StartILOffset); } } - + var visitor = new CollectStackVariablesVisitor(unionFind); - for (int i = 0; i < instructionBuilder.Count; i++) { + for (int i = 0; i < instructionBuilder.Count; i++) + { instructionBuilder[i] = instructionBuilder[i].AcceptVisitor(visitor); } stackVariables = visitor.variables; @@ -426,10 +484,13 @@ namespace ICSharpCode.Decompiler.IL (this.instructionBuilder.Count > 0 && this.instructionBuilder.Last().OpCode == OpCode.Call || this.instructionBuilder.Last().OpCode == OpCode.CallIndirect || - this.instructionBuilder.Last().OpCode == OpCode.CallVirt)) { + this.instructionBuilder.Last().OpCode == OpCode.CallVirt)) + { return true; - } else { + } + else + { return false; } } @@ -439,7 +500,8 @@ namespace ICSharpCode.Decompiler.IL if (stackMismatchPairs.Count == 0) return; var dict = new MultiDictionary(); - foreach (var (origA, origB) in stackMismatchPairs) { + foreach (var (origA, origB) in stackMismatchPairs) + { var a = unionFind.Find(origA); var b = unionFind.Find(origB); Debug.Assert(a.StackType < b.StackType); @@ -448,10 +510,13 @@ namespace ICSharpCode.Decompiler.IL dict.Add(a, b); } var newInstructions = new List(); - foreach (var inst in instructionBuilder) { + foreach (var inst in instructionBuilder) + { newInstructions.Add(inst); - if (inst is StLoc store) { - foreach (var additionalVar in dict[store.Variable]) { + if (inst is StLoc store) + { + foreach (var additionalVar in dict[store.Variable]) + { ILInstruction value = new LdLoc(store.Variable); value = new Conv(value, additionalVar.StackType.ToPrimitiveType(), false, Sign.Signed); newInstructions.Add(new StLoc(additionalVar, value) { @@ -471,8 +536,10 @@ namespace ICSharpCode.Decompiler.IL { Init(method, body, genericContext); ReadInstructions(cancellationToken); - foreach (var inst in instructionBuilder) { - if (inst is StLoc stloc && stloc.IsStackAdjustment) { + foreach (var inst in instructionBuilder) + { + if (inst is StLoc stloc && stloc.IsStackAdjustment) + { output.Write(" "); inst.WriteTo(output, new ILAstWritingOptions()); output.WriteLine(); @@ -480,7 +547,8 @@ namespace ICSharpCode.Decompiler.IL } output.Write(" ["); bool isFirstElement = true; - foreach (var element in stackByOffset[inst.StartILOffset]) { + foreach (var element in stackByOffset[inst.StartILOffset]) + { if (isFirstElement) isFirstElement = false; else @@ -521,14 +589,17 @@ namespace ICSharpCode.Decompiler.IL function.Variables.AddRange(variableByExceptionHandler.Values); function.AddRef(); // mark the root node var removedBlocks = new List(); - foreach (var c in function.Descendants.OfType()) { + foreach (var c in function.Descendants.OfType()) + { var newOrder = c.TopologicalSort(deleteUnreachableBlocks: true); - if (newOrder.Count < c.Blocks.Count) { + if (newOrder.Count < c.Blocks.Count) + { removedBlocks.AddRange(c.Blocks.Except(newOrder)); } c.Blocks.ReplaceList(newOrder); } - if (removedBlocks.Count > 0) { + if (removedBlocks.Count > 0) + { removedBlocks.SortBy(b => b.StartILOffset); function.Warnings.Add("Discarded unreachable code: " + string.Join(", ", removedBlocks.Select(b => $"IL_{b.StartILOffset:x4}"))); @@ -550,10 +621,11 @@ namespace ICSharpCode.Decompiler.IL else return inst; } - + ILInstruction Neg() { - switch (PeekStackType()) { + switch (PeekStackType()) + { case StackType.I4: return Push(new BinaryNumericInstruction(BinaryNumericOperator.Sub, new LdcI4(0), Pop(), checkForOverflow: false, sign: Sign.None)); case StackType.I: @@ -569,13 +641,14 @@ namespace ICSharpCode.Decompiler.IL goto case StackType.I4; } } - + ILInstruction DecodeInstruction() { if (reader.RemainingBytes == 0) return new InvalidBranch("Unexpected end of body"); var opCode = ILParser.DecodeOpCode(ref reader); - switch (opCode) { + switch (opCode) + { case ILOpCode.Constrained: return DecodeConstrainedCall(); case ILOpCode.Readonly: @@ -914,18 +987,18 @@ namespace ICSharpCode.Decompiler.IL case ILOpCode.Xor: return BinaryNumeric(BinaryNumericOperator.BitXor); case ILOpCode.Box: - { - var type = ReadAndDecodeTypeReference(); - return Push(new Box(Pop(type.GetStackType()), type)); - } + { + var type = ReadAndDecodeTypeReference(); + return Push(new Box(Pop(type.GetStackType()), type)); + } case ILOpCode.Castclass: return Push(new CastClass(Pop(StackType.O), ReadAndDecodeTypeReference())); case ILOpCode.Cpobj: - { - var type = ReadAndDecodeTypeReference(); - var ld = new LdObj(PopPointer(), type); - return new StObj(PopPointer(), ld, type); - } + { + var type = ReadAndDecodeTypeReference(); + var ld = new LdObj(PopPointer(), type); + return new StObj(PopPointer(), ld, type); + } case ILOpCode.Initobj: return InitObj(PopPointer(), ReadAndDecodeTypeReference()); case ILOpCode.Isinst: @@ -957,36 +1030,36 @@ namespace ICSharpCode.Decompiler.IL case ILOpCode.Ldelema: return Push(new LdElema(indices: Pop(), array: Pop(), type: ReadAndDecodeTypeReference())); case ILOpCode.Ldfld: - { - var field = ReadAndDecodeFieldReference(); - return Push(new LdObj(new LdFlda(PopLdFldTarget(field), field) { DelayExceptions = true }, field.Type)); - } + { + var field = ReadAndDecodeFieldReference(); + return Push(new LdObj(new LdFlda(PopLdFldTarget(field), field) { DelayExceptions = true }, field.Type)); + } case ILOpCode.Ldflda: - { - var field = ReadAndDecodeFieldReference(); - return Push(new LdFlda(PopFieldTarget(field), field)); - } + { + var field = ReadAndDecodeFieldReference(); + return Push(new LdFlda(PopFieldTarget(field), field)); + } case ILOpCode.Stfld: - { - var field = ReadAndDecodeFieldReference(); - return new StObj(value: Pop(field.Type.GetStackType()), target: new LdFlda(PopFieldTarget(field), field) { DelayExceptions = true }, type: field.Type); - } + { + var field = ReadAndDecodeFieldReference(); + return new StObj(value: Pop(field.Type.GetStackType()), target: new LdFlda(PopFieldTarget(field), field) { DelayExceptions = true }, type: field.Type); + } case ILOpCode.Ldlen: return Push(new LdLen(StackType.I, Pop(StackType.O))); case ILOpCode.Ldobj: return Push(new LdObj(PopPointer(), ReadAndDecodeTypeReference())); case ILOpCode.Ldsfld: - { - var field = ReadAndDecodeFieldReference(); - return Push(new LdObj(new LdsFlda(field), field.Type)); - } + { + var field = ReadAndDecodeFieldReference(); + return Push(new LdObj(new LdsFlda(field), field.Type)); + } case ILOpCode.Ldsflda: return Push(new LdsFlda(ReadAndDecodeFieldReference())); case ILOpCode.Stsfld: - { - var field = ReadAndDecodeFieldReference(); - return new StObj(value: Pop(field.Type.GetStackType()), target: new LdsFlda(field), type: field.Type); - } + { + var field = ReadAndDecodeFieldReference(); + return new StObj(value: Pop(field.Type.GetStackType()), target: new LdsFlda(field), type: field.Type); + } case ILOpCode.Ldtoken: return Push(LdToken(ReadAndDecodeMetadataToken())); case ILOpCode.Ldvirtftn: @@ -1036,7 +1109,7 @@ namespace ICSharpCode.Decompiler.IL return new InvalidBranch($"Unknown opcode: 0x{(int)opCode:X2}"); } } - + StackType PeekStackType() { if (currentStack.IsEmpty) @@ -1058,7 +1131,8 @@ namespace ICSharpCode.Decompiler.IL protected override ILInstruction Default(ILInstruction inst) { - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { var newChild = child.AcceptVisitor(this); if (newChild != child) child.ReplaceWith(newChild); @@ -1069,7 +1143,8 @@ namespace ICSharpCode.Decompiler.IL protected internal override ILInstruction VisitLdLoc(LdLoc inst) { base.VisitLdLoc(inst); - if (inst.Variable.Kind == VariableKind.StackSlot) { + if (inst.Variable.Kind == VariableKind.StackSlot) + { var variable = unionFind.Find(inst.Variable); if (variables.Add(variable)) variable.Name = "S_" + (variables.Count - 1); @@ -1081,7 +1156,8 @@ namespace ICSharpCode.Decompiler.IL protected internal override ILInstruction VisitStLoc(StLoc inst) { base.VisitStLoc(inst); - if (inst.Variable.Kind == VariableKind.StackSlot) { + if (inst.Variable.Kind == VariableKind.StackSlot) + { var variable = unionFind.Find(inst.Variable); if (variables.Add(variable)) variable.Name = "S_" + (variables.Count - 1); @@ -1090,7 +1166,7 @@ namespace ICSharpCode.Decompiler.IL return inst; } } - + ILInstruction Push(ILInstruction inst) { Debug.Assert(inst.ResultType != StackType.Void); @@ -1100,18 +1176,20 @@ namespace ICSharpCode.Decompiler.IL currentStack = currentStack.Push(v); return new StLoc(v, inst); } - + ILInstruction Peek() { - if (currentStack.IsEmpty) { + if (currentStack.IsEmpty) + { return new InvalidExpression("Stack underflow").WithILRange(new Interval(reader.Offset, reader.Offset)); } return new LdLoc(currentStack.Peek()); } - + ILInstruction Pop() { - if (currentStack.IsEmpty) { + if (currentStack.IsEmpty) + { return new InvalidExpression("Stack underflow").WithILRange(new Interval(reader.Offset, reader.Offset)); } ILVariable v; @@ -1127,22 +1205,33 @@ namespace ICSharpCode.Decompiler.IL internal static ILInstruction Cast(ILInstruction inst, StackType expectedType, List warnings, int ilOffset) { - if (expectedType != inst.ResultType) { - if (inst is InvalidExpression) { + if (expectedType != inst.ResultType) + { + if (inst is InvalidExpression) + { ((InvalidExpression)inst).ExpectedResultType = expectedType; - } else if (expectedType == StackType.I && inst.ResultType == StackType.I4) { + } + else if (expectedType == StackType.I && inst.ResultType == StackType.I4) + { // IL allows implicit I4->I conversions inst = new Conv(inst, PrimitiveType.I, false, Sign.None); - } else if (expectedType == StackType.I4 && inst.ResultType == StackType.I) { + } + else if (expectedType == StackType.I4 && inst.ResultType == StackType.I) + { // C++/CLI also sometimes implicitly converts in the other direction: inst = new Conv(inst, PrimitiveType.I4, false, Sign.None); - } else if (expectedType == StackType.Unknown) { + } + else if (expectedType == StackType.Unknown) + { inst = new Conv(inst, PrimitiveType.Unknown, false, Sign.None); - } else if (inst.ResultType == StackType.Ref) { + } + else if (inst.ResultType == StackType.Ref) + { // Implicitly stop GC tracking; this occurs when passing the result of 'ldloca' or 'ldsflda' // to a method expecting a native pointer. inst = new Conv(inst, PrimitiveType.I, false, Sign.None); - switch (expectedType) { + switch (expectedType) + { case StackType.I4: inst = new Conv(inst, PrimitiveType.I4, false, Sign.None); break; @@ -1156,21 +1245,30 @@ namespace ICSharpCode.Decompiler.IL inst = new Conv(inst, expectedType.ToPrimitiveType(), false, Sign.None); break; } - } else if (expectedType == StackType.Ref) { + } + else if (expectedType == StackType.Ref) + { // implicitly start GC tracking / object to interior - if (!inst.ResultType.IsIntegerType() && inst.ResultType != StackType.O) { + if (!inst.ResultType.IsIntegerType() && inst.ResultType != StackType.O) + { // We also handle the invalid to-ref cases here because the else case // below uses expectedType.ToKnownTypeCode(), which doesn't work for Ref. Warn($"Expected {expectedType}, but got {inst.ResultType}"); } inst = new Conv(inst, PrimitiveType.Ref, false, Sign.None); - } else if (expectedType == StackType.F8 && inst.ResultType == StackType.F4) { + } + else if (expectedType == StackType.F8 && inst.ResultType == StackType.F4) + { // IL allows implicit F4->F8 conversions, because in IL F4 and F8 are the same. inst = new Conv(inst, PrimitiveType.R8, false, Sign.Signed); - } else if (expectedType == StackType.F4 && inst.ResultType == StackType.F8) { + } + else if (expectedType == StackType.F4 && inst.ResultType == StackType.F8) + { // IL allows implicit F8->F4 conversions, because in IL F4 and F8 are the same. inst = new Conv(inst, PrimitiveType.R4, false, Sign.Signed); - } else { + } + else + { Warn($"Expected {expectedType}, but got {inst.ResultType}"); inst = new Conv(inst, expectedType.ToPrimitiveType(), false, Sign.Signed); } @@ -1179,16 +1277,18 @@ namespace ICSharpCode.Decompiler.IL void Warn(string message) { - if (warnings != null) { + if (warnings != null) + { warnings.Add(string.Format("IL_{0:x4}: {1}", ilOffset, message)); } } } - + ILInstruction PopPointer() { ILInstruction inst = Pop(); - switch (inst.ResultType) { + switch (inst.ResultType) + { case StackType.I4: case StackType.I8: case StackType.Unknown: @@ -1204,7 +1304,8 @@ namespace ICSharpCode.Decompiler.IL ILInstruction PopFieldTarget(IField field) { - switch (field.DeclaringType.IsReferenceType) { + switch (field.DeclaringType.IsReferenceType) + { case true: return Pop(StackType.O); case false: @@ -1223,7 +1324,8 @@ namespace ICSharpCode.Decompiler.IL /// ILInstruction PopLdFldTarget(IField field) { - switch (field.DeclaringType.IsReferenceType) { + switch (field.DeclaringType.IsReferenceType) + { case true: return Pop(StackType.O); case false: @@ -1256,27 +1358,36 @@ namespace ICSharpCode.Decompiler.IL private ILInstruction Ldarg(int v) { - if (v >= 0 && v < parameterVariables.Length) { + if (v >= 0 && v < parameterVariables.Length) + { return new LdLoc(parameterVariables[v]); - } else { + } + else + { return new InvalidExpression($"ldarg {v} (out-of-bounds)"); } } private ILInstruction Ldarga(int v) { - if (v >= 0 && v < parameterVariables.Length) { + if (v >= 0 && v < parameterVariables.Length) + { return new LdLoca(parameterVariables[v]); - } else { + } + else + { return new InvalidExpression($"ldarga {v} (out-of-bounds)"); } } private ILInstruction Starg(int v) { - if (v >= 0 && v < parameterVariables.Length) { + if (v >= 0 && v < parameterVariables.Length) + { return new StLoc(parameterVariables[v], Pop(parameterVariables[v].StackType)); - } else { + } + else + { Pop(); return new InvalidExpression($"starg {v} (out-of-bounds)"); } @@ -1284,39 +1395,48 @@ namespace ICSharpCode.Decompiler.IL private ILInstruction Ldloc(int v) { - if (v >= 0 && v < localVariables.Length) { + if (v >= 0 && v < localVariables.Length) + { return new LdLoc(localVariables[v]); - } else { + } + else + { return new InvalidExpression($"ldloc {v} (out-of-bounds)"); } } private ILInstruction Ldloca(int v) { - if (v >= 0 && v < localVariables.Length) { + if (v >= 0 && v < localVariables.Length) + { return new LdLoca(localVariables[v]); - } else { + } + else + { return new InvalidExpression($"ldloca {v} (out-of-bounds)"); } } private ILInstruction Stloc(int v) { - if (v >= 0 && v < localVariables.Length) { + if (v >= 0 && v < localVariables.Length) + { return new StLoc(localVariables[v], Pop(localVariables[v].StackType)) { ILStackWasEmpty = currentStack.IsEmpty }; - } else { + } + else + { Pop(); return new InvalidExpression($"stloc {v} (out-of-bounds)"); } } - + private ILInstruction LdElem(IType type) { return Push(new LdObj(new LdElema(indices: Pop(), array: Pop(), type: type) { DelayExceptions = true }, type)); } - + private ILInstruction StElem(IType type) { var value = Pop(type.GetStackType()); @@ -1397,29 +1517,35 @@ namespace ICSharpCode.Decompiler.IL var method = ReadAndDecodeMethodReference(); int firstArgument = (opCode != OpCode.NewObj && !method.IsStatic) ? 1 : 0; var arguments = new ILInstruction[firstArgument + method.Parameters.Count]; - for (int i = method.Parameters.Count - 1; i >= 0; i--) { + for (int i = method.Parameters.Count - 1; i >= 0; i--) + { arguments[firstArgument + i] = Pop(method.Parameters[i].Type.GetStackType()); } - if (firstArgument == 1) { + if (firstArgument == 1) + { arguments[0] = Pop(CallInstruction.ExpectedTypeForThisPointer(constrainedPrefix ?? method.DeclaringType)); } - switch (method.DeclaringType.Kind) { + switch (method.DeclaringType.Kind) + { case TypeKind.Array: var elementType = ((ArrayType)method.DeclaringType).ElementType; if (opCode == OpCode.NewObj) return Push(new NewArr(elementType, arguments)); - if (method.Name == "Set") { + if (method.Name == "Set") + { var target = arguments[0]; var value = arguments.Last(); var indices = arguments.Skip(1).Take(arguments.Length - 2).ToArray(); return new StObj(new LdElema(elementType, target, indices) { DelayExceptions = true }, value, elementType); } - if (method.Name == "Get") { + if (method.Name == "Get") + { var target = arguments[0]; var indices = arguments.Skip(1).ToArray(); return Push(new LdObj(new LdElema(elementType, target, indices) { DelayExceptions = true }, elementType)); } - if (method.Name == "Address") { + if (method.Name == "Address") + { var target = arguments[0]; var indices = arguments.Skip(1).ToArray(); return Push(new LdElema(elementType, target, indices)); @@ -1444,10 +1570,12 @@ namespace ICSharpCode.Decompiler.IL var functionPointer = Pop(StackType.I); int firstArgument = signature.Header.IsInstance ? 1 : 0; var arguments = new ILInstruction[firstArgument + signature.ParameterTypes.Length]; - for (int i = signature.ParameterTypes.Length - 1; i >= 0; i--) { + for (int i = signature.ParameterTypes.Length - 1; i >= 0; i--) + { arguments[firstArgument + i] = Pop(signature.ParameterTypes[i].GetStackType()); } - if (firstArgument == 1) { + if (firstArgument == 1) + { arguments[0] = Pop(); } var call = new CallIndirect( @@ -1470,15 +1598,20 @@ namespace ICSharpCode.Decompiler.IL var right = Pop(); var left = Pop(); - if (left.ResultType == StackType.O && right.ResultType.IsIntegerType()) { + if (left.ResultType == StackType.O && right.ResultType.IsIntegerType()) + { // C++/CLI sometimes compares object references with integers. - if (right.ResultType == StackType.I4) { + if (right.ResultType == StackType.I4) + { // ensure we compare at least native integer size right = new Conv(right, PrimitiveType.I, false, Sign.None); } left = new Conv(left, right.ResultType.ToPrimitiveType(), false, Sign.None); - } else if (right.ResultType == StackType.O && left.ResultType.IsIntegerType()) { - if (left.ResultType == StackType.I4) { + } + else if (right.ResultType == StackType.O && left.ResultType.IsIntegerType()) + { + if (left.ResultType == StackType.I4) + { left = new Conv(left, PrimitiveType.I, false, Sign.None); } right = new Conv(right, left.ResultType.ToPrimitiveType(), false, Sign.None); @@ -1490,29 +1623,43 @@ namespace ICSharpCode.Decompiler.IL MakeExplicitConversion(sourceType: StackType.I, targetType: StackType.I8, conversionType: PrimitiveType.I8); // Based on Table 4: Binary Comparison or Branch Operation - if (left.ResultType.IsFloatType() && right.ResultType.IsFloatType()) { - if (left.ResultType != right.ResultType) { + if (left.ResultType.IsFloatType() && right.ResultType.IsFloatType()) + { + if (left.ResultType != right.ResultType) + { // make the implicit F4->F8 conversion explicit: MakeExplicitConversion(StackType.F4, StackType.F8, PrimitiveType.R8); } - if (un) { + if (un) + { // for floats, 'un' means 'unordered' return Comp.LogicNot(new Comp(kind.Negate(), Sign.None, left, right)); - } else { + } + else + { return new Comp(kind, Sign.None, left, right); } - } else if (left.ResultType.IsIntegerType() && right.ResultType.IsIntegerType() && !kind.IsEqualityOrInequality()) { + } + else if (left.ResultType.IsIntegerType() && right.ResultType.IsIntegerType() && !kind.IsEqualityOrInequality()) + { // integer comparison where the sign matters Debug.Assert(right.ResultType.IsIntegerType()); return new Comp(kind, un ? Sign.Unsigned : Sign.Signed, left, right); - } else if (left.ResultType == right.ResultType) { + } + else if (left.ResultType == right.ResultType) + { // integer equality, object reference or managed reference comparison return new Comp(kind, Sign.None, left, right); - } else { + } + else + { Warn($"Invalid comparison between {left.ResultType} and {right.ResultType}"); - if (left.ResultType < right.ResultType) { + if (left.ResultType < right.ResultType) + { left = new Conv(left, right.ResultType.ToPrimitiveType(), false, Sign.Signed); - } else { + } + else + { right = new Conv(right, left.ResultType.ToPrimitiveType(), false, Sign.Signed); } return new Comp(kind, Sign.None, left, right); @@ -1520,26 +1667,32 @@ namespace ICSharpCode.Decompiler.IL void MakeExplicitConversion(StackType sourceType, StackType targetType, PrimitiveType conversionType) { - if (left.ResultType == sourceType && right.ResultType == targetType) { + if (left.ResultType == sourceType && right.ResultType == targetType) + { left = new Conv(left, conversionType, false, Sign.None); - } else if (left.ResultType == targetType && right.ResultType == sourceType) { + } + else if (left.ResultType == targetType && right.ResultType == sourceType) + { right = new Conv(right, conversionType, false, Sign.None); } } } bool IsInvalidBranch(int target) => target < 0 || target >= reader.Length; - + ILInstruction DecodeComparisonBranch(ILOpCode opCode, ComparisonKind kind, bool un = false) { int start = reader.Offset - 1; // opCode is always one byte in this case int target = ILParser.DecodeBranchTarget(ref reader, opCode); var condition = Comparison(kind, un); condition.AddILRange(new Interval(start, reader.Offset)); - if (!IsInvalidBranch(target)) { + if (!IsInvalidBranch(target)) + { MarkBranchTarget(target); return new IfInstruction(condition, new Branch(target)); - } else { + } + else + { return new IfInstruction(condition, new InvalidBranch("Invalid branch target")); } } @@ -1548,7 +1701,8 @@ namespace ICSharpCode.Decompiler.IL { int target = ILParser.DecodeBranchTarget(ref reader, opCode); ILInstruction condition = Pop(); - switch (condition.ResultType) { + switch (condition.ResultType) + { case StackType.O: // introduce explicit comparison with null condition = new Comp( @@ -1574,21 +1728,26 @@ namespace ICSharpCode.Decompiler.IL Sign.None, new Conv(condition, PrimitiveType.I, false, Sign.None), new Conv(new LdcI4(0), PrimitiveType.I, false, Sign.None)); break; case StackType.I4: - if (negate) { + if (negate) + { condition = Comp.LogicNot(condition); } break; default: condition = new Conv(condition, PrimitiveType.I4, false, Sign.None); - if (negate) { + if (negate) + { condition = Comp.LogicNot(condition); } break; } - if (!IsInvalidBranch(target)) { + if (!IsInvalidBranch(target)) + { MarkBranchTarget(target); return new IfInstruction(condition, new Branch(target)); - } else { + } + else + { return new IfInstruction(condition, new InvalidBranch("Invalid branch target")); } } @@ -1596,13 +1755,17 @@ namespace ICSharpCode.Decompiler.IL ILInstruction DecodeUnconditionalBranch(ILOpCode opCode, bool isLeave = false) { int target = ILParser.DecodeBranchTarget(ref reader, opCode); - if (isLeave) { + if (isLeave) + { currentStack = currentStack.Clear(); } - if (!IsInvalidBranch(target)) { + if (!IsInvalidBranch(target)) + { MarkBranchTarget(target); return new Branch(target); - } else { + } + else + { return new InvalidBranch("Invalid branch target"); } } @@ -1617,15 +1780,19 @@ namespace ICSharpCode.Decompiler.IL { var targets = ILParser.DecodeSwitchTargets(ref reader); var instr = new SwitchInstruction(Pop(StackType.I4)); - - for (int i = 0; i < targets.Length; i++) { + + for (int i = 0; i < targets.Length; i++) + { var section = new SwitchSection(); section.Labels = new LongSet(i); int target = targets[i]; - if (!IsInvalidBranch(target)) { + if (!IsInvalidBranch(target)) + { MarkBranchTarget(target); section.Body = new Branch(target); - } else { + } + else + { section.Body = new InvalidBranch("Invalid branch target"); } instr.Sections.Add(section); @@ -1636,21 +1803,25 @@ namespace ICSharpCode.Decompiler.IL instr.Sections.Add(defaultSection); return instr; } - + ILInstruction BinaryNumeric(BinaryNumericOperator @operator, bool checkForOverflow = false, Sign sign = Sign.None) { var right = Pop(); var left = Pop(); - if (@operator != BinaryNumericOperator.Add && @operator != BinaryNumericOperator.Sub) { + if (@operator != BinaryNumericOperator.Add && @operator != BinaryNumericOperator.Sub) + { // we are treating all Refs as I, make the conversion explicit - if (left.ResultType == StackType.Ref) { + if (left.ResultType == StackType.Ref) + { left = new Conv(left, PrimitiveType.I, false, Sign.None); } - if (right.ResultType == StackType.Ref) { + if (right.ResultType == StackType.Ref) + { right = new Conv(right, PrimitiveType.I, false, Sign.None); } } - if (@operator != BinaryNumericOperator.ShiftLeft && @operator != BinaryNumericOperator.ShiftRight) { + if (@operator != BinaryNumericOperator.ShiftLeft && @operator != BinaryNumericOperator.ShiftRight) + { // make the implicit I4->I conversion explicit: MakeExplicitConversion(sourceType: StackType.I4, targetType: StackType.I, conversionType: PrimitiveType.I); // I4->I8 conversion: @@ -1664,9 +1835,12 @@ namespace ICSharpCode.Decompiler.IL void MakeExplicitConversion(StackType sourceType, StackType targetType, PrimitiveType conversionType) { - if (left.ResultType == sourceType && right.ResultType == targetType) { + if (left.ResultType == sourceType && right.ResultType == targetType) + { left = new Conv(left, conversionType, false, Sign.None); - } else if (left.ResultType == targetType && right.ResultType == sourceType) { + } + else if (left.ResultType == targetType && right.ResultType == sourceType) + { right = new Conv(right, conversionType, false, Sign.None); } } @@ -1679,10 +1853,12 @@ namespace ICSharpCode.Decompiler.IL Call call = new Call(method); call.IsTail = true; call.ILStackWasEmpty = true; - if (!method.IsStatic) { + if (!method.IsStatic) + { call.Arguments.Add(Ldarg(0)); } - foreach (var p in method.Parameters) { + foreach (var p in method.Parameters) + { call.Arguments.Add(Ldarg(call.Arguments.Count)); } return new Leave(mainContainer, call); @@ -1692,7 +1868,8 @@ namespace ICSharpCode.Decompiler.IL { if (token.Kind.IsTypeKind()) return new LdTypeToken(module.ResolveType(token, genericContext)); - if (token.Kind.IsMemberKind()) { + if (token.Kind.IsMemberKind()) + { var entity = module.ResolveEntity(token, genericContext); if (entity is IMember member) return new LdMemberToken(member); diff --git a/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs b/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs index 1bca64d88..fef012cac 100644 --- a/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs +++ b/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs @@ -16,16 +16,18 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using ICSharpCode.Decompiler.TypeSystem; using System.Reflection.Metadata; +using ICSharpCode.Decompiler.TypeSystem; + namespace ICSharpCode.Decompiler.IL { static class ILTypeExtensions { public static StackType GetStackType(this PrimitiveType primitiveType) { - switch (primitiveType) { + switch (primitiveType) + { case PrimitiveType.I1: case PrimitiveType.U1: case PrimitiveType.I2: @@ -52,10 +54,11 @@ namespace ICSharpCode.Decompiler.IL return StackType.O; } } - + public static Sign GetSign(this PrimitiveType primitiveType) { - switch (primitiveType) { + switch (primitiveType) + { case PrimitiveType.I1: case PrimitiveType.I2: case PrimitiveType.I4: @@ -75,7 +78,7 @@ namespace ICSharpCode.Decompiler.IL return Sign.None; } } - + /// /// Gets the size in bytes of the primitive type. /// @@ -84,7 +87,8 @@ namespace ICSharpCode.Decompiler.IL /// public static int GetSize(this PrimitiveType type) { - switch (type) { + switch (type) + { case PrimitiveType.I1: case PrimitiveType.U1: return 1; @@ -108,7 +112,7 @@ namespace ICSharpCode.Decompiler.IL return 0; } } - + /// /// Gets whether the type is a small integer type. /// Small integer types are: @@ -119,7 +123,7 @@ namespace ICSharpCode.Decompiler.IL { return GetSize(type) < 4; } - + public static bool IsIntegerType(this PrimitiveType primitiveType) { return primitiveType.GetStackType().IsIntegerType(); @@ -127,7 +131,8 @@ namespace ICSharpCode.Decompiler.IL public static bool IsFloatType(this PrimitiveType type) { - switch (type) { + switch (type) + { case PrimitiveType.R4: case PrimitiveType.R8: case PrimitiveType.R: @@ -144,7 +149,8 @@ namespace ICSharpCode.Decompiler.IL /// public static IType InferType(this ILInstruction inst, ICompilation compilation) { - switch (inst) { + switch (inst) + { case NewObj newObj: return newObj.Method.DeclaringType; case NewArr newArr: @@ -175,8 +181,10 @@ namespace ICSharpCode.Decompiler.IL case LdsFlda ldsflda: return new ByReferenceType(ldsflda.Field.Type); case LdElema ldelema: - if (ldelema.Array.InferType(compilation) is ArrayType arrayType) { - if (TypeUtils.IsCompatibleTypeForMemoryAccess(arrayType.ElementType, ldelema.Type)) { + if (ldelema.Array.InferType(compilation) is ArrayType arrayType) + { + if (TypeUtils.IsCompatibleTypeForMemoryAccess(arrayType.ElementType, ldelema.Type)) + { return new ByReferenceType(arrayType.ElementType); } } @@ -184,7 +192,8 @@ namespace ICSharpCode.Decompiler.IL case Comp comp: if (compilation == null) return SpecialType.UnknownType; - switch (comp.LiftingKind) { + switch (comp.LiftingKind) + { case ComparisonLiftingKind.None: case ComparisonLiftingKind.CSharp: return compilation.FindType(KnownTypeCode.Boolean); @@ -196,7 +205,8 @@ namespace ICSharpCode.Decompiler.IL case BinaryNumericInstruction bni: if (bni.IsLifted) return SpecialType.UnknownType; - switch (bni.Operator) { + switch (bni.Operator) + { case BinaryNumericOperator.BitAnd: case BinaryNumericOperator.BitOr: case BinaryNumericOperator.BitXor: diff --git a/ICSharpCode.Decompiler/IL/ILVariable.cs b/ICSharpCode.Decompiler/IL/ILVariable.cs index fb833467d..b162d2526 100644 --- a/ICSharpCode.Decompiler/IL/ILVariable.cs +++ b/ICSharpCode.Decompiler/IL/ILVariable.cs @@ -18,10 +18,11 @@ using System; using System.Collections.Generic; -using ICSharpCode.Decompiler.TypeSystem; using System.Diagnostics; using System.Linq; +using ICSharpCode.Decompiler.TypeSystem; + namespace ICSharpCode.Decompiler.IL { public enum VariableKind @@ -94,7 +95,8 @@ namespace ICSharpCode.Decompiler.IL public static bool IsLocal(this VariableKind kind) { - switch (kind) { + switch (kind) + { case VariableKind.Local: case VariableKind.ExceptionLocal: case VariableKind.ForeachLocal: @@ -121,7 +123,8 @@ namespace ICSharpCode.Decompiler.IL internal set { if (kind == VariableKind.Parameter) throw new InvalidOperationException("Kind=Parameter cannot be changed!"); - if (Index != null && value.IsLocal() && !kind.IsLocal()) { + if (Index != null && value.IsLocal() && !kind.IsLocal()) + { // For variables, Index has different meaning than for stack slots, // so we need to reset it to null. // StackSlot -> ForeachLocal can happen sometimes (e.g. PST.TransformForeachOnArray) @@ -132,7 +135,7 @@ namespace ICSharpCode.Decompiler.IL } public readonly StackType StackType; - + IType type; public IType Type { get { @@ -149,7 +152,7 @@ namespace ICSharpCode.Decompiler.IL /// This variable is either a C# 7 'in' parameter or must be declared as 'ref readonly'. /// public bool IsRefReadOnly { get; internal set; } - + /// /// The index of the local variable or parameter (depending on Kind) /// @@ -162,11 +165,12 @@ namespace ICSharpCode.Decompiler.IL /// For other kinds, the index has no meaning, and is usually null. /// public int? Index { get; private set; } - + [Conditional("DEBUG")] internal void CheckInvariant() { - switch (kind) { + switch (kind) + { case VariableKind.Local: case VariableKind.ForeachLocal: case VariableKind.PinnedLocal: @@ -199,7 +203,7 @@ namespace ICSharpCode.Decompiler.IL /// This property is set automatically when the variable is added to the ILFunction.Variables collection. /// public ILFunction Function { get; internal set; } - + /// /// Gets the block container in which this variable is captured. /// For captured variables declared inside the loop, the capture scope is the BlockContainer of the loop. @@ -315,7 +319,7 @@ namespace ICSharpCode.Decompiler.IL } bool hasInitialValue; - + /// /// Gets/Sets whether the variable has an initial value. /// This is always true for parameters (incl. this). @@ -380,7 +384,7 @@ namespace ICSharpCode.Decompiler.IL this.HasInitialValue = true; CheckInvariant(); } - + public ILVariable(VariableKind kind, IType type, StackType stackType, int? index = null) { if (type == null) @@ -398,13 +402,15 @@ namespace ICSharpCode.Decompiler.IL { return Name; } - + internal void WriteDefinitionTo(ITextOutput output) { - if (IsRefReadOnly) { + if (IsRefReadOnly) + { output.Write("readonly "); } - switch (Kind) { + switch (Kind) + { case VariableKind.Local: output.Write("local "); break; @@ -454,36 +460,42 @@ namespace ICSharpCode.Decompiler.IL output.Write(" : "); Type.WriteTo(output); output.Write('('); - if (Kind == VariableKind.Parameter || Kind == VariableKind.Local || Kind == VariableKind.PinnedLocal || Kind == VariableKind.PinnedRegionLocal) { + if (Kind == VariableKind.Parameter || Kind == VariableKind.Local || Kind == VariableKind.PinnedLocal || Kind == VariableKind.PinnedRegionLocal) + { output.Write("Index={0}, ", Index); } output.Write("LoadCount={0}, AddressCount={1}, StoreCount={2})", LoadCount, AddressCount, StoreCount); - if (hasInitialValue && Kind != VariableKind.Parameter) { + if (hasInitialValue && Kind != VariableKind.Parameter) + { output.Write(" init"); } - if (CaptureScope != null) { + if (CaptureScope != null) + { output.Write(" captured in "); output.WriteLocalReference(CaptureScope.EntryPoint.Label, CaptureScope); } - if (StateMachineField != null) { + if (StateMachineField != null) + { output.Write(" from state-machine"); } } - + internal void WriteTo(ITextOutput output) { output.WriteLocalReference(this.Name, this); } - + /// /// Gets whether this variable occurs within the specified instruction. /// internal bool IsUsedWithin(ILInstruction inst) { - if (inst is IInstructionWithVariableOperand iwvo && iwvo.Variable == this) { + if (inst is IInstructionWithVariableOperand iwvo && iwvo.Variable == this) + { return true; } - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { if (IsUsedWithin(child)) return true; } diff --git a/ICSharpCode.Decompiler/IL/InstructionFlags.cs b/ICSharpCode.Decompiler/IL/InstructionFlags.cs index f451c9ab2..49f7ff1b8 100644 --- a/ICSharpCode.Decompiler/IL/InstructionFlags.cs +++ b/ICSharpCode.Decompiler/IL/InstructionFlags.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.IL /// is not considered a side effect, and is modeled by separate flags. /// SideEffect = 0x40, - + /// /// The instruction may throw an exception. /// diff --git a/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs b/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs index b49739bda..b29d768b7 100644 --- a/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs +++ b/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs @@ -20,6 +20,7 @@ using System; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; + using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -43,12 +44,12 @@ namespace ICSharpCode.Decompiler.IL { output.Write(primitiveType.ToString().ToLowerInvariant()); } - + public static void WriteTo(this IType type, ITextOutput output) { output.WriteReference(type, type.ReflectionName); } - + public static void WriteTo(this IMember member, ITextOutput output) { if (member is IMethod method && method.IsConstructor) @@ -69,7 +70,8 @@ namespace ICSharpCode.Decompiler.IL public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput output, Metadata.GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature) { - if (entity.IsNil) { + if (entity.IsNil) + { output.Write(""); return; } @@ -79,118 +81,146 @@ namespace ICSharpCode.Decompiler.IL Action signature; MethodSignature> methodSignature; string memberName; - switch (entity.Kind) { - case HandleKind.TypeDefinition: { - var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity); - output.WriteReference(module, entity, td.GetFullTypeName(metadata).ToILNameString()); - break; + switch (entity.Kind) + { + case HandleKind.TypeDefinition: + { + var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity); + output.WriteReference(module, entity, td.GetFullTypeName(metadata).ToILNameString()); + break; + } + case HandleKind.TypeReference: + { + var tr = metadata.GetTypeReference((TypeReferenceHandle)entity); + EntityHandle resolutionScope; + try + { + resolutionScope = tr.ResolutionScope; } - case HandleKind.TypeReference: { - var tr = metadata.GetTypeReference((TypeReferenceHandle)entity); - EntityHandle resolutionScope; - try { - resolutionScope = tr.ResolutionScope; - } catch (BadImageFormatException) { - resolutionScope = default; + catch (BadImageFormatException) + { + resolutionScope = default; + } + if (!resolutionScope.IsNil) + { + output.Write("["); + var currentTypeRef = tr; + while (currentTypeRef.ResolutionScope.Kind == HandleKind.TypeReference) + { + currentTypeRef = metadata.GetTypeReference((TypeReferenceHandle)currentTypeRef.ResolutionScope); } - if (!resolutionScope.IsNil) { - output.Write("["); - var currentTypeRef = tr; - while (currentTypeRef.ResolutionScope.Kind == HandleKind.TypeReference) { - currentTypeRef = metadata.GetTypeReference((TypeReferenceHandle)currentTypeRef.ResolutionScope); - } - switch (currentTypeRef.ResolutionScope.Kind) { - case HandleKind.ModuleDefinition: - var modDef = metadata.GetModuleDefinition(); - output.Write(DisassemblerHelpers.Escape(metadata.GetString(modDef.Name))); - break; - case HandleKind.ModuleReference: - break; - case HandleKind.AssemblyReference: - var asmRef = metadata.GetAssemblyReference((AssemblyReferenceHandle)currentTypeRef.ResolutionScope); - output.Write(DisassemblerHelpers.Escape(metadata.GetString(asmRef.Name))); - break; - } - output.Write("]"); + switch (currentTypeRef.ResolutionScope.Kind) + { + case HandleKind.ModuleDefinition: + var modDef = metadata.GetModuleDefinition(); + output.Write(DisassemblerHelpers.Escape(metadata.GetString(modDef.Name))); + break; + case HandleKind.ModuleReference: + break; + case HandleKind.AssemblyReference: + var asmRef = metadata.GetAssemblyReference((AssemblyReferenceHandle)currentTypeRef.ResolutionScope); + output.Write(DisassemblerHelpers.Escape(metadata.GetString(asmRef.Name))); + break; } - output.WriteReference(module, entity, entity.GetFullTypeName(metadata).ToILNameString()); - break; - } - case HandleKind.TypeSpecification: { - var ts = metadata.GetTypeSpecification((TypeSpecificationHandle)entity); - signature = ts.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), genericContext); - signature(syntax); - break; + output.Write("]"); } - case HandleKind.FieldDefinition: { - var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)entity); - signature = fd.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.GenericContext(fd.GetDeclaringType(), module)); - signature(ILNameSyntax.SignatureNoNamedTypeParameters); - output.Write(' '); - ((EntityHandle)fd.GetDeclaringType()).WriteTo(module, output, Metadata.GenericContext.Empty, ILNameSyntax.TypeName); + output.WriteReference(module, entity, entity.GetFullTypeName(metadata).ToILNameString()); + break; + } + case HandleKind.TypeSpecification: + { + var ts = metadata.GetTypeSpecification((TypeSpecificationHandle)entity); + signature = ts.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), genericContext); + signature(syntax); + break; + } + case HandleKind.FieldDefinition: + { + var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)entity); + signature = fd.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.GenericContext(fd.GetDeclaringType(), module)); + signature(ILNameSyntax.SignatureNoNamedTypeParameters); + output.Write(' '); + ((EntityHandle)fd.GetDeclaringType()).WriteTo(module, output, Metadata.GenericContext.Empty, ILNameSyntax.TypeName); + output.Write("::"); + output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(fd.Name))); + break; + } + case HandleKind.MethodDefinition: + { + var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity); + methodSignature = md.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.GenericContext((MethodDefinitionHandle)entity, module)); + WriteSignatureHeader(output, methodSignature); + methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); + output.Write(' '); + var declaringType = md.GetDeclaringType(); + if (!declaringType.IsNil) + { + ((EntityHandle)declaringType).WriteTo(module, output, genericContext, ILNameSyntax.TypeName); output.Write("::"); - output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(fd.Name))); - break; } - case HandleKind.MethodDefinition: { - var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity); - methodSignature = md.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new Metadata.GenericContext((MethodDefinitionHandle)entity, module)); - WriteSignatureHeader(output, methodSignature); - methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); - output.Write(' '); - var declaringType = md.GetDeclaringType(); - if (!declaringType.IsNil) { - ((EntityHandle)declaringType).WriteTo(module, output, genericContext, ILNameSyntax.TypeName); - output.Write("::"); - } - bool isCompilerControlled = (md.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; - if (isCompilerControlled) { - output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name) + "$PST" + MetadataTokens.GetToken(entity).ToString("X8"))); - } else { - output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name))); - } - var genericParameters = md.GetGenericParameters(); - if (genericParameters.Count > 0) { - output.Write('<'); - for (int i = 0; i < genericParameters.Count; i++) { - if (i > 0) - output.Write(", "); - var gp = metadata.GetGenericParameter(genericParameters[i]); - if ((gp.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == GenericParameterAttributes.ReferenceTypeConstraint) { - output.Write("class "); - } else if ((gp.Attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) == GenericParameterAttributes.NotNullableValueTypeConstraint) { - output.Write("valuetype "); - } - if ((gp.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) == GenericParameterAttributes.DefaultConstructorConstraint) { - output.Write(".ctor "); - } - var constraints = gp.GetConstraints(); - if (constraints.Count > 0) { - output.Write('('); - for (int j = 0; j < constraints.Count; j++) { - if (j > 0) - output.Write(", "); - var constraint = metadata.GetGenericParameterConstraint(constraints[j]); - constraint.Type.WriteTo(module, output, new Metadata.GenericContext((MethodDefinitionHandle)entity, module), ILNameSyntax.TypeName); - } - output.Write(") "); - } - if ((gp.Attributes & GenericParameterAttributes.Contravariant) == GenericParameterAttributes.Contravariant) { - output.Write('-'); - } else if ((gp.Attributes & GenericParameterAttributes.Covariant) == GenericParameterAttributes.Covariant) { - output.Write('+'); + bool isCompilerControlled = (md.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; + if (isCompilerControlled) + { + output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name) + "$PST" + MetadataTokens.GetToken(entity).ToString("X8"))); + } + else + { + output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name))); + } + var genericParameters = md.GetGenericParameters(); + if (genericParameters.Count > 0) + { + output.Write('<'); + for (int i = 0; i < genericParameters.Count; i++) + { + if (i > 0) + output.Write(", "); + var gp = metadata.GetGenericParameter(genericParameters[i]); + if ((gp.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == GenericParameterAttributes.ReferenceTypeConstraint) + { + output.Write("class "); + } + else if ((gp.Attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) == GenericParameterAttributes.NotNullableValueTypeConstraint) + { + output.Write("valuetype "); + } + if ((gp.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) == GenericParameterAttributes.DefaultConstructorConstraint) + { + output.Write(".ctor "); + } + var constraints = gp.GetConstraints(); + if (constraints.Count > 0) + { + output.Write('('); + for (int j = 0; j < constraints.Count; j++) + { + if (j > 0) + output.Write(", "); + var constraint = metadata.GetGenericParameterConstraint(constraints[j]); + constraint.Type.WriteTo(module, output, new Metadata.GenericContext((MethodDefinitionHandle)entity, module), ILNameSyntax.TypeName); } - output.Write(DisassemblerHelpers.Escape(metadata.GetString(gp.Name))); + output.Write(") "); + } + if ((gp.Attributes & GenericParameterAttributes.Contravariant) == GenericParameterAttributes.Contravariant) + { + output.Write('-'); + } + else if ((gp.Attributes & GenericParameterAttributes.Covariant) == GenericParameterAttributes.Covariant) + { + output.Write('+'); } - output.Write('>'); + output.Write(DisassemblerHelpers.Escape(metadata.GetString(gp.Name))); } - WriteParameterList(output, methodSignature); - break; + output.Write('>'); } + WriteParameterList(output, methodSignature); + break; + } case HandleKind.MemberReference: var mr = metadata.GetMemberReference((MemberReferenceHandle)entity); memberName = metadata.GetString(mr.Name); - switch (mr.GetKind()) { + switch (mr.GetKind()) + { case MemberReferenceKind.Method: methodSignature = mr.DecodeMethodSignature(new DisassemblerSignatureTypeProvider(module, output), genericContext); WriteSignatureHeader(output, methodSignature); @@ -214,7 +244,8 @@ namespace ICSharpCode.Decompiler.IL case HandleKind.MethodSpecification: var ms = metadata.GetMethodSpecification((MethodSpecificationHandle)entity); var substitution = ms.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), genericContext); - switch (ms.Method.Kind) { + switch (ms.Method.Kind) + { case HandleKind.MethodDefinition: var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)ms.Method); var methodName = metadata.GetString(methodDefinition.Name); @@ -223,14 +254,18 @@ namespace ICSharpCode.Decompiler.IL methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); output.Write(' '); var declaringType = methodDefinition.GetDeclaringType(); - if (!declaringType.IsNil) { + if (!declaringType.IsNil) + { ((EntityHandle)declaringType).WriteTo(module, output, genericContext, ILNameSyntax.TypeName); output.Write("::"); } bool isCompilerControlled = (methodDefinition.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; - if (isCompilerControlled) { + if (isCompilerControlled) + { output.Write(DisassemblerHelpers.Escape(methodName + "$PST" + MetadataTokens.GetToken(ms.Method).ToString("X8"))); - } else { + } + else + { output.Write(DisassemblerHelpers.Escape(methodName)); } WriteTypeParameterList(output, syntax, substitution); @@ -254,7 +289,8 @@ namespace ICSharpCode.Decompiler.IL case HandleKind.StandaloneSignature: var standaloneSig = metadata.GetStandaloneSignature((StandaloneSignatureHandle)entity); var header = metadata.GetBlobReader(standaloneSig.Signature).ReadSignatureHeader(); - switch (header.Kind) { + switch (header.Kind) + { case SignatureKind.Method: methodSignature = standaloneSig.DecodeMethodSignature(new DisassemblerSignatureTypeProvider(module, output), genericContext); WriteSignatureHeader(output, methodSignature); @@ -275,7 +311,8 @@ namespace ICSharpCode.Decompiler.IL static void WriteTypeParameterList(ITextOutput output, ILNameSyntax syntax, System.Collections.Immutable.ImmutableArray> substitution) { output.Write('<'); - for (int i = 0; i < substitution.Length; i++) { + for (int i = 0; i < substitution.Length; i++) + { if (i > 0) output.Write(", "); substitution[i](syntax); @@ -286,7 +323,8 @@ namespace ICSharpCode.Decompiler.IL static void WriteParameterList(ITextOutput output, MethodSignature> methodSignature) { output.Write("("); - for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) { + for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) + { if (i > 0) output.Write(", "); if (i == methodSignature.RequiredParameterCount) @@ -298,12 +336,16 @@ namespace ICSharpCode.Decompiler.IL static void WriteSignatureHeader(ITextOutput output, MethodSignature> methodSignature) { - if (methodSignature.Header.HasExplicitThis) { + if (methodSignature.Header.HasExplicitThis) + { output.Write("instance explicit "); - } else if (methodSignature.Header.IsInstance) { + } + else if (methodSignature.Header.IsInstance) + { output.Write("instance "); } - switch (methodSignature.Header.CallingConvention) { + switch (methodSignature.Header.CallingConvention) + { case SignatureCallingConvention.CDecl: output.Write("unmanaged cdecl "); break; @@ -324,7 +366,8 @@ namespace ICSharpCode.Decompiler.IL static void WriteParent(ITextOutput output, PEFile module, MetadataReader metadata, EntityHandle parentHandle, Metadata.GenericContext genericContext, ILNameSyntax syntax) { - switch (parentHandle.Kind) { + switch (parentHandle.Kind) + { case HandleKind.MethodDefinition: var methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)parentHandle); ((EntityHandle)methodDef.GetDeclaringType()).WriteTo(module, output, genericContext, syntax); diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index 66af1937e..6f45ece73 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL @@ -255,21 +256,24 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { default: throw new IndexOutOfRangeException(); } } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { default: throw new IndexOutOfRangeException(); } } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { default: throw new IndexOutOfRangeException(); } @@ -314,7 +318,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.argument; default: @@ -323,7 +328,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Argument = value; break; @@ -333,7 +339,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ArgumentSlot; default: @@ -399,7 +406,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.left; case 1: @@ -410,7 +418,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Left = value; break; @@ -423,7 +432,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return LeftSlot; case 1: @@ -478,14 +488,16 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { default: return this.Arguments[index - 0]; } } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { default: this.Arguments[index - 0] = (ILInstruction)value; break; @@ -493,7 +505,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { default: return ArgumentsSlot; } @@ -556,7 +569,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.target; case 1: @@ -567,7 +581,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Target = value; break; @@ -580,7 +595,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return TargetSlot; case 1: @@ -761,7 +777,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.body; default: @@ -770,7 +787,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Body = value; break; @@ -781,7 +799,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return BodySlot; default: @@ -892,26 +911,26 @@ namespace ICSharpCode.Decompiler.IL variable.AddStoreInstruction(this); } } - + public int IndexInStoreInstructionList { get; set; } = -1; - + int IInstructionWithVariableOperand.IndexInVariableInstructionMapping { get { return ((IStoreInstruction)this).IndexInStoreInstructionList; } set { ((IStoreInstruction)this).IndexInStoreInstructionList = value; } } - + protected override void Connected() { base.Connected(); variable.AddStoreInstruction(this); } - + protected override void Disconnected() { variable.RemoveStoreInstruction(this); base.Disconnected(); } - + public static readonly SlotInfo InitSlot = new SlotInfo("Init", canInlineInto: true); ILInstruction init; public ILInstruction Init { @@ -936,7 +955,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.init; case 1: @@ -947,7 +967,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Init = value; break; @@ -960,7 +981,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return InitSlot; case 1: @@ -1254,7 +1276,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.value; default: @@ -1263,7 +1286,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Value = value; break; @@ -1273,7 +1297,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ValueSlot; default: @@ -1344,7 +1369,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.condition; case 1: @@ -1357,7 +1383,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Condition = value; break; @@ -1373,7 +1400,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ConditionSlot; case 1: @@ -1440,7 +1468,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.valueInst; case 1: @@ -1451,7 +1480,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.ValueInst = value; break; @@ -1464,7 +1494,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ValueInstSlot; case 1: @@ -1544,7 +1575,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.body; default: @@ -1553,7 +1585,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Body = value; break; @@ -1563,7 +1596,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return BodySlot; default: @@ -1657,7 +1691,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.filter; case 1: @@ -1668,7 +1703,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Filter = value; break; @@ -1681,7 +1717,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return FilterSlot; case 1: @@ -1709,26 +1746,26 @@ namespace ICSharpCode.Decompiler.IL variable.AddStoreInstruction(this); } } - + public int IndexInStoreInstructionList { get; set; } = -1; - + int IInstructionWithVariableOperand.IndexInVariableInstructionMapping { get { return ((IStoreInstruction)this).IndexInStoreInstructionList; } set { ((IStoreInstruction)this).IndexInStoreInstructionList = value; } } - + protected override void Connected() { base.Connected(); variable.AddStoreInstruction(this); } - + protected override void Disconnected() { variable.RemoveStoreInstruction(this); base.Disconnected(); } - + public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitTryCatchHandler(this); @@ -1832,7 +1869,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.onExpression; case 1: @@ -1843,7 +1881,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.OnExpression = value; break; @@ -1856,7 +1895,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return OnExpressionSlot; case 1: @@ -1930,26 +1970,26 @@ namespace ICSharpCode.Decompiler.IL variable.AddStoreInstruction(this); } } - + public int IndexInStoreInstructionList { get; set; } = -1; - + int IInstructionWithVariableOperand.IndexInVariableInstructionMapping { get { return ((IStoreInstruction)this).IndexInStoreInstructionList; } set { ((IStoreInstruction)this).IndexInStoreInstructionList = value; } } - + protected override void Connected() { base.Connected(); variable.AddStoreInstruction(this); } - + protected override void Disconnected() { variable.RemoveStoreInstruction(this); base.Disconnected(); } - + public static readonly SlotInfo ResourceExpressionSlot = new SlotInfo("ResourceExpression", canInlineInto: true); ILInstruction resourceExpression; public ILInstruction ResourceExpression { @@ -1974,7 +2014,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.resourceExpression; case 1: @@ -1985,7 +2026,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.ResourceExpression = value; break; @@ -1998,7 +2040,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ResourceExpressionSlot; case 1: @@ -2267,26 +2310,26 @@ namespace ICSharpCode.Decompiler.IL variable.AddLoadInstruction(this); } } - + public int IndexInLoadInstructionList { get; set; } = -1; - + int IInstructionWithVariableOperand.IndexInVariableInstructionMapping { get { return ((ILoadInstruction)this).IndexInLoadInstructionList; } set { ((ILoadInstruction)this).IndexInLoadInstructionList = value; } } - + protected override void Connected() { base.Connected(); variable.AddLoadInstruction(this); } - + protected override void Disconnected() { variable.RemoveLoadInstruction(this); base.Disconnected(); } - + public override StackType ResultType { get { return variable.StackType; } } protected override InstructionFlags ComputeFlags() { @@ -2352,26 +2395,26 @@ namespace ICSharpCode.Decompiler.IL variable.AddAddressInstruction(this); } } - + public int IndexInAddressInstructionList { get; set; } = -1; - + int IInstructionWithVariableOperand.IndexInVariableInstructionMapping { get { return ((IAddressInstruction)this).IndexInAddressInstructionList; } set { ((IAddressInstruction)this).IndexInAddressInstructionList = value; } } - + protected override void Connected() { base.Connected(); variable.AddAddressInstruction(this); } - + protected override void Disconnected() { variable.RemoveAddressInstruction(this); base.Disconnected(); } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); @@ -2428,26 +2471,26 @@ namespace ICSharpCode.Decompiler.IL variable.AddStoreInstruction(this); } } - + public int IndexInStoreInstructionList { get; set; } = -1; - + int IInstructionWithVariableOperand.IndexInVariableInstructionMapping { get { return ((IStoreInstruction)this).IndexInStoreInstructionList; } set { ((IStoreInstruction)this).IndexInStoreInstructionList = value; } } - + protected override void Connected() { base.Connected(); variable.AddStoreInstruction(this); } - + protected override void Disconnected() { variable.RemoveStoreInstruction(this); base.Disconnected(); } - + public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true); ILInstruction value; public ILInstruction Value { @@ -2463,7 +2506,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.value; default: @@ -2472,7 +2516,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Value = value; break; @@ -2482,7 +2527,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ValueSlot; default: @@ -2559,7 +2605,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.value; default: @@ -2568,7 +2615,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Value = value; break; @@ -2578,7 +2626,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ValueSlot; default: @@ -3028,7 +3077,8 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (method != null) { + if (method != null) + { output.Write(' '); method.WriteTo(output); } @@ -3078,7 +3128,8 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (method != null) { + if (method != null) + { output.Write(' '); method.WriteTo(output); } @@ -3140,7 +3191,8 @@ namespace ICSharpCode.Decompiler.IL output.Write(OpCode); output.Write(' '); type.WriteTo(output); - if (method != null) { + if (method != null) + { output.Write(' '); method.WriteTo(output); } @@ -3383,7 +3435,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.destAddress; case 1: @@ -3396,7 +3449,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.DestAddress = value; break; @@ -3412,7 +3466,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return DestAddressSlot; case 1: @@ -3531,7 +3586,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.address; case 1: @@ -3544,7 +3600,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Address = value; break; @@ -3560,7 +3617,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return AddressSlot; case 1: @@ -3660,7 +3718,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.target; default: @@ -3669,7 +3728,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Target = value; break; @@ -3679,7 +3739,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return TargetSlot; default: @@ -3900,7 +3961,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.target; default: @@ -3909,7 +3971,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Target = value; break; @@ -3919,7 +3982,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return TargetSlot; default: @@ -4026,7 +4090,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.target; case 1: @@ -4037,7 +4102,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Target = value; break; @@ -4050,7 +4116,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return TargetSlot; case 1: @@ -4338,14 +4405,16 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { default: return this.Indices[index - 0]; } } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { default: this.Indices[index - 0] = (ILInstruction)value; break; @@ -4353,7 +4422,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { default: return IndicesSlot; } @@ -4383,8 +4453,12 @@ namespace ICSharpCode.Decompiler.IL type.WriteTo(output); output.Write('('); bool first = true; - foreach (var indices in Indices) { - if (!first) output.Write(", "); else first = false; + foreach (var indices in Indices) + { + if (!first) + output.Write(", "); + else + first = false; indices.WriteTo(output, options); } output.Write(')'); @@ -4586,7 +4660,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.array; default: @@ -4595,7 +4670,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Array = value; break; @@ -4605,7 +4681,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ArraySlot; default: @@ -4686,7 +4763,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.array; default: @@ -4695,7 +4773,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Array = value; break; @@ -4706,7 +4785,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ArraySlot; default: @@ -4749,7 +4829,8 @@ namespace ICSharpCode.Decompiler.IL type.WriteTo(output); output.Write('('); this.array.WriteTo(output, options); - foreach (var indices in Indices) { + foreach (var indices in Indices) + { output.Write(", "); indices.WriteTo(output, options); } @@ -4803,7 +4884,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.argument; default: @@ -4812,7 +4894,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Argument = value; break; @@ -4822,7 +4905,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ArgumentSlot; default: @@ -4852,7 +4936,8 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (method != null) { + if (method != null) + { output.Write(' '); method.WriteTo(output); } @@ -4904,7 +4989,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.argument; default: @@ -4913,7 +4999,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Argument = value; break; @@ -4923,7 +5010,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ArgumentSlot; default: @@ -5049,7 +5137,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.left; case 1: @@ -5060,7 +5149,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Left = value; break; @@ -5073,7 +5163,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return LeftSlot; case 1: @@ -5093,7 +5184,8 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (method != null) { + if (method != null) + { output.Write(' '); method.WriteTo(output); } @@ -5151,7 +5243,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.left; case 1: @@ -5162,7 +5255,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Left = value; break; @@ -5175,7 +5269,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return LeftSlot; case 1: @@ -5239,7 +5334,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.left; case 1: @@ -5250,7 +5346,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Left = value; break; @@ -5263,7 +5360,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return LeftSlot; case 1: @@ -5327,7 +5425,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.operand; default: @@ -5336,7 +5435,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Operand = value; break; @@ -5346,7 +5446,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return OperandSlot; default: @@ -5413,7 +5514,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.argument; default: @@ -5422,7 +5524,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Argument = value; break; @@ -5432,7 +5535,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ArgumentSlot; default: @@ -5498,7 +5602,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.target; default: @@ -5507,7 +5612,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Target = value; break; @@ -5517,7 +5623,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return TargetSlot; default: @@ -5592,7 +5699,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.target; case 1: @@ -5603,7 +5711,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Target = value; break; @@ -5616,7 +5725,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return TargetSlot; case 1: @@ -5678,14 +5788,16 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { default: return this.Arguments[index - 0]; } } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { default: this.Arguments[index - 0] = (ILInstruction)value; break; @@ -5693,7 +5805,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { default: return ArgumentsSlot; } @@ -5746,14 +5859,16 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { default: return this.Arguments[index - 0]; } } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { default: this.Arguments[index - 0] = (ILInstruction)value; break; @@ -5761,7 +5876,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { default: return ArgumentsSlot; } @@ -5814,14 +5930,16 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { default: return this.Arguments[index - 0]; } } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { default: this.Arguments[index - 0] = (ILInstruction)value; break; @@ -5829,7 +5947,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { default: return ArgumentsSlot; } @@ -5882,14 +6001,16 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { default: return this.Arguments[index - 0]; } } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { default: this.Arguments[index - 0] = (ILInstruction)value; break; @@ -5897,7 +6018,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { default: return ArgumentsSlot; } @@ -5950,14 +6072,16 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { default: return this.Arguments[index - 0]; } } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { default: this.Arguments[index - 0] = (ILInstruction)value; break; @@ -5965,7 +6089,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { default: return ArgumentsSlot; } @@ -6025,7 +6150,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.argument; default: @@ -6034,7 +6160,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Argument = value; break; @@ -6044,7 +6171,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ArgumentSlot; default: @@ -6116,26 +6244,26 @@ namespace ICSharpCode.Decompiler.IL variable.AddStoreInstruction(this); } } - + public int IndexInStoreInstructionList { get; set; } = -1; - + int IInstructionWithVariableOperand.IndexInVariableInstructionMapping { get { return ((IStoreInstruction)this).IndexInStoreInstructionList; } set { ((IStoreInstruction)this).IndexInStoreInstructionList = value; } } - + protected override void Connected() { base.Connected(); variable.AddStoreInstruction(this); } - + protected override void Disconnected() { variable.RemoveStoreInstruction(this); base.Disconnected(); } - + readonly IMethod method; /// Returns the method operand. public IMethod Method { get { return method; } } @@ -6160,7 +6288,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.testedOperand; default: @@ -6169,7 +6298,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.TestedOperand = value; break; @@ -6180,7 +6310,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return TestedOperandSlot; default: @@ -6382,7 +6513,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.value; default: @@ -6391,7 +6523,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Value = value; break; @@ -6401,7 +6534,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ValueSlot; default: @@ -6475,7 +6609,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return this.value; default: @@ -6484,7 +6619,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: this.Value = value; break; @@ -6494,7 +6630,8 @@ namespace ICSharpCode.Decompiler.IL } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return ValueSlot; default: @@ -6610,21 +6747,24 @@ namespace ICSharpCode.Decompiler.IL.Patterns } protected sealed override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { default: throw new IndexOutOfRangeException(); } } protected sealed override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { default: throw new IndexOutOfRangeException(); } } protected sealed override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { default: throw new IndexOutOfRangeException(); } @@ -6653,7 +6793,7 @@ namespace ICSharpCode.Decompiler.IL { /// Called by Visit*() methods that were not overridden protected abstract void Default(ILInstruction inst); - + protected internal virtual void VisitInvalidBranch(InvalidBranch inst) { Default(inst); @@ -7043,7 +7183,7 @@ namespace ICSharpCode.Decompiler.IL Default(inst); } } - + /// /// Base class for visitor pattern. /// @@ -7051,7 +7191,7 @@ namespace ICSharpCode.Decompiler.IL { /// Called by Visit*() methods that were not overridden protected abstract T Default(ILInstruction inst); - + protected internal virtual T VisitInvalidBranch(InvalidBranch inst) { return Default(inst); @@ -7449,7 +7589,7 @@ namespace ICSharpCode.Decompiler.IL { /// Called by Visit*() methods that were not overridden protected abstract T Default(ILInstruction inst, C context); - + protected internal virtual T VisitInvalidBranch(InvalidBranch inst, C context) { return Default(inst, context); @@ -7839,7 +7979,7 @@ namespace ICSharpCode.Decompiler.IL return Default(inst, context); } } - + partial class InstructionOutputExtensions { static readonly string[] originalOpCodeNames = { @@ -7943,13 +8083,14 @@ namespace ICSharpCode.Decompiler.IL "AnyNode", }; } - + partial class ILInstruction { public bool MatchInvalidBranch() { var inst = this as InvalidBranch; - if (inst != null) { + if (inst != null) + { return true; } return false; @@ -7957,7 +8098,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchInvalidExpression() { var inst = this as InvalidExpression; - if (inst != null) { + if (inst != null) + { return true; } return false; @@ -7965,7 +8107,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchNop() { var inst = this as Nop; - if (inst != null) { + if (inst != null) + { return true; } return false; @@ -7973,7 +8116,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchPinnedRegion(out ILVariable variable, out ILInstruction init, out ILInstruction body) { var inst = this as PinnedRegion; - if (inst != null) { + if (inst != null) + { variable = inst.Variable; init = inst.Init; body = inst.Body; @@ -7987,7 +8131,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchArglist() { var inst = this as Arglist; - if (inst != null) { + if (inst != null) + { return true; } return false; @@ -7995,7 +8140,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchTryCatchHandler(out ILInstruction filter, out ILInstruction body, out ILVariable variable) { var inst = this as TryCatchHandler; - if (inst != null) { + if (inst != null) + { filter = inst.Filter; body = inst.Body; variable = inst.Variable; @@ -8009,7 +8155,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLockInstruction(out ILInstruction onExpression, out ILInstruction body) { var inst = this as LockInstruction; - if (inst != null) { + if (inst != null) + { onExpression = inst.OnExpression; body = inst.Body; return true; @@ -8021,7 +8168,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchUsingInstruction(out ILVariable variable, out ILInstruction resourceExpression, out ILInstruction body) { var inst = this as UsingInstruction; - if (inst != null) { + if (inst != null) + { variable = inst.Variable; resourceExpression = inst.ResourceExpression; body = inst.Body; @@ -8035,7 +8183,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchDebugBreak() { var inst = this as DebugBreak; - if (inst != null) { + if (inst != null) + { return true; } return false; @@ -8043,7 +8192,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchCkfinite(out ILInstruction argument) { var inst = this as Ckfinite; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; return true; } @@ -8053,7 +8203,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdLoc(out ILVariable variable) { var inst = this as LdLoc; - if (inst != null) { + if (inst != null) + { variable = inst.Variable; return true; } @@ -8063,7 +8214,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdLoca(out ILVariable variable) { var inst = this as LdLoca; - if (inst != null) { + if (inst != null) + { variable = inst.Variable; return true; } @@ -8073,7 +8225,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchStLoc(out ILVariable variable, out ILInstruction value) { var inst = this as StLoc; - if (inst != null) { + if (inst != null) + { variable = inst.Variable; value = inst.Value; return true; @@ -8085,7 +8238,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchAddressOf(out ILInstruction value, out IType type) { var inst = this as AddressOf; - if (inst != null) { + if (inst != null) + { value = inst.Value; type = inst.Type; return true; @@ -8097,7 +8251,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchThreeValuedBoolAnd(out ILInstruction left, out ILInstruction right) { var inst = this as ThreeValuedBoolAnd; - if (inst != null) { + if (inst != null) + { left = inst.Left; right = inst.Right; return true; @@ -8109,7 +8264,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchThreeValuedBoolOr(out ILInstruction left, out ILInstruction right) { var inst = this as ThreeValuedBoolOr; - if (inst != null) { + if (inst != null) + { left = inst.Left; right = inst.Right; return true; @@ -8121,7 +8277,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchNullableRewrap(out ILInstruction argument) { var inst = this as NullableRewrap; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; return true; } @@ -8131,7 +8288,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdStr(out string value) { var inst = this as LdStr; - if (inst != null) { + if (inst != null) + { value = inst.Value; return true; } @@ -8141,7 +8299,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdcI4(out int value) { var inst = this as LdcI4; - if (inst != null) { + if (inst != null) + { value = inst.Value; return true; } @@ -8151,7 +8310,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdcI8(out long value) { var inst = this as LdcI8; - if (inst != null) { + if (inst != null) + { value = inst.Value; return true; } @@ -8161,7 +8321,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdcF4(out float value) { var inst = this as LdcF4; - if (inst != null) { + if (inst != null) + { value = inst.Value; return true; } @@ -8171,7 +8332,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdcF8(out double value) { var inst = this as LdcF8; - if (inst != null) { + if (inst != null) + { value = inst.Value; return true; } @@ -8181,7 +8343,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdcDecimal(out decimal value) { var inst = this as LdcDecimal; - if (inst != null) { + if (inst != null) + { value = inst.Value; return true; } @@ -8191,7 +8354,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdNull() { var inst = this as LdNull; - if (inst != null) { + if (inst != null) + { return true; } return false; @@ -8199,7 +8363,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdFtn(out IMethod method) { var inst = this as LdFtn; - if (inst != null) { + if (inst != null) + { method = inst.Method; return true; } @@ -8209,7 +8374,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdVirtFtn(out ILInstruction argument, out IMethod method) { var inst = this as LdVirtFtn; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; method = inst.Method; return true; @@ -8221,7 +8387,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdVirtDelegate(out ILInstruction argument, out IType type, out IMethod method) { var inst = this as LdVirtDelegate; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; type = inst.Type; method = inst.Method; @@ -8235,7 +8402,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdTypeToken(out IType type) { var inst = this as LdTypeToken; - if (inst != null) { + if (inst != null) + { type = inst.Type; return true; } @@ -8245,7 +8413,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdMemberToken(out IMember member) { var inst = this as LdMemberToken; - if (inst != null) { + if (inst != null) + { member = inst.Member; return true; } @@ -8255,7 +8424,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLocAlloc(out ILInstruction argument) { var inst = this as LocAlloc; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; return true; } @@ -8265,7 +8435,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLocAllocSpan(out ILInstruction argument, out IType type) { var inst = this as LocAllocSpan; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; type = inst.Type; return true; @@ -8277,7 +8448,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchCpblk(out ILInstruction destAddress, out ILInstruction sourceAddress, out ILInstruction size) { var inst = this as Cpblk; - if (inst != null) { + if (inst != null) + { destAddress = inst.DestAddress; sourceAddress = inst.SourceAddress; size = inst.Size; @@ -8291,7 +8463,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchInitblk(out ILInstruction address, out ILInstruction value, out ILInstruction size) { var inst = this as Initblk; - if (inst != null) { + if (inst != null) + { address = inst.Address; value = inst.Value; size = inst.Size; @@ -8305,7 +8478,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdFlda(out ILInstruction target, out IField field) { var inst = this as LdFlda; - if (inst != null) { + if (inst != null) + { target = inst.Target; field = inst.Field; return true; @@ -8317,7 +8491,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdsFlda(out IField field) { var inst = this as LdsFlda; - if (inst != null) { + if (inst != null) + { field = inst.Field; return true; } @@ -8327,7 +8502,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchCastClass(out ILInstruction argument, out IType type) { var inst = this as CastClass; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; type = inst.Type; return true; @@ -8339,7 +8515,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchIsInst(out ILInstruction argument, out IType type) { var inst = this as IsInst; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; type = inst.Type; return true; @@ -8351,7 +8528,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdObj(out ILInstruction target, out IType type) { var inst = this as LdObj; - if (inst != null) { + if (inst != null) + { target = inst.Target; type = inst.Type; return true; @@ -8363,7 +8541,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchStObj(out ILInstruction target, out ILInstruction value, out IType type) { var inst = this as StObj; - if (inst != null) { + if (inst != null) + { target = inst.Target; value = inst.Value; type = inst.Type; @@ -8377,7 +8556,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchBox(out ILInstruction argument, out IType type) { var inst = this as Box; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; type = inst.Type; return true; @@ -8389,7 +8569,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchUnbox(out ILInstruction argument, out IType type) { var inst = this as Unbox; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; type = inst.Type; return true; @@ -8401,7 +8582,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchUnboxAny(out ILInstruction argument, out IType type) { var inst = this as UnboxAny; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; type = inst.Type; return true; @@ -8413,7 +8595,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchNewArr(out IType type) { var inst = this as NewArr; - if (inst != null) { + if (inst != null) + { type = inst.Type; return true; } @@ -8423,7 +8606,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchDefaultValue(out IType type) { var inst = this as DefaultValue; - if (inst != null) { + if (inst != null) + { type = inst.Type; return true; } @@ -8433,7 +8617,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchThrow(out ILInstruction argument) { var inst = this as Throw; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; return true; } @@ -8443,7 +8628,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchRethrow() { var inst = this as Rethrow; - if (inst != null) { + if (inst != null) + { return true; } return false; @@ -8451,7 +8637,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchSizeOf(out IType type) { var inst = this as SizeOf; - if (inst != null) { + if (inst != null) + { type = inst.Type; return true; } @@ -8461,7 +8648,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdElema(out IType type, out ILInstruction array) { var inst = this as LdElema; - if (inst != null) { + if (inst != null) + { type = inst.Type; array = inst.Array; return true; @@ -8473,7 +8661,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchGetPinnableReference(out ILInstruction argument, out IMethod method) { var inst = this as GetPinnableReference; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; method = inst.Method; return true; @@ -8485,7 +8674,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchUserDefinedLogicOperator(out IMethod method, out ILInstruction left, out ILInstruction right) { var inst = this as UserDefinedLogicOperator; - if (inst != null) { + if (inst != null) + { method = inst.Method; left = inst.Left; right = inst.Right; @@ -8499,7 +8689,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchMatchInstruction(out ILVariable variable, out IMethod method, out ILInstruction testedOperand) { var inst = this as MatchInstruction; - if (inst != null) { + if (inst != null) + { variable = inst.Variable; method = inst.Method; testedOperand = inst.TestedOperand; @@ -8513,7 +8704,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchMakeRefAny(out ILInstruction argument, out IType type) { var inst = this as MakeRefAny; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; type = inst.Type; return true; @@ -8525,7 +8717,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchRefAnyType(out ILInstruction argument) { var inst = this as RefAnyType; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; return true; } @@ -8535,7 +8728,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchRefAnyValue(out ILInstruction argument, out IType type) { var inst = this as RefAnyValue; - if (inst != null) { + if (inst != null) + { argument = inst.Argument; type = inst.Type; return true; @@ -8547,7 +8741,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchYieldReturn(out ILInstruction value) { var inst = this as YieldReturn; - if (inst != null) { + if (inst != null) + { value = inst.Value; return true; } @@ -8557,7 +8752,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchAwait(out ILInstruction value) { var inst = this as Await; - if (inst != null) { + if (inst != null) + { value = inst.Value; return true; } diff --git a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs index f31db7d29..2ab7ceef8 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs @@ -18,6 +18,7 @@ using System; using System.Diagnostics; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL @@ -36,14 +37,14 @@ namespace ICSharpCode.Decompiler.IL ShiftLeft, ShiftRight } - + public partial class BinaryNumericInstruction : BinaryInstruction, ILiftableInstruction { /// /// Gets whether the instruction checks for overflow. /// public readonly bool CheckForOverflow; - + /// /// For integer operations that depend on the sign, specifies whether the operation /// is signed or unsigned. @@ -92,22 +93,27 @@ namespace ICSharpCode.Decompiler.IL this.IsLifted = isLifted; this.resultType = ComputeResultType(op, LeftInputType, RightInputType); } - + internal static StackType ComputeResultType(BinaryNumericOperator op, StackType left, StackType right) { // Based on Table 2: Binary Numeric Operations // also works for Table 5: Integer Operations // and for Table 7: Overflow Arithmetic Operations - if (left == right || op == BinaryNumericOperator.ShiftLeft || op == BinaryNumericOperator.ShiftRight) { + if (left == right || op == BinaryNumericOperator.ShiftLeft || op == BinaryNumericOperator.ShiftRight) + { // Shift op codes use Table 6 return left; } - if (left == StackType.Ref || right == StackType.Ref) { - if (left == StackType.Ref && right == StackType.Ref) { + if (left == StackType.Ref || right == StackType.Ref) + { + if (left == StackType.Ref && right == StackType.Ref) + { // sub(&, &) = I Debug.Assert(op == BinaryNumericOperator.Sub); return StackType.I; - } else { + } + else + { // add/sub with I or I4 and & Debug.Assert(op == BinaryNumericOperator.Add || op == BinaryNumericOperator.Sub); return StackType.Ref; @@ -115,7 +121,7 @@ namespace ICSharpCode.Decompiler.IL } return StackType.Unknown; } - + public StackType UnderlyingResultType { get => resultType; } public sealed override StackType ResultType { @@ -125,7 +131,8 @@ namespace ICSharpCode.Decompiler.IL internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); - if (!IsLifted) { + if (!IsLifted) + { Debug.Assert(LeftInputType == Left.ResultType); Debug.Assert(RightInputType == Right.ResultType); } @@ -138,7 +145,7 @@ namespace ICSharpCode.Decompiler.IL flags |= InstructionFlags.MayThrow; return flags; } - + public override InstructionFlags DirectFlags { get { if (CheckForOverflow || (Operator == BinaryNumericOperator.Div || Operator == BinaryNumericOperator.Rem)) @@ -149,7 +156,8 @@ namespace ICSharpCode.Decompiler.IL internal static string GetOperatorName(BinaryNumericOperator @operator) { - switch (@operator) { + switch (@operator) + { case BinaryNumericOperator.Add: return "add"; case BinaryNumericOperator.Sub: @@ -180,17 +188,22 @@ namespace ICSharpCode.Decompiler.IL WriteILRange(output, options); output.Write(OpCode); output.Write("." + GetOperatorName(Operator)); - if (CheckForOverflow) { + if (CheckForOverflow) + { output.Write(".ovf"); } - if (Sign == Sign.Unsigned) { + if (Sign == Sign.Unsigned) + { output.Write(".unsigned"); - } else if (Sign == Sign.Signed) { + } + else if (Sign == Sign.Signed) + { output.Write(".signed"); } output.Write('.'); output.Write(resultType.ToString().ToLowerInvariant()); - if (IsLifted) { + if (IsLifted) + { output.Write(".lifted"); } output.Write('('); diff --git a/ICSharpCode.Decompiler/IL/Instructions/Block.cs b/ICSharpCode.Decompiler/IL/Instructions/Block.cs index 99fe130ea..e9d91b280 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Block.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Block.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -105,11 +106,13 @@ namespace ICSharpCode.Decompiler.IL internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); - for (int i = 0; i < Instructions.Count - 1; i++) { + for (int i = 0; i < Instructions.Count - 1; i++) + { // only the last instruction may have an unreachable endpoint Debug.Assert(!Instructions[i].HasFlag(InstructionFlags.EndPointUnreachable)); } - switch (this.Kind) { + switch (this.Kind) + { case BlockKind.ControlFlow: Debug.Assert(finalInstruction.OpCode == OpCode.Nop); break; @@ -118,7 +121,8 @@ namespace ICSharpCode.Decompiler.IL break; case BlockKind.CallWithNamedArgs: Debug.Assert(finalInstruction is CallInstruction); - foreach (var inst in Instructions) { + foreach (var inst in Instructions) + { var stloc = inst as StLoc; Debug.Assert(stloc != null, "Instructions in CallWithNamedArgs must be assignments"); Debug.Assert(stloc.Variable.Kind == VariableKind.NamedArgument); @@ -126,7 +130,8 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(stloc.Variable.LoadInstructions.Single().Parent == finalInstruction); } var call = (CallInstruction)finalInstruction; - if (call.IsInstanceCall) { + if (call.IsInstanceCall) + { // special case: with instance calls, Instructions[0] must be for the this parameter ILVariable v = ((StLoc)Instructions[0]).Variable; Debug.Assert(call.Arguments[0].MatchLdLoc(v)); @@ -137,7 +142,8 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(final != null && final.Variable.IsSingleDefinition && final.Variable.Kind == VariableKind.InitializerTarget); IType type = null; Debug.Assert(Instructions[0].MatchStLoc(final.Variable, out var init) && init.MatchNewArr(out type)); - for (int i = 1; i < Instructions.Count; i++) { + for (int i = 1; i < Instructions.Count; i++) + { Debug.Assert(Instructions[i].MatchStObj(out ILInstruction target, out _, out var t) && type != null && type.Equals(t)); Debug.Assert(target.MatchLdElema(out t, out ILInstruction array) && type.Equals(t)); Debug.Assert(array.MatchLdLoc(out ILVariable v) && v == final.Variable); @@ -153,7 +159,8 @@ namespace ICSharpCode.Decompiler.IL bool condition = Instructions[0].MatchStLoc(final2.Variable, out var init2); Debug.Assert(condition); Debug.Assert(init2 is NewObj || init2 is DefaultValue || (init2 is Block named && named.Kind == BlockKind.CallWithNamedArgs)); - switch (init2) { + switch (init2) + { case NewObj newObj: type2 = newObj.Method.DeclaringType; break; @@ -167,7 +174,8 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(false); break; } - for (int i = 1; i < Instructions.Count; i++) { + for (int i = 1; i < Instructions.Count; i++) + { Debug.Assert(Instructions[i] is StLoc || AccessPathElement.GetAccessPath(Instructions[i], type2).Kind != IL.Transforms.AccessPathKind.Invalid); } break; @@ -207,15 +215,18 @@ namespace ICSharpCode.Decompiler.IL output.WriteLine("{"); output.Indent(); int index = 0; - foreach (var inst in Instructions) { - if (options.ShowChildIndexInBlock) { + foreach (var inst in Instructions) + { + if (options.ShowChildIndexInBlock) + { output.Write("[" + index + "] "); index++; } inst.WriteTo(output, options); output.WriteLine(); } - if (finalInstruction.OpCode != OpCode.Nop) { + if (finalInstruction.OpCode != OpCode.Nop) + { output.Write("final: "); finalInstruction.WriteTo(output, options); output.WriteLine(); @@ -256,7 +267,8 @@ namespace ICSharpCode.Decompiler.IL protected override InstructionFlags ComputeFlags() { var flags = InstructionFlags.None; - foreach (var inst in Instructions) { + foreach (var inst in Instructions) + { flags |= inst.Flags; } flags |= FinalInstruction.Flags; @@ -290,7 +302,8 @@ namespace ICSharpCode.Decompiler.IL public void RunTransforms(IEnumerable transforms, BlockTransformContext context) { this.CheckInvariant(ILPhase.Normal); - foreach (var transform in transforms) { + foreach (var transform in transforms) + { context.CancellationToken.ThrowIfCancellationRequested(); context.StepStartGroup(transform.GetType().Name); transform.Run(this, context); @@ -305,9 +318,12 @@ namespace ICSharpCode.Decompiler.IL /// public static ILInstruction GetPredecessor(ILInstruction inst) { - if (inst.Parent is Block block && inst.ChildIndex > 0) { + if (inst.Parent is Block block && inst.ChildIndex > 0) + { return block.Instructions[inst.ChildIndex - 1]; - } else { + } + else + { return null; } } @@ -318,7 +334,8 @@ namespace ICSharpCode.Decompiler.IL /// public static ILInstruction Unwrap(ILInstruction inst) { - if (inst is Block block) { + if (inst is Block block) + { if (block.Instructions.Count == 1 && block.finalInstruction.MatchNop()) return block.Instructions[0]; } @@ -332,7 +349,8 @@ namespace ICSharpCode.Decompiler.IL public static Block FindClosestBlock(ILInstruction inst) { var curr = inst; - while (curr != null) { + while (curr != null) + { if (curr is Block) return (Block)curr; curr = curr.Parent; @@ -365,10 +383,12 @@ namespace ICSharpCode.Decompiler.IL falseInst = null; if (Instructions.Count < 2) return false; - if (Instructions[Instructions.Count - 2].MatchIfInstruction(out condition, out trueInst)) { + if (Instructions[Instructions.Count - 2].MatchIfInstruction(out condition, out trueInst)) + { // Swap trueInst<>falseInst for every logic.not in the condition. falseInst = Instructions.Last(); - while (condition.MatchLogicNot(out var arg)) { + while (condition.MatchLogicNot(out var arg)) + { condition = arg; (trueInst, falseInst) = (falseInst, trueInst); } @@ -377,7 +397,7 @@ namespace ICSharpCode.Decompiler.IL return false; } } - + public enum BlockKind { /// diff --git a/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs b/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs index 15f0f10b6..609e1386b 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Util; @@ -55,7 +56,7 @@ namespace ICSharpCode.Decompiler.IL InvalidateFlags(); } } - + Block entryPoint; /// @@ -85,43 +86,46 @@ namespace ICSharpCode.Decompiler.IL clone.AddILRange(this); clone.Blocks.AddRange(this.Blocks.Select(block => (Block)block.Clone())); // Adjust branch instructions to point to the new container - foreach (var branch in clone.Descendants.OfType()) { + foreach (var branch in clone.Descendants.OfType()) + { if (branch.TargetBlock != null && branch.TargetBlock.Parent == this) branch.TargetBlock = clone.Blocks[branch.TargetBlock.ChildIndex]; } - foreach (var leave in clone.Descendants.OfType()) { + foreach (var leave in clone.Descendants.OfType()) + { if (leave.TargetContainer == this) leave.TargetContainer = clone; } return clone; } - + protected internal override void InstructionCollectionUpdateComplete() { base.InstructionCollectionUpdateComplete(); this.EntryPoint = this.Blocks.FirstOrDefault(); } - + protected override void Connected() { base.Connected(); if (entryPoint != null) entryPoint.IncomingEdgeCount++; } - + protected override void Disconnected() { base.Disconnected(); if (entryPoint != null) entryPoint.IncomingEdgeCount--; } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); output.WriteLocalReference("BlockContainer", this, isDefinition: true); output.Write(' '); - switch (Kind) { + switch (Kind) + { case ContainerKind.Loop: output.Write("(while-true) "); break; @@ -141,10 +145,14 @@ namespace ICSharpCode.Decompiler.IL output.MarkFoldStart("{...}"); output.WriteLine("{"); output.Indent(); - foreach (var inst in Blocks) { - if (inst.Parent == this) { + foreach (var inst in Blocks) + { + if (inst.Parent == this) + { inst.WriteTo(output, options); - } else { + } + else + { output.Write("stale reference to "); output.WriteLocalReference(inst.Label, inst); } @@ -155,17 +163,17 @@ namespace ICSharpCode.Decompiler.IL output.Write("}"); output.MarkFoldEnd(); } - + protected override int GetChildCount() { return Blocks.Count; } - + protected override ILInstruction GetChild(int index) { return Blocks[index]; } - + protected override void SetChild(int index, ILInstruction value) { if (Blocks[index] != value) @@ -187,7 +195,8 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(Blocks.All(b => b.Kind == BlockKind.ControlFlow)); // this also implies that the blocks don't use FinalInstruction Debug.Assert(TopologicalSort(deleteUnreachableBlocks: true).Count == Blocks.Count, "Container should not have any unreachable blocks"); Block bodyStartBlock; - switch (Kind) { + switch (Kind) + { case ContainerKind.Normal: break; case ContainerKind.Loop: @@ -223,7 +232,8 @@ namespace ICSharpCode.Decompiler.IL protected override InstructionFlags ComputeFlags() { InstructionFlags flags = InstructionFlags.ControlFlow; - foreach (var block in Blocks) { + foreach (var block in Blocks) + { flags |= block.Flags; } // The end point of the BlockContainer is only reachable if there's a leave instruction @@ -233,7 +243,7 @@ namespace ICSharpCode.Decompiler.IL flags &= ~InstructionFlags.EndPointUnreachable; return flags; } - + public override InstructionFlags DirectFlags { get { return InstructionFlags.ControlFlow; @@ -265,8 +275,10 @@ namespace ICSharpCode.Decompiler.IL List postOrder = new List(); Visit(EntryPoint); postOrder.Reverse(); - if (!deleteUnreachableBlocks) { - for (int i = 0; i < Blocks.Count; i++) { + if (!deleteUnreachableBlocks) + { + for (int i = 0; i < Blocks.Count; i++) + { if (!visited[i]) postOrder.Add(Blocks[i]); } @@ -276,11 +288,14 @@ namespace ICSharpCode.Decompiler.IL void Visit(Block block) { Debug.Assert(block.Parent == this); - if (!visited[block.ChildIndex]) { + if (!visited[block.ChildIndex]) + { visited[block.ChildIndex] = true; - foreach (var branch in block.Descendants.OfType()) { - if (branch.TargetBlock.Parent == this) { + foreach (var branch in block.Descendants.OfType()) + { + if (branch.TargetBlock.Parent == this) + { Visit(branch.TargetBlock); } } @@ -306,7 +321,8 @@ namespace ICSharpCode.Decompiler.IL public static BlockContainer FindClosestContainer(ILInstruction inst) { - while (inst != null) { + while (inst != null) + { if (inst is BlockContainer bc) return bc; inst = inst.Parent; @@ -316,7 +332,8 @@ namespace ICSharpCode.Decompiler.IL public static BlockContainer FindClosestSwitchContainer(ILInstruction inst) { - while (inst != null) { + while (inst != null) + { if (inst is BlockContainer bc && bc.entryPoint.Instructions.FirstOrDefault() is SwitchInstruction) return bc; inst = inst.Parent; diff --git a/ICSharpCode.Decompiler/IL/Instructions/Branch.cs b/ICSharpCode.Decompiler/IL/Instructions/Branch.cs index b42eed3b2..4eda178cb 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Branch.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Branch.cs @@ -31,22 +31,22 @@ namespace ICSharpCode.Decompiler.IL { readonly int targetILOffset; Block targetBlock; - + public Branch(int targetILOffset) : base(OpCode.Branch) { this.targetILOffset = targetILOffset; } - + public Branch(Block targetBlock) : base(OpCode.Branch) { this.targetBlock = targetBlock ?? throw new ArgumentNullException(nameof(targetBlock)); this.targetILOffset = targetBlock.StartILOffset; } - + public int TargetILOffset { get { return targetBlock != null ? targetBlock.StartILOffset : targetILOffset; } } - + public Block TargetBlock { get { return targetBlock; } set { @@ -57,28 +57,28 @@ namespace ICSharpCode.Decompiler.IL targetBlock.IncomingEdgeCount++; } } - + /// /// Gets the BlockContainer that contains the target block. /// public BlockContainer TargetContainer { get { return (BlockContainer)targetBlock?.Parent; } } - + protected override void Connected() { base.Connected(); if (targetBlock != null) targetBlock.IncomingEdgeCount++; } - + protected override void Disconnected() { base.Disconnected(); if (targetBlock != null) targetBlock.IncomingEdgeCount--; } - + public string TargetLabel { get { return targetBlock != null ? targetBlock.Label : string.Format("IL_{0:x4}", TargetILOffset); } } @@ -94,7 +94,8 @@ namespace ICSharpCode.Decompiler.IL internal static bool GetExecutesFinallyBlock(ILInstruction inst, BlockContainer container) { - for (; inst != container; inst = inst.Parent) { + for (; inst != container; inst = inst.Parent) + { if (inst.Parent is TryFinally && inst.SlotInfo == TryFinally.TryBlockSlot) return true; } @@ -104,13 +105,14 @@ namespace ICSharpCode.Decompiler.IL internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); - if (phase > ILPhase.InILReader) { + if (phase > ILPhase.InILReader) + { Debug.Assert(targetBlock.Parent is BlockContainer); Debug.Assert(this.IsDescendantOf(targetBlock.Parent)); Debug.Assert(targetBlock.Parent.Children[targetBlock.ChildIndex] == targetBlock); } } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); diff --git a/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs b/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs index fb83552da..c4da53a0c 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL @@ -93,18 +94,20 @@ namespace ICSharpCode.Decompiler.IL output.Write('('); functionPointer.WriteTo(output, options); int firstArgument = IsInstance ? 1 : 0; - if (firstArgument == 1) { + if (firstArgument == 1) + { output.Write(", "); Arguments[0].WriteTo(output, options); } - foreach (var (inst, type) in Arguments.Zip(ParameterTypes, (a,b) => (a,b))) { + foreach (var (inst, type) in Arguments.Zip(ParameterTypes, (a, b) => (a, b))) + { output.Write(", "); inst.WriteTo(output, options); output.Write(" : "); type.WriteTo(output); } if (Arguments.Count > 0) - output.Write(')'); + output.Write(')'); } protected override int GetChildCount() @@ -139,7 +142,8 @@ namespace ICSharpCode.Decompiler.IL { var flags = this.DirectFlags; flags |= functionPointer.Flags; - foreach (var inst in Arguments) { + foreach (var inst in Arguments) + { flags |= inst.Flags; } return flags; @@ -161,7 +165,8 @@ namespace ICSharpCode.Decompiler.IL return false; if (ParameterTypes.Length != other.ParameterTypes.Length) return false; - for (int i = 0; i < ParameterTypes.Length; i++) { + for (int i = 0; i < ParameterTypes.Length; i++) + { if (!ParameterTypes[i].Equals(other.ParameterTypes[i])) return false; } diff --git a/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs index 72033be1a..6e87d9c4e 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs @@ -18,6 +18,7 @@ using System; using System.Diagnostics; + using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.TypeSystem; @@ -27,7 +28,8 @@ namespace ICSharpCode.Decompiler.IL { public static CallInstruction Create(OpCode opCode, IMethod method) { - switch (opCode) { + switch (opCode) + { case OpCode.Call: return new Call(method); case OpCode.CallVirt: @@ -40,7 +42,7 @@ namespace ICSharpCode.Decompiler.IL } public readonly IMethod Method; - + /// /// Gets/Sets whether the call has the 'tail.' prefix. /// @@ -79,12 +81,13 @@ namespace ICSharpCode.Decompiler.IL public IParameter GetParameter(int argumentIndex) { int firstParamIndex = (Method.IsStatic || OpCode == OpCode.NewObj) ? 0 : 1; - if (argumentIndex < firstParamIndex) { + if (argumentIndex < firstParamIndex) + { return null; // asking for 'this' parameter } return Method.Parameters[argumentIndex - firstParamIndex]; } - + public override StackType ResultType { get { if (OpCode == OpCode.NewObj) @@ -105,7 +108,8 @@ namespace ICSharpCode.Decompiler.IL { if (type.Kind == TypeKind.TypeParameter) return StackType.Ref; - switch (type.IsReferenceType) { + switch (type.IsReferenceType) + { case true: return StackType.O; case false: @@ -120,11 +124,13 @@ namespace ICSharpCode.Decompiler.IL base.CheckInvariant(phase); int firstArgument = (OpCode != OpCode.NewObj && !Method.IsStatic) ? 1 : 0; Debug.Assert(Method.Parameters.Count + firstArgument == Arguments.Count); - if (firstArgument == 1) { + if (firstArgument == 1) + { if (!(Arguments[0].ResultType == ExpectedTypeForThisPointer(ConstrainedTo ?? Method.DeclaringType))) Debug.Fail($"Stack type mismatch in 'this' argument in call to {Method.Name}()"); } - for (int i = 0; i < Method.Parameters.Count; ++i) { + for (int i = 0; i < Method.Parameters.Count; ++i) + { if (!(Arguments[firstArgument + i].ResultType == Method.Parameters[i].Type.GetStackType())) Debug.Fail($"Stack type mismatch in parameter {i} in call to {Method.Name}()"); } @@ -133,7 +139,8 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); - if (ConstrainedTo != null) { + if (ConstrainedTo != null) + { output.Write("constrained["); ConstrainedTo.WriteTo(output); output.Write("]."); @@ -144,14 +151,15 @@ namespace ICSharpCode.Decompiler.IL output.Write(' '); Method.WriteTo(output); output.Write('('); - for (int i = 0; i < Arguments.Count; i++) { + for (int i = 0; i < Arguments.Count; i++) + { if (i > 0) output.Write(", "); Arguments[i].WriteTo(output, options); } output.Write(')'); } - + protected internal sealed override bool PerformMatch(ILInstruction other, ref Patterns.Match match) { CallInstruction o = other as CallInstruction; diff --git a/ICSharpCode.Decompiler/IL/Instructions/Comp.cs b/ICSharpCode.Decompiler/IL/Instructions/Comp.cs index 34e4ecf39..62cf86bed 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Comp.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Comp.cs @@ -18,6 +18,7 @@ using System; using System.Diagnostics; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -33,17 +34,18 @@ namespace ICSharpCode.Decompiler.IL GreaterThan, GreaterThanOrEqual } - + static class ComparisonKindExtensions { public static bool IsEqualityOrInequality(this ComparisonKind kind) { return kind == ComparisonKind.Equality || kind == ComparisonKind.Inequality; } - + public static ComparisonKind Negate(this ComparisonKind kind) { - switch (kind) { + switch (kind) + { case ComparisonKind.Equality: return ComparisonKind.Inequality; case ComparisonKind.Inequality: @@ -60,10 +62,11 @@ namespace ICSharpCode.Decompiler.IL throw new ArgumentOutOfRangeException(); } } - + public static BinaryOperatorType ToBinaryOperatorType(this ComparisonKind kind) { - switch (kind) { + switch (kind) + { case ComparisonKind.Equality: return BinaryOperatorType.Equality; case ComparisonKind.Inequality: @@ -80,13 +83,13 @@ namespace ICSharpCode.Decompiler.IL throw new ArgumentOutOfRangeException(); } } - + public static string GetToken(this ComparisonKind kind) { return BinaryOperatorExpression.GetOperatorRole(kind.ToBinaryOperatorType()).Token; } } - + public enum ComparisonLiftingKind { /// @@ -164,10 +167,13 @@ namespace ICSharpCode.Decompiler.IL internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); - if (LiftingKind == ComparisonLiftingKind.None) { + if (LiftingKind == ComparisonLiftingKind.None) + { Debug.Assert(Left.ResultType == InputType); Debug.Assert(Right.ResultType == InputType); - } else { + } + else + { Debug.Assert(Left.ResultType == InputType || Left.ResultType == StackType.O); Debug.Assert(Right.ResultType == InputType || Right.ResultType == StackType.O); } @@ -176,7 +182,8 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); - if (options.UseLogicOperationSugar && MatchLogicNot(out var arg)) { + if (options.UseLogicOperationSugar && MatchLogicNot(out var arg)) + { output.Write("logic.not("); arg.WriteTo(output, options); output.Write(')'); @@ -185,7 +192,8 @@ namespace ICSharpCode.Decompiler.IL output.Write(OpCode); output.Write('.'); output.Write(InputType.ToString().ToLower()); - switch (Sign) { + switch (Sign) + { case Sign.Signed: output.Write(".signed"); break; @@ -193,7 +201,8 @@ namespace ICSharpCode.Decompiler.IL output.Write(".unsigned"); break; } - switch (LiftingKind) { + switch (LiftingKind) + { case ComparisonLiftingKind.CSharp: output.Write(".lifted[C#]"); break; diff --git a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs index 3f1b56725..fb5723db2 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Linq.Expressions; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL @@ -85,8 +86,9 @@ namespace ICSharpCode.Decompiler.IL [Conditional("DEBUG")] void CheckValidTarget() - { - switch (TargetKind) { + { + switch (TargetKind) + { case CompoundTargetKind.Address: Debug.Assert(target.ResultType == StackType.Ref || target.ResultType == StackType.I); break; @@ -103,7 +105,8 @@ namespace ICSharpCode.Decompiler.IL protected void WriteSuffix(ITextOutput output) { - switch (TargetKind) { + switch (TargetKind) + { case CompoundTargetKind.Address: output.Write(".address"); break; @@ -111,7 +114,8 @@ namespace ICSharpCode.Decompiler.IL output.Write(".property"); break; } - switch (EvalMode) { + switch (EvalMode) + { case CompoundEvalMode.EvaluatesToNewValue: output.Write(".new"); break; @@ -170,15 +174,20 @@ namespace ICSharpCode.Decompiler.IL /// internal static bool IsBinaryCompatibleWithType(BinaryNumericInstruction binary, IType type, DecompilerSettings settings) { - if (binary.IsLifted) { + if (binary.IsLifted) + { if (!NullableType.IsNullable(type)) return false; type = NullableType.GetUnderlyingType(type); } - if (type.Kind == TypeKind.Unknown) { + if (type.Kind == TypeKind.Unknown) + { return false; // avoid introducing a potentially-incorrect compound assignment - } else if (type.Kind == TypeKind.Enum) { - switch (binary.Operator) { + } + else if (type.Kind == TypeKind.Enum) + { + switch (binary.Operator) + { case BinaryNumericOperator.Add: case BinaryNumericOperator.Sub: case BinaryNumericOperator.BitAnd: @@ -188,8 +197,11 @@ namespace ICSharpCode.Decompiler.IL default: return false; // operator not supported on enum types } - } else if (type.Kind == TypeKind.Pointer) { - switch (binary.Operator) { + } + else if (type.Kind == TypeKind.Pointer) + { + switch (binary.Operator) + { case BinaryNumericOperator.Add: case BinaryNumericOperator.Sub: // ensure that the byte offset is a multiple of the pointer size @@ -201,26 +213,34 @@ namespace ICSharpCode.Decompiler.IL default: return false; // operator not supported on pointer types } - } else if (type.IsKnownType(KnownTypeCode.IntPtr) || type.IsKnownType(KnownTypeCode.UIntPtr)) { + } + else if (type.IsKnownType(KnownTypeCode.IntPtr) || type.IsKnownType(KnownTypeCode.UIntPtr)) + { // "target.intptr *= 2;" is compiler error, but // "target.intptr *= (nint)2;" works - if (settings != null && !settings.NativeIntegers) { + if (settings != null && !settings.NativeIntegers) + { // But if native integers are not available, we cannot use compound assignment. return false; } // The trick with casting the RHS to n(u)int doesn't work for shifts: - switch (binary.Operator) { + switch (binary.Operator) + { case BinaryNumericOperator.ShiftLeft: case BinaryNumericOperator.ShiftRight: return false; } } - if (binary.Sign != Sign.None) { - if (type.IsCSharpSmallIntegerType()) { + if (binary.Sign != Sign.None) + { + if (type.IsCSharpSmallIntegerType()) + { // C# will use numeric promotion to int, binary op must be signed if (binary.Sign != Sign.Signed) return false; - } else { + } + else + { // C# will use sign from type if (type.GetSign() != binary.Sign) return false; @@ -239,7 +259,7 @@ namespace ICSharpCode.Decompiler.IL flags |= InstructionFlags.MayThrow; return flags; } - + public override InstructionFlags DirectFlags { get { var flags = InstructionFlags.SideEffect; @@ -248,23 +268,28 @@ namespace ICSharpCode.Decompiler.IL return flags; } } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); output.Write(OpCode); output.Write("." + BinaryNumericInstruction.GetOperatorName(Operator)); - if (CheckForOverflow) { + if (CheckForOverflow) + { output.Write(".ovf"); } - if (Sign == Sign.Unsigned) { + if (Sign == Sign.Unsigned) + { output.Write(".unsigned"); - } else if (Sign == Sign.Signed) { + } + else if (Sign == Sign.Signed) + { output.Write(".signed"); } output.Write('.'); output.Write(UnderlyingResultType.ToString().ToLowerInvariant()); - if (IsLifted) { + if (IsLifted) + { output.Write(".lifted"); } base.WriteSuffix(output); @@ -281,7 +306,7 @@ namespace ICSharpCode.Decompiler.IL public readonly IMethod Method; public bool IsLifted => false; // TODO: implement lifted user-defined compound assignments - public UserDefinedCompoundAssign(IMethod method, CompoundEvalMode evalMode, + public UserDefinedCompoundAssign(IMethod method, CompoundEvalMode evalMode, ILInstruction target, CompoundTargetKind targetKind, ILInstruction value) : base(OpCode.UserDefinedCompoundAssign, evalMode, target, targetKind, value) { @@ -320,7 +345,7 @@ namespace ICSharpCode.Decompiler.IL public CSharpBinderFlags BinderFlags { get; } public DynamicCompoundAssign(ExpressionType op, CSharpBinderFlags binderFlags, - ILInstruction target, CSharpArgumentInfo targetArgumentInfo, + ILInstruction target, CSharpArgumentInfo targetArgumentInfo, ILInstruction value, CSharpArgumentInfo valueArgumentInfo, CompoundTargetKind targetKind = CompoundTargetKind.Dynamic) : base(OpCode.DynamicCompoundAssign, CompoundEvalModeFromOperation(op), target, targetKind, value) @@ -367,7 +392,8 @@ namespace ICSharpCode.Decompiler.IL static CompoundEvalMode CompoundEvalModeFromOperation(ExpressionType op) { - switch (op) { + switch (op) + { case ExpressionType.PostIncrementAssign: case ExpressionType.PostDecrementAssign: return CompoundEvalMode.EvaluatesToOldValue; diff --git a/ICSharpCode.Decompiler/IL/Instructions/Conv.cs b/ICSharpCode.Decompiler/IL/Instructions/Conv.cs index 6b23db08d..703fc995f 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Conv.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Conv.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Diagnostics; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL @@ -89,7 +90,7 @@ namespace ICSharpCode.Decompiler.IL /// ObjectInterior } - + partial class Conv : UnaryInstruction, ILiftableInstruction { /// @@ -147,7 +148,7 @@ namespace ICSharpCode.Decompiler.IL /// Target type == PrimitiveType.None can happen for implicit conversions to O in invalid IL. /// public readonly PrimitiveType TargetType; - + public Conv(ILInstruction argument, PrimitiveType targetType, bool checkForOverflow, Sign inputSign) : this(argument, argument.ResultType, inputSign, targetType, checkForOverflow) { @@ -180,12 +181,14 @@ namespace ICSharpCode.Decompiler.IL /// static ConversionKind GetConversionKind(PrimitiveType targetType, StackType inputType, Sign inputSign) { - switch (targetType) { + switch (targetType) + { case PrimitiveType.I1: case PrimitiveType.I2: case PrimitiveType.U1: case PrimitiveType.U2: - switch (inputType) { + switch (inputType) + { case StackType.I4: case StackType.I8: case StackType.I: @@ -198,7 +201,8 @@ namespace ICSharpCode.Decompiler.IL } case PrimitiveType.I4: case PrimitiveType.U4: - switch (inputType) { + switch (inputType) + { case StackType.I4: return ConversionKind.Nop; case StackType.I: @@ -212,7 +216,8 @@ namespace ICSharpCode.Decompiler.IL } case PrimitiveType.I8: case PrimitiveType.U8: - switch (inputType) { + switch (inputType) + { case StackType.I4: case StackType.I: if (inputSign == Sign.None) @@ -232,7 +237,8 @@ namespace ICSharpCode.Decompiler.IL } case PrimitiveType.I: case PrimitiveType.U: - switch (inputType) { + switch (inputType) + { case StackType.I4: if (inputSign == Sign.None) return targetType == PrimitiveType.I ? ConversionKind.SignExtend : ConversionKind.ZeroExtend; @@ -252,7 +258,8 @@ namespace ICSharpCode.Decompiler.IL return ConversionKind.Invalid; } case PrimitiveType.R4: - switch (inputType) { + switch (inputType) + { case StackType.I4: case StackType.I: case StackType.I8: @@ -266,7 +273,8 @@ namespace ICSharpCode.Decompiler.IL } case PrimitiveType.R: case PrimitiveType.R8: - switch (inputType) { + switch (inputType) + { case StackType.I4: case StackType.I: case StackType.I8: @@ -281,7 +289,8 @@ namespace ICSharpCode.Decompiler.IL case PrimitiveType.Ref: // There's no "conv.ref" in IL, but IL allows these conversions implicitly, // whereas we represent them explicitly in the ILAst. - switch (inputType) { + switch (inputType) + { case StackType.I4: case StackType.I: case StackType.I8: @@ -295,7 +304,7 @@ namespace ICSharpCode.Decompiler.IL return ConversionKind.Invalid; } } - + public override StackType ResultType { get => IsLifted ? StackType.O : TargetType.GetStackType(); } @@ -308,15 +317,20 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (CheckForOverflow) { + if (CheckForOverflow) + { output.Write(".ovf"); } - if (InputSign == Sign.Unsigned) { + if (InputSign == Sign.Unsigned) + { output.Write(".unsigned"); - } else if (InputSign == Sign.Signed) { + } + else if (InputSign == Sign.Signed) + { output.Write(".signed"); } - if (IsLifted) { + if (IsLifted) + { output.Write(".lifted"); } output.Write(' '); @@ -324,7 +338,8 @@ namespace ICSharpCode.Decompiler.IL output.Write("->"); output.Write(TargetType); output.Write(' '); - switch (Kind) { + switch (Kind) + { case ConversionKind.SignExtend: output.Write(""); break; @@ -339,7 +354,7 @@ namespace ICSharpCode.Decompiler.IL Argument.WriteTo(output, options); output.Write(')'); } - + protected override InstructionFlags ComputeFlags() { var flags = base.ComputeFlags(); @@ -347,7 +362,7 @@ namespace ICSharpCode.Decompiler.IL flags |= InstructionFlags.MayThrow; return flags; } - + public override ILInstruction UnwrapConv(ConversionKind kind) { if (this.Kind == kind && !IsLifted) diff --git a/ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs index 62ba9aae1..d49a684de 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs @@ -74,7 +74,8 @@ namespace ICSharpCode.Decompiler.IL protected sealed override ILInstruction GetChild(int index) { - switch (index - Init.Count) { + switch (index - Init.Count) + { case 0: return this.pattern; case 1: @@ -88,7 +89,8 @@ namespace ICSharpCode.Decompiler.IL protected sealed override void SetChild(int index, ILInstruction value) { - switch (index - Init.Count) { + switch (index - Init.Count) + { case 0: this.Pattern = (MatchInstruction)value; break; @@ -106,7 +108,8 @@ namespace ICSharpCode.Decompiler.IL protected sealed override SlotInfo GetChildSlot(int index) { - switch (index - Init.Count) { + switch (index - Init.Count) + { case 0: return PatternSlot; case 1: @@ -131,7 +134,8 @@ namespace ICSharpCode.Decompiler.IL protected override InstructionFlags ComputeFlags() { var flags = InstructionFlags.None; - foreach (var inst in Init) { + foreach (var inst in Init) + { flags |= inst.Flags; } flags |= pattern.Flags | conversions.Flags | assignments.Flags; @@ -164,7 +168,8 @@ namespace ICSharpCode.Decompiler.IL output.Indent(); output.WriteLine("init:"); output.Indent(); - foreach (var inst in this.Init) { + foreach (var inst in this.Init) + { inst.WriteTo(output, options); output.WriteLine(); } @@ -191,7 +196,8 @@ namespace ICSharpCode.Decompiler.IL if (!inst.MatchStLoc(out variable, out var value)) return false; ILInstruction input; - switch (value) { + switch (value) + { case Conv conv: input = conv.Argument; break; @@ -208,16 +214,23 @@ namespace ICSharpCode.Decompiler.IL { expectedType = null; value = null; - switch (inst) { + switch (inst) + { case CallInstruction call: if (call.Method.AccessorKind != System.Reflection.MethodSemanticsAttributes.Setter) return false; - for (int i = 0; i < call.Arguments.Count - 1; i++) { + for (int i = 0; i < call.Arguments.Count - 1; i++) + { ILInstruction arg = call.Arguments[i]; - if (arg.Flags == InstructionFlags.None) { + if (arg.Flags == InstructionFlags.None) + { // OK - we accept integer literals, etc. - } else if (arg.MatchLdLoc(out var v)) { - } else { + } + else if (arg.MatchLdLoc(out var v)) + { + } + else + { return false; } } @@ -232,10 +245,15 @@ namespace ICSharpCode.Decompiler.IL var target = stobj.Target; while (target.MatchLdFlda(out var nestedTarget, out _)) target = nestedTarget; - if (target.Flags == InstructionFlags.None) { + if (target.Flags == InstructionFlags.None) + { // OK - we accept integer literals, etc. - } else if (target.MatchLdLoc(out var v)) { - } else { + } + else if (target.MatchLdLoc(out var v)) + { + } + else + { return false; } if (stobj.Target.InferType(typeSystem) is ByReferenceType brt) @@ -255,14 +273,16 @@ namespace ICSharpCode.Decompiler.IL var patternVariables = new HashSet(); var conversionVariables = new HashSet(); - foreach (StLoc init in this.Init) { + foreach (StLoc init in this.Init) + { Debug.Assert(init.Variable.IsSingleDefinition && init.Variable.LoadCount == 1); Debug.Assert(init.Variable.LoadInstructions[0].IsDescendantOf(assignments)); } ValidatePattern(pattern); - foreach (var inst in this.conversions.Instructions) { + foreach (var inst in this.conversions.Instructions) + { if (!IsConversionStLoc(inst, out var variable, out var inputVariable)) Debug.Fail("inst is not a conversion stloc!"); Debug.Assert(variable.IsSingleDefinition && variable.LoadCount == 1); @@ -272,7 +292,8 @@ namespace ICSharpCode.Decompiler.IL } Debug.Assert(this.conversions.FinalInstruction is Nop); - foreach (var inst in assignments.Instructions) { + foreach (var inst in assignments.Instructions) + { if (!(IsAssignment(inst, typeSystem: null, out _, out var value) && value.MatchLdLoc(out var inputVariable))) throw new InvalidOperationException("inst is not an assignment!"); Debug.Assert(patternVariables.Contains(inputVariable) || conversionVariables.Contains(inputVariable)); @@ -284,13 +305,17 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(inst.IsDeconstructCall || inst.IsDeconstructTuple); Debug.Assert(!inst.CheckNotNull && !inst.CheckType); Debug.Assert(!inst.HasDesignator); - foreach (var subPattern in inst.SubPatterns.Cast()) { - if (subPattern.IsVar) { + foreach (var subPattern in inst.SubPatterns.Cast()) + { + if (subPattern.IsVar) + { Debug.Assert(subPattern.Variable.IsSingleDefinition && subPattern.Variable.LoadCount <= 1); if (subPattern.Variable.LoadCount == 1) Debug.Assert(subPattern.Variable.LoadInstructions[0].IsDescendantOf(this)); patternVariables.Add(subPattern.Variable); - } else { + } + else + { ValidatePattern(subPattern); } } diff --git a/ICSharpCode.Decompiler/IL/Instructions/DeconstructResultInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/DeconstructResultInstruction.cs index 998a0e37c..2a6ed9655 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/DeconstructResultInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/DeconstructResultInstruction.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Diagnostics; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL @@ -48,7 +49,8 @@ namespace ICSharpCode.Decompiler.IL MatchInstruction FindMatch() { - for (ILInstruction inst = this; inst != null; inst = inst.Parent) { + for (ILInstruction inst = this; inst != null; inst = inst.Parent) + { if (inst.Parent is MatchInstruction match && inst != match.TestedOperand) return match; } diff --git a/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs b/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs index d11c69171..537475072 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; + using ICSharpCode.Decompiler.IL.Patterns; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -112,7 +113,8 @@ namespace ICSharpCode.Decompiler.IL { output.Write('('); int j = 0; - foreach (var (arg, info) in arguments) { + foreach (var (arg, info) in arguments) + { if (j > 0) output.Write(", "); output.Write("[flags: "); @@ -186,10 +188,12 @@ namespace ICSharpCode.Decompiler.IL WriteBinderFlags(output, options); output.Write(' '); output.Write(Name); - if (TypeArguments.Count > 0) { + if (TypeArguments.Count > 0) + { output.Write('<'); int i = 0; - foreach (var typeArg in TypeArguments) { + foreach (var typeArg in TypeArguments) + { if (i > 0) output.Write(", "); typeArg.WriteTo(output); @@ -273,7 +277,8 @@ namespace ICSharpCode.Decompiler.IL public override CSharpArgumentInfo GetArgumentInfoOfChild(int index) { - switch (index) { + switch (index) + { case 0: return TargetArgumentInfo; case 1: @@ -414,7 +419,8 @@ namespace ICSharpCode.Decompiler.IL public override CSharpArgumentInfo GetArgumentInfoOfChild(int index) { - switch (index) { + switch (index) + { case 0: return LeftArgumentInfo; case 1: @@ -463,7 +469,8 @@ namespace ICSharpCode.Decompiler.IL public override CSharpArgumentInfo GetArgumentInfoOfChild(int index) { - switch (index) { + switch (index) + { case 0: return LeftArgumentInfo; case 1: @@ -499,7 +506,8 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { - switch (Operation) { + switch (Operation) + { case ExpressionType.IsFalse: case ExpressionType.IsTrue: return StackType.I4; // bool @@ -511,7 +519,8 @@ namespace ICSharpCode.Decompiler.IL public override CSharpArgumentInfo GetArgumentInfoOfChild(int index) { - switch (index) { + switch (index) + { case 0: return OperandArgumentInfo; default: diff --git a/ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs b/ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs index 059572ff5..5b963f4e0 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL @@ -20,7 +21,8 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (IsChecked) output.Write(".checked"); + if (IsChecked) + output.Write(".checked"); output.Write(' '); type.WriteTo(output); output.Write('('); diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs index d66248133..f372c88b5 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs @@ -18,9 +18,9 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using System.Collections.Immutable; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -129,10 +129,12 @@ namespace ICSharpCode.Decompiler.IL /// internal int ChainedConstructorCallILOffset { get { - if (ctorCallStart == int.MinValue) { + if (ctorCallStart == int.MinValue) + { if (!this.Method.IsConstructor || this.Method.IsStatic) ctorCallStart = -1; - else { + else + { ctorCallStart = this.Descendants.FirstOrDefault(d => d is CallInstruction call && !(call is NewObj) && call.Method.IsConstructor && call.Method.DeclaringType.IsReferenceType == true @@ -217,7 +219,8 @@ namespace ICSharpCode.Decompiler.IL internal override void CheckInvariant(ILPhase phase) { - switch (kind) { + switch (kind) + { case ILFunctionKind.TopLevelFunction: Debug.Assert(Parent == null); Debug.Assert(DelegateType == null); @@ -241,7 +244,8 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(Method != null); break; } - for (int i = 0; i < Variables.Count; i++) { + for (int i = 0; i < Variables.Count; i++) + { Debug.Assert(Variables[i].Function == this); Debug.Assert(Variables[i].IndexInFunction == i); Variables[i].CheckInvariant(); @@ -258,11 +262,13 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (Method != null) { + if (Method != null) + { output.Write(' '); Method.WriteTo(output); } - switch (kind) { + switch (kind) + { case ILFunctionKind.ExpressionTree: output.Write(".ET"); break; @@ -270,7 +276,8 @@ namespace ICSharpCode.Decompiler.IL output.Write(".local"); break; } - if (DelegateType != null) { + if (DelegateType != null) + { output.Write("["); DelegateType.WriteTo(output); output.Write("]"); @@ -278,41 +285,49 @@ namespace ICSharpCode.Decompiler.IL output.WriteLine(" {"); output.Indent(); - if (IsAsync) { + if (IsAsync) + { output.WriteLine(".async"); } - if (IsIterator) { + if (IsIterator) + { output.WriteLine(".iterator"); } - if (DeclarationScope != null) { + if (DeclarationScope != null) + { output.Write("declared as " + Name + " in "); output.WriteLocalReference(DeclarationScope.EntryPoint.Label, DeclarationScope); output.WriteLine(); } output.MarkFoldStart(Variables.Count + " variable(s)", true); - foreach (var variable in Variables) { + foreach (var variable in Variables) + { variable.WriteDefinitionTo(output); output.WriteLine(); } output.MarkFoldEnd(); output.WriteLine(); - foreach (string warning in Warnings) { + foreach (string warning in Warnings) + { output.WriteLine("//" + warning); } body.WriteTo(output, options); output.WriteLine(); - foreach (var localFunction in LocalFunctions) { + foreach (var localFunction in LocalFunctions) + { output.WriteLine(); localFunction.WriteTo(output, options); } - if (options.ShowILRanges) { + if (options.ShowILRanges) + { var unusedILRanges = FindUnusedILRanges(); - if (!unusedILRanges.IsEmpty) { + if (!unusedILRanges.IsEmpty) + { output.Write("// Unused IL Ranges: "); output.Write(string.Join(", ", unusedILRanges.Intervals.Select( range => $"[{range.Start:x4}..{range.InclusiveEnd:x4}]"))); @@ -323,7 +338,7 @@ namespace ICSharpCode.Decompiler.IL output.Unindent(); output.WriteLine("}"); } - + LongSet FindUnusedILRanges() { var usedILRanges = new List(); @@ -332,11 +347,14 @@ namespace ICSharpCode.Decompiler.IL void MarkUsedILRanges(ILInstruction inst) { - if (CSharp.SequencePointBuilder.HasUsableILRange(inst)) { + if (CSharp.SequencePointBuilder.HasUsableILRange(inst)) + { usedILRanges.Add(new LongInterval(inst.StartILOffset, inst.EndILOffset)); } - if (!(inst is ILFunction)) { - foreach (var child in inst.Children) { + if (!(inst is ILFunction)) + { + foreach (var child in inst.Children) + { MarkUsedILRanges(child); } } @@ -349,7 +367,7 @@ namespace ICSharpCode.Decompiler.IL // We intentionally don't propagate any flags from the lambda body! return InstructionFlags.MayThrow | InstructionFlags.ControlFlow; } - + public override InstructionFlags DirectFlags { get { return InstructionFlags.MayThrow | InstructionFlags.ControlFlow; @@ -371,11 +389,15 @@ namespace ICSharpCode.Decompiler.IL public void RunTransforms(IEnumerable transforms, ILTransformContext context) { this.CheckInvariant(ILPhase.Normal); - foreach (var transform in transforms) { + foreach (var transform in transforms) + { context.CancellationToken.ThrowIfCancellationRequested(); - if (transform is BlockILTransform blockTransform) { + if (transform is BlockILTransform blockTransform) + { context.StepStartGroup(blockTransform.ToString()); - } else { + } + else + { context.StepStartGroup(transform.GetType().Name); } transform.Run(this, context); @@ -400,7 +422,8 @@ namespace ICSharpCode.Decompiler.IL ILVariable RegisterVariable(VariableKind kind, IType type, StackType stackType, string name = null) { var variable = new ILVariable(kind, type, stackType); - if (string.IsNullOrWhiteSpace(name)) { + if (string.IsNullOrWhiteSpace(name)) + { name = "I_" + (helperVariableCount++); variable.HasGeneratedName = true; } @@ -417,13 +440,16 @@ namespace ICSharpCode.Decompiler.IL if (variable1 == variable2) return; Debug.Assert(ILVariableEqualityComparer.Instance.Equals(variable1, variable2)); - foreach (var ldloc in variable2.LoadInstructions.ToArray()) { + foreach (var ldloc in variable2.LoadInstructions.ToArray()) + { ldloc.Variable = variable1; } - foreach (var store in variable2.StoreInstructions.ToArray()) { + foreach (var store in variable2.StoreInstructions.ToArray()) + { store.Variable = variable1; } - foreach (var ldloca in variable2.AddressInstructions.ToArray()) { + foreach (var ldloca in variable2.AddressInstructions.ToArray()) + { ldloca.Variable = variable1; } bool ok = Variables.Remove(variable2); diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs index 01a37daa2..2f5ea6fdc 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; + using ICSharpCode.Decompiler.IL.Patterns; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -44,19 +45,19 @@ namespace ICSharpCode.Decompiler.IL /// InAsyncAwait } - + /// /// Represents a decoded IL instruction /// public abstract partial class ILInstruction { public readonly OpCode OpCode; - + protected ILInstruction(OpCode opCode) { this.OpCode = opCode; } - + protected void ValidateChild(ILInstruction inst) { if (inst == null) @@ -65,11 +66,12 @@ namespace ICSharpCode.Decompiler.IL // If a call to ReplaceWith() triggers the "ILAst must form a tree" assertion, // make sure to read the remarks on the ReplaceWith() method. } - + [Conditional("DEBUG")] internal virtual void CheckInvariant(ILPhase phase) { - foreach (var child in Children) { + foreach (var child in Children) + { Debug.Assert(child.Parent == this); Debug.Assert(this.GetChild(child.ChildIndex) == child); // if child flags are invalid, parent flags must be too @@ -80,7 +82,7 @@ namespace ICSharpCode.Decompiler.IL } Debug.Assert((this.DirectFlags & ~this.Flags) == 0, "All DirectFlags must also appear in this.Flags"); } - + /// /// Gets whether this node is a descendant of . /// Also returns true if this==. @@ -92,7 +94,8 @@ namespace ICSharpCode.Decompiler.IL /// public bool IsDescendantOf(ILInstruction possibleAncestor) { - for (ILInstruction ancestor = this; ancestor != null; ancestor = ancestor.Parent) { + for (ILInstruction ancestor = this; ancestor != null; ancestor = ancestor.Parent) + { if (ancestor == possibleAncestor) return true; } @@ -110,17 +113,20 @@ namespace ICSharpCode.Decompiler.IL int levelA = a.CountAncestors(); int levelB = b.CountAncestors(); - while (levelA > levelB) { + while (levelA > levelB) + { a = a.Parent; levelA--; } - while (levelB > levelA) { + while (levelB > levelA) + { b = b.Parent; levelB--; } - while (a != b) { + while (a != b) + { a = a.Parent; b = b.Parent; } @@ -145,23 +151,27 @@ namespace ICSharpCode.Decompiler.IL int originalLevelA = levelA; int originalLevelB = levelB; - while (levelA > levelB) { + while (levelA > levelB) + { a = a.Parent; levelA--; } - while (levelB > levelA) { + while (levelB > levelA) + { b = b.Parent; levelB--; } - if (a == b) { + if (a == b) + { // a or b is a descendant of the other, // whichever node has the higher level comes first in post-order walk. return originalLevelA > originalLevelB; } - while (a.Parent != b.Parent) { + while (a.Parent != b.Parent) + { a = a.Parent; b = b.Parent; } @@ -173,17 +183,18 @@ namespace ICSharpCode.Decompiler.IL private int CountAncestors() { int level = 0; - for (ILInstruction ancestor = this; ancestor != null; ancestor = ancestor.Parent) { + for (ILInstruction ancestor = this; ancestor != null; ancestor = ancestor.Parent) + { level++; } return level; } - + /// /// Gets the stack type of the value produced by this instruction. /// public abstract StackType ResultType { get; } - + /* Not sure if it's a good idea to offer this on all instructions -- * e.g. ldloc for a local of type `int?` would return StackType.O (because it's not a lifted operation), * even though the underlying type is int = StackType.I4. @@ -229,16 +240,17 @@ namespace ICSharpCode.Decompiler.IL protected private void MakeDirty() { #if DEBUG - for (ILInstruction inst = this; inst != null && !inst.IsDirty; inst = inst.parent) { + for (ILInstruction inst = this; inst != null && !inst.IsDirty; inst = inst.parent) + { inst.IsDirty = true; } #endif } - + const InstructionFlags invalidFlags = (InstructionFlags)(-1); - + InstructionFlags flags = invalidFlags; - + /// /// Gets the flags describing the behavior of this instruction. /// This property computes the flags on-demand and caches them @@ -251,7 +263,8 @@ namespace ICSharpCode.Decompiler.IL /// public InstructionFlags Flags { get { - if (flags == invalidFlags) { + if (flags == invalidFlags) + { flags = ComputeFlags(); } return flags; @@ -265,7 +278,7 @@ namespace ICSharpCode.Decompiler.IL { return (this.Flags & flags) != 0; } - + /// /// Returns whether the instruction (without considering child instructions) has at least one of the specified flags. /// @@ -273,20 +286,20 @@ namespace ICSharpCode.Decompiler.IL { return (this.DirectFlags & flags) != 0; } - + protected void InvalidateFlags() { for (ILInstruction inst = this; inst != null && inst.flags != invalidFlags; inst = inst.parent) inst.flags = invalidFlags; } - + protected abstract InstructionFlags ComputeFlags(); - + /// /// Gets the flags for this instruction only, without considering the child instructions. /// public abstract InstructionFlags DirectFlags { get; } - + /// /// Gets the ILRange for this instruction alone, ignoring the operands. /// @@ -299,20 +312,28 @@ namespace ICSharpCode.Decompiler.IL protected static Interval CombineILRange(Interval oldRange, Interval newRange) { - if (oldRange.IsEmpty) { + if (oldRange.IsEmpty) + { return newRange; } - if (newRange.IsEmpty) { + if (newRange.IsEmpty) + { return oldRange; } - if (newRange.Start <= oldRange.Start) { - if (newRange.End < oldRange.Start) { + if (newRange.Start <= oldRange.Start) + { + if (newRange.End < oldRange.Start) + { return newRange; // use the earlier range - } else { + } + else + { // join overlapping ranges return new Interval(newRange.Start, Math.Max(newRange.End, oldRange.End)); } - } else if (newRange.Start <= oldRange.End) { + } + else if (newRange.Start <= oldRange.End) + { // join overlapping ranges return new Interval(oldRange.Start, Math.Max(newRange.End, oldRange.End)); } @@ -356,27 +377,28 @@ namespace ICSharpCode.Decompiler.IL { var output = new PlainTextOutput(); WriteTo(output, new ILAstWritingOptions()); - if (!ILRange.IsEmpty) { + if (!ILRange.IsEmpty) + { output.Write(" at IL_" + ILRange.Start.ToString("x4")); } return output.ToString(); } - + /// /// Calls the Visit*-method on the visitor corresponding to the concrete type of this instruction. /// public abstract void AcceptVisitor(ILVisitor visitor); - + /// /// Calls the Visit*-method on the visitor corresponding to the concrete type of this instruction. /// public abstract T AcceptVisitor(ILVisitor visitor); - + /// /// Calls the Visit*-method on the visitor corresponding to the concrete type of this instruction. /// public abstract T AcceptVisitor(ILVisitor visitor, C context); - + /// /// Gets the child nodes of this instruction. /// @@ -389,73 +411,73 @@ namespace ICSharpCode.Decompiler.IL return new ChildrenCollection(this); } } - + protected abstract int GetChildCount(); protected abstract ILInstruction GetChild(int index); protected abstract void SetChild(int index, ILInstruction value); protected abstract SlotInfo GetChildSlot(int index); - + #region ChildrenCollection + ChildrenEnumerator public readonly struct ChildrenCollection : IReadOnlyList { readonly ILInstruction inst; - + internal ChildrenCollection(ILInstruction inst) { Debug.Assert(inst != null); this.inst = inst; } - + public int Count { get { return inst.GetChildCount(); } } - + public ILInstruction this[int index] { get { return inst.GetChild(index); } set { inst.SetChild(index, value); } } - + public ChildrenEnumerator GetEnumerator() { return new ChildrenEnumerator(inst); } - + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } - + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } - - #if DEBUG + +#if DEBUG int activeEnumerators; - + [Conditional("DEBUG")] internal void StartEnumerator() { activeEnumerators++; } - + [Conditional("DEBUG")] internal void StopEnumerator() { Debug.Assert(activeEnumerators > 0); activeEnumerators--; } - #endif - +#endif + [Conditional("DEBUG")] internal void AssertNoEnumerators() { - #if DEBUG +#if DEBUG Debug.Assert(activeEnumerators == 0); - #endif +#endif } - + /// /// Enumerator over the children of an ILInstruction. /// Warning: even though this is a struct, it is invalid to copy: @@ -466,18 +488,18 @@ namespace ICSharpCode.Decompiler.IL ILInstruction inst; readonly int end; int pos; - + internal ChildrenEnumerator(ILInstruction inst) { Debug.Assert(inst != null); this.inst = inst; this.pos = -1; this.end = inst.GetChildCount(); - #if DEBUG +#if DEBUG inst.StartEnumerator(); - #endif +#endif } - + public ILInstruction Current { get { return inst.GetChild(pos); @@ -491,18 +513,19 @@ namespace ICSharpCode.Decompiler.IL public void Dispose() { - #if DEBUG - if (inst != null) { +#if DEBUG + if (inst != null) + { inst.StopEnumerator(); inst = null; } - #endif +#endif } - + object System.Collections.IEnumerator.Current { get { return this.Current; } } - + void System.Collections.IEnumerator.Reset() { pos = -1; @@ -538,7 +561,7 @@ namespace ICSharpCode.Decompiler.IL return; parent.SetChild(ChildIndex, replacement); } - + /// /// Returns all descendants of the ILInstruction in post-order. /// (including the ILInstruction itself) @@ -559,37 +582,47 @@ namespace ICSharpCode.Decompiler.IL // if the ILAst is modified during enumeration. Stack stack = new Stack(); ChildrenEnumerator enumerator = new ChildrenEnumerator(this); - try { - while (true) { - while (enumerator.MoveNext()) { + try + { + while (true) + { + while (enumerator.MoveNext()) + { var element = enumerator.Current; stack.Push(enumerator); enumerator = new ChildrenEnumerator(element); } enumerator.Dispose(); - if (stack.Count > 0) { + if (stack.Count > 0) + { enumerator = stack.Pop(); yield return enumerator.Current; - } else { + } + else + { break; } } - } finally { + } + finally + { enumerator.Dispose(); - while (stack.Count > 0) { + while (stack.Count > 0) + { stack.Pop().Dispose(); } } yield return this; } } - + /// /// Gets the ancestors of this node (including the node itself as first element). /// public IEnumerable Ancestors { get { - for (ILInstruction node = this; node != null; node = node.Parent) { + for (ILInstruction node = this; node != null; node = node.Parent) + { yield return node; } } @@ -602,22 +635,24 @@ namespace ICSharpCode.Decompiler.IL /// or possibly even more (re-arrangement with stale positions). /// byte refCount; - + internal void AddRef() { - if (refCount++ == 0) { + if (refCount++ == 0) + { Connected(); } } - + internal void ReleaseRef() { Debug.Assert(refCount > 0); - if (--refCount == 0) { + if (--refCount == 0) + { Disconnected(); } } - + /// /// Gets whether this ILInstruction is connected to the root node of the ILAst. /// @@ -629,7 +664,7 @@ namespace ICSharpCode.Decompiler.IL protected internal bool IsConnected { get { return refCount > 0; } } - + /// /// Called after the ILInstruction was connected to the root node of the ILAst. /// @@ -638,7 +673,7 @@ namespace ICSharpCode.Decompiler.IL foreach (var child in Children) child.AddRef(); } - + /// /// Called after the ILInstruction was disconnected from the root node of the ILAst. /// @@ -647,9 +682,9 @@ namespace ICSharpCode.Decompiler.IL foreach (var child in Children) child.ReleaseRef(); } - + ILInstruction parent; - + /// /// Gets the parent of this ILInstruction. /// @@ -677,7 +712,7 @@ namespace ICSharpCode.Decompiler.IL public ILInstruction Parent { get { return parent; } } - + /// /// Gets the index of this node in the Parent.Children collection. /// @@ -686,7 +721,7 @@ namespace ICSharpCode.Decompiler.IL /// this property returns the index of the primary position of this node (see remarks on ). /// public int ChildIndex { get; internal set; } = -1; - + /// /// Gets information about the slot in which this instruction is stored. /// (i.e., the relation of this instruction to its parent instruction) @@ -705,7 +740,7 @@ namespace ICSharpCode.Decompiler.IL return parent.GetChildSlot(this.ChildIndex); } } - + /// /// Replaces a child of this ILInstruction. /// @@ -720,13 +755,15 @@ namespace ICSharpCode.Decompiler.IL if (oldValue == newValue && newValue?.parent == this && newValue.ChildIndex == index) return; childPointer = newValue; - if (newValue != null) { + if (newValue != null) + { newValue.parent = this; newValue.ChildIndex = index; } InvalidateFlags(); MakeDirty(); - if (refCount > 0) { + if (refCount > 0) + { // The new value may be a subtree of the old value. // We first call AddRef(), then ReleaseRef() to prevent the subtree // that stays connected from receiving a Disconnected() notification followed by a Connected() notification. @@ -736,7 +773,7 @@ namespace ICSharpCode.Decompiler.IL oldValue.ReleaseRef(); } } - + /// /// Called when a new child is added to a InstructionCollection. /// @@ -750,7 +787,7 @@ namespace ICSharpCode.Decompiler.IL if (refCount > 0) newChild.AddRef(); } - + /// /// Called when a child is removed from a InstructionCollection. /// @@ -759,7 +796,7 @@ namespace ICSharpCode.Decompiler.IL if (refCount > 0) oldChild.ReleaseRef(); } - + /// /// Called when a series of add/remove operations on the InstructionCollection is complete. /// @@ -768,7 +805,7 @@ namespace ICSharpCode.Decompiler.IL InvalidateFlags(); MakeDirty(); } - + /// /// Creates a deep clone of the ILInstruction. /// @@ -778,7 +815,7 @@ namespace ICSharpCode.Decompiler.IL /// multiple positions will be cloned once per position). /// public abstract ILInstruction Clone(); - + /// /// Creates a shallow clone of the ILInstruction. /// @@ -792,12 +829,12 @@ namespace ICSharpCode.Decompiler.IL inst.refCount = 0; inst.parent = null; inst.flags = invalidFlags; - #if DEBUG +#if DEBUG inst.activeEnumerators = 0; - #endif +#endif return inst; } - + /// /// Attempts to match the specified node against the pattern. /// @@ -814,7 +851,7 @@ namespace ICSharpCode.Decompiler.IL match.Success = PerformMatch(node, ref match); return match; } - + /// /// Attempts matching this instruction against the other instruction. /// @@ -825,7 +862,7 @@ namespace ICSharpCode.Decompiler.IL /// If the method returns false, the match object may remain in a partially-updated state and /// needs to be restored before it can be reused. protected internal abstract bool PerformMatch(ILInstruction other, ref Match match); - + /// /// Attempts matching this instruction against a list of other instructions (or a part of said list). /// @@ -840,8 +877,10 @@ namespace ICSharpCode.Decompiler.IL { // Base implementation expects the node to match a single element. // Any patterns matching 0 or more than 1 element must override this method. - if (listMatch.SyntaxIndex < listMatch.SyntaxList.Count) { - if (PerformMatch(listMatch.SyntaxList[listMatch.SyntaxIndex], ref match)) { + if (listMatch.SyntaxIndex < listMatch.SyntaxList.Count) + { + if (PerformMatch(listMatch.SyntaxList[listMatch.SyntaxIndex], ref match)) + { listMatch.SyntaxIndex++; return true; } @@ -870,13 +909,16 @@ namespace ICSharpCode.Decompiler.IL /// True if extraction is possible; false otherwise. internal virtual bool PrepareExtract(int childIndex, Transforms.ExtractionContext ctx) { - if (!GetChildSlot(childIndex).CanInlineInto) { + if (!GetChildSlot(childIndex).CanInlineInto) + { return false; } // Check whether re-ordering with predecessors is valid: - for (int i = childIndex - 1; i >= 0; --i) { + for (int i = childIndex - 1; i >= 0; --i) + { ILInstruction predecessor = GetChild(i); - if (!GetChildSlot(i).CanInlineInto) { + if (!GetChildSlot(i).CanInlineInto) + { return false; } ctx.RegisterMoveIfNecessary(predecessor); @@ -893,17 +935,17 @@ namespace ICSharpCode.Decompiler.IL return GetChildSlot(childIndex).CanInlineInto; } } - + public interface IInstructionWithTypeOperand { IType Type { get; } } - + public interface IInstructionWithFieldOperand { IField Field { get; } } - + public interface IInstructionWithMethodOperand { IMethod Method { get; } diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILVariableCollection.cs b/ICSharpCode.Decompiler/IL/Instructions/ILVariableCollection.cs index f27d962a7..356844065 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ILVariableCollection.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ILVariableCollection.cs @@ -29,12 +29,12 @@ namespace ICSharpCode.Decompiler.IL { readonly ILFunction scope; readonly List list = new List(); - + internal ILVariableCollection(ILFunction scope) { this.scope = scope; } - + /// /// Gets a variable given its IndexInFunction. /// @@ -43,10 +43,11 @@ namespace ICSharpCode.Decompiler.IL return list[index]; } } - + public bool Add(ILVariable item) { - if (item.Function != null) { + if (item.Function != null) + { if (item.Function == scope) return false; else @@ -57,26 +58,27 @@ namespace ICSharpCode.Decompiler.IL list.Add(item); return true; } - + void ICollection.Add(ILVariable item) { Add(item); } - + public void Clear() { - foreach (var v in list) { + foreach (var v in list) + { v.Function = null; } list.Clear(); } - + public bool Contains(ILVariable item) { Debug.Assert(item.Function != scope || list[item.IndexInFunction] == item); return item.Function == scope; } - + public bool Remove(ILVariable item) { if (item.Function != scope) @@ -85,7 +87,7 @@ namespace ICSharpCode.Decompiler.IL RemoveAt(item.IndexInFunction); return true; } - + void RemoveAt(int index) { list[index].Function = null; @@ -94,48 +96,52 @@ namespace ICSharpCode.Decompiler.IL list[index].IndexInFunction = index; list.RemoveAt(list.Count - 1); } - + /// /// Remove variables that have StoreCount == LoadCount == AddressCount == 0. /// public void RemoveDead() { - for (int i = 0; i < list.Count;) { + for (int i = 0; i < list.Count;) + { var v = list[i]; // Note: we cannot remove display-class locals from the collection, // even if they are unused - which is always the case, if TDCU succeeds, // because they are necessary for PDB generation to produce correct results. - if (v.IsDead && v.Kind != VariableKind.DisplayClassLocal) { + if (v.IsDead && v.Kind != VariableKind.DisplayClassLocal) + { RemoveAt(i); - } else { + } + else + { i++; } } } - + public int Count { get { return list.Count; } } - + public void CopyTo(ILVariable[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); } - + bool ICollection.IsReadOnly { get { return false; } } - + public List.Enumerator GetEnumerator() { return list.GetEnumerator(); } - + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } - + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); diff --git a/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs index fb28f1c7b..1d668423b 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs @@ -60,7 +60,7 @@ namespace ICSharpCode.Decompiler.IL || trueInst.HasDirectFlag(InstructionFlags.EndPointUnreachable) || falseInst.HasDirectFlag(InstructionFlags.EndPointUnreachable)); } - + public override StackType ResultType { get { if (trueInst.HasDirectFlag(InstructionFlags.EndPointUnreachable)) @@ -69,23 +69,25 @@ namespace ICSharpCode.Decompiler.IL return trueInst.ResultType; } } - + public override InstructionFlags DirectFlags { get { return InstructionFlags.ControlFlow; } } - + protected override InstructionFlags ComputeFlags() { return InstructionFlags.ControlFlow | condition.Flags | SemanticHelper.CombineBranches(trueInst.Flags, falseInst.Flags); } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); - if (options.UseLogicOperationSugar) { - if (MatchLogicAnd(out var lhs, out var rhs)) { + if (options.UseLogicOperationSugar) + { + if (MatchLogicAnd(out var lhs, out var rhs)) + { output.Write("logic.and("); lhs.WriteTo(output, options); output.Write(", "); @@ -93,7 +95,8 @@ namespace ICSharpCode.Decompiler.IL output.Write(')'); return; } - if (MatchLogicOr(out lhs, out rhs)) { + if (MatchLogicOr(out lhs, out rhs)) + { output.Write("logic.or("); lhs.WriteTo(output, options); output.Write(", "); @@ -107,7 +110,8 @@ namespace ICSharpCode.Decompiler.IL condition.WriteTo(output, options); output.Write(") "); trueInst.WriteTo(output, options); - if (falseInst.OpCode != OpCode.Nop) { + if (falseInst.OpCode != OpCode.Nop) + { output.Write(" else "); falseInst.WriteTo(output, options); } @@ -123,7 +127,8 @@ namespace ICSharpCode.Decompiler.IL return true; if (slot == IfInstruction.TrueInstSlot || slot == IfInstruction.FalseInstSlot || slot == NullCoalescingInstruction.FallbackInstSlot) return IsInConditionSlot(inst.Parent); - if (inst.Parent is Comp comp) { + if (inst.Parent is Comp comp) + { if (comp.Left == inst && comp.Right.MatchLdcI4(0)) return true; if (comp.Right == inst && comp.Left.MatchLdcI4(0)) diff --git a/ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs b/ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs index 63d5fd97d..8301c66cb 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs @@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.IL readonly ILInstruction parentInstruction; readonly int firstChildIndex; readonly List list = new List(); - + public InstructionCollection(ILInstruction parentInstruction, int firstChildIndex) { if (parentInstruction == null) @@ -35,16 +35,17 @@ namespace ICSharpCode.Decompiler.IL this.parentInstruction = parentInstruction; this.firstChildIndex = firstChildIndex; } - + public int Count { get { return list.Count; } } - + public T this[int index] { get { return list[index]; } set { T oldValue = list[index]; - if (!(oldValue == value && value.Parent == parentInstruction && value.ChildIndex == index)) { + if (!(oldValue == value && value.Parent == parentInstruction && value.ChildIndex == index)) + { list[index] = value; value.ChildIndex = index + firstChildIndex; parentInstruction.InstructionCollectionAdded(value); @@ -59,7 +60,7 @@ namespace ICSharpCode.Decompiler.IL { return new Enumerator(this); } - + /// /// Custom enumerator for InstructionCollection. /// Unlike List{T}.Enumerator, this enumerator allows replacing an item during the enumeration. @@ -71,22 +72,22 @@ namespace ICSharpCode.Decompiler.IL /// public struct Enumerator : IEnumerator { - #if DEBUG +#if DEBUG ILInstruction parentInstruction; - #endif +#endif readonly List list; int pos; - + public Enumerator(InstructionCollection col) { this.list = col.list; this.pos = -1; - #if DEBUG +#if DEBUG this.parentInstruction = col.parentInstruction; col.parentInstruction.StartEnumerator(); - #endif +#endif } - + [DebuggerStepThrough] public bool MoveNext() { @@ -101,24 +102,25 @@ namespace ICSharpCode.Decompiler.IL [DebuggerStepThrough] public void Dispose() { - #if DEBUG - if (parentInstruction != null) { +#if DEBUG + if (parentInstruction != null) + { parentInstruction.StopEnumerator(); parentInstruction = null; } - #endif +#endif } void System.Collections.IEnumerator.Reset() { pos = -1; } - + object System.Collections.IEnumerator.Current { get { return this.Current; } } } - + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); @@ -129,7 +131,7 @@ namespace ICSharpCode.Decompiler.IL return GetEnumerator(); } #endregion - + /// /// Gets the index of the instruction in this collection. /// Returns -1 if the instruction does not exist in the collection. @@ -140,7 +142,8 @@ namespace ICSharpCode.Decompiler.IL /// public int IndexOf(T item) { - if (item == null) { + if (item == null) + { // InstructionCollection can't contain nulls return -1; } @@ -173,7 +176,7 @@ namespace ICSharpCode.Decompiler.IL bool ICollection.IsReadOnly { get { return false; } } - + public void Add(T value) { parentInstruction.AssertNoEnumerators(); @@ -182,18 +185,19 @@ namespace ICSharpCode.Decompiler.IL parentInstruction.InstructionCollectionAdded(value); parentInstruction.InstructionCollectionUpdateComplete(); } - + public void AddRange(IEnumerable values) { parentInstruction.AssertNoEnumerators(); - foreach (T value in values) { + foreach (T value in values) + { value.ChildIndex = list.Count + firstChildIndex; list.Add(value); parentInstruction.InstructionCollectionAdded(value); } parentInstruction.InstructionCollectionUpdateComplete(); } - + /// /// Replaces all entries in the InstructionCollection with the newList. /// @@ -204,20 +208,25 @@ namespace ICSharpCode.Decompiler.IL { parentInstruction.AssertNoEnumerators(); int index = 0; - foreach (T value in newList) { + foreach (T value in newList) + { value.ChildIndex = index + firstChildIndex; - if (index < list.Count) { + if (index < list.Count) + { T oldValue = list[index]; list[index] = value; parentInstruction.InstructionCollectionAdded(value); parentInstruction.InstructionCollectionRemoved(oldValue); - } else { + } + else + { list.Add(value); parentInstruction.InstructionCollectionAdded(value); } index++; } - for (int i = index; i < list.Count; i++) { + for (int i = index; i < list.Count; i++) + { parentInstruction.InstructionCollectionRemoved(list[i]); } list.RemoveRange(index, list.Count - index); @@ -230,7 +239,8 @@ namespace ICSharpCode.Decompiler.IL list.Insert(index, item); item.ChildIndex = index; parentInstruction.InstructionCollectionAdded(item); - for (int i = index + 1; i < list.Count; i++) { + for (int i = index + 1; i < list.Count; i++) + { T other_item = list[i]; // Update ChildIndex of items after the inserted one, but only if // that's their 'primary position' (in case of multiple parents) @@ -245,14 +255,15 @@ namespace ICSharpCode.Decompiler.IL parentInstruction.AssertNoEnumerators(); parentInstruction.InstructionCollectionRemoved(list[index]); list.RemoveAt(index); - for (int i = index; i < list.Count; i++) { + for (int i = index; i < list.Count; i++) + { var other_item = list[i]; if (other_item.Parent == parentInstruction && other_item.ChildIndex == i + firstChildIndex + 1) other_item.ChildIndex = i + firstChildIndex; } parentInstruction.InstructionCollectionUpdateComplete(); } - + /// /// Remove item at index index in O(1) by swapping it with the last element in the collection. /// @@ -271,7 +282,8 @@ namespace ICSharpCode.Decompiler.IL public void Clear() { parentInstruction.AssertNoEnumerators(); - foreach (var entry in list) { + foreach (var entry in list) + { parentInstruction.InstructionCollectionRemoved(entry); } list.Clear(); @@ -281,21 +293,24 @@ namespace ICSharpCode.Decompiler.IL public bool Remove(T item) { int index = IndexOf(item); - if (index >= 0) { + if (index >= 0) + { RemoveAt(index); return true; } return false; } - + public void RemoveRange(int index, int count) { parentInstruction.AssertNoEnumerators(); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { parentInstruction.InstructionCollectionRemoved(list[index + i]); } list.RemoveRange(index, count); - for (int i = index; i < list.Count; i++) { + for (int i = index; i < list.Count; i++) + { var other_item = list[i]; if (other_item.Parent == parentInstruction && other_item.ChildIndex == i + firstChildIndex + count) other_item.ChildIndex = i + firstChildIndex; @@ -314,11 +329,15 @@ namespace ICSharpCode.Decompiler.IL { parentInstruction.AssertNoEnumerators(); int j = 0; - for (int i = 0; i < list.Count; i++) { + for (int i = 0; i < list.Count; i++) + { T item = list[i]; - if (predicate(item)) { + if (predicate(item)) + { parentInstruction.InstructionCollectionRemoved(item); - } else { + } + else + { // keep the item if (item.Parent == parentInstruction && item.ChildIndex == i + firstChildIndex) item.ChildIndex = j + firstChildIndex; @@ -327,7 +346,8 @@ namespace ICSharpCode.Decompiler.IL } } int removed = list.Count - j; - if (removed > 0) { + if (removed > 0) + { list.RemoveRange(j, removed); parentInstruction.InstructionCollectionUpdateComplete(); } @@ -349,7 +369,8 @@ namespace ICSharpCode.Decompiler.IL { parentInstruction.AssertNoEnumerators(); int oldIndex = IndexOf(item); - if (oldIndex >= 0) { + if (oldIndex >= 0) + { Insert(newIndex, item); if (oldIndex < newIndex) RemoveAt(oldIndex); @@ -383,17 +404,17 @@ namespace ICSharpCode.Decompiler.IL { return list[list.Count - 1]; } - + public T LastOrDefault() { return list.Count > 0 ? list[list.Count - 1] : null; } - + public T SecondToLastOrDefault() { return list.Count > 1 ? list[list.Count - 2] : null; } - + public T ElementAtOrDefault(int index) { if (index >= 0 && index < list.Count) diff --git a/ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs b/ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs index 8d9dc850b..ecfaa3744 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs @@ -25,7 +25,8 @@ namespace ICSharpCode.Decompiler.IL internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); - switch (field.DeclaringType.IsReferenceType) { + switch (field.DeclaringType.IsReferenceType) + { case true: Debug.Assert(target.ResultType == StackType.O, "Class fields can only be accessed with an object on the stack"); @@ -54,7 +55,8 @@ namespace ICSharpCode.Decompiler.IL /// public bool CanInlineIntoTargetSlot(ILInstruction inst) { - switch (inst.OpCode) { + switch (inst.OpCode) + { case OpCode.LdElema: case OpCode.LdFlda: Debug.Assert(inst.HasDirectFlag(InstructionFlags.MayThrow)); @@ -62,8 +64,8 @@ namespace ICSharpCode.Decompiler.IL // to turn into a delayed exception after the translation to C#. // This is only valid if the value computation doesn't involve any side effects. return SemanticHelper.IsPure(this.Value.Flags); - // Note that after inlining such a ldelema/ldflda, the normal inlining rules will - // prevent us from inlining an effectful instruction into the value slot. + // Note that after inlining such a ldelema/ldflda, the normal inlining rules will + // prevent us from inlining an effectful instruction into the value slot. default: return true; } @@ -74,10 +76,12 @@ namespace ICSharpCode.Decompiler.IL /// void CheckTargetSlot() { - switch (this.Target.OpCode) { + switch (this.Target.OpCode) + { case OpCode.LdElema: case OpCode.LdFlda: - if (this.Target.HasDirectFlag(InstructionFlags.MayThrow)) { + if (this.Target.HasDirectFlag(InstructionFlags.MayThrow)) + { Debug.Assert(SemanticHelper.IsPure(this.Value.Flags)); } break; diff --git a/ICSharpCode.Decompiler/IL/Instructions/LdLen.cs b/ICSharpCode.Decompiler/IL/Instructions/LdLen.cs index 4d520883d..e36781759 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/LdLen.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/LdLen.cs @@ -26,18 +26,18 @@ namespace ICSharpCode.Decompiler.IL public sealed partial class LdLen { readonly StackType resultType; - + public LdLen(StackType type, ILInstruction array) : base(OpCode.LdLen) { Debug.Assert(type == StackType.I || type == StackType.I4 || type == StackType.I8); this.resultType = type; this.Array = array; } - + public override StackType ResultType { get { return resultType; } } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); diff --git a/ICSharpCode.Decompiler/IL/Instructions/Leave.cs b/ICSharpCode.Decompiler/IL/Instructions/Leave.cs index d0acbd891..73290f922 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Leave.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Leave.cs @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.IL partial class Leave : ILInstruction, IBranchOrLeaveInstruction { BlockContainer targetContainer; - + public Leave(BlockContainer targetContainer, ILInstruction value = null) : base(OpCode.Leave) { // Note: ILReader will create Leave instructions with targetContainer==null to represent 'endfinally', @@ -41,18 +41,18 @@ namespace ICSharpCode.Decompiler.IL this.targetContainer = targetContainer; this.Value = value ?? new Nop(); } - + protected override InstructionFlags ComputeFlags() { return value.Flags | InstructionFlags.MayBranch | InstructionFlags.EndPointUnreachable; } - + public override InstructionFlags DirectFlags { get { return InstructionFlags.MayBranch | InstructionFlags.EndPointUnreachable; } } - + public BlockContainer TargetContainer { get { return targetContainer; } set { @@ -63,25 +63,25 @@ namespace ICSharpCode.Decompiler.IL targetContainer.LeaveCount++; } } - + protected override void Connected() { base.Connected(); if (targetContainer != null) targetContainer.LeaveCount++; } - + protected override void Disconnected() { base.Disconnected(); if (targetContainer != null) targetContainer.LeaveCount--; } - + public string TargetLabel { get { return targetContainer?.EntryPoint != null ? targetContainer.EntryPoint.Label : string.Empty; } } - + /// /// Gets whether the leave instruction is leaving the whole ILFunction. /// (TargetContainer == main container of the function). @@ -108,12 +108,13 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(targetContainer)); Debug.Assert(phase <= ILPhase.InILReader || phase == ILPhase.InAsyncAwait || value.ResultType == targetContainer.ResultType); } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); output.Write(OpCode); - if (targetContainer != null) { + if (targetContainer != null) + { output.Write(' '); output.WriteLocalReference(TargetLabel, targetContainer); output.Write(" ("); diff --git a/ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs index e29784ebe..955ece6e8 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL @@ -119,7 +120,8 @@ namespace ICSharpCode.Decompiler.IL /// public static bool IsPatternMatch(ILInstruction inst, out ILInstruction testedOperand) { - switch (inst) { + switch (inst) + { case MatchInstruction m: testedOperand = m.testedOperand; return true; @@ -150,14 +152,16 @@ namespace ICSharpCode.Decompiler.IL internal IType GetDeconstructResultType(int index) { - if (this.IsDeconstructCall) { + if (this.IsDeconstructCall) + { int firstOutParam = (method.IsStatic ? 1 : 0); var outParamType = this.Method.Parameters[firstOutParam + index].Type; if (!(outParamType is ByReferenceType brt)) throw new InvalidOperationException("deconstruct out param must be by reference"); return brt.ElementType; } - if (this.IsDeconstructTuple) { + if (this.IsDeconstructTuple) + { var elementTypes = TupleType.GetTupleElementTypes(this.variable.Type); return elementTypes[index]; } @@ -167,29 +171,41 @@ namespace ICSharpCode.Decompiler.IL void AdditionalInvariants() { Debug.Assert(variable.Kind == VariableKind.PatternLocal); - if (this.IsDeconstructCall) { + if (this.IsDeconstructCall) + { Debug.Assert(IsDeconstructMethod(method)); - } else { + } + else + { Debug.Assert(method == null); } - if (this.IsDeconstructTuple) { + if (this.IsDeconstructTuple) + { Debug.Assert(variable.Type.Kind == TypeKind.Tuple); } Debug.Assert(SubPatterns.Count >= NumPositionalPatterns); - foreach (var subPattern in SubPatterns) { + foreach (var subPattern in SubPatterns) + { if (!IsPatternMatch(subPattern, out ILInstruction operand)) Debug.Fail("Sub-Pattern must be a valid pattern"); // the first child is TestedOperand int subPatternIndex = subPattern.ChildIndex - 1; - if (subPatternIndex < NumPositionalPatterns) { + if (subPatternIndex < NumPositionalPatterns) + { // positional pattern - Debug.Assert(operand is DeconstructResultInstruction result && result.Index == subPatternIndex); - } else if (operand.MatchLdFld(out var target, out _)) { + Debug.Assert(operand is DeconstructResultInstruction result && result.Index == subPatternIndex); + } + else if (operand.MatchLdFld(out var target, out _)) + { Debug.Assert(target.MatchLdLoc(variable)); - } else if (operand is CallInstruction call) { + } + else if (operand is CallInstruction call) + { Debug.Assert(call.Method.AccessorKind == System.Reflection.MethodSemanticsAttributes.Getter); Debug.Assert(call.Arguments[0].MatchLdLoc(variable)); - } else { + } + else + { Debug.Fail("Tested operand of sub-pattern is invalid."); } } @@ -202,11 +218,14 @@ namespace ICSharpCode.Decompiler.IL if (method.ReturnType.Kind != TypeKind.Void) return false; int firstOutParam = (method.IsStatic ? 1 : 0); - if (method.IsStatic) { + if (method.IsStatic) + { if (!method.IsExtensionMethod) return false; // TODO : check whether all type arguments can be inferred from the first argument - } else { + } + else + { if (method.TypeParameters.Count != 0) return false; } @@ -216,7 +235,8 @@ namespace ICSharpCode.Decompiler.IL if (method.Parameters.Count < firstOutParam) return false; - for (int i = firstOutParam; i < method.Parameters.Count; i++) { + for (int i = firstOutParam; i < method.Parameters.Count; i++) + { if (!method.Parameters[i].IsOut) return false; } @@ -228,20 +248,24 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (CheckNotNull) { + if (CheckNotNull) + { output.Write(".notnull"); } - if (CheckType) { + if (CheckType) + { output.Write(".type["); variable.Type.WriteTo(output); output.Write(']'); } - if (IsDeconstructCall) { + if (IsDeconstructCall) + { output.Write(".deconstruct["); method.WriteTo(output); output.Write(']'); } - if (IsDeconstructTuple) { + if (IsDeconstructTuple) + { output.Write(".tuple"); } output.Write(' '); @@ -250,11 +274,13 @@ namespace ICSharpCode.Decompiler.IL output.Write(" = "); TestedOperand.WriteTo(output, options); output.Write(')'); - if (SubPatterns.Count > 0) { + if (SubPatterns.Count > 0) + { output.MarkFoldStart("{...}"); output.WriteLine("{"); output.Indent(); - foreach (var pattern in SubPatterns) { + foreach (var pattern in SubPatterns) + { pattern.WriteTo(output, options); output.WriteLine(); } diff --git a/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs b/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs index d4e8bc7c1..a10d96d59 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs @@ -39,8 +39,10 @@ namespace ICSharpCode.Decompiler.IL { public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - if (options.UseFieldSugar) { - if (this.MatchLdFld(out var target, out var field)) { + if (options.UseFieldSugar) + { + if (this.MatchLdFld(out var target, out var field)) + { WriteILRange(output, options); output.Write("ldfld "); field.WriteTo(output); @@ -48,7 +50,9 @@ namespace ICSharpCode.Decompiler.IL target.WriteTo(output, options); output.Write(')'); return; - } else if (this.MatchLdsFld(out field)) { + } + else if (this.MatchLdsFld(out field)) + { WriteILRange(output, options); output.Write("ldsfld "); field.WriteTo(output); @@ -63,8 +67,10 @@ namespace ICSharpCode.Decompiler.IL { public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - if (options.UseFieldSugar) { - if (this.MatchStFld(out var target, out var field, out var value)) { + if (options.UseFieldSugar) + { + if (this.MatchStFld(out var target, out var field, out var value)) + { WriteILRange(output, options); output.Write("stfld "); field.WriteTo(output); @@ -74,7 +80,9 @@ namespace ICSharpCode.Decompiler.IL value.WriteTo(output, options); output.Write(')'); return; - } else if (this.MatchStsFld(out field, out value)) { + } + else if (this.MatchStsFld(out field, out value)) + { WriteILRange(output, options); output.Write("stsfld "); field.WriteTo(output); diff --git a/ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs b/ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs index 8e2b2e430..05fffc1bc 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs @@ -18,6 +18,7 @@ using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.IL.Transforms; namespace ICSharpCode.Decompiler.IL @@ -68,7 +69,8 @@ namespace ICSharpCode.Decompiler.IL { this.ResultType = unwrappedType; this.RefInput = refInput; - if (unwrappedType == StackType.Ref) { + if (unwrappedType == StackType.Ref) + { Debug.Assert(refInput); } } @@ -76,9 +78,12 @@ namespace ICSharpCode.Decompiler.IL internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); - if (this.RefInput) { + if (this.RefInput) + { Debug.Assert(Argument.ResultType == StackType.Ref, "nullable.unwrap expects reference to nullable type as input"); - } else { + } + else + { Debug.Assert(Argument.ResultType == StackType.O, "nullable.unwrap expects nullable type as input"); } Debug.Assert(Ancestors.Any(a => a is NullableRewrap)); @@ -87,7 +92,8 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { output.Write("nullable.unwrap."); - if (RefInput) { + if (RefInput) + { output.Write("refinput."); } output.Write(ResultType); diff --git a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs index 145e7a5f1..5c245dcdc 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs @@ -44,15 +44,21 @@ namespace ICSharpCode.Decompiler.IL { if (MatchLdcI8(out val)) return true; - if (MatchLdcI4(out int intVal)) { + if (MatchLdcI4(out int intVal)) + { val = intVal; return true; } - if (this is Conv conv) { - if (conv.Kind == ConversionKind.SignExtend) { + if (this is Conv conv) + { + if (conv.Kind == ConversionKind.SignExtend) + { return conv.Argument.MatchLdcI(out val); - } else if (conv.Kind == ConversionKind.ZeroExtend && conv.InputType == StackType.I4) { - if (conv.Argument.MatchLdcI(out val)) { + } + else if (conv.Kind == ConversionKind.ZeroExtend && conv.InputType == StackType.I4) + { + if (conv.Argument.MatchLdcI(out val)) + { // clear top 32 bits val &= uint.MaxValue; return true; @@ -92,7 +98,8 @@ namespace ICSharpCode.Decompiler.IL /// public bool MatchLdLocRef(out ILVariable variable) { - switch (this) { + switch (this) + { case LdLoc ldloc: variable = ldloc.Variable; return variable.Type.IsReferenceType == true; @@ -114,7 +121,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchStLoc(out ILVariable variable) { var inst = this as StLoc; - if (inst != null) { + if (inst != null) + { variable = inst.Variable; return true; } @@ -125,7 +133,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchStLoc(ILVariable variable, out ILInstruction value) { var inst = this as StLoc; - if (inst != null && inst.Variable == variable) { + if (inst != null && inst.Variable == variable) + { value = inst.Value; return true; } @@ -136,7 +145,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdLen(StackType type, out ILInstruction array) { var inst = this as LdLen; - if (inst != null && inst.ResultType == type) { + if (inst != null && inst.ResultType == type) + { array = inst.Array; return true; } @@ -147,7 +157,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchReturn(out ILInstruction value) { var inst = this as Leave; - if (inst != null && inst.IsLeavingFunction) { + if (inst != null && inst.IsLeavingFunction) + { value = inst.Value; return true; } @@ -158,7 +169,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchBranch(out Block targetBlock) { var inst = this as Branch; - if (inst != null) { + if (inst != null) + { targetBlock = inst.TargetBlock; return true; } @@ -175,7 +187,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLeave(out BlockContainer targetContainer, out ILInstruction value) { var inst = this as Leave; - if (inst != null) { + if (inst != null) + { targetContainer = inst.TargetContainer; value = inst.Value; return true; @@ -188,7 +201,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLeave(BlockContainer targetContainer, out ILInstruction value) { var inst = this as Leave; - if (inst != null && targetContainer == inst.TargetContainer) { + if (inst != null && targetContainer == inst.TargetContainer) + { value = inst.Value; return true; } @@ -199,7 +213,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLeave(out BlockContainer targetContainer) { var inst = this as Leave; - if (inst != null && inst.Value.MatchNop()) { + if (inst != null && inst.Value.MatchNop()) + { targetContainer = inst.TargetContainer; return true; } @@ -216,7 +231,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchIfInstruction(out ILInstruction condition, out ILInstruction trueInst, out ILInstruction falseInst) { var inst = this as IfInstruction; - if (inst != null) { + if (inst != null) + { condition = inst.Condition; trueInst = inst.TrueInst; falseInst = inst.FalseInst; @@ -230,9 +246,11 @@ namespace ICSharpCode.Decompiler.IL public bool MatchIfInstructionPositiveCondition(out ILInstruction condition, out ILInstruction trueInst, out ILInstruction falseInst) { - if (MatchIfInstruction(out condition, out trueInst, out falseInst)) { + if (MatchIfInstruction(out condition, out trueInst, out falseInst)) + { // Swap trueInst<>falseInst for every logic.not in the condition. - while (condition.MatchLogicNot(out var arg)) { + while (condition.MatchLogicNot(out var arg)) + { condition = arg; ILInstruction tmp = trueInst; trueInst = falseInst; @@ -249,7 +267,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchIfInstruction(out ILInstruction condition, out ILInstruction trueInst) { var inst = this as IfInstruction; - if (inst != null && inst.FalseInst.MatchNop()) { + if (inst != null && inst.FalseInst.MatchNop()) + { condition = inst.Condition; trueInst = inst.TrueInst; return true; @@ -267,7 +286,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLogicAnd(out ILInstruction lhs, out ILInstruction rhs) { var inst = this as IfInstruction; - if (inst != null && inst.FalseInst.MatchLdcI4(0)) { + if (inst != null && inst.FalseInst.MatchLdcI4(0)) + { lhs = inst.Condition; rhs = inst.TrueInst; return true; @@ -285,7 +305,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLogicOr(out ILInstruction lhs, out ILInstruction rhs) { var inst = this as IfInstruction; - if (inst != null && inst.TrueInst.MatchLdcI4(1)) { + if (inst != null && inst.TrueInst.MatchLdcI4(1)) + { lhs = inst.Condition; rhs = inst.FalseInst; return true; @@ -302,7 +323,8 @@ namespace ICSharpCode.Decompiler.IL { if (this is Comp comp && comp.Kind == ComparisonKind.Equality && comp.LiftingKind == ComparisonLiftingKind.None - && comp.Right.MatchLdcI4(0)) { + && comp.Right.MatchLdcI4(0)) + { arg = comp.Left; return true; } @@ -313,7 +335,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchTryCatchHandler(out ILVariable variable) { var inst = this as TryCatchHandler; - if (inst != null) { + if (inst != null) + { variable = inst.Variable; return true; } @@ -328,18 +351,22 @@ namespace ICSharpCode.Decompiler.IL { ILInstruction thisInst = this; var compKind = ComparisonKind.Equality; - while (thisInst.MatchLogicNot(out var arg) && arg is Comp) { + while (thisInst.MatchLogicNot(out var arg) && arg is Comp) + { thisInst = arg; if (compKind == ComparisonKind.Equality) compKind = ComparisonKind.Inequality; else compKind = ComparisonKind.Equality; } - if (thisInst is Comp comp && comp.Kind == compKind && !comp.IsLifted) { + if (thisInst is Comp comp && comp.Kind == compKind && !comp.IsLifted) + { left = comp.Left; right = comp.Right; return true; - } else { + } + else + { left = null; right = null; return false; @@ -351,17 +378,23 @@ namespace ICSharpCode.Decompiler.IL /// public bool MatchCompEqualsNull(out ILInstruction arg) { - if (!MatchCompEquals(out var left, out var right)) { + if (!MatchCompEquals(out var left, out var right)) + { arg = null; return false; } - if (right.MatchLdNull()) { + if (right.MatchLdNull()) + { arg = left; return true; - } else if (left.MatchLdNull()) { + } + else if (left.MatchLdNull()) + { arg = right; return true; - } else { + } + else + { arg = null; return false; } @@ -372,17 +405,23 @@ namespace ICSharpCode.Decompiler.IL /// public bool MatchCompNotEqualsNull(out ILInstruction arg) { - if (!MatchCompNotEquals(out var left, out var right)) { + if (!MatchCompNotEquals(out var left, out var right)) + { arg = null; return false; } - if (right.MatchLdNull()) { + if (right.MatchLdNull()) + { arg = left; return true; - } else if (left.MatchLdNull()) { + } + else if (left.MatchLdNull()) + { arg = right; return true; - } else { + } + else + { arg = null; return false; } @@ -395,18 +434,22 @@ namespace ICSharpCode.Decompiler.IL { ILInstruction thisInst = this; var compKind = ComparisonKind.Inequality; - while (thisInst.MatchLogicNot(out var arg) && arg is Comp) { + while (thisInst.MatchLogicNot(out var arg) && arg is Comp) + { thisInst = arg; if (compKind == ComparisonKind.Equality) compKind = ComparisonKind.Inequality; else compKind = ComparisonKind.Equality; } - if (thisInst is Comp comp && comp.Kind == compKind && !comp.IsLifted) { + if (thisInst is Comp comp && comp.Kind == compKind && !comp.IsLifted) + { left = comp.Left; right = comp.Right; return true; - } else { + } + else + { left = null; right = null; return false; @@ -415,9 +458,11 @@ namespace ICSharpCode.Decompiler.IL public bool MatchLdFld(out ILInstruction target, out IField field) { - if (this is LdObj ldobj && ldobj.Target is LdFlda ldflda && ldobj.UnalignedPrefix == 0 && !ldobj.IsVolatile) { + if (this is LdObj ldobj && ldobj.Target is LdFlda ldflda && ldobj.UnalignedPrefix == 0 && !ldobj.IsVolatile) + { field = ldflda.Field; - if (field.DeclaringType.IsReferenceType == true || !ldflda.Target.MatchAddressOf(out target, out _)) { + if (field.DeclaringType.IsReferenceType == true || !ldflda.Target.MatchAddressOf(out target, out _)) + { target = ldflda.Target; } return true; @@ -426,10 +471,11 @@ namespace ICSharpCode.Decompiler.IL field = null; return false; } - + public bool MatchLdsFld(out IField field) { - if (this is LdObj ldobj && ldobj.Target is LdsFlda ldsflda && ldobj.UnalignedPrefix == 0 && !ldobj.IsVolatile) { + if (this is LdObj ldobj && ldobj.Target is LdsFlda ldsflda && ldobj.UnalignedPrefix == 0 && !ldobj.IsVolatile) + { field = ldsflda.Field; return true; } @@ -444,7 +490,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchStsFld(out IField field, out ILInstruction value) { - if (this is StObj stobj && stobj.Target is LdsFlda ldsflda && stobj.UnalignedPrefix == 0 && !stobj.IsVolatile) { + if (this is StObj stobj && stobj.Target is LdsFlda ldsflda && stobj.UnalignedPrefix == 0 && !stobj.IsVolatile) + { field = ldsflda.Field; value = stobj.Value; return true; @@ -456,7 +503,8 @@ namespace ICSharpCode.Decompiler.IL public bool MatchStFld(out ILInstruction target, out IField field, out ILInstruction value) { - if (this is StObj stobj && stobj.Target is LdFlda ldflda && stobj.UnalignedPrefix == 0 && !stobj.IsVolatile) { + if (this is StObj stobj && stobj.Target is LdFlda ldflda && stobj.UnalignedPrefix == 0 && !stobj.IsVolatile) + { target = ldflda.Target; field = ldflda.Field; value = stobj.Value; @@ -467,17 +515,18 @@ namespace ICSharpCode.Decompiler.IL value = null; return false; } - + public bool MatchBinaryNumericInstruction(BinaryNumericOperator @operator) { var op = this as BinaryNumericInstruction; return op != null && op.Operator == @operator; } - + public bool MatchBinaryNumericInstruction(BinaryNumericOperator @operator, out ILInstruction left, out ILInstruction right) { var op = this as BinaryNumericInstruction; - if (op != null && op.Operator == @operator) { + if (op != null && op.Operator == @operator) + { left = op.Left; right = op.Right; return true; @@ -486,11 +535,12 @@ namespace ICSharpCode.Decompiler.IL right = null; return false; } - + public bool MatchBinaryNumericInstruction(out BinaryNumericOperator @operator, out ILInstruction left, out ILInstruction right) { var op = this as BinaryNumericInstruction; - if (op != null) { + if (op != null) + { @operator = op.Operator; left = op.Left; right = op.Right; @@ -501,7 +551,7 @@ namespace ICSharpCode.Decompiler.IL right = null; return false; } - + /// /// If this instruction is a conversion of the specified kind, return its argument. /// Otherwise, return the instruction itself. diff --git a/ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs index 0882e9149..bcd30b628 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs @@ -37,7 +37,7 @@ namespace ICSharpCode.Decompiler.IL Normal, Pop } - + partial class Nop { public string Comment; @@ -48,10 +48,12 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (Kind != NopKind.Normal) { + if (Kind != NopKind.Normal) + { output.Write("." + Kind.ToString().ToLowerInvariant()); } - if (!string.IsNullOrEmpty(Comment)) { + if (!string.IsNullOrEmpty(Comment)) + { output.Write(" // " + Comment); } } @@ -61,21 +63,22 @@ namespace ICSharpCode.Decompiler.IL { public string Message; public StackType ExpectedResultType = StackType.Void; - + public InvalidBranch(string message) : this() { this.Message = message; } - + public override StackType ResultType { get { return ExpectedResultType; } } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); output.Write(OpCode); - if (!string.IsNullOrEmpty(Message)) { + if (!string.IsNullOrEmpty(Message)) + { output.Write("(\""); output.Write(Message); output.Write("\")"); @@ -93,8 +96,7 @@ namespace ICSharpCode.Decompiler.IL this.Message = message; } - public override StackType ResultType - { + public override StackType ResultType { get { return ExpectedResultType; } } @@ -102,7 +104,8 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (!string.IsNullOrEmpty(Message)) { + if (!string.IsNullOrEmpty(Message)) + { output.Write("(\""); output.Write(Message); output.Write("\")"); diff --git a/ICSharpCode.Decompiler/IL/Instructions/StLoc.cs b/ICSharpCode.Decompiler/IL/Instructions/StLoc.cs index 9a5f26c4d..f8a0c8914 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/StLoc.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/StLoc.cs @@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.IL /// This field is only used in ILReader and BlockBuilder, and should be ignored by ILAst transforms. /// internal bool IsStackAdjustment; - + /// /// Gets whether the IL stack was empty after this store. /// Only set for store instructions from the IL; not for stores to the stack diff --git a/ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs b/ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs index 881ca2c03..9b3044eae 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs @@ -40,7 +40,8 @@ namespace ICSharpCode.Decompiler.IL static List<(string Key, int Value)> ArrayToDictionary(string[] map) { var dict = new List<(string Key, int Value)>(); - for (int i = 0; i < map.Length; i++) { + for (int i = 0; i < map.Length; i++) + { dict.Add((map[i], i)); } return dict; @@ -53,8 +54,10 @@ namespace ICSharpCode.Decompiler.IL Argument.WriteTo(output, options); output.Write(", { "); int i = 0; - foreach (var entry in Map) { - if (i > 0) output.Write(", "); + foreach (var entry in Map) + { + if (i > 0) + output.Write(", "); if (entry.Key is null) output.Write($"[null] = {entry.Value}"); else diff --git a/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs index 63924b18e..816de88e8 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL @@ -47,7 +48,7 @@ namespace ICSharpCode.Decompiler.IL this.Value = value; this.Sections = new InstructionCollection(this, 1); } - + ILInstruction value; public ILInstruction Value { get { return this.value; } @@ -56,24 +57,25 @@ namespace ICSharpCode.Decompiler.IL SetChildInstruction(ref this.value, value, 0); } } - + public readonly InstructionCollection Sections; protected override InstructionFlags ComputeFlags() { var sectionFlags = InstructionFlags.EndPointUnreachable; // neutral element for CombineBranches() - foreach (var section in Sections) { + foreach (var section in Sections) + { sectionFlags = SemanticHelper.CombineBranches(sectionFlags, section.Flags); } return value.Flags | InstructionFlags.ControlFlow | sectionFlags; } - + public override InstructionFlags DirectFlags { get { return InstructionFlags.ControlFlow; } } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); @@ -86,7 +88,8 @@ namespace ICSharpCode.Decompiler.IL output.MarkFoldStart("{...}"); output.WriteLine("{"); output.Indent(); - foreach (var section in this.Sections) { + foreach (var section in this.Sections) + { section.WriteTo(output, options); output.WriteLine(); } @@ -94,19 +97,19 @@ namespace ICSharpCode.Decompiler.IL output.Write('}'); output.MarkFoldEnd(); } - + protected override int GetChildCount() { return 1 + Sections.Count; } - + protected override ILInstruction GetChild(int index) { if (index == 0) return value; return Sections[index - 1]; } - + protected override void SetChild(int index, ILInstruction value) { if (index == 0) @@ -114,14 +117,14 @@ namespace ICSharpCode.Decompiler.IL else Sections[index - 1] = (SwitchSection)value; } - + protected override SlotInfo GetChildSlot(int index) { if (index == 0) return ValueSlot; return SectionSlot; } - + public override ILInstruction Clone() { var clone = new SwitchInstruction(value.Clone()); @@ -145,8 +148,10 @@ namespace ICSharpCode.Decompiler.IL base.CheckInvariant(phase); bool expectNullSection = this.IsLifted; LongSet sets = LongSet.Empty; - foreach (var section in Sections) { - if (section.HasNullLabel) { + foreach (var section in Sections) + { + if (section.HasNullLabel) + { Debug.Assert(expectNullSection, "Duplicate 'case null' or 'case null' in non-lifted switch."); expectNullSection = false; } @@ -164,15 +169,17 @@ namespace ICSharpCode.Decompiler.IL { // Pick the section with the most labels as default section. IL.SwitchSection defaultSection = Sections.First(); - foreach (var section in Sections) { - if (section.Labels.Count() > defaultSection.Labels.Count()) { + foreach (var section in Sections) + { + if (section.Labels.Count() > defaultSection.Labels.Count()) + { defaultSection = section; } } return defaultSection; } } - + partial class SwitchSection { public SwitchSection() @@ -190,34 +197,38 @@ namespace ICSharpCode.Decompiler.IL /// The set of labels that cause execution to jump to this switch section. /// public LongSet Labels { get; set; } - + protected override InstructionFlags ComputeFlags() { return body.Flags; } - + public override InstructionFlags DirectFlags { get { return InstructionFlags.None; } } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); output.WriteLocalReference("case", this, isDefinition: true); output.Write(' '); - if (HasNullLabel) { + if (HasNullLabel) + { output.Write("null"); - if (!Labels.IsEmpty) { + if (!Labels.IsEmpty) + { output.Write(", "); output.Write(Labels.ToString()); } - } else { + } + else + { output.Write(Labels.ToString()); } output.Write(": "); - + body.WriteTo(output, options); } } diff --git a/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs index 4e87bacc9..228695ff1 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL @@ -26,12 +27,12 @@ namespace ICSharpCode.Decompiler.IL public abstract class TryInstruction : ILInstruction { public static readonly SlotInfo TryBlockSlot = new SlotInfo("TryBlock"); - + protected TryInstruction(OpCode opCode, ILInstruction tryBlock) : base(opCode) { this.TryBlock = tryBlock; } - + ILInstruction tryBlock; public ILInstruction TryBlock { get { return this.tryBlock; } @@ -41,7 +42,7 @@ namespace ICSharpCode.Decompiler.IL } } } - + /// /// Try-catch statement. /// @@ -52,12 +53,12 @@ namespace ICSharpCode.Decompiler.IL { public static readonly SlotInfo HandlerSlot = new SlotInfo("Handler", isCollection: true); public readonly InstructionCollection Handlers; - + public TryCatch(ILInstruction tryBlock) : base(OpCode.TryCatch, tryBlock) { this.Handlers = new InstructionCollection(this, 1); } - + public override ILInstruction Clone() { var clone = new TryCatch(TryBlock.Clone()); @@ -65,22 +66,23 @@ namespace ICSharpCode.Decompiler.IL clone.Handlers.AddRange(this.Handlers.Select(h => (TryCatchHandler)h.Clone())); return clone; } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); output.Write(".try "); TryBlock.WriteTo(output, options); - foreach (var handler in Handlers) { + foreach (var handler in Handlers) + { output.Write(' '); handler.WriteTo(output, options); } } - + public override StackType ResultType { get { return StackType.Void; } } - + protected override InstructionFlags ComputeFlags() { var flags = TryBlock.Flags; @@ -88,18 +90,18 @@ namespace ICSharpCode.Decompiler.IL flags = SemanticHelper.CombineBranches(flags, handler.Flags); return flags | InstructionFlags.ControlFlow; } - + public override InstructionFlags DirectFlags { get { return InstructionFlags.ControlFlow; } } - + protected override int GetChildCount() { return 1 + Handlers.Count; } - + protected override ILInstruction GetChild(int index) { if (index == 0) @@ -107,7 +109,7 @@ namespace ICSharpCode.Decompiler.IL else return Handlers[index - 1]; } - + protected override void SetChild(int index, ILInstruction value) { if (index == 0) @@ -115,7 +117,7 @@ namespace ICSharpCode.Decompiler.IL else Handlers[index - 1] = (TryCatchHandler)value; } - + protected override SlotInfo GetChildSlot(int index) { if (index == 0) @@ -124,7 +126,7 @@ namespace ICSharpCode.Decompiler.IL return HandlerSlot; } } - + /// /// Catch handler within a try-catch statement. /// @@ -144,16 +146,16 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(filter.ResultType == StackType.I4); Debug.Assert(this.IsDescendantOf(variable.Function)); } - + public override StackType ResultType { get { return StackType.Void; } } - + protected override InstructionFlags ComputeFlags() { return filter.Flags | body.Flags | InstructionFlags.ControlFlow | InstructionFlags.MayWriteLocals; } - + public override InstructionFlags DirectFlags { get { // the body is not evaluated if the filter returns 0 @@ -165,7 +167,8 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write("catch "); - if (variable != null) { + if (variable != null) + { output.WriteLocalReference(variable.Name, variable, isDefinition: true); output.Write(" : "); Disassembler.DisassemblerHelpers.WriteOperand(output, variable.Type); @@ -189,16 +192,16 @@ namespace ICSharpCode.Decompiler.IL ExceptionSpecifierILRange = CombineILRange(ExceptionSpecifierILRange, newRange); } } - + partial class TryFinally { public static readonly SlotInfo FinallyBlockSlot = new SlotInfo("FinallyBlock"); - + public TryFinally(ILInstruction tryBlock, ILInstruction finallyBlock) : base(OpCode.TryFinally, tryBlock) { this.FinallyBlock = finallyBlock; } - + ILInstruction finallyBlock; public ILInstruction FinallyBlock { get { return this.finallyBlock; } @@ -207,7 +210,7 @@ namespace ICSharpCode.Decompiler.IL SetChildInstruction(ref this.finallyBlock, value, 1); } } - + public override ILInstruction Clone() { return new TryFinally(TryBlock.Clone(), finallyBlock.Clone()).WithILRange(this); @@ -233,21 +236,22 @@ namespace ICSharpCode.Decompiler.IL // if the endpoint of either the try or the finally is unreachable, the endpoint of the try-finally will be unreachable return TryBlock.Flags | finallyBlock.Flags | InstructionFlags.ControlFlow; } - + public override InstructionFlags DirectFlags { get { return InstructionFlags.ControlFlow; } } - + protected override int GetChildCount() { return 2; } - + protected override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return TryBlock; case 1: @@ -256,10 +260,11 @@ namespace ICSharpCode.Decompiler.IL throw new IndexOutOfRangeException(); } } - + protected override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: TryBlock = value; break; @@ -270,10 +275,11 @@ namespace ICSharpCode.Decompiler.IL throw new IndexOutOfRangeException(); } } - + protected override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return TryBlockSlot; case 1: @@ -283,16 +289,16 @@ namespace ICSharpCode.Decompiler.IL } } } - + partial class TryFault { public static readonly SlotInfo FaultBlockSlot = new SlotInfo("FaultBlock"); - + public TryFault(ILInstruction tryBlock, ILInstruction faultBlock) : base(OpCode.TryFinally, tryBlock) { this.FaultBlock = faultBlock; } - + ILInstruction faultBlock; public ILInstruction FaultBlock { get { return this.faultBlock; } @@ -301,12 +307,12 @@ namespace ICSharpCode.Decompiler.IL SetChildInstruction(ref this.faultBlock, value, 1); } } - + public override ILInstruction Clone() { return new TryFault(TryBlock.Clone(), faultBlock.Clone()).WithILRange(this); } - + public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { WriteILRange(output, options); @@ -315,31 +321,32 @@ namespace ICSharpCode.Decompiler.IL output.Write(" fault "); faultBlock.WriteTo(output, options); } - + public override StackType ResultType { get { return TryBlock.ResultType; } } - + protected override InstructionFlags ComputeFlags() { // The endpoint of the try-fault is unreachable iff the try endpoint is unreachable return TryBlock.Flags | (faultBlock.Flags & ~InstructionFlags.EndPointUnreachable) | InstructionFlags.ControlFlow; } - + public override InstructionFlags DirectFlags { get { return InstructionFlags.ControlFlow; } } - + protected override int GetChildCount() { return 2; } - + protected override ILInstruction GetChild(int index) { - switch (index) { + switch (index) + { case 0: return TryBlock; case 1: @@ -348,10 +355,11 @@ namespace ICSharpCode.Decompiler.IL throw new IndexOutOfRangeException(); } } - + protected override void SetChild(int index, ILInstruction value) { - switch (index) { + switch (index) + { case 0: TryBlock = value; break; @@ -362,10 +370,11 @@ namespace ICSharpCode.Decompiler.IL throw new IndexOutOfRangeException(); } } - + protected override SlotInfo GetChildSlot(int index) { - switch (index) { + switch (index) + { case 0: return TryBlockSlot; case 1: diff --git a/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs index ed4230f22..de0a7e02b 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs @@ -53,7 +53,8 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write(OpCode); - if (IsLifted) { + if (IsLifted) + { output.Write(".lifted"); } output.Write('('); diff --git a/ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs index 5b7550927..b7a678ad4 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs @@ -44,10 +44,12 @@ namespace ICSharpCode.Decompiler.IL { WriteILRange(output, options); output.Write("using"); - if (IsAsync) { + if (IsAsync) + { output.Write(".async"); } - if (IsRefStruct) { + if (IsRefStruct) + { output.Write(".ref"); } output.Write(" ("); diff --git a/ICSharpCode.Decompiler/IL/Patterns/AnyNode.cs b/ICSharpCode.Decompiler/IL/Patterns/AnyNode.cs index 0f54a7979..9f4f507ba 100644 --- a/ICSharpCode.Decompiler/IL/Patterns/AnyNode.cs +++ b/ICSharpCode.Decompiler/IL/Patterns/AnyNode.cs @@ -12,12 +12,12 @@ namespace ICSharpCode.Decompiler.IL.Patterns { throw new NotSupportedException(); } - + public override T AcceptVisitor(ILVisitor visitor, C context) { throw new NotSupportedException(); } - + public override T AcceptVisitor(ILVisitor visitor) { throw new NotSupportedException(); @@ -28,8 +28,7 @@ namespace ICSharpCode.Decompiler.IL.Patterns throw new NotSupportedException(); } - public override InstructionFlags DirectFlags - { + public override InstructionFlags DirectFlags { get { throw new NotSupportedException(); } diff --git a/ICSharpCode.Decompiler/IL/Patterns/ListMatch.cs b/ICSharpCode.Decompiler/IL/Patterns/ListMatch.cs index a22999434..426e2a8d9 100644 --- a/ICSharpCode.Decompiler/IL/Patterns/ListMatch.cs +++ b/ICSharpCode.Decompiler/IL/Patterns/ListMatch.cs @@ -47,8 +47,10 @@ namespace ICSharpCode.Decompiler.IL.Patterns internal static bool DoMatch(IReadOnlyList patterns, IReadOnlyList syntaxList, ref Match match) { ListMatch listMatch = new ListMatch(syntaxList); - do { - if (PerformMatchSequence(patterns, ref listMatch, ref match)) { + do + { + if (PerformMatchSequence(patterns, ref listMatch, ref match)) + { // If we have a successful match and it matches the whole list, // we are done. if (listMatch.SyntaxIndex == syntaxList.Count) @@ -58,7 +60,7 @@ namespace ICSharpCode.Decompiler.IL.Patterns } while (listMatch.RestoreSavePoint(ref match)); return false; } - + /// /// PerformMatch() for a sequence of patterns. /// @@ -74,7 +76,8 @@ namespace ICSharpCode.Decompiler.IL.Patterns { // The patterns may create savepoints, so we need to save the 'i' variable // as part of those checkpoints. - for (int i = listMatch.PopFromSavePoint() ?? 0; i < patterns.Count; i++) { + for (int i = listMatch.PopFromSavePoint() ?? 0; i < patterns.Count; i++) + { int startMarker = listMatch.GetSavePointStartMarker(); bool success = patterns[i].PerformMatch(ref listMatch, ref match); listMatch.PushToSavePoints(startMarker, i); @@ -83,7 +86,7 @@ namespace ICSharpCode.Decompiler.IL.Patterns } return true; } - + /// /// A savepoint that the list matching operation can be restored from. /// @@ -92,7 +95,7 @@ namespace ICSharpCode.Decompiler.IL.Patterns internal readonly int CheckPoint; internal readonly int SyntaxIndex; internal readonly Stack stack; - + public SavePoint(int checkpoint, int syntaxIndex) { this.CheckPoint = checkpoint; @@ -100,17 +103,17 @@ namespace ICSharpCode.Decompiler.IL.Patterns this.stack = new Stack(); } } - + /// /// The syntax list we are matching against. /// internal readonly IReadOnlyList SyntaxList; - + /// /// The current index in the syntax list. /// internal int SyntaxIndex; - + ListMatch(IReadOnlyList syntaxList) { this.SyntaxList = syntaxList; @@ -118,45 +121,46 @@ namespace ICSharpCode.Decompiler.IL.Patterns this.backtrackingStack = null; this.restoreStack = null; } - + List backtrackingStack; Stack restoreStack; - + void AddSavePoint(SavePoint savepoint) { if (backtrackingStack == null) backtrackingStack = new List(); backtrackingStack.Add(savepoint); } - + internal void AddSavePoint(ref Match match, int data) { var savepoint = new SavePoint(match.CheckPoint(), this.SyntaxIndex); savepoint.stack.Push(data); AddSavePoint(savepoint); } - + internal int GetSavePointStartMarker() { return backtrackingStack != null ? backtrackingStack.Count : 0; } - + internal void PushToSavePoints(int startMarker, int data) { if (backtrackingStack == null) return; - for (int i = startMarker; i < backtrackingStack.Count; i++) { + for (int i = startMarker; i < backtrackingStack.Count; i++) + { backtrackingStack[i].stack.Push(data); } } - + internal int? PopFromSavePoint() { if (restoreStack == null || restoreStack.Count == 0) return null; return restoreStack.Pop(); } - + /// /// Restores the listmatch state from a savepoint. /// diff --git a/ICSharpCode.Decompiler/IL/Patterns/Match.cs b/ICSharpCode.Decompiler/IL/Patterns/Match.cs index 1c6a55ce4..0cad96243 100644 --- a/ICSharpCode.Decompiler/IL/Patterns/Match.cs +++ b/ICSharpCode.Decompiler/IL/Patterns/Match.cs @@ -20,8 +20,8 @@ using System.Collections.Generic; namespace ICSharpCode.Decompiler.IL.Patterns { - public class CaptureGroup {} - + public class CaptureGroup { } + /// /// Data holder for the overall pattern matching operation. /// @@ -32,9 +32,9 @@ namespace ICSharpCode.Decompiler.IL.Patterns public struct Match { static readonly List> emptyResults = new List>(); - + List> results; - + /// /// Gets whether the match was successful. /// @@ -43,15 +43,18 @@ namespace ICSharpCode.Decompiler.IL.Patterns return results != null; } internal set { - if (value) { + if (value) + { if (results == null) results = emptyResults; - } else { + } + else + { results = null; } } } - + /// /// Gets whether the match was successful. /// @@ -59,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL.Patterns { return m.Success; } - + /// /// Gets whether the match failed. /// @@ -67,29 +70,31 @@ namespace ICSharpCode.Decompiler.IL.Patterns { return !m.Success; } - + internal void Add(CaptureGroup g, ILInstruction n) { if (results == null) results = new List>(); results.Add(new KeyValuePair(g, n)); } - + internal int CheckPoint() { return results != null ? results.Count : 0; } - + internal void RestoreCheckPoint(int checkPoint) { if (results != null) results.RemoveRange(checkPoint, results.Count - checkPoint); } - + public IEnumerable Get(CaptureGroup captureGroup) { - if (results != null) { - foreach (var pair in results) { + if (results != null) + { + foreach (var pair in results) + { if (pair.Key == captureGroup) yield return pair.Value; } diff --git a/ICSharpCode.Decompiler/IL/PointerArithmeticOffset.cs b/ICSharpCode.Decompiler/IL/PointerArithmeticOffset.cs index 3064a4520..169f7969b 100644 --- a/ICSharpCode.Decompiler/IL/PointerArithmeticOffset.cs +++ b/ICSharpCode.Decompiler/IL/PointerArithmeticOffset.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL @@ -24,33 +25,45 @@ namespace ICSharpCode.Decompiler.IL bool checkForOverflow, bool unwrapZeroExtension = false) { - if (byteOffsetInst is Conv conv && conv.InputType == StackType.I8 && conv.ResultType == StackType.I) { + if (byteOffsetInst is Conv conv && conv.InputType == StackType.I8 && conv.ResultType == StackType.I) + { byteOffsetInst = conv.Argument; } int? elementSize = ComputeSizeOf(pointerElementType); - if (elementSize == 1) { + if (elementSize == 1) + { return byteOffsetInst; - } else if (byteOffsetInst is BinaryNumericInstruction mul && mul.Operator == BinaryNumericOperator.Mul) { + } + else if (byteOffsetInst is BinaryNumericInstruction mul && mul.Operator == BinaryNumericOperator.Mul) + { if (mul.IsLifted) return null; if (mul.CheckForOverflow != checkForOverflow) return null; if (elementSize > 0 && mul.Right.MatchLdcI(elementSize.Value) - || mul.Right.UnwrapConv(ConversionKind.SignExtend) is SizeOf sizeOf && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(sizeOf.Type, pointerElementType)) { + || mul.Right.UnwrapConv(ConversionKind.SignExtend) is SizeOf sizeOf && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(sizeOf.Type, pointerElementType)) + { var countOffsetInst = mul.Left; - if (unwrapZeroExtension) { + if (unwrapZeroExtension) + { countOffsetInst = countOffsetInst.UnwrapConv(ConversionKind.ZeroExtend); } return countOffsetInst; } - } else if (byteOffsetInst.UnwrapConv(ConversionKind.SignExtend) is SizeOf sizeOf && sizeOf.Type.Equals(pointerElementType)) { + } + else if (byteOffsetInst.UnwrapConv(ConversionKind.SignExtend) is SizeOf sizeOf && sizeOf.Type.Equals(pointerElementType)) + { return new LdcI4(1).WithILRange(byteOffsetInst); - } else if (byteOffsetInst.MatchLdcI(out long val)) { + } + else if (byteOffsetInst.MatchLdcI(out long val)) + { // If the offset is a constant, it's possible that the compiler // constant-folded the multiplication. - if (elementSize > 0 && (val % elementSize == 0) && val > 0) { + if (elementSize > 0 && (val % elementSize == 0) && val > 0) + { val /= elementSize.Value; - if (val <= int.MaxValue) { + if (val <= int.MaxValue) + { return new LdcI4((int)val).WithILRange(byteOffsetInst); } } @@ -60,7 +73,8 @@ namespace ICSharpCode.Decompiler.IL public static int? ComputeSizeOf(IType type) { - switch (type.GetEnumUnderlyingType().GetDefinition()?.KnownTypeCode) { + switch (type.GetEnumUnderlyingType().GetDefinition()?.KnownTypeCode) + { case KnownTypeCode.Boolean: case KnownTypeCode.SByte: case KnownTypeCode.Byte: @@ -90,7 +104,8 @@ namespace ICSharpCode.Decompiler.IL /// internal static bool IsFixedVariable(ILInstruction inst) { - switch (inst) { + switch (inst) + { case LdLoca ldloca: return ldloca.Variable.CaptureScope == null; // locals are fixed if uncaptured case LdFlda ldflda: diff --git a/ICSharpCode.Decompiler/IL/SemanticHelper.cs b/ICSharpCode.Decompiler/IL/SemanticHelper.cs index 7102628b9..8a071b80f 100644 --- a/ICSharpCode.Decompiler/IL/SemanticHelper.cs +++ b/ICSharpCode.Decompiler/IL/SemanticHelper.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Linq; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL @@ -29,7 +30,7 @@ namespace ICSharpCode.Decompiler.IL const InstructionFlags combineWithAnd = InstructionFlags.EndPointUnreachable; return (trueFlags & falseFlags) | ((trueFlags | falseFlags) & ~combineWithAnd); } - + /// /// Gets whether instruction is pure: /// * must not have side effects @@ -43,7 +44,7 @@ namespace ICSharpCode.Decompiler.IL const InstructionFlags pureFlags = InstructionFlags.MayReadLocals | InstructionFlags.ControlFlow; return (inst & ~pureFlags) == 0; } - + /// /// Gets whether the instruction sequence 'inst1; inst2;' may be ordered to 'inst2; inst1;' /// @@ -63,19 +64,24 @@ namespace ICSharpCode.Decompiler.IL static bool Inst2MightWriteToVariableReadByInst1(ILInstruction inst1, ILInstruction inst2) { - if (!inst1.HasFlag(InstructionFlags.MayReadLocals)) { + if (!inst1.HasFlag(InstructionFlags.MayReadLocals)) + { // quick exit if inst1 doesn't read any variables return false; } var variables = inst1.Descendants.OfType().Select(load => load.Variable).ToHashSet(); - if (inst2.HasFlag(InstructionFlags.SideEffect) && variables.Any(v => v.AddressCount > 0)) { + if (inst2.HasFlag(InstructionFlags.SideEffect) && variables.Any(v => v.AddressCount > 0)) + { // If inst2 might have indirect writes, we cannot reorder with any loads of variables that have their address taken. return true; } - foreach (var inst in inst2.Descendants) { - if (inst.HasDirectFlag(InstructionFlags.MayWriteLocals)) { + foreach (var inst in inst2.Descendants) + { + if (inst.HasDirectFlag(InstructionFlags.MayWriteLocals)) + { ILVariable v = ((IInstructionWithVariableOperand)inst).Variable; - if (variables.Contains(v)) { + if (variables.Contains(v)) + { return true; } } diff --git a/ICSharpCode.Decompiler/IL/SlotInfo.cs b/ICSharpCode.Decompiler/IL/SlotInfo.cs index e72d8e897..ec96ed0a3 100644 --- a/ICSharpCode.Decompiler/IL/SlotInfo.cs +++ b/ICSharpCode.Decompiler/IL/SlotInfo.cs @@ -25,12 +25,12 @@ namespace ICSharpCode.Decompiler.IL public class SlotInfo { public static SlotInfo None = new SlotInfo(""); - + /// /// Gets the name of the slot. /// public readonly string Name; - + /// /// Gets whether it is possible to inline into this slot. /// @@ -40,14 +40,14 @@ namespace ICSharpCode.Decompiler.IL /// Gets whether this slot belongs to a collection. /// public readonly bool IsCollection; - + public SlotInfo(string name, bool canInlineInto = false, bool isCollection = false) { this.IsCollection = isCollection; this.Name = name; this.CanInlineInto = canInlineInto; } - + public override string ToString() { return Name; diff --git a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs index 86541e59a..58dc0766a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs @@ -23,6 +23,7 @@ using System.Reflection; using System.Reflection.Metadata; using Humanizer; + using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -64,27 +65,38 @@ namespace ICSharpCode.Decompiler.IL.Transforms reservedVariableNames = new Dictionary(); localFunctionMapping = new Dictionary(); loopCounters = CollectLoopCounters(function); - foreach (var f in function.Descendants.OfType()) { - if (f.Method != null) { - if (IsSetOrEventAccessor(f.Method) && f.Method.Parameters.Count > 0) { - for (int i = 0; i < f.Method.Parameters.Count - 1; i++) { + foreach (var f in function.Descendants.OfType()) + { + if (f.Method != null) + { + if (IsSetOrEventAccessor(f.Method) && f.Method.Parameters.Count > 0) + { + for (int i = 0; i < f.Method.Parameters.Count - 1; i++) + { AddExistingName(reservedVariableNames, f.Method.Parameters[i].Name); } var lastParameter = f.Method.Parameters.Last(); - switch (f.Method.AccessorOwner) { + switch (f.Method.AccessorOwner) + { case IProperty prop: - if (f.Method.AccessorKind == MethodSemanticsAttributes.Setter) { - if (prop.Parameters.Any(p => p.Name == "value")) { + if (f.Method.AccessorKind == MethodSemanticsAttributes.Setter) + { + if (prop.Parameters.Any(p => p.Name == "value")) + { f.Warnings.Add("Parameter named \"value\" already present in property signature!"); break; } var variableForLastParameter = f.Variables.FirstOrDefault(v => v.Function == f && v.Kind == VariableKind.Parameter && v.Index == f.Method.Parameters.Count - 1); - if (variableForLastParameter == null) { + if (variableForLastParameter == null) + { AddExistingName(reservedVariableNames, lastParameter.Name); - } else { - if (variableForLastParameter.Name != "value") { + } + else + { + if (variableForLastParameter.Name != "value") + { variableForLastParameter.Name = "value"; } AddExistingName(reservedVariableNames, variableForLastParameter.Name); @@ -92,14 +104,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms } break; case IEvent ev: - if (f.Method.AccessorKind != MethodSemanticsAttributes.Raiser) { + if (f.Method.AccessorKind != MethodSemanticsAttributes.Raiser) + { var variableForLastParameter = f.Variables.FirstOrDefault(v => v.Function == f && v.Kind == VariableKind.Parameter && v.Index == f.Method.Parameters.Count - 1); - if (variableForLastParameter == null) { + if (variableForLastParameter == null) + { AddExistingName(reservedVariableNames, lastParameter.Name); - } else { - if (variableForLastParameter.Name != "value") { + } + else + { + if (variableForLastParameter.Name != "value") + { variableForLastParameter.Name = "value"; } AddExistingName(reservedVariableNames, variableForLastParameter.Name); @@ -110,23 +127,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms AddExistingName(reservedVariableNames, lastParameter.Name); break; } - } else { + } + else + { foreach (var p in f.Method.Parameters) AddExistingName(reservedVariableNames, p.Name); } - } else { + } + else + { foreach (var p in f.Variables.Where(v => v.Kind == VariableKind.Parameter)) AddExistingName(reservedVariableNames, p.Name); } } - foreach (ILFunction f in function.Descendants.OfType().Reverse()) { + foreach (ILFunction f in function.Descendants.OfType().Reverse()) + { PerformAssignment(f); } } bool IsSetOrEventAccessor(IMethod method) { - switch (method.AccessorKind) { + switch (method.AccessorKind) + { case MethodSemanticsAttributes.Setter: case MethodSemanticsAttributes.Adder: case MethodSemanticsAttributes.Remover: @@ -142,8 +165,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms function.Variables.RemoveDead(); int numDisplayClassLocals = 0; Dictionary assignedLocalSignatureIndices = new Dictionary(); - foreach (var v in function.Variables.OrderBy(v => v.Name)) { - switch (v.Kind) { + foreach (var v in function.Variables.OrderBy(v => v.Name)) + { + switch (v.Kind) + { case VariableKind.Parameter: // ignore break; case VariableKind.InitializerTarget: // keep generated names @@ -153,11 +178,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms v.Name = "CS$<>8__locals" + (numDisplayClassLocals++); break; case VariableKind.Local when v.Index != null: - if (assignedLocalSignatureIndices.TryGetValue(v.Index.Value, out string name)) { + if (assignedLocalSignatureIndices.TryGetValue(v.Index.Value, out string name)) + { // make sure all local ILVariables that refer to the same slot in the locals signature // are assigned the same name. v.Name = name; - } else { + } + else + { AssignName(); // Remember the newly assigned name: assignedLocalSignatureIndices.Add(v.Index.Value, v.Name); @@ -170,17 +198,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms void AssignName() { - if (v.HasGeneratedName || !IsValidName(v.Name) || ConflictWithLocal(v)) { + if (v.HasGeneratedName || !IsValidName(v.Name) || ConflictWithLocal(v)) + { // don't use the name from the debug symbols if it looks like a generated name v.Name = null; - } else { + } + else + { // use the name from the debug symbols // (but ensure we don't use the same name for two variables) v.Name = GetAlternativeName(v.Name); } } } - foreach (var localFunction in function.LocalFunctions) { + foreach (var localFunction in function.LocalFunctions) + { if (!LocalFunctionDecompiler.ParseLocalFunctionName(localFunction.Name, out _, out var newName) || !IsValidName(newName)) newName = null; localFunction.Name = newName; @@ -188,28 +220,36 @@ namespace ICSharpCode.Decompiler.IL.Transforms } // Now generate names: var mapping = new Dictionary(ILVariableEqualityComparer.Instance); - foreach (var inst in function.Descendants.OfType()) { + foreach (var inst in function.Descendants.OfType()) + { var v = inst.Variable; - if (!mapping.TryGetValue(v, out string name)) { + if (!mapping.TryGetValue(v, out string name)) + { if (string.IsNullOrEmpty(v.Name)) v.Name = GenerateNameForVariable(v); mapping.Add(v, v.Name); - } else { + } + else + { v.Name = name; } } - foreach (var localFunction in function.LocalFunctions) { + foreach (var localFunction in function.LocalFunctions) + { var newName = localFunction.Name; - if (newName == null) { + if (newName == null) + { newName = GetAlternativeName("f"); } localFunction.Name = newName; localFunction.ReducedMethod.Name = newName; localFunctionMapping[(MethodDefinitionHandle)localFunction.ReducedMethod.MetadataToken] = newName; } - foreach (var inst in function.Descendants) { + foreach (var inst in function.Descendants) + { LocalFunctionMethod localFunction; - switch (inst) { + switch (inst) + { case Call call: localFunction = call.Method as LocalFunctionMethod; break; @@ -231,7 +271,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// internal static bool IsSupportedInstruction(object arg) { - switch (arg) { + switch (arg) + { case LdObj ldobj: case LdFlda ldflda: case LdsFlda ldsflda: @@ -244,7 +285,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool ConflictWithLocal(ILVariable v) { - if (v.Kind == VariableKind.UsingLocal || v.Kind == VariableKind.ForeachLocal) { + if (v.Kind == VariableKind.UsingLocal || v.Kind == VariableKind.ForeachLocal) + { if (reservedVariableNames.ContainsKey(v.Name)) return true; } @@ -257,7 +299,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!(char.IsLetter(varName[0]) || varName[0] == '_')) return false; - for (int i = 1; i < varName.Length; i++) { + for (int i = 1; i < varName.Length; i++) + { if (!(char.IsLetterOrDigit(varName[i]) || varName[i] == '_')) return false; } @@ -266,9 +309,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms public string GetAlternativeName(string oldVariableName) { - if (oldVariableName.Length == 1 && oldVariableName[0] >= 'i' && oldVariableName[0] <= maxLoopVariableName) { - for (char c = 'i'; c <= maxLoopVariableName; c++) { - if (!reservedVariableNames.ContainsKey(c.ToString())) { + if (oldVariableName.Length == 1 && oldVariableName[0] >= 'i' && oldVariableName[0] <= maxLoopVariableName) + { + for (char c = 'i'; c <= maxLoopVariableName; c++) + { + if (!reservedVariableNames.ContainsKey(c.ToString())) + { reservedVariableNames.Add(c.ToString(), 1); return c.ToString(); } @@ -277,17 +323,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms string nameWithoutDigits = SplitName(oldVariableName, out int number); - if (!reservedVariableNames.ContainsKey(nameWithoutDigits)) { + if (!reservedVariableNames.ContainsKey(nameWithoutDigits)) + { reservedVariableNames.Add(nameWithoutDigits, number - 1); } int count = ++reservedVariableNames[nameWithoutDigits]; string nameWithDigits = nameWithoutDigits + count.ToString(); - if (oldVariableName == nameWithDigits) { + if (oldVariableName == nameWithDigits) + { return oldVariableName; } - if (count != 1) { + if (count != 1) + { return nameWithDigits; - } else { + } + else + { return nameWithoutDigits; } } @@ -295,10 +346,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms HashSet CollectLoopCounters(ILFunction function) { var loopCounters = new HashSet(); - - foreach (BlockContainer possibleLoop in function.Descendants.OfType()) { - if (possibleLoop.Kind != ContainerKind.For) continue; - foreach (var inst in possibleLoop.Blocks.Last().Instructions) { + + foreach (BlockContainer possibleLoop in function.Descendants.OfType()) + { + if (possibleLoop.Kind != ContainerKind.For) + continue; + foreach (var inst in possibleLoop.Blocks.Last().Instructions) + { if (HighLevelLoopTransform.MatchIncrement(inst, out var variable)) loopCounters.Add(variable); } @@ -310,12 +364,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms string GenerateNameForVariable(ILVariable variable) { string proposedName = null; - if (variable.Type.IsKnownType(KnownTypeCode.Int32)) { + if (variable.Type.IsKnownType(KnownTypeCode.Int32)) + { // test whether the variable might be a loop counter - if (loopCounters.Contains(variable)) { + if (loopCounters.Contains(variable)) + { // For loop variables, use i,j,k,l,m,n - for (char c = 'i'; c <= maxLoopVariableName; c++) { - if (!reservedVariableNames.ContainsKey(c.ToString())) { + for (char c = 'i'; c <= maxLoopVariableName; c++) + { + if (!reservedVariableNames.ContainsKey(c.ToString())) + { proposedName = c.ToString(); break; } @@ -324,63 +382,78 @@ namespace ICSharpCode.Decompiler.IL.Transforms } // The ComponentResourceManager inside InitializeComponent must be named "resources", // otherwise the WinForms designer won't load the Form. - if (CSharp.CSharpDecompiler.IsWindowsFormsInitializeComponentMethod(context.Function.Method) && variable.Type.FullName == "System.ComponentModel.ComponentResourceManager") { + if (CSharp.CSharpDecompiler.IsWindowsFormsInitializeComponentMethod(context.Function.Method) && variable.Type.FullName == "System.ComponentModel.ComponentResourceManager") + { proposedName = "resources"; } - if (string.IsNullOrEmpty(proposedName)) { + if (string.IsNullOrEmpty(proposedName)) + { var proposedNameForAddress = variable.AddressInstructions.OfType() .Select(arg => arg.Parent is CallInstruction c ? c.GetParameter(arg.ChildIndex)?.Name : null) .Where(arg => !string.IsNullOrWhiteSpace(arg)) .Except(currentFieldNames).ToList(); - if (proposedNameForAddress.Count > 0) { + if (proposedNameForAddress.Count > 0) + { proposedName = proposedNameForAddress[0]; } } - if (string.IsNullOrEmpty(proposedName)) { + if (string.IsNullOrEmpty(proposedName)) + { var proposedNameForStores = variable.StoreInstructions.OfType() .Select(expr => GetNameFromInstruction(expr.Value)) .Except(currentFieldNames).ToList(); - if (proposedNameForStores.Count == 1) { + if (proposedNameForStores.Count == 1) + { proposedName = proposedNameForStores[0]; } } - if (string.IsNullOrEmpty(proposedName)) { + if (string.IsNullOrEmpty(proposedName)) + { var proposedNameForLoads = variable.LoadInstructions .Select(arg => GetNameForArgument(arg.Parent, arg.ChildIndex)) .Except(currentFieldNames).ToList(); - if (proposedNameForLoads.Count == 1) { + if (proposedNameForLoads.Count == 1) + { proposedName = proposedNameForLoads[0]; } } - if (string.IsNullOrEmpty(proposedName) && variable.Kind == VariableKind.StackSlot) { + if (string.IsNullOrEmpty(proposedName) && variable.Kind == VariableKind.StackSlot) + { var proposedNameForStoresFromNewObj = variable.StoreInstructions.OfType() .Select(expr => GetNameByType(GuessType(variable.Type, expr.Value, context))) .Except(currentFieldNames).ToList(); - if (proposedNameForStoresFromNewObj.Count == 1) { + if (proposedNameForStoresFromNewObj.Count == 1) + { proposedName = proposedNameForStoresFromNewObj[0]; } } - if (string.IsNullOrEmpty(proposedName)) { + if (string.IsNullOrEmpty(proposedName)) + { proposedName = GetNameByType(variable.Type); } // remove any numbers from the proposed name proposedName = SplitName(proposedName, out int number); - if (!reservedVariableNames.ContainsKey(proposedName)) { + if (!reservedVariableNames.ContainsKey(proposedName)) + { reservedVariableNames.Add(proposedName, 0); } int count = ++reservedVariableNames[proposedName]; - if (count > 1) { + if (count > 1) + { return proposedName + count.ToString(); - } else { + } + else + { return proposedName; } } static string GetNameFromInstruction(ILInstruction inst) { - switch (inst) { + switch (inst) + { case LdObj ldobj: return GetNameFromInstruction(ldobj.Target); case LdFlda ldflda: @@ -388,12 +461,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms case LdsFlda ldsflda: return CleanUpVariableName(ldsflda.Field.Name); case CallInstruction call: - if (call is NewObj) break; + if (call is NewObj) + break; IMethod m = call.Method; - if (m.Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase) && m.Parameters.Count == 0) { + if (m.Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase) && m.Parameters.Count == 0) + { // use name from properties, but not from indexers return CleanUpVariableName(m.Name.Substring(4)); - } else if (m.Name.StartsWith("Get", StringComparison.OrdinalIgnoreCase) && m.Name.Length >= 4 && char.IsUpper(m.Name[3])) { + } + else if (m.Name.StartsWith("Get", StringComparison.OrdinalIgnoreCase) && m.Name.Length >= 4 && char.IsUpper(m.Name[3])) + { // use name from Get-methods return CleanUpVariableName(m.Name.Substring(3)); } @@ -404,7 +481,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static string GetNameForArgument(ILInstruction parent, int i) { - switch (parent) { + switch (parent) + { case StObj stobj: IField field; if (stobj.Target is LdFlda ldflda) @@ -416,11 +494,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms return CleanUpVariableName(field.Name); case CallInstruction call: IMethod m = call.Method; - if (m.Parameters.Count == 1 && i == call.Arguments.Count - 1) { + if (m.Parameters.Count == 1 && i == call.Arguments.Count - 1) + { // argument might be value of a setter - if (m.Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase)) { + if (m.Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase)) + { return CleanUpVariableName(m.Name.Substring(4)); - } else if (m.Name.StartsWith("Set", StringComparison.OrdinalIgnoreCase) && m.Name.Length >= 4 && char.IsUpper(m.Name[3])) { + } + else if (m.Name.StartsWith("Set", StringComparison.OrdinalIgnoreCase) && m.Name.Length >= 4 && char.IsUpper(m.Name[3])) + { return CleanUpVariableName(m.Name.Substring(3)); } } @@ -437,7 +519,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static string GetNameByType(IType type) { type = NullableType.GetUnderlyingType(type); - while (type is ModifiedType || type is PinnedType) { + while (type is ModifiedType || type is PinnedType) + { type = NullableType.GetUnderlyingType(((TypeWithElementType)type).ElementType); } @@ -454,16 +537,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms TypeKind.NUInt => "num", _ => null }; - if (name != null) { + if (name != null) + { return name; } - if (type.IsAnonymousType()) { + if (type.IsAnonymousType()) + { name = "anon"; - } else if (type.Name.EndsWith("Exception", StringComparison.Ordinal)) { + } + else if (type.Name.EndsWith("Exception", StringComparison.Ordinal)) + { name = "ex"; - } else if (type.IsCSharpNativeIntegerType()) { + } + else if (type.IsCSharpNativeIntegerType()) + { name = "num"; - } else if (!typeNameToVariableNameDict.TryGetValue(type.FullName, out name)) { + } + else if (!typeNameToVariableNameDict.TryGetValue(type.FullName, out name)) + { name = type.Name; // remove the 'I' for interfaces if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2])) @@ -478,9 +569,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (string.IsNullOrEmpty(name)) return; string nameWithoutDigits = SplitName(name, out int number); - if (reservedVariableNames.TryGetValue(nameWithoutDigits, out int existingNumber)) { + if (reservedVariableNames.TryGetValue(nameWithoutDigits, out int existingNumber)) + { reservedVariableNames[nameWithoutDigits] = Math.Max(number, existingNumber); - } else { + } + else + { reservedVariableNames.Add(nameWithoutDigits, number); } } @@ -491,8 +585,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms int pos = name.Length; while (pos > 0 && name[pos - 1] >= '0' && name[pos - 1] <= '9') pos--; - if (pos < name.Length) { - if (int.TryParse(name.Substring(pos), out number)) { + if (pos < name.Length) + { + if (int.TryParse(name.Substring(pos), out number)) + { return name.Substring(0, pos); } } @@ -513,7 +609,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms else if (name.Length > 1 && name[0] == '_' && (char.IsLetter(name[1]) || name[1] == '_')) name = name.Substring(1); - if (TextWriterTokenWriter.ContainsNonPrintableIdentifierChar(name)) { + if (TextWriterTokenWriter.ContainsNonPrintableIdentifierChar(name)) + { return null; } @@ -539,11 +636,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms { var reservedVariableNames = new Dictionary(); var rootFunction = function.Ancestors.OfType().Single(f => f.Parent == null); - foreach (var f in rootFunction.Descendants.OfType()) { - foreach (var p in rootFunction.Parameters) { + foreach (var f in rootFunction.Descendants.OfType()) + { + foreach (var p in rootFunction.Parameters) + { AddExistingName(reservedVariableNames, p.Name); } - foreach (var v in f.Variables.Where(v => v.Kind != VariableKind.Parameter)) { + foreach (var v in f.Variables.Where(v => v.Kind != VariableKind.Parameter)) + { if (v != existingVariable) AddExistingName(reservedVariableNames, v.Name); } @@ -557,26 +657,36 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (function == null) throw new ArgumentNullException(nameof(function)); - if (existingVariable != null && !existingVariable.HasGeneratedName) { + if (existingVariable != null && !existingVariable.HasGeneratedName) + { return existingVariable.Name; } var reservedVariableNames = CollectReservedVariableNames(function, existingVariable); string baseName = GetNameFromInstruction(valueContext); - if (string.IsNullOrEmpty(baseName)) { - if (valueContext is LdLoc ldloc && ldloc.Variable.Kind == VariableKind.Parameter) { + if (string.IsNullOrEmpty(baseName)) + { + if (valueContext is LdLoc ldloc && ldloc.Variable.Kind == VariableKind.Parameter) + { baseName = ldloc.Variable.Name; } } string proposedName = "item"; - - if (!string.IsNullOrEmpty(baseName)) { - if (!IsPlural(baseName, ref proposedName)) { - if (baseName.Length > 4 && baseName.EndsWith("List", StringComparison.Ordinal)) { + + if (!string.IsNullOrEmpty(baseName)) + { + if (!IsPlural(baseName, ref proposedName)) + { + if (baseName.Length > 4 && baseName.EndsWith("List", StringComparison.Ordinal)) + { proposedName = baseName.Substring(0, baseName.Length - 4); - } else if (baseName.Equals("list", StringComparison.OrdinalIgnoreCase)) { + } + else if (baseName.Equals("list", StringComparison.OrdinalIgnoreCase)) + { proposedName = "item"; - } else if (baseName.EndsWith("children", StringComparison.OrdinalIgnoreCase)) { + } + else if (baseName.EndsWith("children", StringComparison.OrdinalIgnoreCase)) + { proposedName = baseName.Remove(baseName.Length - 3); } } @@ -585,13 +695,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms // remove any numbers from the proposed name proposedName = SplitName(proposedName, out int number); - if (!reservedVariableNames.ContainsKey(proposedName)) { + if (!reservedVariableNames.ContainsKey(proposedName)) + { reservedVariableNames.Add(proposedName, 0); } int count = ++reservedVariableNames[proposedName]; - if (count > 1) { + if (count > 1) + { return proposedName + count.ToString(); - } else { + } + else + { return proposedName; } } @@ -605,15 +719,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms string baseName = valueContext != null ? GetNameFromInstruction(valueContext) ?? GetNameByType(type) : GetNameByType(type); string proposedName = "obj"; - if (!string.IsNullOrEmpty(baseName)) { - if (!IsPlural(baseName, ref proposedName)) { - if (baseName.Length > 4 && baseName.EndsWith("List", StringComparison.Ordinal)) { + if (!string.IsNullOrEmpty(baseName)) + { + if (!IsPlural(baseName, ref proposedName)) + { + if (baseName.Length > 4 && baseName.EndsWith("List", StringComparison.Ordinal)) + { proposedName = baseName.Substring(0, baseName.Length - 4); - } else if (baseName.Equals("list", StringComparison.OrdinalIgnoreCase)) { + } + else if (baseName.Equals("list", StringComparison.OrdinalIgnoreCase)) + { proposedName = "item"; - } else if (baseName.EndsWith("children", StringComparison.OrdinalIgnoreCase)) { + } + else if (baseName.EndsWith("children", StringComparison.OrdinalIgnoreCase)) + { proposedName = baseName.Remove(baseName.Length - 3); - } else { + } + else + { proposedName = baseName; } } @@ -622,13 +745,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms // remove any numbers from the proposed name proposedName = SplitName(proposedName, out int number); - if (!reservedVariableNames.ContainsKey(proposedName)) { + if (!reservedVariableNames.ContainsKey(proposedName)) + { reservedVariableNames.Add(proposedName, 0); } int count = ++reservedVariableNames[proposedName]; - if (count > 1) { + if (count > 1) + { return proposedName + count.ToString(); - } else { + } + else + { return proposedName; } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/BlockTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/BlockTransform.cs index 9836b1242..ef1370f07 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/BlockTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/BlockTransform.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.IL.ControlFlow; @@ -77,16 +78,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (running) throw new InvalidOperationException("Reentrancy detected. Transforms (and the CSharpDecompiler) are neither thread-safe nor re-entrant."); - try { + try + { running = true; var blockContext = new BlockTransformContext(context); Debug.Assert(blockContext.Function == function); - foreach (var container in function.Descendants.OfType().ToList()) { + foreach (var container in function.Descendants.OfType().ToList()) + { context.CancellationToken.ThrowIfCancellationRequested(); blockContext.ControlFlowGraph = new ControlFlowGraph(container, context.CancellationToken); VisitBlock(blockContext.ControlFlowGraph.GetNode(container.EntryPoint), blockContext); } - } finally { + } + finally + { running = false; } } @@ -103,7 +108,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // First, process the children in the dominator tree. // The ConditionDetection transform requires dominated blocks to // be already processed. - foreach (var child in cfgNode.DominatorTreeChildren) { + foreach (var child in cfgNode.DominatorTreeChildren) + { VisitBlock(child, context); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs b/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs index 38ba30608..ff33796ff 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms @@ -31,17 +32,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms this.context = context; if (!context.Settings.AnonymousMethods) return; - for (int i = block.Instructions.Count - 1; i >= 0; i--) { - if (block.Instructions[i] is IfInstruction inst) { - if (CachedDelegateInitializationWithField(inst)) { + for (int i = block.Instructions.Count - 1; i >= 0; i--) + { + if (block.Instructions[i] is IfInstruction inst) + { + if (CachedDelegateInitializationWithField(inst)) + { block.Instructions.RemoveAt(i); continue; } - if (CachedDelegateInitializationWithLocal(inst)) { + if (CachedDelegateInitializationWithLocal(inst)) + { ILInlining.InlineOneIfPossible(block, i, InliningOptions.Aggressive, context); continue; } - if (CachedDelegateInitializationRoslynInStaticWithLocal(inst) || CachedDelegateInitializationRoslynWithLocal(inst)) { + if (CachedDelegateInitializationRoslynInStaticWithLocal(inst) || CachedDelegateInitializationRoslynWithLocal(inst)) + { block.Instructions.RemoveAt(i); continue; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/CombineExitsTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/CombineExitsTransform.cs index 4efb09a95..03e6ffbf1 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CombineExitsTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/CombineExitsTransform.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // if (cond) { // if (cond2) { // leave (value) - // } + // } // leave (value2) // } // leave (value3) diff --git a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs index 4c5fe176d..766da7b98 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs @@ -16,12 +16,13 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.Util; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Util; + namespace ICSharpCode.Decompiler.IL.Transforms { /// @@ -45,12 +46,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms public void Run(ILFunction function, ILTransformContext context) { var splitVariables = new HashSet(ILVariableEqualityComparer.Instance); - foreach (var g in function.Variables.GroupBy(v => v, ILVariableEqualityComparer.Instance)) { - if (g.Count() > 1) { + foreach (var g in function.Variables.GroupBy(v => v, ILVariableEqualityComparer.Instance)) + { + if (g.Count() > 1) + { splitVariables.Add(g.Key); } } - foreach (var block in function.Descendants.OfType()) { + foreach (var block in function.Descendants.OfType()) + { if (block.Kind != BlockKind.ControlFlow) continue; RunOnBlock(block, context, splitVariables); @@ -59,24 +63,32 @@ namespace ICSharpCode.Decompiler.IL.Transforms static void RunOnBlock(Block block, ILTransformContext context, HashSet splitVariables = null) { - for (int i = 0; i < block.Instructions.Count; i++) { - if (block.Instructions[i].MatchStLoc(out ILVariable v, out ILInstruction copiedExpr)) { - if (v.IsSingleDefinition && v.LoadCount == 0 && v.Kind == VariableKind.StackSlot) { + for (int i = 0; i < block.Instructions.Count; i++) + { + if (block.Instructions[i].MatchStLoc(out ILVariable v, out ILInstruction copiedExpr)) + { + if (v.IsSingleDefinition && v.LoadCount == 0 && v.Kind == VariableKind.StackSlot) + { // dead store to stack - if (SemanticHelper.IsPure(copiedExpr.Flags)) { + if (SemanticHelper.IsPure(copiedExpr.Flags)) + { // no-op -> delete context.Step("remove dead store to stack: no-op -> delete", block.Instructions[i]); block.Instructions.RemoveAt(i); // This can open up new inlining opportunities: int c = ILInlining.InlineInto(block, i, InliningOptions.None, context: context); i -= c + 1; - } else { + } + else + { // evaluate the value for its side-effects context.Step("remove dead store to stack: evaluate the value for its side-effects", block.Instructions[i]); copiedExpr.AddILRange(block.Instructions[i]); block.Instructions[i] = copiedExpr; } - } else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr, splitVariables)) { + } + else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr, splitVariables)) + { DoPropagate(v, copiedExpr, block, ref i, context); } } @@ -88,13 +100,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms Debug.Assert(target.StackType == value.ResultType); if (target.Type.IsSmallIntegerType()) return false; - if (splitVariables != null && splitVariables.Contains(target)) { + if (splitVariables != null && splitVariables.Contains(target)) + { return false; // non-local code move might change semantics when there's split variables } - switch (value.OpCode) { + switch (value.OpCode) + { case OpCode.LdLoca: -// case OpCode.LdElema: -// case OpCode.LdFlda: + // case OpCode.LdElema: + // case OpCode.LdFlda: case OpCode.LdsFlda: // All address-loading instructions always return the same value for a given operand/argument combination, // so they can be safely copied. @@ -103,10 +117,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; case OpCode.LdLoc: var v = ((LdLoc)value).Variable; - if (splitVariables != null && splitVariables.Contains(v)) { + if (splitVariables != null && splitVariables.Contains(v)) + { return false; // non-local code move might change semantics when there's split variables } - switch (v.Kind) { + switch (v.Kind) + { case VariableKind.Parameter: // Parameters can be copied only if they aren't assigned to (directly or indirectly via ldarga) // note: the initialization by the caller is the first store -> StoreCount must be 1 @@ -129,7 +145,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step($"Copy propagate {v.Name}", copiedExpr); // un-inline the arguments of the ldArg instruction ILVariable[] uninlinedArgs = new ILVariable[copiedExpr.Children.Count]; - for (int j = 0; j < uninlinedArgs.Length; j++) { + for (int j = 0; j < uninlinedArgs.Length; j++) + { var arg = copiedExpr.Children[j]; var type = context.TypeSystem.FindType(arg.ResultType.ToKnownTypeCode()); uninlinedArgs[j] = new ILVariable(VariableKind.StackSlot, type, arg.ResultType) { @@ -140,9 +157,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms } v.Function.Variables.AddRange(uninlinedArgs); // perform copy propagation: - foreach (var expr in v.LoadInstructions.ToArray()) { + foreach (var expr in v.LoadInstructions.ToArray()) + { var clone = copiedExpr.Clone(); - for (int j = 0; j < uninlinedArgs.Length; j++) { + for (int j = 0; j < uninlinedArgs.Length; j++) + { clone.Children[j].ReplaceWith(new LdLoc(uninlinedArgs[j])); } expr.ReplaceWith(clone); diff --git a/ICSharpCode.Decompiler/IL/Transforms/DeconstructionTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/DeconstructionTransform.cs index 409d3a907..9174218d1 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DeconstructionTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DeconstructionTransform.cs @@ -68,7 +68,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!context.Settings.Deconstruction) return; - try { + try + { this.context = context; Reset(); @@ -76,7 +77,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; if (InlineDeconstructionInitializer(block, pos)) return; - } finally { + } + finally + { this.context = null; Reset(); } @@ -103,12 +106,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms int FindIndex(ILInstruction inst, out Action delayedActions) { delayedActions = null; - if (inst.MatchLdLoc(out var v)) { + if (inst.MatchLdLoc(out var v)) + { if (!deconstructionResultsLookup.TryGetValue(v, out int index)) return -1; return index; } - if (inst.MatchLdFld(out _, out _)) { + if (inst.MatchLdFld(out _, out _)) + { if (!TupleTransform.MatchTupleFieldAccess((LdFlda)((LdObj)inst).Target, out var tupleType, out var target, out int index)) return -1; // Item fields are one-based, we use zero-based indexing. @@ -117,7 +122,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms tupleType = TupleType.FromUnderlyingType(context.TypeSystem, tupleType); if (!target.MatchLdLoca(out v)) return -1; - if (this.tupleVariable == null) { + if (this.tupleVariable == null) + { this.tupleVariable = v; this.tupleType = (TupleType)tupleType; this.deconstructionResults = new ILVariable[this.tupleType.Cardinality]; @@ -126,7 +132,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return -1; if (v != tupleVariable || !this.tupleType.Equals(tupleType)) return -1; - if (this.deconstructionResults[index] == null) { + if (this.deconstructionResults[index] == null) + { var freshVar = new ILVariable(VariableKind.StackSlot, this.tupleType.ElementTypes[index]) { Name = "E_" + index }; delayedActions += _ => context.Function.Variables.Add(freshVar); this.deconstructionResults[index] = freshVar; @@ -160,11 +167,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms LdLoc loadInst = v.LoadInstructions[0]; if (!loadInst.IsDescendantOf(deconstruction.Assignments)) return false; - if (loadInst.SlotInfo == StObj.TargetSlot) { + if (loadInst.SlotInfo == StObj.TargetSlot) + { if (value.OpCode == OpCode.LdFlda || value.OpCode == OpCode.LdElema) return false; } - if (deconstruction.Init.Count > 0) { + if (deconstruction.Init.Count > 0) + { var a = deconstruction.Init[0].Variable.LoadInstructions.Single(); var b = v.LoadInstructions.Single(); if (!b.IsBefore(a)) @@ -198,13 +207,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step("Deconstruction", block.Instructions[startPos]); DeconstructInstruction replacement = new DeconstructInstruction(); IType deconstructedType; - if (deconstructMethod == null) { + if (deconstructMethod == null) + { deconstructedType = this.tupleType; rootTestedOperand = new LdLoc(this.tupleVariable); - } else { - if (deconstructMethod.IsStatic) { + } + else + { + if (deconstructMethod.IsStatic) + { deconstructedType = deconstructMethod.Parameters[0].Type; - } else { + } + else + { deconstructedType = deconstructMethod.DeclaringType; } } @@ -214,13 +229,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms IsDeconstructTuple = this.tupleType != null }; int index = 0; - foreach (ILVariable v in deconstructionResults) { + foreach (ILVariable v in deconstructionResults) + { var result = v; - if (result == null) { + if (result == null) + { var freshVar = new ILVariable(VariableKind.PatternLocal, this.tupleType.ElementTypes[index]) { Name = "E_" + index }; context.Function.Variables.Add(freshVar); result = freshVar; - } else { + } + else + { result.Kind = VariableKind.PatternLocal; } replacement.Pattern.SubPatterns.Add( @@ -232,7 +251,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms index++; } replacement.Conversions = new Block(BlockKind.DeconstructionConversions); - foreach (var convInst in conversionStLocs) { + foreach (var convInst in conversionStLocs) + { replacement.Conversions.Instructions.Add(convInst); } replacement.Assignments = new Block(BlockKind.DeconstructionAssignments); @@ -257,7 +277,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (call.Arguments.Count < 3) return false; deconstructionResults = new ILVariable[call.Arguments.Count - 1]; - for (int i = 0; i < deconstructionResults.Length; i++) { + for (int i = 0; i < deconstructionResults.Length; i++) + { if (!call.Arguments[i + 1].MatchLdLoca(out var v)) return false; // TODO v.LoadCount may be 2 if the deconstruction is assigned to a tuple variable @@ -282,7 +303,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms int previousIndex = -1; while (MatchConversion( block.Instructions.ElementAtOrDefault(pos), out var inputInstruction, - out var outputVariable, out var info)) { + out var outputVariable, out var info)) + { int index = FindIndex(inputInstruction, out var tupleAccessAdjustment); if (index <= previousIndex) return false; @@ -323,7 +345,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms int previousIndex = -1; int conversionStLocIndex = 0; int startPos = pos; - while (MatchAssignment(block.Instructions.ElementAtOrDefault(pos), out var targetType, out var valueInst, out var addAssignment)) { + while (MatchAssignment(block.Instructions.ElementAtOrDefault(pos), out var targetType, out var valueInst, out var addAssignment)) + { int index = FindIndex(valueInst, out var tupleAccessAdjustment); if (index <= previousIndex) return false; @@ -338,11 +361,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (block.Instructions[pos].MatchStLoc(out var assignmentTarget, out _) && assignmentTarget.Kind == VariableKind.StackSlot && assignmentTarget.IsSingleDefinition - && conversionInfo.conv == null) { + && conversionInfo.conv == null) + { delayedActions += _ => { assignmentTarget.Type = conversionInfo.inputType; }; - } else { + } + else + { if (!IsCompatibleImplicitConversion(targetType, conversionInfo)) return false; } @@ -356,13 +382,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms void AddMissingAssignmentsForConversions(int index, ref Action delayedActions) { - while (conversionStLocIndex < conversionStLocs.Count) { + while (conversionStLocIndex < conversionStLocs.Count) + { var stLoc = conversionStLocs[conversionStLocIndex]; int conversionResultIndex = deconstructionResultsLookup[stLoc.Variable]; if (conversionResultIndex >= index) break; - if (conversionResultIndex > previousIndex) { + if (conversionResultIndex > previousIndex) + { delayedActions += (DeconstructInstruction deconstructInst) => { var freshVar = context.Function.RegisterVariable(VariableKind.StackSlot, stLoc.Variable.Type); deconstructInst.Assignments.Instructions.Add(new StLoc(stLoc.Variable, new LdLoc(freshVar))); @@ -382,7 +410,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (inst == null) return false; if (inst.MatchStLoc(out var v, out var value) - && value is Block block && block.MatchInlineAssignBlock(out var call, out valueInst)) { + && value is Block block && block.MatchInlineAssignBlock(out var call, out valueInst)) + { if (!DeconstructInstruction.IsAssignment(call, context.TypeSystem, out targetType, out _)) return false; if (!(v.IsSingleDefinition && v.LoadCount == 0)) @@ -393,13 +422,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms deconstructInst.Assignments.Instructions.Add(call); }; return true; - } else if (DeconstructInstruction.IsAssignment(inst, context.TypeSystem, out targetType, out valueInst)) { + } + else if (DeconstructInstruction.IsAssignment(inst, context.TypeSystem, out targetType, out valueInst)) + { // OK - use the assignment as is addAssignment = (DeconstructInstruction deconstructInst) => { deconstructInst.Assignments.Instructions.Add(inst); }; return true; - } else { + } + else + { return false; } } @@ -412,11 +445,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; var inputType = conversionInfo.inputType; var conv = conversionInfo.conv; - if (c.IsIdentityConversion || c.IsReferenceConversion) { + if (c.IsIdentityConversion || c.IsReferenceConversion) + { return conv == null || conv.Kind == ConversionKind.Nop; } - if (c.IsNumericConversion) { - switch (conv.Kind) { + if (c.IsNumericConversion) + { + switch (conv.Kind) + { case ConversionKind.IntToFloat: return inputType.GetSign() == conv.InputSign; case ConversionKind.FloatPrecisionChange: diff --git a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs index 27143e9b3..a03a9d450 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.TypeSystem; @@ -32,29 +33,36 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILTransformContext context; ITypeResolveContext decompilationContext; readonly Stack activeMethods = new Stack(); - + void IILTransform.Run(ILFunction function, ILTransformContext context) { if (!context.Settings.AnonymousMethods) return; var prevContext = this.context; var prevDecompilationContext = this.decompilationContext; - try { + try + { activeMethods.Push((MethodDefinitionHandle)function.Method.MetadataToken); this.context = context; this.decompilationContext = new SimpleTypeResolveContext(function.Method); var cancellationToken = context.CancellationToken; - foreach (var inst in function.Descendants) { + foreach (var inst in function.Descendants) + { cancellationToken.ThrowIfCancellationRequested(); - if (inst is NewObj call) { + if (inst is NewObj call) + { context.StepStartGroup($"TransformDelegateConstruction {call.StartILOffset}", call); ILFunction f = TransformDelegateConstruction(call, out ILInstruction target); - if (f != null && target is IInstructionWithVariableOperand instWithVar) { - if (instWithVar.Variable.Kind == VariableKind.Local) { + if (f != null && target is IInstructionWithVariableOperand instWithVar) + { + if (instWithVar.Variable.Kind == VariableKind.Local) + { instWithVar.Variable.Kind = VariableKind.DisplayClassLocal; } - if (instWithVar.Variable.IsSingleDefinition && instWithVar.Variable.StoreInstructions.SingleOrDefault() is StLoc store) { - if (store.Value is NewObj) { + if (instWithVar.Variable.IsSingleDefinition && instWithVar.Variable.StoreInstructions.SingleOrDefault() is StLoc store) + { + if (store.Value is NewObj) + { instWithVar.Variable.CaptureScope = BlockContainer.FindClosestContainer(store); } } @@ -62,7 +70,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.StepEndGroup(); } } - } finally { + } + finally + { this.context = prevContext; this.decompilationContext = prevDecompilationContext; activeMethods.Pop(); @@ -79,7 +89,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms var typeKind = inst.Method.DeclaringType.Kind; return typeKind == TypeKind.Delegate || typeKind == TypeKind.Unknown; } - + static bool IsAnonymousMethod(ITypeDefinition decompiledTypeDefinition, IMethod method) { if (method == null) @@ -97,27 +107,32 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (method.ReturnType.ContainsAnonymousType()) return true; - foreach (var p in method.Parameters) { + foreach (var p in method.Parameters) + { if (p.Type.ContainsAnonymousType()) return true; } return false; } - + static GenericContext? GenericContextFromTypeArguments(TypeParameterSubstitution subst) { var classTypeParameters = new List(); var methodTypeParameters = new List(); - if (subst.ClassTypeArguments != null) { - foreach (var t in subst.ClassTypeArguments) { + if (subst.ClassTypeArguments != null) + { + foreach (var t in subst.ClassTypeArguments) + { if (t is ITypeParameter tp) classTypeParameters.Add(tp); else return null; } } - if (subst.MethodTypeArguments != null) { - foreach (var t in subst.MethodTypeArguments) { + if (subst.MethodTypeArguments != null) + { + foreach (var t in subst.MethodTypeArguments) + { if (t is ITypeParameter tp) methodTypeParameters.Add(tp); else @@ -143,7 +158,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!ValidateDelegateTarget(target)) return null; var handle = (MethodDefinitionHandle)targetMethod.MetadataToken; - if (activeMethods.Contains(handle)) { + if (activeMethods.Contains(handle)) + { this.context.Function.Warnings.Add(" Found self-referencing delegate construction. Abort transformation to avoid stack overflow."); return null; } @@ -163,7 +179,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms function.CheckInvariant(ILPhase.Normal); var contextPrefix = targetMethod.Name; - foreach (ILVariable v in function.Variables.Where(v => v.Kind != VariableKind.Parameter)) { + foreach (ILVariable v in function.Variables.Where(v => v.Kind != VariableKind.Parameter)) + { v.Name = contextPrefix + v.Name; } @@ -183,7 +200,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms private static bool ValidateDelegateTarget(ILInstruction inst) { - switch (inst) { + switch (inst) + { case LdNull _: return true; case LdLoc ldloc: @@ -196,12 +214,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms // TODO : ldfld chains must be validated more thoroughly, i.e., we should make sure // that the value of the field is never changed. ILInstruction target = ldobj; - while (target is LdObj || target is LdFlda) { - if (target is LdObj o) { + while (target is LdObj || target is LdFlda) + { + if (target is LdObj o) + { target = o.Target; continue; } - if (target is LdFlda f) { + if (target is LdFlda f) + { target = f.Target; continue; } @@ -225,31 +246,35 @@ namespace ICSharpCode.Decompiler.IL.Transforms { readonly ILVariable thisVariable; readonly ILInstruction target; - + public ReplaceDelegateTargetVisitor(ILInstruction target, ILVariable thisVariable) { this.target = target; this.thisVariable = thisVariable; } - + protected override void Default(ILInstruction inst) { - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { child.AcceptVisitor(this); } } protected internal override void VisitILFunction(ILFunction function) { - if (function == thisVariable?.Function) { + if (function == thisVariable?.Function) + { ILVariable v = null; - switch (target) { + switch (target) + { case LdLoc l: v = l.Variable; break; case LdObj lo: ILInstruction inner = lo.Target; - while (inner is LdFlda ldf) { + while (inner is LdFlda ldf) + { inner = ldf.Target; } if (inner is LdLoc l2) @@ -264,7 +289,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitLdLoc(LdLoc inst) { - if (inst.Variable == thisVariable) { + if (inst.Variable == thisVariable) + { inst.ReplaceWith(target.Clone()); return; } @@ -273,7 +299,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitLdObj(LdObj inst) { - if (inst.Target.MatchLdLoca(thisVariable)) { + if (inst.Target.MatchLdLoca(thisVariable)) + { inst.ReplaceWith(target.Clone()); return; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs index 2a40c48c2..91aeefc81 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms @@ -26,7 +27,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { public void Run(ILFunction function, ILTransformContext context) { - foreach (var catchBlock in function.Descendants.OfType()) { + foreach (var catchBlock in function.Descendants.OfType()) + { if (catchBlock.Filter is BlockContainer container && MatchCatchWhenEntryPoint(catchBlock.Variable, container, container.EntryPoint, out var exceptionType, out var exceptionSlot, out var whenConditionBlock) @@ -45,7 +47,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // br whenConditionBlock // } var instructions = container.EntryPoint.Instructions; - if (instructions.Count == 3) { + if (instructions.Count == 3) + { // stloc temp(isinst exceptionType(ldloc exceptionVar)) // if (comp(ldloc temp != ldnull)) br whenConditionBlock // br falseBlock @@ -53,7 +56,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms instructions[1].ReplaceWith(new Branch(whenConditionBlock)); instructions.RemoveAt(2); container.SortBlocks(deleteUnreachableBlocks: true); - } else if (instructions.Count == 2) { + } + else if (instructions.Count == 2) + { // if (comp(isinst exceptionType(ldloc exceptionVar) != ldnull)) br whenConditionBlock // br falseBlock instructions[0].ReplaceWith(new Branch(whenConditionBlock)); @@ -78,7 +83,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms whenConditionBlock = null; if (entryPoint == null || entryPoint.IncomingEdgeCount != 1) return false; - if (entryPoint.Instructions.Count == 3) { + if (entryPoint.Instructions.Count == 3) + { // stloc temp(isinst exceptionType(ldloc exceptionVar)) // if (comp(ldloc temp != ldnull)) br whenConditionBlock // br falseBlock @@ -93,10 +99,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!entryPoint.Instructions[2].MatchBranch(out var falseBlock) || !MatchFalseBlock(container, falseBlock, out var returnVar, out var exitBlock)) return false; - if ((left.MatchLdNull() && right.MatchLdLoc(temp)) || (right.MatchLdNull() && left.MatchLdLoc(temp))) { + if ((left.MatchLdNull() && right.MatchLdLoc(temp)) || (right.MatchLdNull() && left.MatchLdLoc(temp))) + { return branch.MatchBranch(out whenConditionBlock); } - } else if (entryPoint.Instructions.Count == 2) { + } + else if (entryPoint.Instructions.Count == 2) + { // if (comp(isinst exceptionType(ldloc exceptionVar) != ldnull)) br whenConditionBlock // br falseBlock if (!entryPoint.Instructions[0].MatchIfInstruction(out var condition, out var branch)) @@ -109,7 +118,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!exceptionSlot.MatchLdLoc(exceptionVar)) return false; - if (right.MatchLdNull()) { + if (right.MatchLdNull()) + { return branch.MatchBranch(out whenConditionBlock); } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/DynamicCallSiteTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/DynamicCallSiteTransform.cs index 88c30641b..7290273a5 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DynamicCallSiteTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DynamicCallSiteTransform.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -46,22 +47,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms Dictionary callsites = new Dictionary(); HashSet modifiedContainers = new HashSet(); - foreach (var block in function.Descendants.OfType()) { - if (block.Instructions.Count < 2) continue; + foreach (var block in function.Descendants.OfType()) + { + if (block.Instructions.Count < 2) + continue; // Check if, we deal with a callsite cache field null check: // if (comp(ldsfld <>p__3 == ldnull)) br IL_000c // br IL_002b - if (!(block.Instructions.SecondToLastOrDefault() is IfInstruction ifInst)) continue; - if (!(block.Instructions.LastOrDefault() is Branch branchAfterInit)) continue; + if (!(block.Instructions.SecondToLastOrDefault() is IfInstruction ifInst)) + continue; + if (!(block.Instructions.LastOrDefault() is Branch branchAfterInit)) + continue; if (!MatchCallSiteCacheNullCheck(ifInst.Condition, out var callSiteCacheField, out var callSiteDelegate, out bool invertBranches)) continue; if (!ifInst.TrueInst.MatchBranch(out var trueBlock)) continue; Block callSiteInitBlock, targetBlockAfterInit; - if (invertBranches) { + if (invertBranches) + { callSiteInitBlock = branchAfterInit.TargetBlock; targetBlockAfterInit = trueBlock; - } else { + } + else + { callSiteInitBlock = trueBlock; targetBlockAfterInit = branchAfterInit.TargetBlock; } @@ -78,11 +86,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms var storesToRemove = new List(); - foreach (var invokeCall in function.Descendants.OfType()) { + foreach (var invokeCall in function.Descendants.OfType()) + { if (invokeCall.Method.DeclaringType.Kind != TypeKind.Delegate || invokeCall.Method.Name != "Invoke" || invokeCall.Arguments.Count == 0) continue; var firstArgument = invokeCall.Arguments[0]; - if (firstArgument.MatchLdLoc(out var stackSlot) && stackSlot.Kind == VariableKind.StackSlot && stackSlot.IsSingleDefinition) { + if (firstArgument.MatchLdLoc(out var stackSlot) && stackSlot.Kind == VariableKind.StackSlot && stackSlot.IsSingleDefinition) + { firstArgument = ((StLoc)stackSlot.StoreInstructions[0]).Value; } if (!firstArgument.MatchLdFld(out var cacheFieldLoad, out var targetField)) @@ -99,16 +109,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms invokeCall.ReplaceWith(replacement); Debug.Assert(callsite.ConditionalJumpToInit?.Parent is Block); var block = ((Block)callsite.ConditionalJumpToInit.Parent); - if (callsite.Inverted) { + if (callsite.Inverted) + { block.Instructions.Remove(callsite.ConditionalJumpToInit); callsite.BranchAfterInit.ReplaceWith(callsite.ConditionalJumpToInit.TrueInst); - } else { + } + else + { block.Instructions.Remove(callsite.ConditionalJumpToInit); } - foreach (var arg in deadArguments) { - if (arg.MatchLdLoc(out var temporary) && temporary.Kind == VariableKind.StackSlot && temporary.IsSingleDefinition && temporary.LoadCount == 0) { + foreach (var arg in deadArguments) + { + if (arg.MatchLdLoc(out var temporary) && temporary.Kind == VariableKind.StackSlot && temporary.IsSingleDefinition && temporary.LoadCount == 0) + { StLoc stLoc = (StLoc)temporary.StoreInstructions[0]; - if (stLoc.Parent is Block storeParentBlock) { + if (stLoc.Parent is Block storeParentBlock) + { var value = stLoc.Value; if (value.MatchLdsFld(out var cacheFieldCopy) && cacheFieldCopy.Equals(cacheField)) storesToRemove.Add(stLoc); @@ -120,7 +136,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms modifiedContainers.Add((BlockContainer)block.Parent); } - foreach (var inst in storesToRemove) { + foreach (var inst in storesToRemove) + { Block parentBlock = (Block)inst.Parent; parentBlock.Instructions.RemoveAt(inst.ChildIndex); } @@ -131,7 +148,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInstruction MakeDynamicInstruction(CallSiteInfo callsite, CallVirt targetInvokeCall, List deadArguments) { - switch (callsite.Kind) { + switch (callsite.Kind) + { case BinderMethodKind.BinaryOperation: deadArguments.AddRange(targetInvokeCall.Arguments.Take(2)); return new DynamicBinaryOperatorInstruction( @@ -151,7 +169,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms type: callsite.ConvertTargetType, argument: targetInvokeCall.Arguments[2] ); - if (result.ResultType == StackType.Unknown) { + if (result.ResultType == StackType.Unknown) + { // if references are missing, we need to coerce the primitive type to None. // Otherwise we will get loads of assertions. result = new Conv(result, PrimitiveType.None, ((DynamicConvertInstruction)result).IsChecked, Sign.None); @@ -187,7 +206,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // Extract type information from targetInvokeCall: // Must either be an inlined type or // a reference to a variable that is initialized with a type. - if (!TransformExpressionTrees.MatchGetTypeFromHandle(arguments[0], out var type)) { + if (!TransformExpressionTrees.MatchGetTypeFromHandle(arguments[0], out var type)) + { if (!(arguments[0].MatchLdLoc(out var temp) && temp.IsSingleDefinition && temp.StoreInstructions.FirstOrDefault() is StLoc initStore)) return null; if (!TransformExpressionTrees.MatchGetTypeFromHandle(initStore.Value, out type)) @@ -269,7 +289,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; callSiteInfo.DelegateType = callSiteDelegateType; callSiteInfo.InitBlock = callSiteInitBlock; - switch (binderCall.Method.Name) { + switch (binderCall.Method.Name) + { case "IsEvent": callSiteInfo.Kind = BinderMethodKind.IsEvent; // In the case of Binder.IsEvent all arguments should already be properly inlined, as there is no array initializer: @@ -331,25 +352,31 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!callSiteInitBlock.Instructions[2].MatchStLoc(out var variableOrTemporary, out value)) return false; int numberOfTypeArguments = 0; - if (!value.MatchLdNull()) { - if (value is NewArr typeArgsNewArr && typeArgsNewArr.Type.IsKnownType(KnownTypeCode.Type) && typeArgsNewArr.Indices.Count == 1 && typeArgsNewArr.Indices[0].MatchLdcI4(out numberOfTypeArguments)) { + if (!value.MatchLdNull()) + { + if (value is NewArr typeArgsNewArr && typeArgsNewArr.Type.IsKnownType(KnownTypeCode.Type) && typeArgsNewArr.Indices.Count == 1 && typeArgsNewArr.Indices[0].MatchLdcI4(out numberOfTypeArguments)) + { if (!TransformArrayInitializers.HandleSimpleArrayInitializer(context.Function, callSiteInitBlock, 3, variableOrTemporary, typeArgsNewArr.Type, new[] { numberOfTypeArguments }, out var typeArguments, out _)) return false; int i = 0; callSiteInfo.TypeArguments = new IType[numberOfTypeArguments]; - foreach (var (_, typeArg) in typeArguments) { + foreach (var (_, typeArg) in typeArguments) + { if (!TransformExpressionTrees.MatchGetTypeFromHandle(typeArg, out var type)) return false; callSiteInfo.TypeArguments[i] = type; i++; } - } else { + } + else + { return false; } } int typeArgumentsOffset = numberOfTypeArguments; // Special case for csc array initializers: - if (variableOrTemporary != variable) { + if (variableOrTemporary != variable) + { // store temporary from array initializer in variable if (!callSiteInitBlock.Instructions[3 + typeArgumentsOffset].MatchStLoc(variable, out value)) return false; @@ -416,7 +443,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms case "SetIndex": case "InvokeConstructor": case "Invoke": - switch (binderCall.Method.Name) { + switch (binderCall.Method.Name) + { case "GetIndex": callSiteInfo.Kind = BinderMethodKind.GetIndex; break; @@ -515,7 +543,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (invokeMethod == null) return false; var compileTimeTypes = invokeMethod.Parameters.SelectReadOnlyArray(p => p.Type); - foreach (var (_, arg) in arguments) { + foreach (var (_, arg) in arguments) + { if (!(arg is Call createCall)) return false; if (!(createCall.Method.Name == "Create" && createCall.Method.DeclaringType.FullName == "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo" && createCall.Arguments.Count == 2)) @@ -536,7 +565,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms callSiteCacheField = null; callSiteDelegate = null; invertBranches = false; - if (!condition.MatchCompEqualsNull(out var argument)) { + if (!condition.MatchCompEqualsNull(out var argument)) + { if (!condition.MatchCompNotEqualsNull(out argument)) return false; invertBranches = true; diff --git a/ICSharpCode.Decompiler/IL/Transforms/DynamicIsEventAssignmentTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/DynamicIsEventAssignmentTransform.cs index 5903ecef3..9afcb2706 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DynamicIsEventAssignmentTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DynamicIsEventAssignmentTransform.cs @@ -51,10 +51,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms int offset = 2; if (block.Instructions[pos + offset].MatchStLoc(out var valueVariable) && pos + 4 < block.Instructions.Count && valueVariable.IsSingleDefinition && valueVariable.LoadCount == 2 - && valueVariable.LoadInstructions.All(ld => ld.Parent is DynamicInstruction)) { + && valueVariable.LoadInstructions.All(ld => ld.Parent is DynamicInstruction)) + { offset++; } - foreach (var descendant in block.Instructions[pos + offset].Descendants) { + foreach (var descendant in block.Instructions[pos + offset].Descendants) + { if (!MatchIsEventAssignmentIfInstruction(descendant, isEvent, flagVar, getMemberVar, out var setMemberInst, out var getMemberVarUse, out var isEventConditionUse)) continue; context.Step("DynamicIsEventAssignmentTransform", block.Instructions[pos]); @@ -84,16 +86,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms isEventConditionUse = null; if (!ifInst.MatchIfInstruction(out var condition, out var trueInst, out var falseInst)) return false; - if (MatchFlagEqualsZero(condition, flagVar)) { + if (MatchFlagEqualsZero(condition, flagVar)) + { if (!condition.MatchCompEquals(out var left, out _)) return false; isEventConditionUse = left; - } else if (condition.MatchLdLoc(flagVar)) { + } + else if (condition.MatchLdLoc(flagVar)) + { var tmp = trueInst; trueInst = falseInst; falseInst = tmp; isEventConditionUse = condition; - } else + } + else return false; setMemberInst = Block.Unwrap(trueInst) as DynamicSetMemberInstruction; if (setMemberInst == null) diff --git a/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs index 8bba5a9a0..1c510935a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms @@ -37,7 +38,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected override void Default(ILInstruction inst) { - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { child.AcceptVisitor(this); } } @@ -47,7 +49,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms base.VisitStObj(inst); StObjToStLoc(inst, context); } - + // This transform is required because ILInlining only works with stloc/ldloc internal static bool StObjToStLoc(StObj inst, ILTransformContext context) { @@ -91,14 +93,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms // ldobj(...(ldloca V)) var temp = inst.Target; var range = temp.ILRanges; - while (temp.MatchLdFlda(out var ldfldaTarget, out _)) { + while (temp.MatchLdFlda(out var ldfldaTarget, out _)) + { temp = ldfldaTarget; range = range.Concat(temp.ILRanges); } - if (temp.MatchAddressOf(out var addressOfTarget, out _) && addressOfTarget.MatchLdLoc(out var v)) { + if (temp.MatchAddressOf(out var addressOfTarget, out _) && addressOfTarget.MatchLdLoc(out var v)) + { context.Step($"ldobj(...(addressof(ldloca {v.Name}))) => ldobj(...(ldloca {v.Name}))", inst); var replacement = new LdLoca(v).WithILRange(addressOfTarget); - foreach (var r in range) { + foreach (var r in range) + { replacement = replacement.WithILRange(r); } temp.ReplaceWith(replacement); @@ -108,17 +113,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitCall(Call inst) { var expr = HandleCall(inst, context); - if (expr != null) { + if (expr != null) + { // The resulting expression may trigger further rules, so continue visiting the replacement: expr.AcceptVisitor(this); - } else { + } + else + { base.VisitCall(inst); } } internal static ILInstruction HandleCall(Call inst, ILTransformContext context) { - if (inst.Method.IsConstructor && !inst.Method.IsStatic && inst.Method.DeclaringType.Kind == TypeKind.Struct) { + if (inst.Method.IsConstructor && !inst.Method.IsStatic && inst.Method.DeclaringType.Kind == TypeKind.Struct) + { Debug.Assert(inst.Arguments.Count == inst.Method.Parameters.Count + 1); context.Step("Transform call to struct constructor", inst); // call(ref, ...) diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index fd0006b1a..659b34361 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -56,14 +57,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected override void Default(ILInstruction inst) { - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { child.AcceptVisitor(this); } } protected internal override void VisitBlockContainer(BlockContainer container) { - if (container.Kind == ContainerKind.Switch) { + if (container.Kind == ContainerKind.Switch) + { // Special case for switch: Only visit the switch condition block. var switchInst = (SwitchInstruction)container.EntryPoint.Instructions[0]; switchInst.Value.AcceptVisitor(this); @@ -75,7 +78,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitBlock(Block block) { - if (block.Kind == BlockKind.ControlFlow) { + if (block.Kind == BlockKind.ControlFlow) + { // Don't visit child control flow blocks; // since this is a block transform // we know those were already handled previously. @@ -87,12 +91,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitComp(Comp inst) { // "logic.not(arg)" is sugar for "comp(arg != ldc.i4 0)" - if (inst.MatchLogicNot(out var arg)) { + if (inst.MatchLogicNot(out var arg)) + { VisitLogicNot(inst, arg); return; - } else if (inst.Kind == ComparisonKind.Inequality && inst.LiftingKind == ComparisonLiftingKind.None - && inst.Right.MatchLdcI4(0) && (IfInstruction.IsInConditionSlot(inst) || inst.Left is Comp) - ) { + } + else if (inst.Kind == ComparisonKind.Inequality && inst.LiftingKind == ComparisonLiftingKind.None + && inst.Right.MatchLdcI4(0) && (IfInstruction.IsInConditionSlot(inst) || inst.Left is Comp) + ) + { // if (comp(x != 0)) ==> if (x) // comp(comp(...) != 0) => comp(...) context.Step("Remove redundant comp(... != 0)", inst); @@ -103,22 +110,32 @@ namespace ICSharpCode.Decompiler.IL.Transforms } base.VisitComp(inst); - if (inst.IsLifted) { + if (inst.IsLifted) + { return; } - if (inst.Right.MatchLdNull()) { - if (inst.Kind == ComparisonKind.GreaterThan) { + if (inst.Right.MatchLdNull()) + { + if (inst.Kind == ComparisonKind.GreaterThan) + { context.Step("comp(left > ldnull) => comp(left != ldnull)", inst); inst.Kind = ComparisonKind.Inequality; - } else if (inst.Kind == ComparisonKind.LessThanOrEqual) { + } + else if (inst.Kind == ComparisonKind.LessThanOrEqual) + { context.Step("comp(left <= ldnull) => comp(left == ldnull)", inst); inst.Kind = ComparisonKind.Equality; } - } else if (inst.Left.MatchLdNull()) { - if (inst.Kind == ComparisonKind.LessThan) { + } + else if (inst.Left.MatchLdNull()) + { + if (inst.Kind == ComparisonKind.LessThan) + { context.Step("comp(ldnull < right) => comp(ldnull != right)", inst); inst.Kind = ComparisonKind.Inequality; - } else if (inst.Kind == ComparisonKind.GreaterThanOrEqual) { + } + else if (inst.Kind == ComparisonKind.GreaterThanOrEqual) + { context.Step("comp(ldnull >= right) => comp(ldnull == right)", inst); inst.Kind = ComparisonKind.Equality; } @@ -127,20 +144,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms var rightWithoutConv = inst.Right.UnwrapConv(ConversionKind.SignExtend).UnwrapConv(ConversionKind.ZeroExtend); if (rightWithoutConv.MatchLdcI4(0) && inst.Sign == Sign.Unsigned - && (inst.Kind == ComparisonKind.GreaterThan || inst.Kind == ComparisonKind.LessThanOrEqual)) { - if (inst.Kind == ComparisonKind.GreaterThan) { + && (inst.Kind == ComparisonKind.GreaterThan || inst.Kind == ComparisonKind.LessThanOrEqual)) + { + if (inst.Kind == ComparisonKind.GreaterThan) + { context.Step("comp.unsigned(left > ldc.i4 0) => comp(left != ldc.i4 0)", inst); inst.Kind = ComparisonKind.Inequality; VisitComp(inst); return; - } else if (inst.Kind == ComparisonKind.LessThanOrEqual) { + } + else if (inst.Kind == ComparisonKind.LessThanOrEqual) + { context.Step("comp.unsigned(left <= ldc.i4 0) => comp(left == ldc.i4 0)", inst); inst.Kind = ComparisonKind.Equality; VisitComp(inst); return; } - } else if (rightWithoutConv.MatchLdcI4(0) && inst.Kind.IsEqualityOrInequality()) { - if (inst.Left.MatchLdLen(StackType.I, out ILInstruction array)) { + } + else if (rightWithoutConv.MatchLdcI4(0) && inst.Kind.IsEqualityOrInequality()) + { + if (inst.Left.MatchLdLen(StackType.I, out ILInstruction array)) + { // comp.unsigned(ldlen array == conv i4->i(ldc.i4 0)) // => comp(ldlen.i4 array == ldc.i4 0) // This is a special case where the C# compiler doesn't generate conv.i4 after ldlen. @@ -148,7 +172,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms inst.InputType = StackType.I4; inst.Left.ReplaceWith(new LdLen(StackType.I4, array).WithILRange(inst.Left)); inst.Right = rightWithoutConv; - } else if (inst.Left is Conv conv && conv.TargetType == PrimitiveType.I && conv.Argument.ResultType == StackType.O) { + } + else if (inst.Left is Conv conv && conv.TargetType == PrimitiveType.I && conv.Argument.ResultType == StackType.O) + { // C++/CLI sometimes uses this weird comparison with null: context.Step("comp(conv o->i (ldloc obj) == conv i4->i (ldc.i4 0))", inst); // -> comp(ldloc obj == ldnull) @@ -159,12 +185,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } - if (inst.Right.MatchLdNull() && inst.Left.MatchBox(out arg, out var type) && type.Kind == TypeKind.TypeParameter) { - if (inst.Kind == ComparisonKind.Equality) { + if (inst.Right.MatchLdNull() && inst.Left.MatchBox(out arg, out var type) && type.Kind == TypeKind.TypeParameter) + { + if (inst.Kind == ComparisonKind.Equality) + { context.Step("comp(box T(..) == ldnull) -> comp(.. == ldnull)", inst); inst.Left = arg; } - if (inst.Kind == ComparisonKind.Inequality) { + if (inst.Kind == ComparisonKind.Inequality) + { context.Step("comp(box T(..) != ldnull) -> comp(.. != ldnull)", inst); inst.Left = arg; } @@ -175,14 +204,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms { inst.Argument.AcceptVisitor(this); if (inst.Argument.MatchLdLen(StackType.I, out ILInstruction array) && inst.TargetType.IsIntegerType() - && (!inst.CheckForOverflow || context.Settings.AssumeArrayLengthFitsIntoInt32)) { + && (!inst.CheckForOverflow || context.Settings.AssumeArrayLengthFitsIntoInt32)) + { context.Step("conv.i4(ldlen array) => ldlen.i4(array)", inst); inst.AddILRange(inst.Argument); inst.ReplaceWith(new LdLen(inst.TargetType.GetStackType(), array).WithILRange(inst)); return; } if (inst.TargetType.IsFloatType() && inst.Argument is Conv conv - && conv.Kind == ConversionKind.IntToFloat && conv.TargetType == PrimitiveType.R) { + && conv.Kind == ConversionKind.IntToFloat && conv.TargetType == PrimitiveType.R) + { // IL conv.r.un does not indicate whether to convert the target type to R4 or R8, // so the C# compiler usually follows it with an explicit conv.r4 or conv.r8. // To avoid emitting '(float)(double)val', we combine these two conversions: @@ -195,7 +226,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitBox(Box inst) { inst.Argument.AcceptVisitor(this); - if (inst.Type.IsReferenceType == true && inst.Argument.ResultType == inst.ResultType) { + if (inst.Type.IsReferenceType == true && inst.Argument.ResultType == inst.ResultType) + { // For reference types, box is a no-op. context.Step("box ref-type(arg) => arg", inst); inst.Argument.AddILRange(inst); @@ -219,11 +251,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms void CleanUpArrayIndices(InstructionCollection indices) { - foreach (ILInstruction index in indices) { + foreach (ILInstruction index in indices) + { if (index is Conv conv && conv.ResultType == StackType.I && (conv.Kind == ConversionKind.Truncate && conv.CheckForOverflow || conv.Kind == ConversionKind.ZeroExtend || conv.Kind == ConversionKind.SignExtend) - ) { + ) + { context.Step("Remove conv.i from array index", index); index.ReplaceWith(conv.Argument); } @@ -233,15 +267,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms void VisitLogicNot(Comp inst, ILInstruction arg) { ILInstruction lhs, rhs; - if (arg is Comp comp) { - if ((!comp.InputType.IsFloatType() && !comp.IsLifted) || comp.Kind.IsEqualityOrInequality()) { + if (arg is Comp comp) + { + if ((!comp.InputType.IsFloatType() && !comp.IsLifted) || comp.Kind.IsEqualityOrInequality()) + { context.Step("push negation into comparison", inst); comp.Kind = comp.Kind.Negate(); comp.AddILRange(inst); inst.ReplaceWith(comp); } comp.AcceptVisitor(this); - } else if (arg.MatchLogicAnd(out lhs, out rhs)) { + } + else if (arg.MatchLogicAnd(out lhs, out rhs)) + { // logic.not(if (lhs) rhs else ldc.i4 0) // ==> if (logic.not(lhs)) ldc.i4 1 else logic.not(rhs) context.Step("push negation into logic.and", inst); @@ -253,7 +291,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms ifInst.FalseInst = Comp.LogicNot(rhs).WithILRange(inst); inst.ReplaceWith(ifInst); ifInst.AcceptVisitor(this); - } else if (arg.MatchLogicOr(out lhs, out rhs)) { + } + else if (arg.MatchLogicOr(out lhs, out rhs)) + { // logic.not(if (lhs) ldc.i4 1 else rhs) // ==> if (logic.not(lhs)) logic.not(rhs) else ldc.i4 0) context.Step("push negation into logic.or", inst); @@ -265,7 +305,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms ifInst.FalseInst = new LdcI4(0).WithILRange(ldc1); inst.ReplaceWith(ifInst); ifInst.AcceptVisitor(this); - } else { + } + else + { arg.AcceptVisitor(this); } } @@ -273,10 +315,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitCall(Call inst) { var expr = EarlyExpressionTransforms.HandleCall(inst, context); - if (expr != null) { + if (expr != null) + { // The resulting expression may trigger further rules, so continue visiting the replacement: expr.AcceptVisitor(this); - } else { + } + else + { base.VisitCall(inst); TransformAssignment.HandleCompoundAssign(inst, context); } @@ -290,19 +335,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitNewObj(NewObj inst) { - if (TransformDecimalCtorToConstant(inst, out LdcDecimal decimalConstant)) { + if (TransformDecimalCtorToConstant(inst, out LdcDecimal decimalConstant)) + { context.Step("TransformDecimalCtorToConstant", inst); inst.ReplaceWith(decimalConstant); return; } Block block; - if (TransformSpanTCtorContainingStackAlloc(inst, out ILInstruction locallocSpan)) { + if (TransformSpanTCtorContainingStackAlloc(inst, out ILInstruction locallocSpan)) + { context.Step("new Span(stackalloc) -> stackalloc Span", inst); inst.ReplaceWith(locallocSpan); block = null; ILInstruction stmt = locallocSpan; - while (stmt.Parent != null) { - if (stmt.Parent is Block b) { + while (stmt.Parent != null) + { + if (stmt.Parent is Block b) + { block = b; break; } @@ -313,12 +362,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInlining.InlineIfPossible(block, stmt.ChildIndex, context); return; } - if (TransformArrayInitializers.TransformSpanTArrayInitialization(inst, context, out block)) { + if (TransformArrayInitializers.TransformSpanTArrayInitialization(inst, context, out block)) + { context.Step("TransformSpanTArrayInitialization: single-dim", inst); inst.ReplaceWith(block); return; } - if (TransformDelegateCtorLdVirtFtnToLdVirtDelegate(inst, out LdVirtDelegate ldVirtDelegate)) { + if (TransformDelegateCtorLdVirtFtnToLdVirtDelegate(inst, out LdVirtDelegate ldVirtDelegate)) + { context.Step("new Delegate(target, ldvirtftn Method) -> ldvirtdelegate Delegate Method(target)", inst); inst.ReplaceWith(ldVirtDelegate); return; @@ -377,24 +428,28 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (newObj.Arguments.Count != 2 || type.TypeArguments.Count != 1) return false; IType elementType = type.TypeArguments[0]; - if (newObj.Arguments[0].MatchLocAlloc(out var sizeInBytes) && MatchesElementCount(sizeInBytes, elementType, newObj.Arguments[1])) { + if (newObj.Arguments[0].MatchLocAlloc(out var sizeInBytes) && MatchesElementCount(sizeInBytes, elementType, newObj.Arguments[1])) + { locallocSpan = new LocAllocSpan(newObj.Arguments[1], type); return true; } - if (newObj.Arguments[0] is Block initializer && initializer.Kind == BlockKind.StackAllocInitializer) { + if (newObj.Arguments[0] is Block initializer && initializer.Kind == BlockKind.StackAllocInitializer) + { if (!initializer.Instructions[0].MatchStLoc(out var initializerVariable, out var value)) return false; if (!(value.MatchLocAlloc(out sizeInBytes) && MatchesElementCount(sizeInBytes, elementType, newObj.Arguments[1]))) return false; var newVariable = initializerVariable.Function.RegisterVariable(VariableKind.InitializerTarget, type); - foreach (var load in initializerVariable.LoadInstructions.ToArray()) { + foreach (var load in initializerVariable.LoadInstructions.ToArray()) + { ILInstruction newInst = new LdLoc(newVariable); newInst.AddILRange(load); if (load.Parent != initializer) newInst = new Conv(newInst, PrimitiveType.I, false, Sign.None); load.ReplaceWith(newInst); } - foreach (var store in initializerVariable.StoreInstructions.ToArray()) { + foreach (var store in initializerVariable.StoreInstructions.ToArray()) + { store.Variable = newVariable; } value.ReplaceWith(new LocAllocSpan(newObj.Arguments[1], type)); @@ -420,17 +475,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!t.IsKnownType(KnownTypeCode.Decimal)) return false; var args = inst.Arguments; - if (args.Count == 1) { + if (args.Count == 1) + { int val; - if (args[0].MatchLdcI4(out val)) { + if (args[0].MatchLdcI4(out val)) + { result = new LdcDecimal(val); return true; } - } else if (args.Count == 5) { + } + else if (args.Count == 5) + { int lo, mid, hi, isNegative, scale; if (args[0].MatchLdcI4(out lo) && args[1].MatchLdcI4(out mid) && args[2].MatchLdcI4(out hi) && args[3].MatchLdcI4(out isNegative) && - args[4].MatchLdcI4(out scale)) { + args[4].MatchLdcI4(out scale)) + { result = new LdcDecimal(new decimal(lo, mid, hi, isNegative != 0, (byte)scale)); return true; } @@ -440,16 +500,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool TransformDecimalFieldToConstant(LdObj inst, out LdcDecimal result) { - if (inst.MatchLdsFld(out var field) && field.DeclaringType.IsKnownType(KnownTypeCode.Decimal)) { + if (inst.MatchLdsFld(out var field) && field.DeclaringType.IsKnownType(KnownTypeCode.Decimal)) + { decimal? value = null; - if (field.Name == "One") { + if (field.Name == "One") + { value = decimal.One; - } else if (field.Name == "MinusOne") { + } + else if (field.Name == "MinusOne") + { value = decimal.MinusOne; - } else if (field.Name == "Zero") { + } + else if (field.Name == "Zero") + { value = decimal.Zero; } - if (value != null) { + if (value != null) + { result = new LdcDecimal(value.Value).WithILRange(inst).WithILRange(inst.Target); return true; } @@ -464,7 +531,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms EarlyExpressionTransforms.AddressOfLdLocToLdLoca(inst, context); if (EarlyExpressionTransforms.LdObjToLdLoc(inst, context)) return; - if (TransformDecimalFieldToConstant(inst, out LdcDecimal decimalConstant)) { + if (TransformDecimalFieldToConstant(inst, out LdcDecimal decimalConstant)) + { context.Step("TransformDecimalFieldToConstant", inst); inst.ReplaceWith(decimalConstant); return; @@ -474,7 +542,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitStObj(StObj inst) { base.VisitStObj(inst); - if (EarlyExpressionTransforms.StObjToStLoc(inst, context)) { + if (EarlyExpressionTransforms.StObjToStLoc(inst, context)) + { context.RequestRerun(); return; } @@ -499,7 +568,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // Be careful: when both LHS and RHS are the constant 1, we must not // swap the arguments as it would lead to an infinite transform loop. if (inst.TrueInst.MatchLdcI4(0) && !inst.FalseInst.MatchLdcI4(0) - || inst.FalseInst.MatchLdcI4(1) && !inst.TrueInst.MatchLdcI4(1)) { + || inst.FalseInst.MatchLdcI4(1) && !inst.TrueInst.MatchLdcI4(1)) + { context.Step("canonicalize logic and/or", inst); var t = inst.TrueInst; inst.TrueInst = inst.FalseInst; @@ -514,12 +584,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (TransformDynamicAddAssignOrRemoveAssign(inst)) return; - if (inst.MatchIfInstructionPositiveCondition(out var condition, out var trueInst, out var falseInst)) { + if (inst.MatchIfInstructionPositiveCondition(out var condition, out var trueInst, out var falseInst)) + { ILInstruction transformed = UserDefinedLogicTransform.Transform(condition, trueInst, falseInst); - if (transformed == null) { + if (transformed == null) + { transformed = UserDefinedLogicTransform.TransformDynamic(condition, trueInst, falseInst); } - if (transformed != null) { + if (transformed != null) + { context.Step("User-defined short-circuiting logic operator (roslyn pattern)", condition); transformed.AddILRange(inst); inst.ReplaceWith(transformed); @@ -539,7 +612,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return inst; ILVariable v; ILInstruction value1, value2; - if (trueInst.Instructions[0].MatchStLoc(out v, out value1) && falseInst.Instructions[0].MatchStLoc(v, out value2)) { + if (trueInst.Instructions[0].MatchStLoc(out v, out value1) && falseInst.Instructions[0].MatchStLoc(v, out value2)) + { context.Step("conditional operator", inst); var newIf = new IfInstruction(Comp.LogicNot(inst.Condition), value2, value1); newIf.AddILRange(inst); @@ -560,8 +634,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms StackType resultType = StackType.Void; BlockContainer leaveTarget = null; ILVariable resultVariable = null; - foreach (var section in switchInst.Sections) { - if (section != defaultSection) { + foreach (var section in switchInst.Sections) + { + if (section != defaultSection) + { // every section except for the default must have exactly 1 label if (section.Labels.Count() != (section.HasNullLabel ? 0u : 1u)) return; @@ -572,19 +648,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; if (sectionBlock.Parent != container) return; - if (sectionBlock.Instructions.Count == 1) { - if (sectionBlock.Instructions[0] is Throw) { + if (sectionBlock.Instructions.Count == 1) + { + if (sectionBlock.Instructions[0] is Throw) + { // OK - } else if (sectionBlock.Instructions[0] is Leave leave) { + } + else if (sectionBlock.Instructions[0] is Leave leave) + { if (!leave.IsLeavingFunction) return; leaveTarget ??= leave.TargetContainer; Debug.Assert(leaveTarget == leave.TargetContainer); resultType = leave.Value.ResultType; - } else { + } + else + { return; } - } else if (sectionBlock.Instructions.Count == 2) { + } + else if (sectionBlock.Instructions.Count == 2) + { if (!sectionBlock.Instructions[0].MatchStLoc(out var v, out _)) return; if (!sectionBlock.Instructions[1].MatchLeave(container)) @@ -593,17 +677,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (resultVariable != v) return; resultType = resultVariable.StackType; - } else { + } + else + { return; } } // Exactly one of resultVariable/leaveTarget must be null if ((resultVariable == null) == (leaveTarget == null)) return; - if (switchInst.Value is StringToInt str2int) { + if (switchInst.Value is StringToInt str2int) + { // validate that each integer is used for exactly one value var integersUsed = new HashSet(); - foreach ((string key, int val) in str2int.Map) { + foreach ((string key, int val) in str2int.Map) + { if (!integersUsed.Add(val)) return; } @@ -611,24 +699,36 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step("Switch Expression", switchInst); switchInst.SetResultType(resultType); - foreach (var section in switchInst.Sections) { + foreach (var section in switchInst.Sections) + { var block = ((Branch)section.Body).TargetBlock; - if (block.Instructions.Count == 1) { - if (block.Instructions[0] is Throw t) { + if (block.Instructions.Count == 1) + { + if (block.Instructions[0] is Throw t) + { t.resultType = resultType; section.Body = t; - } else if (block.Instructions[0] is Leave leave) { + } + else if (block.Instructions[0] is Leave leave) + { section.Body = leave.Value; - } else { + } + else + { throw new InvalidOperationException(); } - } else { + } + else + { section.Body = ((StLoc)block.Instructions[0]).Value; } } - if (resultVariable != null) { + if (resultVariable != null) + { container.ReplaceWith(new StLoc(resultVariable, switchInst)); - } else { + } + else + { container.ReplaceWith(new Leave(leaveTarget, switchInst)); } context.RequestRerun(); // new StLoc might trigger inlining @@ -664,7 +764,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!(invokeMember.BinderFlags.HasFlag(CSharpBinderFlags.InvokeSpecialName) && invokeMember.BinderFlags.HasFlag(CSharpBinderFlags.ResultDiscarded))) return false; - switch (dynamicCompoundAssign.Operation) { + switch (dynamicCompoundAssign.Operation) + { case ExpressionType.AddAssign: if (invokeMember.Name != "add_" + getMember.Name) return false; @@ -732,7 +833,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (inst.Arguments.Count != dynamicGetIndex.Arguments.Count + 1) return; // Ensure that same arguments are passed to dynamicGetIndex and inst: - for (int j = 0; j < dynamicGetIndex.Arguments.Count; j++) { + for (int j = 0; j < dynamicGetIndex.Arguments.Count; j++) + { if (!SemanticHelper.IsPure(dynamicGetIndex.Arguments[j].Flags)) return; if (!dynamicGetIndex.Arguments[j].Match(inst.Arguments[j]).Success) @@ -747,11 +849,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitBinaryNumericInstruction(BinaryNumericInstruction inst) { base.VisitBinaryNumericInstruction(inst); - switch (inst.Operator) { + switch (inst.Operator) + { case BinaryNumericOperator.ShiftLeft: case BinaryNumericOperator.ShiftRight: if (inst.Right.MatchBinaryNumericInstruction(BinaryNumericOperator.BitAnd, out var lhs, out var rhs) - && rhs.MatchLdcI4(inst.ResultType == StackType.I8 ? 63 : 31)) { + && rhs.MatchLdcI4(inst.ResultType == StackType.I8 ? 63 : 31)) + { // a << (b & 31) => a << b context.Step("Combine bit.and into shift", inst); inst.Right = lhs; @@ -759,8 +863,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms break; case BinaryNumericOperator.BitAnd: if (inst.Left.InferType(context.TypeSystem).IsKnownType(KnownTypeCode.Boolean) - && inst.Right.InferType(context.TypeSystem).IsKnownType(KnownTypeCode.Boolean)) { - if (new NullableLiftingTransform(context).Run(inst)) { + && inst.Right.InferType(context.TypeSystem).IsKnownType(KnownTypeCode.Boolean)) + { + if (new NullableLiftingTransform(context).Run(inst)) + { // e.g. "(a.GetValueOrDefault() == b.GetValueOrDefault()) & (a.HasValue & b.HasValue)" } } @@ -771,7 +877,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitTryCatchHandler(TryCatchHandler inst) { base.VisitTryCatchHandler(inst); - if (inst.Filter is BlockContainer filterContainer && filterContainer.Blocks.Count == 1) { + if (inst.Filter is BlockContainer filterContainer && filterContainer.Blocks.Count == 1) + { TransformCatchWhen(inst, filterContainer.EntryPoint); } if (inst.Body is BlockContainer catchContainer) @@ -796,11 +903,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (!handler.Variable.IsSingleDefinition || handler.Variable.LoadCount != 1) return; // handle.Variable already has non-trivial uses - if (!entryPoint.Instructions[0].MatchStLoc(out var exceptionVar, out var exceptionSlotLoad)) { + if (!entryPoint.Instructions[0].MatchStLoc(out var exceptionVar, out var exceptionSlotLoad)) + { // Not the pattern with a second exceptionVar. // However, it is still possible that we need to remove a pointless UnboxAny: - if (handler.Variable.LoadInstructions.Single().Parent is UnboxAny inlinedUnboxAny) { - if (inlinedUnboxAny.Type.Equals(handler.Variable.Type)) { + if (handler.Variable.LoadInstructions.Single().Parent is UnboxAny inlinedUnboxAny) + { + if (inlinedUnboxAny.Type.Equals(handler.Variable.Type)) + { context.Step("TransformCatchVariable - remove inlined UnboxAny", inlinedUnboxAny); inlinedUnboxAny.ReplaceWith(inlinedUnboxAny.Argument); foreach (var range in inlinedUnboxAny.ILRanges) @@ -811,7 +921,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms } if (exceptionVar.Kind != VariableKind.Local && exceptionVar.Kind != VariableKind.StackSlot) return; - if (exceptionSlotLoad is UnboxAny unboxAny) { + if (exceptionSlotLoad is UnboxAny unboxAny) + { // When catching a type parameter, csc emits an unbox.any instruction if (!unboxAny.Type.Equals(handler.Variable.Type)) return; @@ -823,7 +934,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var allUses = exceptionVar.LoadInstructions .Concat(exceptionVar.StoreInstructions.Cast()) .Concat(exceptionVar.AddressInstructions); - foreach (var inst in allUses) { + foreach (var inst in allUses) + { if (!inst.IsDescendantOf(handler)) return; } @@ -831,7 +943,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms exceptionVar.Kind = VariableKind.ExceptionLocal; exceptionVar.Type = handler.Variable.Type; handler.Variable = exceptionVar; - if (isCatchBlock) { + if (isCatchBlock) + { foreach (var offset in entryPoint.Instructions[0].Descendants.SelectMany(o => o.ILRanges)) handler.AddExceptionSpecifierILRange(offset); } @@ -844,7 +957,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms void TransformCatchWhen(TryCatchHandler handler, Block entryPoint) { TransformCatchVariable(handler, entryPoint, isCatchBlock: false); - if (entryPoint.Instructions.Count == 1 && entryPoint.Instructions[0].MatchLeave(out _, out var condition)) { + if (entryPoint.Instructions.Count == 1 && entryPoint.Instructions[0].MatchLeave(out _, out var condition)) + { context.Step("TransformCatchWhen", entryPoint.Instructions[0]); handler.Filter = condition; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs b/ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs index 6d5367e75..f70f3e972 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp; namespace ICSharpCode.Decompiler.IL.Transforms @@ -33,26 +34,33 @@ namespace ICSharpCode.Decompiler.IL.Transforms void IILTransform.Run(ILFunction function, ILTransformContext context) { var instructionsToFix = new List(); - foreach (var isInst in function.Descendants.OfType()) { - if (isInst.Type.IsReferenceType == true) { + foreach (var isInst in function.Descendants.OfType()) + { + if (isInst.Type.IsReferenceType == true) + { continue; // reference-type isinst is always supported } - if (SemanticHelper.IsPure(isInst.Argument.Flags)) { + if (SemanticHelper.IsPure(isInst.Argument.Flags)) + { continue; // emulated via "expr is T ? (T)expr : null" } - if (isInst.Parent is UnboxAny unboxAny && ExpressionBuilder.IsUnboxAnyWithIsInst(unboxAny, isInst)) { + if (isInst.Parent is UnboxAny unboxAny && ExpressionBuilder.IsUnboxAnyWithIsInst(unboxAny, isInst)) + { continue; // supported pattern "expr as T?" } - if (isInst.Parent.MatchCompEqualsNull(out _) || isInst.Parent.MatchCompNotEqualsNull(out _)) { + if (isInst.Parent.MatchCompEqualsNull(out _) || isInst.Parent.MatchCompNotEqualsNull(out _)) + { continue; // supported pattern "expr is T" } - if (isInst.Parent is Block { Kind: BlockKind.ControlFlow }) { + if (isInst.Parent is Block { Kind: BlockKind.ControlFlow }) + { continue; // supported via StatementBuilder.VisitIsInst } instructionsToFix.Add(isInst); } // Need to delay fixing until we're done with iteration, because Extract() modifies parents - foreach (var isInst in instructionsToFix) { + foreach (var isInst in instructionsToFix) + { // Use extraction to turn isInst.Argument into a pure instruction, thus making the emulation possible context.Step("FixLoneIsInst", isInst); isInst.Argument.Extract(); diff --git a/ICSharpCode.Decompiler/IL/Transforms/FixRemainingIncrements.cs b/ICSharpCode.Decompiler/IL/Transforms/FixRemainingIncrements.cs index 59d9e345d..b79ff09c4 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/FixRemainingIncrements.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/FixRemainingIncrements.cs @@ -17,9 +17,10 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Linq; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms @@ -29,19 +30,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms void IILTransform.Run(ILFunction function, ILTransformContext context) { var callsToFix = new List(); - foreach (var call in function.Descendants.OfType()) { + foreach (var call in function.Descendants.OfType()) + { if (!(call.Method.IsOperator && (call.Method.Name == "op_Increment" || call.Method.Name == "op_Decrement"))) continue; if (call.Arguments.Count != 1) continue; - if (call.Method.DeclaringType.IsKnownType(KnownTypeCode.Decimal)) { + if (call.Method.DeclaringType.IsKnownType(KnownTypeCode.Decimal)) + { // For decimal, legacy csc can optimize "d + 1m" to "op_Increment(d)". // We can handle these calls in ReplaceMethodCallsWithOperators. continue; } callsToFix.Add(call); } - foreach (var call in callsToFix) { + foreach (var call in callsToFix) + { // A user-defined increment/decrement that was not handled by TransformAssignment. // This can happen because the variable-being-incremented was optimized out by Roslyn, // e.g. @@ -52,7 +56,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // } // can end up being compiled to: // Console.WriteLine(UserType.op_Increment(a + b)); - if (call.SlotInfo == StLoc.ValueSlot && call.Parent.SlotInfo == Block.InstructionSlot) { + if (call.SlotInfo == StLoc.ValueSlot && call.Parent.SlotInfo == Block.InstructionSlot) + { var store = (StLoc)call.Parent; var block = (Block)store.Parent; context.Step($"Fix {call.Method.Name} call at 0x{call.StartILOffset:x4} using {store.Variable.Name}", call); @@ -64,10 +69,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms block.Instructions.Insert(store.ChildIndex + 1, new UserDefinedCompoundAssign(call.Method, CompoundEvalMode.EvaluatesToNewValue, new LdLoca(store.Variable), CompoundTargetKind.Address, new LdcI4(1)).WithILRange(call)); - } else { + } + else + { context.Step($"Fix {call.Method.Name} call at 0x{call.StartILOffset:x4} using new local", call); var newVariable = call.Arguments[0].Extract(); - if (newVariable == null) { + if (newVariable == null) + { Debug.Fail("Failed to extract argument of remaining increment/decrement"); continue; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs index b119f0c62..40014772e 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.IL.ControlFlow; using ICSharpCode.Decompiler.Util; @@ -38,10 +39,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms { this.context = context; - foreach (var loop in function.Descendants.OfType()) { + foreach (var loop in function.Descendants.OfType()) + { if (loop.Kind != ContainerKind.Loop) continue; - if (MatchWhileLoop(loop, out var condition, out var loopBody)) { + if (MatchWhileLoop(loop, out var condition, out var loopBody)) + { if (context.Settings.ForStatement) MatchForLoop(loop, condition, loopBody); continue; @@ -69,20 +72,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; condition = ifInstruction; - if (!ifInstruction.TrueInst.MatchLeave(loop)) { + if (!ifInstruction.TrueInst.MatchLeave(loop)) + { // sometimes the loop-body is nested within the if // if (loop-condition) { loop-body } // leave loop-container if (loopBody.Instructions.Count != 2 || !loop.EntryPoint.Instructions.Last().MatchLeave(loop)) return false; - + if (!ifInstruction.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable)) ((Block)ifInstruction.TrueInst).Instructions.Add(new Leave(loop)); ConditionDetection.InvertIf(loopBody, ifInstruction, context); } - + context.Step("Transform to while (condition) loop: " + loop.EntryPoint.Label, loop); loop.Kind = ContainerKind.While; //invert comparison @@ -96,7 +100,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms ifInstruction.TrueInst = new Branch(loopBody); ExpressionTransforms.RunOnSingleStatement(ifInstruction, context); - + // Analyze conditions and decide whether to move some of them out of the condition block: /*var conditions = new List(); SplitConditions(condition.Condition, conditions); @@ -109,7 +113,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms ExpressionTransforms.RunOnSingleStatment(inst, context); } }*/ - + return true; } @@ -132,10 +136,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms void SplitConditions(ILInstruction expression, List conditions) { - if (expression.MatchLogicAnd(out var l, out var r)) { + if (expression.MatchLogicAnd(out var l, out var r)) + { SplitConditions(l, conditions); SplitConditions(r, conditions); - } else { + } + else + { conditions.Add(expression); } } @@ -155,7 +162,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms Block conditionBlock; // first we remove all extracted instructions from the original block. var originalBlock = (Block)exit.Parent; - if (unwrap) { + if (unwrap) + { // we found a condition block nested in a condition that is followed by a return statement: // we flip the condition and swap the blocks Debug.Assert(originalBlock.Parent is IfInstruction); @@ -175,12 +183,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms } originalBlock.Instructions.RemoveRange(originalBlock.Instructions.Count - conditions.Count - 1, conditions.Count + 1); // we need to split the block: - if (split) { + if (split) + { // add a new block at the end and add a branch to the new block. conditionBlock = new Block(); loop.Blocks.Add(conditionBlock); originalBlock.Instructions.Add(new Branch(conditionBlock)); - } else { + } + else + { // move the condition block to the end. conditionBlock = originalBlock; loop.Blocks.MoveElementToEnd(originalBlock); @@ -188,22 +199,32 @@ namespace ICSharpCode.Decompiler.IL.Transforms // combine all conditions and the exit instruction into one IfInstruction: IfInstruction condition = null; conditionBlock.AddILRange(exit); - foreach (var inst in conditions) { + foreach (var inst in conditions) + { conditionBlock.AddILRange(inst); - if (condition == null) { + if (condition == null) + { condition = inst; - if (swap) { + if (swap) + { // branches must be swapped and condition negated: condition.Condition = Comp.LogicNot(condition.Condition); condition.FalseInst = condition.TrueInst; condition.TrueInst = exit; - } else { + } + else + { condition.FalseInst = exit; } - } else { - if (swap) { + } + else + { + if (swap) + { condition.Condition = IfInstruction.LogicAnd(Comp.LogicNot(inst.Condition), condition.Condition); - } else { + } + else + { condition.Condition = IfInstruction.LogicAnd(inst.Condition, condition.Condition); } } @@ -221,9 +242,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms { // we iterate over all blocks from the bottom, because the entry-point // should only be considered as condition block, if there are no other blocks. - foreach (var block in loop.Blocks.Reverse()) { + foreach (var block in loop.Blocks.Reverse()) + { // first we match the end of the block: - if (MatchDoWhileConditionBlock(loop, block, out bool swap, out bool unwrapCondtionBlock, out Block conditionBlock)) { + if (MatchDoWhileConditionBlock(loop, block, out bool swap, out bool unwrapCondtionBlock, out Block conditionBlock)) + { // now collect all instructions that are usable as loop conditions var conditions = CollectConditions(loop, conditionBlock, swap); // split only if the block is either the entry-point or contains other instructions as well. @@ -242,16 +265,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms { var list = new List(); int i = block.Instructions.Count - 2; - while (i >= 0 && block.Instructions[i] is IfInstruction ifInst) { + while (i >= 0 && block.Instructions[i] is IfInstruction ifInst) + { if (!ifInst.FalseInst.MatchNop()) break; if (UsesVariableCapturedInLoop(loop, ifInst.Condition)) break; - if (swap) { + if (swap) + { if (!ifInst.TrueInst.MatchLeave(loop)) break; list.Add(ifInst); - } else { + } + else + { if (!ifInst.TrueInst.MatchBranch(loop.EntryPoint)) break; list.Add(ifInst); @@ -264,7 +291,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool UsesVariableCapturedInLoop(BlockContainer loop, ILInstruction condition) { - foreach (var inst in condition.Descendants.OfType()) { + foreach (var inst in condition.Descendants.OfType()) + { if (inst.Variable.CaptureScope == loop) return true; } @@ -292,7 +320,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; // the block ends in a return statement preceeded by an IfInstruction // take a look at the nested block and check if that might be a condition block - if (last.MatchReturn(out _) && ifInstruction.TrueInst is Block nestedConditionBlock) { + if (last.MatchReturn(out _) && ifInstruction.TrueInst is Block nestedConditionBlock) + { if (nestedConditionBlock.Instructions.Count < 2) return false; last = nestedConditionBlock.Instructions.Last(); @@ -308,12 +337,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms swapBranches = true; else if (last.MatchLeave(loop)) swapBranches = false; - else return false; + else + return false; // match the IfInstruction - if (swapBranches) { + if (swapBranches) + { if (!ifInstruction.TrueInst.MatchLeave(loop)) return false; - } else { + } + else + { if (!ifInstruction.TrueInst.MatchBranch(loop.EntryPoint)) return false; } @@ -332,16 +365,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; return (ifInstruction.TrueInst.MatchBranch(out target1) || ifInstruction.TrueInst.MatchReturn(out var _)) && - (last.MatchBranch(out target2) || last.MatchReturn(out var _)); + (last.MatchBranch(out target2) || last.MatchReturn(out var _)); } - internal static Block GetIncrementBlock(BlockContainer loop, Block whileLoopBody) => + internal static Block GetIncrementBlock(BlockContainer loop, Block whileLoopBody) => loop.Blocks.SingleOrDefault(b => b != whileLoopBody - && b.Instructions.Last().MatchBranch(loop.EntryPoint) - && b.Instructions.SkipLast(1).All(IsSimpleStatement)); + && b.Instructions.Last().MatchBranch(loop.EntryPoint) + && b.Instructions.SkipLast(1).All(IsSimpleStatement)); internal static bool MatchIncrementBlock(Block block, out Block loopHead) => - block.Instructions.Last().MatchBranch(out loopHead) + block.Instructions.Last().MatchBranch(out loopHead) && block.Instructions.SkipLast(1).All(IsSimpleStatement); bool MatchForLoop(BlockContainer loop, IfInstruction whileCondition, Block whileLoopBody) @@ -352,7 +385,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // try to find an increment block: // consists of simple statements only. var incrementBlock = GetIncrementBlock(loop, whileLoopBody); - if (incrementBlock != null) { + if (incrementBlock != null) + { // we found a possible increment block, just make sure, that there are at least three blocks: // - condition block // - loop body @@ -363,7 +397,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms // move the block to the end of the loop: loop.Blocks.MoveElementToEnd(incrementBlock); loop.Kind = ContainerKind.For; - } else { + } + else + { // we need to move the increment statements into its own block: // last must be a branch entry-point var last = whileLoopBody.Instructions.LastOrDefault(); @@ -383,16 +419,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms SplitConditions(whileCondition.Condition, conditions); IfInstruction forCondition = null; int numberOfConditions = 0; - foreach (var condition in conditions) { + foreach (var condition in conditions) + { // the increment variable must be used in the condition if (!condition.Descendants.Any(inst => inst.MatchLdLoc(incrementVariable))) break; // condition should not contain an assignment if (condition.Descendants.Any(IsAssignment)) break; - if (forCondition == null) { + if (forCondition == null) + { forCondition = new IfInstruction(condition, whileCondition.TrueInst, whileCondition.FalseInst); - } else { + } + else + { forCondition.Condition = IfInstruction.LogicAnd(forCondition.Condition, condition); } numberOfConditions++; @@ -403,7 +443,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // split condition block: whileCondition.ReplaceWith(forCondition); ExpressionTransforms.RunOnSingleStatement(forCondition, context); - for (int i = conditions.Count - 1; i >= numberOfConditions; i--) { + for (int i = conditions.Count - 1; i >= numberOfConditions; i--) + { IfInstruction inst; whileLoopBody.Instructions.Insert(0, inst = new IfInstruction(Comp.LogicNot(conditions[i]), new Leave(loop))); ExpressionTransforms.RunOnSingleStatement(inst, context); @@ -439,11 +480,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// public static bool MatchIncrement(ILInstruction inst, out ILVariable variable) { - if (inst.MatchStLoc(out variable, out var value)) { - if (value.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out var left, out var right)) { + if (inst.MatchStLoc(out variable, out var value)) + { + if (value.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out var left, out var right)) + { return left.MatchLdLoc(variable); } - } else if (inst is CompoundAssignmentInstruction cai) { + } + else if (inst is CompoundAssignmentInstruction cai) + { return cai.TargetKind == CompoundTargetKind.Address && cai.Target.MatchLdLoca(out variable); } return false; @@ -455,7 +500,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// static bool IsSimpleStatement(ILInstruction inst) { - switch (inst.OpCode) { + switch (inst.OpCode) + { case OpCode.Call: case OpCode.CallVirt: case OpCode.NewObj: diff --git a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs index d6e38c103..e813ebaed 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Threading; + using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.TypeSystem; @@ -92,7 +93,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { Stepper.Step(description, near); } - + [Conditional("STEP")] internal void StepStartGroup(string description, ILInstruction near = null) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs b/ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs index 644c43a7f..ba47d4738 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs @@ -65,7 +65,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms internal void RegisterMoveIfNecessary(ILInstruction predecessor) { - if (!CanReorderWithInstructionsBeingMoved(predecessor)) { + if (!CanReorderWithInstructionsBeingMoved(predecessor)) + { RegisterMove(predecessor); } } @@ -96,16 +97,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms ExtractionContext ctx = new ExtractionContext(function); ctx.FlagsBeingMoved = instToExtract.Flags; ILInstruction inst = instToExtract; - while (inst != null) { - if (inst.Parent is IfInstruction ifInst && inst.SlotInfo != IfInstruction.ConditionSlot) { + while (inst != null) + { + if (inst.Parent is IfInstruction ifInst && inst.SlotInfo != IfInstruction.ConditionSlot) + { // this context doesn't support extraction, but maybe we can create a block here? - if (ifInst.ResultType == StackType.Void) { + if (ifInst.ResultType == StackType.Void) + { Block newBlock = new Block(); inst.ReplaceWith(newBlock); newBlock.Instructions.Add(inst); } } - if (inst.Parent is Block block && block.Kind == BlockKind.ControlFlow) { + if (inst.Parent is Block block && block.Kind == BlockKind.ControlFlow) + { // We've reached the target block, and extraction is possible all the way. int insertIndex = inst.ChildIndex; // Move instToExtract itself: @@ -113,7 +118,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms instToExtract.ReplaceWith(new LdLoc(v)); block.Instructions.Insert(insertIndex, new StLoc(v, instToExtract)); // Apply the other move actions: - foreach (var moveAction in ctx.MoveActions) { + foreach (var moveAction in ctx.MoveActions) + { block.Instructions.Insert(insertIndex, moveAction()); } return v; diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index 82225949c..6a2fe5ede 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -20,6 +20,7 @@ using System; using System.Diagnostics; using System.Linq; using System.Reflection; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -41,7 +42,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { public void Run(ILFunction function, ILTransformContext context) { - foreach (var block in function.Descendants.OfType()) { + foreach (var block in function.Descendants.OfType()) + { InlineAllInBlock(function, block, context); } function.Variables.RemoveDead(); @@ -60,9 +62,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms internal static InliningOptions OptionsForBlock(Block block, int pos, ILTransformContext context) { InliningOptions options = InliningOptions.None; - if (context.Settings.AggressiveInlining || IsCatchWhenBlock(block)) { + if (context.Settings.AggressiveInlining || IsCatchWhenBlock(block)) + { options |= InliningOptions.Aggressive; - } else { + } + else + { var function = block.Ancestors.OfType().FirstOrDefault(); var inst = block.Instructions[pos]; if (IsInConstructorInitializer(function, inst)) @@ -75,12 +80,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms { bool modified = false; var instructions = block.Instructions; - for (int i = instructions.Count - 1; i >= 0; i--) { - if (instructions[i] is StLoc inst) { + for (int i = instructions.Count - 1; i >= 0; i--) + { + if (instructions[i] is StLoc inst) + { InliningOptions options = InliningOptions.None; if (context.Settings.AggressiveInlining || IsCatchWhenBlock(block) || IsInConstructorInitializer(function, inst)) options = InliningOptions.Aggressive; - if (InlineOneIfPossible(block, i, options, context)) { + if (InlineOneIfPossible(block, i, options, context)) + { modified = true; continue; } @@ -116,7 +124,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (pos >= block.Instructions.Count) return 0; int count = 0; - while (--pos >= 0) { + while (--pos >= 0) + { if (InlineOneIfPossible(block, pos, options, context)) count++; else @@ -124,7 +133,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } return count; } - + /// /// Aggressively inlines the stloc instruction at block.Body[pos] into the next instruction, if possible. /// @@ -154,7 +163,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // return false; // stloc might perform implicit truncation return InlineOne(stloc, options, context); } - + /// /// Inlines the stloc instruction at block.Instructions[pos] into the next instruction. /// @@ -166,22 +175,28 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILVariable v = stloc.Variable; Block block = (Block)stloc.Parent; int pos = stloc.ChildIndex; - if (DoInline(v, stloc.Value, block.Instructions.ElementAtOrDefault(pos + 1), options, context)) { + if (DoInline(v, stloc.Value, block.Instructions.ElementAtOrDefault(pos + 1), options, context)) + { // Assign the ranges of the stloc instruction: stloc.Value.AddILRange(stloc); // Remove the stloc instruction: Debug.Assert(block.Instructions[pos] == stloc); block.Instructions.RemoveAt(pos); return true; - } else if (v.LoadCount == 0 && v.AddressCount == 0) { + } + else if (v.LoadCount == 0 && v.AddressCount == 0) + { // The variable is never loaded - if (SemanticHelper.IsPure(stloc.Value.Flags)) { + if (SemanticHelper.IsPure(stloc.Value.Flags)) + { // Remove completely if the instruction has no effects // (except for reading locals) context.Step("Remove dead store without side effects", stloc); block.Instructions.RemoveAt(pos); return true; - } else if (v.Kind == VariableKind.StackSlot) { + } + else if (v.Kind == VariableKind.StackSlot) + { context.Step("Remove dead store, but keep expression", stloc); // Assign the ranges of the stloc instruction: stloc.Value.AddILRange(stloc); @@ -192,7 +207,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } return false; } - + /// /// Inlines 'expr' into 'next', if possible. /// @@ -202,21 +217,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool DoInline(ILVariable v, ILInstruction inlinedExpression, ILInstruction next, InliningOptions options, ILTransformContext context) { var r = FindLoadInNext(next, v, inlinedExpression, options); - if (r.Type == FindResultType.Found || r.Type == FindResultType.NamedArgument) { + if (r.Type == FindResultType.Found || r.Type == FindResultType.NamedArgument) + { var loadInst = r.LoadInst; - if (loadInst.OpCode == OpCode.LdLoca) { + if (loadInst.OpCode == OpCode.LdLoca) + { if (!IsGeneratedValueTypeTemporary((LdLoca)loadInst, v, inlinedExpression)) return false; - } else { + } + else + { Debug.Assert(loadInst.OpCode == OpCode.LdLoc); bool aggressive = (options & InliningOptions.Aggressive) != 0; if (!aggressive && v.Kind != VariableKind.StackSlot - && !NonAggressiveInlineInto(next, r, inlinedExpression, v)) { + && !NonAggressiveInlineInto(next, r, inlinedExpression, v)) + { return false; } } - if (r.Type == FindResultType.NamedArgument) { + if (r.Type == FindResultType.NamedArgument) + { NamedArgumentTransform.IntroduceNamedArgument(r.CallArgument, context); // Now that the argument is evaluated early, we can inline as usual } @@ -224,13 +245,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step($"Inline variable '{v.Name}'", inlinedExpression); // Assign the ranges of the ldloc instruction: inlinedExpression.AddILRange(loadInst); - - if (loadInst.OpCode == OpCode.LdLoca) { + + if (loadInst.OpCode == OpCode.LdLoca) + { // it was an ldloca instruction, so we need to use the pseudo-opcode 'addressof' // to preserve the semantics of the compiler-generated temporary Debug.Assert(((LdLoca)loadInst).Variable == v); loadInst.ReplaceWith(new AddressOf(inlinedExpression, v.Type)); - } else { + } + else + { loadInst.ReplaceWith(inlinedExpression); } return true; @@ -251,8 +275,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms // Thus, we have to ensure we're operating on an r-value. // Additionally, we cannot inline in cases where the C# compiler prohibits the direct use // of the rvalue (e.g. M(ref (MyStruct)obj); is invalid). - if (IsUsedAsThisPointerInCall(loadInst, out var method)) { - switch (ClassifyExpression(inlinedExpression)) { + if (IsUsedAsThisPointerInCall(loadInst, out var method)) + { + switch (ClassifyExpression(inlinedExpression)) + { case ExpressionClassification.RValue: // For struct method calls on rvalues, the C# compiler always generates temporaries. return true; @@ -266,10 +292,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms default: throw new InvalidOperationException("invalid expression classification"); } - } else if (IsUsedAsThisPointerInFieldRead(loadInst)) { + } + else if (IsUsedAsThisPointerInFieldRead(loadInst)) + { // mcs generated temporaries for field reads on rvalues (#1555) return ClassifyExpression(inlinedExpression) == ExpressionClassification.RValue; - } else { + } + else + { return false; } } @@ -297,22 +327,28 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (ldloca.Variable.Type.IsReferenceType ?? false) return false; ILInstruction inst = ldloca; - while (inst.Parent is LdFlda ldflda) { + while (inst.Parent is LdFlda ldflda) + { inst = ldflda; } if (inst.ChildIndex != 0) return false; - switch (inst.Parent.OpCode) { + switch (inst.Parent.OpCode) + { case OpCode.Call: case OpCode.CallVirt: method = ((CallInstruction)inst.Parent).Method; - if (method.IsAccessor) { - if (method.AccessorKind == MethodSemanticsAttributes.Getter) { + if (method.IsAccessor) + { + if (method.AccessorKind == MethodSemanticsAttributes.Getter) + { // C# doesn't allow property compound assignments on temporary structs return !(inst.Parent.Parent is CompoundAssignmentInstruction cai && cai.TargetKind == CompoundTargetKind.Property && cai.Target == inst.Parent); - } else { + } + else + { // C# doesn't allow calling setters on temporary structs return false; } @@ -333,7 +369,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (ldloca.Variable.Type.IsReferenceType ?? false) return false; ILInstruction inst = ldloca; - while (inst.Parent is LdFlda ldflda) { + while (inst.Parent is LdFlda ldflda) + { inst = ldflda; } return inst != ldloca && inst.Parent is LdObj; @@ -354,36 +391,49 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// internal static ExpressionClassification ClassifyExpression(ILInstruction inst) { - switch (inst.OpCode) { + switch (inst.OpCode) + { case OpCode.LdLoc: case OpCode.StLoc: - if (((IInstructionWithVariableOperand)inst).Variable.IsRefReadOnly) { + if (((IInstructionWithVariableOperand)inst).Variable.IsRefReadOnly) + { return ExpressionClassification.ReadonlyLValue; - } else { + } + else + { return ExpressionClassification.MutableLValue; } case OpCode.LdObj: // ldobj typically refers to a storage location, // but readonly fields are an exception. - if (IsReadonlyReference(((LdObj)inst).Target)) { + if (IsReadonlyReference(((LdObj)inst).Target)) + { return ExpressionClassification.ReadonlyLValue; - } else { + } + else + { return ExpressionClassification.MutableLValue; } case OpCode.StObj: // stobj is the same as ldobj. - if (IsReadonlyReference(((StObj)inst).Target)) { + if (IsReadonlyReference(((StObj)inst).Target)) + { return ExpressionClassification.ReadonlyLValue; - } else { + } + else + { return ExpressionClassification.MutableLValue; } case OpCode.Call: var m = ((CallInstruction)inst).Method; // multi-dimensional array getters are lvalues, // everything else is an rvalue. - if (m.DeclaringType.Kind == TypeKind.Array) { + if (m.DeclaringType.Kind == TypeKind.Array) + { return ExpressionClassification.MutableLValue; - } else { + } + else + { return ExpressionClassification.RValue; } default: @@ -393,7 +443,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms internal static bool IsReadonlyReference(ILInstruction addr) { - switch (addr) { + switch (addr) + { case LdFlda ldflda: return ldflda.Field.IsReadOnly || (ldflda.Field.DeclaringType.Kind == TypeKind.Struct && IsReadonlyReference(ldflda.Target)); @@ -419,7 +470,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// The expression being inlined static bool NonAggressiveInlineInto(ILInstruction next, FindResult findResult, ILInstruction inlinedExpression, ILVariable v) { - if (findResult.Type == FindResultType.NamedArgument) { + if (findResult.Type == FindResultType.NamedArgument) + { var originalStore = (StLoc)inlinedExpression.Parent; return !originalStore.ILStackWasEmpty; } @@ -427,9 +479,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms var loadInst = findResult.LoadInst; Debug.Assert(loadInst.IsDescendantOf(next)); - + // decide based on the source expression being inlined - switch (inlinedExpression.OpCode) { + switch (inlinedExpression.OpCode) + { case OpCode.DefaultValue: case OpCode.StObj: case OpCode.NumericCompoundAssign: @@ -438,14 +491,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms case OpCode.SwitchInstruction: return true; case OpCode.LdLoc: - if (v.StateMachineField == null && ((LdLoc)inlinedExpression).Variable.StateMachineField != null) { + if (v.StateMachineField == null && ((LdLoc)inlinedExpression).Variable.StateMachineField != null) + { // Roslyn likes to put the result of fetching a state machine field into a temporary variable, // so inline more aggressively in such cases. return true; } break; } - if (inlinedExpression.ResultType == StackType.Ref) { + if (inlinedExpression.ResultType == StackType.Ref) + { // VB likes to use ref locals for compound assignment // (the C# compiler uses ref stack slots instead). // We want to avoid unnecessary ref locals, so we'll always inline them if possible. @@ -453,15 +508,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms } var parent = loadInst.Parent; - if (NullableLiftingTransform.MatchNullableCtor(parent, out _, out _)) { + if (NullableLiftingTransform.MatchNullableCtor(parent, out _, out _)) + { // inline into nullable ctor call in lifted operator parent = parent.Parent; } - if (parent is ILiftableInstruction liftable && liftable.IsLifted) { + if (parent is ILiftableInstruction liftable && liftable.IsLifted) + { return true; // inline into lifted operators } // decide based on the new parent into which we are inlining: - switch (parent.OpCode) { + switch (parent.OpCode) + { case OpCode.NullCoalescingInstruction: if (NullableType.IsNullable(v.Type)) return true; // inline nullables into ?? operator @@ -485,15 +543,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms case OpCode.CallVirt: // Aggressive inline into property/indexer getter calls for compound assignment calls // (The compiler generates locals for these because it doesn't want to evalute the args twice for getter+setter) - if (parent.SlotInfo == CompoundAssignmentInstruction.TargetSlot) { + if (parent.SlotInfo == CompoundAssignmentInstruction.TargetSlot) + { return true; } - if (((CallInstruction)parent).Method is SyntheticRangeIndexAccessor) { + if (((CallInstruction)parent).Method is SyntheticRangeIndexAccessor) + { return true; } break; case OpCode.LdElema: - if (((LdElema)parent).WithSystemIndex) { + if (((LdElema)parent).WithSystemIndex) + { return true; } break; @@ -508,9 +569,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; } // decide based on the top-level target instruction into which we are inlining: - switch (next.OpCode) { + switch (next.OpCode) + { case OpCode.IfInstruction: - while (parent.MatchLogicNot(out _)) { + while (parent.MatchLogicNot(out _)) + { parent = parent.Parent; } return parent == next; @@ -518,7 +581,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; } } - + /// /// Gets whether 'expressionBeingMoved' can be inlined into 'expr'. /// @@ -599,16 +662,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (expr == null) return FindResult.Stop; - if (expr.MatchLdLoc(v) || expr.MatchLdLoca(v)) { + if (expr.MatchLdLoc(v) || expr.MatchLdLoca(v)) + { // Match found, we can inline - if (expr.SlotInfo == StObj.TargetSlot && !((StObj)expr.Parent).CanInlineIntoTargetSlot(expressionBeingMoved)) { + if (expr.SlotInfo == StObj.TargetSlot && !((StObj)expr.Parent).CanInlineIntoTargetSlot(expressionBeingMoved)) + { // special case: the StObj.TargetSlot does not accept some kinds of expressions return FindResult.Stop; } return FindResult.Found(expr); - } else if (expr is Block block) { + } + else if (expr is Block block) + { // Inlining into inline-blocks? - switch (block.Kind) { + switch (block.Kind) + { case BlockKind.ControlFlow when block.Parent is BlockContainer: case BlockKind.ArrayInitializer: case BlockKind.CollectionInitializer: @@ -618,23 +686,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (block.Instructions.Count == 0) return FindResult.Stop; return NoContinue(FindLoadInNext(block.Instructions[0], v, expressionBeingMoved, options)); - // If FindLoadInNext() returns null, we still can't continue searching - // because we can't inline over the remainder of the block. + // If FindLoadInNext() returns null, we still can't continue searching + // because we can't inline over the remainder of the block. case BlockKind.CallWithNamedArgs: return NamedArgumentTransform.CanExtendNamedArgument(block, v, expressionBeingMoved); default: return FindResult.Stop; } - } else if (options.HasFlag(InliningOptions.FindDeconstruction) && expr is DeconstructInstruction di) { + } + else if (options.HasFlag(InliningOptions.FindDeconstruction) && expr is DeconstructInstruction di) + { return FindResult.Deconstruction(di); } - foreach (var child in expr.Children) { + foreach (var child in expr.Children) + { if (!expr.CanInlineIntoSlot(child.ChildIndex, expressionBeingMoved)) return FindResult.Stop; - + // Recursively try to find the load instruction FindResult r = FindLoadInNext(child, v, expressionBeingMoved, options); - if (r.Type != FindResultType.Continue) { + if (r.Type != FindResultType.Continue) + { if (r.Type == FindResultType.Stop && (options & InliningOptions.IntroduceNamedArguments) != 0 && expr is CallInstruction call) return NamedArgumentTransform.CanIntroduceNamedArgument(call, child, v, expressionBeingMoved); return r; @@ -667,11 +739,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// internal static CallInstruction FindFirstInlinedCall(ILInstruction inst) { - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { if (!child.SlotInfo.CanInlineInto) break; var call = FindFirstInlinedCall(child); - if (call != null) { + if (call != null) + { return call; } } @@ -684,12 +758,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms public static bool CanMoveInto(ILInstruction expressionBeingMoved, ILInstruction stmt, ILInstruction targetLoad) { Debug.Assert(targetLoad.IsDescendantOf(stmt)); - for (ILInstruction inst = targetLoad; inst != stmt; inst = inst.Parent) { + for (ILInstruction inst = targetLoad; inst != stmt; inst = inst.Parent) + { if (!inst.Parent.CanInlineIntoSlot(inst.ChildIndex, expressionBeingMoved)) return false; // Check whether re-ordering with predecessors is valid: int childIndex = inst.ChildIndex; - for (int i = 0; i < childIndex; ++i) { + for (int i = 0; i < childIndex; ++i) + { ILInstruction predecessor = inst.Parent.Children[i]; if (!IsSafeForInlineOver(predecessor, expressionBeingMoved)) return false; diff --git a/ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs index 651113ce6..5d32d344d 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IndexRangeTransform.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -42,7 +43,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (ldelema.Indices.Count != 1) return false; // the index/range feature doesn't support multi-dimensional arrays var index = ldelema.Indices[0]; - if (index is CallInstruction call && call.Method.Name == "GetOffset" && call.Method.DeclaringType.IsKnownType(KnownTypeCode.Index)) { + if (index is CallInstruction call && call.Method.Name == "GetOffset" && call.Method.DeclaringType.IsKnownType(KnownTypeCode.Index)) + { // ldelema T(ldloc array, call GetOffset(..., ldlen.i4(ldloc array))) // -> withsystemindex.ldelema T(ldloc array, ...) if (call.Arguments.Count != 2) @@ -57,7 +59,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms // The method call had a `ref System.Index` argument for the this pointer, but we want a `System.Index` by-value. ldelema.Indices[0] = new LdObj(call.Arguments[0], call.Method.DeclaringType); return true; - } else if (index is BinaryNumericInstruction bni && bni.Operator == BinaryNumericOperator.Sub && !bni.IsLifted && !bni.CheckForOverflow) { + } + else if (index is BinaryNumericInstruction bni && bni.Operator == BinaryNumericOperator.Sub && !bni.IsLifted && !bni.CheckForOverflow) + { // ldelema T(ldloc array, binary.sub.i4(ldlen.i4(ldloc array), ...)) // -> withsystemindex.ldelema T(ldloc array, newobj System.Index(..., fromEnd: true)) if (!(bni.Left.MatchLdLen(StackType.I4, out var arrayLoad) && arrayLoad.MatchLdLoc(array))) @@ -93,33 +97,42 @@ namespace ICSharpCode.Decompiler.IL.Transforms public IndexMethods(ICompilation compilation) { var indexType = compilation.FindType(KnownTypeCode.Index); - foreach (var ctor in indexType.GetConstructors(m => m.Parameters.Count == 2)) { + foreach (var ctor in indexType.GetConstructors(m => m.Parameters.Count == 2)) + { if (ctor.Parameters[0].Type.IsKnownType(KnownTypeCode.Int32) - && ctor.Parameters[1].Type.IsKnownType(KnownTypeCode.Boolean)) { + && ctor.Parameters[1].Type.IsKnownType(KnownTypeCode.Boolean)) + { this.IndexCtor = ctor; } } - foreach (var op in indexType.GetMethods(m => m.IsOperator && m.Name == "op_Implicit")) { - if (op.Parameters.Count == 1 && op.Parameters[0].Type.IsKnownType(KnownTypeCode.Int32)) { + foreach (var op in indexType.GetMethods(m => m.IsOperator && m.Name == "op_Implicit")) + { + if (op.Parameters.Count == 1 && op.Parameters[0].Type.IsKnownType(KnownTypeCode.Int32)) + { this.IndexImplicitConv = op; } } var rangeType = compilation.FindType(KnownTypeCode.Range); - foreach (var ctor in rangeType.GetConstructors(m => m.Parameters.Count == 2)) { + foreach (var ctor in rangeType.GetConstructors(m => m.Parameters.Count == 2)) + { if (ctor.Parameters[0].Type.IsKnownType(KnownTypeCode.Index) - && ctor.Parameters[1].Type.IsKnownType(KnownTypeCode.Index)) { + && ctor.Parameters[1].Type.IsKnownType(KnownTypeCode.Index)) + { this.RangeCtor = ctor; } } - foreach (var m in rangeType.GetMethods(m => m.Parameters.Count == 1)) { - if (m.Parameters.Count == 1 && m.Parameters[0].Type.IsKnownType(KnownTypeCode.Index)) { + foreach (var m in rangeType.GetMethods(m => m.Parameters.Count == 1)) + { + if (m.Parameters.Count == 1 && m.Parameters[0].Type.IsKnownType(KnownTypeCode.Index)) + { if (m.Name == "StartAt") this.RangeStartAt = m; else if (m.Name == "EndAt") this.RangeEndAt = m; } } - foreach (var p in rangeType.GetProperties(p => p.IsStatic && p.Name == "All")) { + foreach (var p in rangeType.GetProperties(p => p.IsStatic && p.Name == "All")) + { this.RangeGetAll = p.Getter; } } @@ -140,24 +153,31 @@ namespace ICSharpCode.Decompiler.IL.Transforms int startPos = pos; ILVariable containerVar = null; // The container length access may be a separate instruction, or it may be inline with the variable's use - if (MatchContainerLengthStore(block.Instructions[pos], out ILVariable containerLengthVar, ref containerVar)) { + if (MatchContainerLengthStore(block.Instructions[pos], out ILVariable containerLengthVar, ref containerVar)) + { // stloc containerLengthVar(call get_Length/get_Count(ldloc container)) pos++; - } else { + } + else + { // Reset if MatchContainerLengthStore only had a partial match. MatchGetOffset() will then set `containerVar`. containerLengthVar = null; containerVar = null; } - if (block.Instructions[pos].MatchStLoc(out var rangeVar, out var rangeVarInit) && rangeVar.Type.IsKnownType(KnownTypeCode.Range)) { + if (block.Instructions[pos].MatchStLoc(out var rangeVar, out var rangeVarInit) && rangeVar.Type.IsKnownType(KnownTypeCode.Range)) + { // stloc rangeVar(rangeVarInit) pos++; - } else { + } + else + { rangeVar = null; rangeVarInit = null; } // stloc startOffsetVar(call GetOffset(startIndexLoad, ldloc length)) - if (!block.Instructions[pos].MatchStLoc(out ILVariable startOffsetVar, out ILInstruction startOffsetVarInit)) { + if (!block.Instructions[pos].MatchStLoc(out ILVariable startOffsetVar, out ILInstruction startOffsetVarInit)) + { // Not our primary indexing/slicing pattern. // However, we might be dealing with a partially-transformed pattern that needs to be extended. ExtendSlicing(); @@ -167,9 +187,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; var startIndexKind = MatchGetOffset(startOffsetVarInit, out ILInstruction startIndexLoad, containerLengthVar, ref containerVar); pos++; - if (startOffsetVar.LoadCount == 1) { + if (startOffsetVar.LoadCount == 1) + { TransformIndexing(); - } else if (startOffsetVar.LoadCount == 2) { + } + else if (startOffsetVar.LoadCount == 2) + { // might be slicing: startOffset is used once for the slice length calculation, and once for the Slice() method call TransformSlicing(); } @@ -182,33 +205,43 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; if (!(startOffsetVar.LoadInstructions.Single().Parent is CallInstruction call)) return; - if (call.Method.AccessorKind == System.Reflection.MethodSemanticsAttributes.Getter && call.Arguments.Count == 2) { + if (call.Method.AccessorKind == System.Reflection.MethodSemanticsAttributes.Getter && call.Arguments.Count == 2) + { if (call.Method.AccessorOwner?.SymbolKind != SymbolKind.Indexer) return; if (call.Method.Parameters.Count != 1) return; - } else if (call.Method.AccessorKind == System.Reflection.MethodSemanticsAttributes.Setter && call.Arguments.Count == 3) { + } + else if (call.Method.AccessorKind == System.Reflection.MethodSemanticsAttributes.Setter && call.Arguments.Count == 3) + { if (call.Method.AccessorOwner?.SymbolKind != SymbolKind.Indexer) return; if (call.Method.Parameters.Count != 2) return; - } else if (IsSlicingMethod(call.Method)) { + } + else if (IsSlicingMethod(call.Method)) + { TransformSlicing(sliceLengthWasMisdetectedAsStartOffset: true); return; - } else { + } + else + { return; } - if (startIndexKind == IndexKind.FromStart) { + if (startIndexKind == IndexKind.FromStart) + { // FromStart is only relevant for slicing; indexing from the start does not involve System.Index at all. return; } - if (!CheckContainerLengthVariableUseCount(containerLengthVar, startIndexKind)) { + if (!CheckContainerLengthVariableUseCount(containerLengthVar, startIndexKind)) + { return; } if (!call.IsDescendantOf(block.Instructions[pos])) return; // startOffsetVar might be used deep inside a complex statement, ensure we can inline up to that point: - for (int i = startPos; i < pos; i++) { + for (int i = startPos; i < pos; i++) + { if (!ILInlining.CanInlineInto(block.Instructions[pos], startOffsetVar, block.Instructions[i])) return; } @@ -233,7 +266,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms newCall.Arguments.Add(MakeIndex(startIndexKind, startIndexLoad, specialMethods)); newCall.Arguments.AddRange(call.Arguments.Skip(2)); newCall.AddILRange(call); - for (int i = startPos; i < pos; i++) { + for (int i = startPos; i < pos; i++) + { newCall.AddILRange(block.Instructions[i]); } call.ReplaceWith(newCall); @@ -244,7 +278,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { ILVariable sliceLengthVar; ILInstruction sliceLengthVarInit; - if (sliceLengthWasMisdetectedAsStartOffset) { + if (sliceLengthWasMisdetectedAsStartOffset) + { // Special case: when slicing without a start point, the slice length calculation is mis-detected as the start offset, // and since it only has a single use, we end in TransformIndexing(), which then calls TransformSlicing // on this code path. @@ -253,7 +288,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms startOffsetVar = null; startIndexLoad = new LdcI4(0); startIndexKind = IndexKind.TheStart; - } else { + } + else + { // stloc containerLengthVar(call get_Length(ldloc containerVar)) // stloc startOffset(call GetOffset(startIndexLoad, ldloc length)) // -- we are here -- @@ -269,10 +306,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; if (!MatchSliceLength(sliceLengthVarInit, out IndexKind endIndexKind, out ILInstruction endIndexLoad, containerLengthVar, ref containerVar, startOffsetVar)) return; - if (!CheckContainerLengthVariableUseCount(containerLengthVar, startIndexKind, endIndexKind)) { + if (!CheckContainerLengthVariableUseCount(containerLengthVar, startIndexKind, endIndexKind)) + { return; } - if (rangeVar != null) { + if (rangeVar != null) + { return; // this should only ever happen in the second step (ExtendSlicing) } if (!(sliceLengthVar.LoadInstructions.Single().Parent is CallInstruction call)) @@ -285,11 +324,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; if (!MatchContainerVar(call.Arguments[0], ref containerVar)) return; - if (startOffsetVar == null) { + if (startOffsetVar == null) + { Debug.Assert(startIndexKind == IndexKind.TheStart); if (!call.Arguments[1].MatchLdcI4(0)) return; - } else { + } + else + { if (!call.Arguments[1].MatchLdLoc(startOffsetVar)) return; if (!ILInlining.CanMoveInto(startOffsetVarInit, block.Instructions[pos], call.Arguments[1])) @@ -313,7 +355,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms newCall.Arguments.Add(call.Arguments[0]); newCall.Arguments.Add(MakeRange(startIndexKind, startIndexLoad, endIndexKind, endIndexLoad, specialMethods)); newCall.AddILRange(call); - for (int i = startPos; i < pos; i++) { + for (int i = startPos; i < pos; i++) + { newCall.AddILRange(block.Instructions[i]); } call.ReplaceWith(newCall); @@ -322,19 +365,28 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInstruction MakeRange(IndexKind startIndexKind, ILInstruction startIndexLoad, IndexKind endIndexKind, ILInstruction endIndexLoad, IndexMethods specialMethods) { - if (rangeVar != null) { + if (rangeVar != null) + { return rangeVarInit; - } else if (startIndexKind == IndexKind.TheStart && endIndexKind == IndexKind.TheEnd && specialMethods.RangeGetAll != null) { + } + else if (startIndexKind == IndexKind.TheStart && endIndexKind == IndexKind.TheEnd && specialMethods.RangeGetAll != null) + { return new Call(specialMethods.RangeGetAll); - } else if (startIndexKind == IndexKind.TheStart && specialMethods.RangeEndAt != null) { + } + else if (startIndexKind == IndexKind.TheStart && specialMethods.RangeEndAt != null) + { var rangeCtorCall = new Call(specialMethods.RangeEndAt); rangeCtorCall.Arguments.Add(MakeIndex(endIndexKind, endIndexLoad, specialMethods)); return rangeCtorCall; - } else if (endIndexKind == IndexKind.TheEnd && specialMethods.RangeStartAt != null) { + } + else if (endIndexKind == IndexKind.TheEnd && specialMethods.RangeStartAt != null) + { var rangeCtorCall = new Call(specialMethods.RangeStartAt); rangeCtorCall.Arguments.Add(MakeIndex(startIndexKind, startIndexLoad, specialMethods)); return rangeCtorCall; - } else { + } + else + { var rangeCtorCall = new NewObj(specialMethods.RangeCtor); rangeCtorCall.Arguments.Add(MakeIndex(startIndexKind, startIndexLoad, specialMethods)); rangeCtorCall.Arguments.Add(MakeIndex(endIndexKind, endIndexLoad, specialMethods)); @@ -354,14 +406,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms // int length = span.Length; // Range range = GetRange(); // Console.WriteLine(span[range.Start.GetOffset(length)..range.End.GetOffset(length)].ToString()); - if (containerLengthVar == null) { + if (containerLengthVar == null) + { return; // need a container length to extend with } Debug.Assert(containerLengthVar.IsSingleDefinition); Debug.Assert(containerLengthVar.LoadCount == 1 || containerLengthVar.LoadCount == 2); NewObj rangeCtorCall = null; - foreach (var inst in containerLengthVar.LoadInstructions[0].Ancestors) { - if (inst is NewObj newobj && IndexMethods.IsRangeCtor(newobj.Method)) { + foreach (var inst in containerLengthVar.LoadInstructions[0].Ancestors) + { + if (inst is NewObj newobj && IndexMethods.IsRangeCtor(newobj.Method)) + { rangeCtorCall = newobj; break; } @@ -384,12 +439,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; var startIndexKind = MatchGetOffset(startOffsetInst, out var startIndexLoad, containerLengthVar, ref containerVar); var endIndexKind = MatchGetOffset(endOffsetInst, out var endIndexLoad, containerLengthVar, ref containerVar); - if (!CheckContainerLengthVariableUseCount(containerLengthVar, startIndexKind, endIndexKind)) { + if (!CheckContainerLengthVariableUseCount(containerLengthVar, startIndexKind, endIndexKind)) + { return; } // holds because we've used containerLengthVar at least once Debug.Assert(startIndexKind != IndexKind.FromStart || endIndexKind != IndexKind.FromStart); - if (rangeVar != null) { + if (rangeVar != null) + { if (!ILInlining.CanMoveInto(rangeVarInit, block.Instructions[pos], startIndexLoad)) return; if (!MatchIndexFromRange(startIndexKind, startIndexLoad, rangeVar, "get_Start")) @@ -402,7 +459,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; context.Step("Merge containerLengthVar into slicing", slicingCall); rangeCtorCall.ReplaceWith(MakeRange(startIndexKind, startIndexLoad, endIndexKind, endIndexLoad, specialMethods)); - for (int i = startPos; i < pos; i++) { + for (int i = startPos; i < pos; i++) + { slicingCall.AddILRange(block.Instructions[i]); } block.Instructions.RemoveRange(startPos, pos - startPos); @@ -447,9 +505,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms expectedUses += 1; if (endIndexKind != IndexKind.FromStart && endIndexKind != IndexKind.TheStart) expectedUses += 1; - if (containerLengthVar != null) { + if (containerLengthVar != null) + { return containerLengthVar.LoadCount == expectedUses; - } else { + } + else + { return expectedUses <= 1; // can have one inline use } } @@ -478,20 +539,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms static ILInstruction MakeIndex(IndexKind indexKind, ILInstruction indexLoad, IndexMethods specialMethods) { - if (indexKind == IndexKind.RefSystemIndex) { + if (indexKind == IndexKind.RefSystemIndex) + { // stloc containerLengthVar(call get_Length/get_Count(ldloc container)) // stloc startOffsetVar(call GetOffset(startIndexLoad, ldloc length)) // complex_expr(call get_Item(ldloc container, ldloc startOffsetVar)) // --> // complex_expr(call get_Item(ldloc container, ldobj startIndexLoad)) return new LdObj(indexLoad, specialMethods.IndexType); - } else if (indexKind == IndexKind.FromEnd || indexKind == IndexKind.TheEnd) { + } + else if (indexKind == IndexKind.FromEnd || indexKind == IndexKind.TheEnd) + { // stloc offsetVar(binary.sub.i4(call get_Length/get_Count(ldloc container), startIndexLoad)) // complex_expr(call get_Item(ldloc container, ldloc startOffsetVar)) // --> // complex_expr(call get_Item(ldloc container, newobj System.Index(startIndexLoad, fromEnd: true))) return new NewObj(specialMethods.IndexCtor) { Arguments = { indexLoad, new LdcI4(1) } }; - } else { + } + else + { Debug.Assert(indexKind == IndexKind.FromStart || indexKind == IndexKind.TheStart); return new Call(specialMethods.IndexImplicitConv) { Arguments = { indexLoad } }; } @@ -506,23 +572,35 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool foundIndexOverload = false; bool foundRangeOverload = false; bool foundCountProperty = false; - foreach (var prop in declaringType.GetProperties(p => p.IsIndexer || (p.Name == "Length" || p.Name == "Count"))) { - if (prop.IsIndexer && prop.Parameters.Count == 1) { + foreach (var prop in declaringType.GetProperties(p => p.IsIndexer || (p.Name == "Length" || p.Name == "Count"))) + { + if (prop.IsIndexer && prop.Parameters.Count == 1) + { var p = prop.Parameters[0]; - if (p.Type.IsKnownType(KnownTypeCode.Int32)) { + if (p.Type.IsKnownType(KnownTypeCode.Int32)) + { foundInt32Overload = true; - } else if (p.Type.IsKnownType(KnownTypeCode.Index)) { + } + else if (p.Type.IsKnownType(KnownTypeCode.Index)) + { foundIndexOverload = true; - } else if (p.Type.IsKnownType(KnownTypeCode.Range)) { + } + else if (p.Type.IsKnownType(KnownTypeCode.Range)) + { foundRangeOverload = true; } - } else if (prop.Name == "Length" || prop.Name == "Count") { + } + else if (prop.Name == "Length" || prop.Name == "Count") + { foundCountProperty = true; } } - if (slicing) { + if (slicing) + { return /* foundSlicingMethod && */ foundCountProperty && !foundRangeOverload; - } else { + } + else + { return foundInt32Overload && foundCountProperty && !foundIndexOverload; } } @@ -550,7 +628,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// static bool MatchContainerLength(ILInstruction init, ILVariable lengthVar, ref ILVariable containerVar) { - if (lengthVar != null) { + if (lengthVar != null) + { Debug.Assert(containerVar != null); return init.MatchLdLoc(lengthVar); } @@ -562,9 +641,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!(call.Method.AccessorOwner is IProperty lengthProp)) return false; - if (lengthProp.Name == "Length") { + if (lengthProp.Name == "Length") + { // OK, Length is preferred - } else if (lengthProp.Name == "Count") { + } + else if (lengthProp.Name == "Count") + { // Also works, but only if the type doesn't have "Length" if (lengthProp.DeclaringType.GetProperties(p => p.Name == "Length").Any()) return false; @@ -579,10 +661,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms } static bool MatchContainerVar(ILInstruction inst, ref ILVariable containerVar) - { - if (containerVar != null) { + { + if (containerVar != null) + { return inst.MatchLdLoc(containerVar) || inst.MatchLdLoca(containerVar); - } else { + } + else + { return inst.MatchLdLoc(out containerVar) || inst.MatchLdLoca(out containerVar); } } @@ -623,10 +708,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILVariable containerLengthVar, ref ILVariable containerVar) { indexLoad = inst; - if (MatchContainerLength(inst, containerLengthVar, ref containerVar)) { + if (MatchContainerLength(inst, containerLengthVar, ref containerVar)) + { indexLoad = new LdcI4(0); return IndexKind.TheEnd; - } else if (inst is CallInstruction call) { + } + else if (inst is CallInstruction call) + { // call System.Index.GetOffset(indexLoad, ldloc containerLengthVar) if (call.Method.Name != "GetOffset") return IndexKind.FromStart; @@ -638,7 +726,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return IndexKind.FromStart; indexLoad = call.Arguments[0]; return IndexKind.RefSystemIndex; - } else if (inst is BinaryNumericInstruction bni && bni.Operator == BinaryNumericOperator.Sub) { + } + else if (inst is BinaryNumericInstruction bni && bni.Operator == BinaryNumericOperator.Sub) + { if (bni.CheckForOverflow || bni.ResultType != StackType.I4 || bni.IsLifted) return IndexKind.FromStart; // binary.sub.i4(ldloc containerLengthVar, indexLoad) @@ -646,7 +736,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return IndexKind.FromStart; indexLoad = bni.Right; return IndexKind.FromEnd; - } else { + } + else + { return IndexKind.FromStart; } } @@ -659,24 +751,32 @@ namespace ICSharpCode.Decompiler.IL.Transforms { endIndexKind = default; endIndexLoad = default; - if (inst is BinaryNumericInstruction bni && bni.Operator == BinaryNumericOperator.Sub) { + if (inst is BinaryNumericInstruction bni && bni.Operator == BinaryNumericOperator.Sub) + { if (bni.CheckForOverflow || bni.ResultType != StackType.I4 || bni.IsLifted) return false; - if (startOffsetVar == null) { + if (startOffsetVar == null) + { // When slicing without explicit start point: `a[..endIndex]` if (!bni.Right.MatchLdcI4(0)) return false; - } else { + } + else + { if (!bni.Right.MatchLdLoc(startOffsetVar)) return false; } endIndexKind = MatchGetOffset(bni.Left, out endIndexLoad, containerLengthVar, ref containerVar); return true; - } else if (startOffsetVar == null) { + } + else if (startOffsetVar == null) + { // When slicing without explicit start point: `a[..endIndex]`, the compiler doesn't always emit the "- 0". endIndexKind = MatchGetOffset(inst, out endIndexLoad, containerLengthVar, ref containerVar); return true; - } else { + } + else + { return false; } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/InlineReturnTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/InlineReturnTransform.cs index e9c53f8ca..e04fb3eb1 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/InlineReturnTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/InlineReturnTransform.cs @@ -32,7 +32,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var instructionsToModify = new List<(BlockContainer, Block, Branch)>(); // Process all leave instructions in a leave-block, that is a block consisting solely of a leave instruction. - foreach (var leave in function.Descendants.OfType()) { + foreach (var leave in function.Descendants.OfType()) + { if (!(leave.Parent is Block leaveBlock && leaveBlock.Instructions.Count == 1)) continue; // Skip, if the leave instruction has no value or the value is not a load of a local variable. @@ -43,13 +44,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms instructionsToModify.AddRange(list); } - foreach (var (container, b, br) in instructionsToModify) { + foreach (var (container, b, br) in instructionsToModify) + { Block block = b; // if there is only one branch to this return block, move it to the matching container. // otherwise duplicate the return block. - if (block.IncomingEdgeCount == 1) { + if (block.IncomingEdgeCount == 1) + { block.Remove(); - } else { + } + else + { block = (Block)block.Clone(); } container.Blocks.Add(block); @@ -72,7 +77,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool CanModifyInstructions(ILVariable returnVar, Block leaveBlock, out List<(BlockContainer, Block, Branch)> instructionsToModify) { instructionsToModify = new List<(BlockContainer, Block, Branch)>(); - foreach (var inst in returnVar.StoreInstructions) { + foreach (var inst in returnVar.StoreInstructions) + { if (!(inst is StLoc store)) return false; if (!(store.Parent is Block storeBlock)) diff --git a/ICSharpCode.Decompiler/IL/Transforms/IntroduceDynamicTypeOnLocals.cs b/ICSharpCode.Decompiler/IL/Transforms/IntroduceDynamicTypeOnLocals.cs index a16786ea1..072113440 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IntroduceDynamicTypeOnLocals.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IntroduceDynamicTypeOnLocals.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Text; + using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -28,19 +29,24 @@ namespace ICSharpCode.Decompiler.IL { public void Run(ILFunction function, ILTransformContext context) { - foreach (var variable in function.Variables) { + foreach (var variable in function.Variables) + { if (variable.Kind != VariableKind.Local && variable.Kind != VariableKind.StackSlot && variable.Kind != VariableKind.ForeachLocal && - variable.Kind != VariableKind.UsingLocal) { + variable.Kind != VariableKind.UsingLocal) + { continue; } if (!variable.Type.IsKnownType(KnownTypeCode.Object) || variable.LoadCount == 0) continue; - foreach (var load in variable.LoadInstructions) { - if (load.Parent is DynamicInstruction dynamicInstruction) { + foreach (var load in variable.LoadInstructions) + { + if (load.Parent is DynamicInstruction dynamicInstruction) + { var argumentInfo = dynamicInstruction.GetArgumentInfoOfChild(load.ChildIndex); - if (!argumentInfo.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType)) { + if (!argumentInfo.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType)) + { variable.Type = SpecialType.Dynamic; } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/IntroduceNativeIntTypeOnLocals.cs b/ICSharpCode.Decompiler/IL/Transforms/IntroduceNativeIntTypeOnLocals.cs index 27962a359..94f531a2e 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IntroduceNativeIntTypeOnLocals.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IntroduceNativeIntTypeOnLocals.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -31,18 +32,21 @@ namespace ICSharpCode.Decompiler.IL { if (!context.Settings.NativeIntegers) return; - foreach (var variable in function.Variables) { + foreach (var variable in function.Variables) + { if (variable.Kind != VariableKind.Local && variable.Kind != VariableKind.StackSlot && variable.Kind != VariableKind.ForeachLocal && - variable.Kind != VariableKind.UsingLocal) { + variable.Kind != VariableKind.UsingLocal) + { continue; } if (!(variable.Type.IsKnownType(KnownTypeCode.IntPtr) || variable.Type.IsKnownType(KnownTypeCode.UIntPtr))) continue; bool isUsedAsNativeInt = variable.LoadInstructions.Any(IsUsedAsNativeInt); bool isAssignedNativeInt = variable.StoreInstructions.Any(store => IsNativeIntStore(store, context.TypeSystem)); - if (isUsedAsNativeInt || isAssignedNativeInt) { + if (isUsedAsNativeInt || isAssignedNativeInt) + { variable.Type = variable.Type.GetSign() == Sign.Unsigned ? SpecialType.NUInt : SpecialType.NInt; } } @@ -61,8 +65,10 @@ namespace ICSharpCode.Decompiler.IL static bool IsNativeIntStore(IStoreInstruction store, ICompilation compilation) { - if (store is StLoc stloc) { - switch (stloc.Value) { + if (store is StLoc stloc) + { + switch (stloc.Value) + { case BinaryNumericInstruction { UnderlyingResultType: StackType.I }: return true; case Conv { ResultType: StackType.I }: diff --git a/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs b/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs index 233bf87ef..946f15363 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IntroduceRefReadOnlyModifierOnLocals.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -29,11 +30,13 @@ namespace ICSharpCode.Decompiler.IL { public void Run(ILFunction function, ILTransformContext context) { - foreach (var variable in function.Variables) { + foreach (var variable in function.Variables) + { if (variable.Type.Kind != TypeKind.ByReference || variable.Kind == VariableKind.Parameter) continue; // ref readonly - if (IsUsedAsRefReadonly(variable)) { + if (IsUsedAsRefReadonly(variable)) + { variable.IsRefReadOnly = true; continue; } @@ -47,7 +50,8 @@ namespace ICSharpCode.Decompiler.IL /// bool IsUsedAsRefReadonly(ILVariable variable) { - foreach (var store in variable.StoreInstructions.OfType()) { + foreach (var store in variable.StoreInstructions.OfType()) + { if (ILInlining.IsReadonlyReference(store.Value)) return true; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index 003462046..a8dd67315 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -25,6 +25,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Text; using System.Text.RegularExpressions; + using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -94,7 +95,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms private void ReplaceReferencesToDisplayClassThis(Dictionary.ValueCollection localFunctions) { - foreach (var info in localFunctions) { + foreach (var info in localFunctions) + { var localFunction = info.Definition; if (localFunction.Method.IsStatic) continue; @@ -112,44 +114,55 @@ namespace ICSharpCode.Decompiler.IL.Transforms private void DetermineCaptureAndDeclarationScopes(Dictionary.ValueCollection localFunctions) { - foreach (var info in localFunctions) { + foreach (var info in localFunctions) + { context.CancellationToken.ThrowIfCancellationRequested(); - if (info.Definition == null) { + if (info.Definition == null) + { context.Function.Warnings.Add($"Could not decode local function '{info.Method}'"); continue; } context.StepStartGroup($"Determine and move to declaration scope of " + info.Definition.Name, info.Definition); - try { + try + { var localFunction = info.Definition; - foreach (var useSite in info.UseSites) { + foreach (var useSite in info.UseSites) + { DetermineCaptureAndDeclarationScope(info, useSite); - if (context.Function.Method.IsConstructor && localFunction.DeclarationScope == null) { + if (context.Function.Method.IsConstructor && localFunction.DeclarationScope == null) + { localFunction.DeclarationScope = BlockContainer.FindClosestContainer(useSite); } } - if (localFunction.DeclarationScope == null) { + if (localFunction.DeclarationScope == null) + { localFunction.DeclarationScope = (BlockContainer)context.Function.Body; } ILFunction declaringFunction = GetDeclaringFunction(localFunction); - if (declaringFunction != context.Function) { + if (declaringFunction != context.Function) + { context.Step($"Move {localFunction.Name} from {context.Function.Name} to {declaringFunction.Name}", localFunction); context.Function.LocalFunctions.Remove(localFunction); declaringFunction.LocalFunctions.Add(localFunction); } - if (TryValidateSkipCount(info, out int skipCount) && skipCount != localFunction.ReducedMethod.NumberOfCompilerGeneratedTypeParameters) { + if (TryValidateSkipCount(info, out int skipCount) && skipCount != localFunction.ReducedMethod.NumberOfCompilerGeneratedTypeParameters) + { Debug.Assert(false); context.Function.Warnings.Add($"Could not decode local function '{info.Method}'"); - if (declaringFunction != context.Function) { + if (declaringFunction != context.Function) + { declaringFunction.LocalFunctions.Remove(localFunction); } } - } finally { + } + finally + { context.StepEndGroup(keepIfEmpty: true); } } @@ -157,20 +170,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms private void TransformUseSites(Dictionary.ValueCollection localFunctions) { - foreach (var info in localFunctions) { + foreach (var info in localFunctions) + { context.CancellationToken.ThrowIfCancellationRequested(); - if (info.Definition == null) continue; + if (info.Definition == null) + continue; context.StepStartGroup($"TransformUseSites of " + info.Definition.Name, info.Definition); - try { - foreach (var useSite in info.UseSites) { + try + { + foreach (var useSite in info.UseSites) + { context.Step($"Transform use-site at IL_{useSite.StartILOffset:x4}", useSite); - if (useSite.OpCode == OpCode.NewObj) { + if (useSite.OpCode == OpCode.NewObj) + { TransformToLocalFunctionReference(info.Definition, useSite); - } else { + } + else + { TransformToLocalFunctionInvocation(info.Definition.ReducedMethod, useSite); } } - } finally { + } + finally + { context.StepEndGroup(); } } @@ -178,33 +200,44 @@ namespace ICSharpCode.Decompiler.IL.Transforms private void PropagateClosureParameterArguments(Dictionary localFunctions) { - foreach (var localFunction in context.Function.Descendants.OfType()) { + foreach (var localFunction in context.Function.Descendants.OfType()) + { if (localFunction.Kind != ILFunctionKind.LocalFunction) continue; context.CancellationToken.ThrowIfCancellationRequested(); var token = (MethodDefinitionHandle)localFunction.Method.MetadataToken; var info = localFunctions[token]; - foreach (var useSite in info.UseSites) { - if (useSite is NewObj) { + foreach (var useSite in info.UseSites) + { + if (useSite is NewObj) + { AddAsArgument(-1, useSite.Arguments[0]); - } else { + } + else + { int firstArgumentIndex; - if (info.Method.IsStatic) { + if (info.Method.IsStatic) + { firstArgumentIndex = 0; - } else { + } + else + { firstArgumentIndex = 1; AddAsArgument(-1, useSite.Arguments[0]); } - for (int i = useSite.Arguments.Count - 1; i >= firstArgumentIndex; i--) { + for (int i = useSite.Arguments.Count - 1; i >= firstArgumentIndex; i--) + { AddAsArgument(i - firstArgumentIndex, useSite.Arguments[i]); } } } context.StepStartGroup($"PropagateClosureParameterArguments of " + info.Definition.Name, info.Definition); - try { - foreach (var (index, arguments) in info.LocalFunctionArguments) { + try + { + foreach (var (index, arguments) in info.LocalFunctionArguments) + { var targetVariable = info.Definition.Variables.SingleOrDefault(p => p.Kind == VariableKind.Parameter && p.Index == index); if (targetVariable == null) continue; @@ -214,13 +247,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step($"Replace '{targetVariable}' with '{compatibleArgument}'", info.Definition); info.Definition.AcceptVisitor(new DelegateConstruction.ReplaceDelegateTargetVisitor(compatibleArgument, targetVariable)); } - } finally { + } + finally + { context.StepEndGroup(keepIfEmpty: true); } void AddAsArgument(int index, ILInstruction argument) { - switch (argument) { + switch (argument) + { case LdLoc _: case LdLoca _: case LdFlda _: @@ -234,7 +270,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; } - if (!info.LocalFunctionArguments.TryGetValue(index, out var arguments)) { + if (!info.LocalFunctionArguments.TryGetValue(index, out var arguments)) + { arguments = new List(); info.LocalFunctionArguments.Add(index, arguments); } @@ -245,7 +282,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms private ILInstruction FindCompatibleArgument(LocalFunctionInfo info, IList arguments, bool ignoreStructure = false) { - foreach (var arg in arguments) { + foreach (var arg in arguments) + { if (arg is IInstructionWithVariableOperand ld2 && (ignoreStructure || info.Definition.IsDescendantOf(ld2.Variable.Function))) return arg; var v = ResolveAncestorScopeReference(arg); @@ -263,8 +301,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms return null; if (!(TransformDisplayClassUsage.IsPotentialClosure(context, field.Type.GetDefinition()) || context.Function.Method.DeclaringType.Equals(field.Type))) return null; - foreach (var v in context.Function.Descendants.OfType().SelectMany(f => f.Variables)) { - if (v.Kind != VariableKind.Local && v.Kind != VariableKind.DisplayClassLocal && v.Kind != VariableKind.StackSlot) { + foreach (var v in context.Function.Descendants.OfType().SelectMany(f => f.Variables)) + { + if (v.Kind != VariableKind.Local && v.Kind != VariableKind.DisplayClassLocal && v.Kind != VariableKind.StackSlot) + { if (!(v.Kind == VariableKind.Parameter && v.Index == -1)) continue; if (v.Type.Equals(field.Type)) @@ -282,7 +322,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (localFunction.DeclarationScope == null) return null; ILInstruction inst = localFunction.DeclarationScope; - while (inst != null) { + while (inst != null) + { if (inst is ILFunction declaringFunction) return declaringFunction; inst = inst.Parent; @@ -306,15 +347,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (skipCount < 0 || skipCount > method.TypeArguments.Count) return false; - if (skipCount > 0) { + if (skipCount > 0) + { #if DEBUG - foreach (var useSite in info.UseSites) { + foreach (var useSite in info.UseSites) + { var callerMethod = useSite.Ancestors.OfType().First().Method; callerMethod = callerMethod.ReducedFrom ?? callerMethod; IMethod method0; - if (useSite.OpCode == OpCode.NewObj) { + if (useSite.OpCode == OpCode.NewObj) + { method0 = ((LdFtn)useSite.Arguments[1]).Method; - } else { + } + else + { method0 = useSite.Method; } var totalSkipCount = skipCount + method0.DeclaringType.TypeParameterCount; @@ -330,18 +376,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms void FindUseSites(ILFunction function, ILTransformContext context, Dictionary localFunctions) { - foreach (var inst in function.Body.Descendants) { + foreach (var inst in function.Body.Descendants) + { context.CancellationToken.ThrowIfCancellationRequested(); - if (inst is CallInstruction call && !call.Method.IsLocalFunction && IsLocalFunctionMethod(call.Method, context)) { + if (inst is CallInstruction call && !call.Method.IsLocalFunction && IsLocalFunctionMethod(call.Method, context)) + { HandleUseSite(call.Method, call); - } else if (inst is LdFtn ldftn && !ldftn.Method.IsLocalFunction && ldftn.Parent is NewObj newObj && IsLocalFunctionMethod(ldftn.Method, context) && DelegateConstruction.IsDelegateConstruction(newObj)) { + } + else if (inst is LdFtn ldftn && !ldftn.Method.IsLocalFunction && ldftn.Parent is NewObj newObj && IsLocalFunctionMethod(ldftn.Method, context) && DelegateConstruction.IsDelegateConstruction(newObj)) + { HandleUseSite(ldftn.Method, newObj); } } void HandleUseSite(IMethod targetMethod, CallInstruction inst) { - if (!localFunctions.TryGetValue((MethodDefinitionHandle)targetMethod.MetadataToken, out var info)) { + if (!localFunctions.TryGetValue((MethodDefinitionHandle)targetMethod.MetadataToken, out var info)) + { context.StepStartGroup($"Read local function '{targetMethod.Name}'", inst); info = new LocalFunctionInfo() { UseSites = new List() { inst }, @@ -352,11 +403,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms int skipCount = GetSkipCount(rootFunction, targetMethod); info.Definition = ReadLocalFunctionDefinition(rootFunction, targetMethod, skipCount); localFunctions.Add((MethodDefinitionHandle)targetMethod.MetadataToken, info); - if (info.Definition != null) { + if (info.Definition != null) + { FindUseSites(info.Definition, context, localFunctions); } context.StepEndGroup(); - } else { + } + else + { info.UseSites.Add(inst); } } @@ -389,10 +443,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms { targetMethod = (IMethod)targetMethod.MemberDefinition; var skipCount = rootFunction.Method.DeclaringType.TypeParameters.Count + rootFunction.Method.TypeParameters.Count - targetMethod.DeclaringType.TypeParameters.Count; - if (skipCount < 0) { + if (skipCount < 0) + { skipCount = 0; } - if (targetMethod.TypeParameters.Count > 0) { + if (targetMethod.TypeParameters.Count > 0) + { var lastParams = targetMethod.Parameters.Where(p => IsClosureParameter(p, this.resolveContext)).SelectMany(p => UnwrapByRef(p.Type).TypeArguments) .Select(pt => (int?)targetMethod.TypeParameters.IndexOf(pt)).DefaultIfEmpty().Max(); if (lastParams != null && lastParams.GetValueOrDefault() + 1 > skipCount) @@ -403,7 +459,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static TypeSystem.GenericContext? GenericContextFromTypeArguments(IMethod targetMethod, int skipCount) { - if (skipCount < 0 || skipCount > targetMethod.TypeParameters.Count) { + if (skipCount < 0 || skipCount > targetMethod.TypeParameters.Count) + { Debug.Assert(false); return null; } @@ -415,15 +472,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms var methodTypeParameters = new List(targetMethod.TypeParameters); var skippedTypeArguments = targetMethod.DeclaringType.TypeArguments.Concat(targetMethod.TypeArguments).Take(total); int idx = 0; - foreach (var skippedTA in skippedTypeArguments) { + foreach (var skippedTA in skippedTypeArguments) + { int curIdx; List curParameters; IReadOnlyList curArgs; - if (idx < classTypeParameters.Count) { + if (idx < classTypeParameters.Count) + { curIdx = idx; curParameters = classTypeParameters; curArgs = targetMethod.DeclaringType.TypeArguments; - } else { + } + else + { curIdx = idx - classTypeParameters.Count; curParameters = methodTypeParameters; curArgs = targetMethod.TypeArguments; @@ -433,7 +494,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms curParameters[curIdx] = (ITypeParameter)skippedTA; idx++; } - if (idx != total) { + if (idx != total) + { Debug.Assert(false); return null; } @@ -460,7 +522,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static IType UnwrapByRef(IType type) { - if (type is ByReferenceType byRef) { + if (type is ByReferenceType byRef) + { type = byRef.ElementType; } return type; @@ -468,7 +531,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms internal static ILInstruction GetStatement(ILInstruction inst) { - while (inst.Parent != null) { + while (inst.Parent != null) + { if (inst.Parent is Block b && b.Kind == BlockKind.ControlFlow) return inst; inst = inst.Parent; @@ -479,7 +543,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms LocalFunctionMethod ReduceToLocalFunction(IMethod method, int typeParametersToRemove) { int parametersToRemove = 0; - for (int i = method.Parameters.Count - 1; i >= 0; i--) { + for (int i = method.Parameters.Count - 1; i >= 0; i--) + { if (!IsClosureParameter(method.Parameters[i], resolveContext)) break; parametersToRemove++; @@ -511,7 +576,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { ILInstruction target = useSite.Arguments[0]; target.ReplaceWith(new LdNull().WithILRange(target)); - if (target is IInstructionWithVariableOperand withVar && withVar.Variable.Kind == VariableKind.Local) { + if (target is IInstructionWithVariableOperand withVar && withVar.Variable.Kind == VariableKind.Local) + { withVar.Variable.Kind = VariableKind.DisplayClassLocal; } var fnptr = (IInstructionWithMethodOperand)useSite.Arguments[1]; @@ -535,15 +601,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms replacement.IsTail = useSite.IsTail; // copy IL ranges replacement.AddILRange(useSite); - if (wasInstanceCall) { + if (wasInstanceCall) + { replacement.AddILRange(useSite.Arguments[0]); - if (useSite.Arguments[0].MatchLdLocRef(out var variable) && variable.Kind == VariableKind.NamedArgument) { + if (useSite.Arguments[0].MatchLdLocRef(out var variable) && variable.Kind == VariableKind.NamedArgument) + { // remove the store instruction of the simple load, if it is a named argument. var storeInst = (ILInstruction)variable.StoreInstructions[0]; ((Block)storeInst.Parent).Instructions.RemoveAt(storeInst.ChildIndex); } } - for (int i = 0; i < reducedMethod.NumberOfCompilerGeneratedParameters; i++) { + for (int i = 0; i < reducedMethod.NumberOfCompilerGeneratedParameters; i++) + { replacement.AddILRange(useSite.Arguments[argumentCount - i - 1]); } useSite.ReplaceWith(replacement); @@ -552,11 +621,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms void DetermineCaptureAndDeclarationScope(LocalFunctionInfo info, CallInstruction useSite) { int firstArgumentIndex = info.Definition.Method.IsStatic ? 0 : 1; - for (int i = useSite.Arguments.Count - 1; i >= firstArgumentIndex; i--) { + for (int i = useSite.Arguments.Count - 1; i >= firstArgumentIndex; i--) + { if (!DetermineCaptureAndDeclarationScope(info, i - firstArgumentIndex, useSite.Arguments[i])) break; } - if (firstArgumentIndex > 0) { + if (firstArgumentIndex > 0) + { DetermineCaptureAndDeclarationScope(info, -1, useSite.Arguments[0]); } } @@ -565,11 +636,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms { ILFunction function = info.Definition; ILVariable closureVar; - if (parameterIndex >= 0) { + if (parameterIndex >= 0) + { if (!(parameterIndex < function.Method.Parameters.Count && IsClosureParameter(function.Method.Parameters[parameterIndex], resolveContext))) return false; } - if (!(arg.MatchLdLoc(out closureVar) || arg.MatchLdLoca(out closureVar))) { + if (!(arg.MatchLdLoc(out closureVar) || arg.MatchLdLoca(out closureVar))) + { closureVar = ResolveAncestorScopeReference(arg); if (closureVar == null) return false; @@ -583,12 +656,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms var additionalScope = BlockContainer.FindClosestContainer(initializer); if (closureVar.CaptureScope == null) closureVar.CaptureScope = additionalScope; - else { + else + { BlockContainer combinedScope = FindCommonAncestorInstruction(closureVar.CaptureScope, additionalScope); Debug.Assert(combinedScope != null); closureVar.CaptureScope = combinedScope; } - if (closureVar.Kind == VariableKind.Local) { + if (closureVar.Kind == VariableKind.Local) + { closureVar.Kind = VariableKind.DisplayClassLocal; } if (function.DeclarationScope == null) @@ -662,7 +737,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms FindRefStructParameters visitor = new FindRefStructParameters(); method.DecodeSignature(visitor, default); - foreach (var h in visitor.RefStructTypes) { + foreach (var h in visitor.RefStructTypes) + { var td = metadata.GetTypeDefinition(h); if (td.IsCompilerGenerated(metadata) && td.IsValueType(metadata)) return true; @@ -687,7 +763,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var declaringTypeHandle = type.GetDeclaringType(); var declaringType = metadata.GetTypeDefinition(declaringTypeHandle); - foreach (var method in declaringType.GetMethods()) { + foreach (var method in declaringType.GetMethods()) + { if (!IsLocalFunctionMethod(module, method, context)) continue; var md = metadata.GetMethodDefinition(method); diff --git a/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs index ab7a4bb83..072d344fc 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms @@ -31,9 +32,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms void IBlockTransform.Run(Block block, BlockTransformContext context) { - if (!context.Settings.LockStatement) return; + if (!context.Settings.LockStatement) + return; this.context = context; - for (int i = block.Instructions.Count - 1; i >= 0; i--) { + for (int i = block.Instructions.Count - 1; i >= 0; i--) + { if (!TransformLockRoslyn(block, i)) if (!TransformLockV4(block, i)) if (!TransformLockV2(block, i)) @@ -71,7 +74,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// bool TransformLockMCS(Block block, int i) { - if (i < 2) return false; + if (i < 2) + return false; if (!(block.Instructions[i] is TryFinally body) || !(block.Instructions[i - 2] is StLoc objectStore) || !MatchCall(block.Instructions[i - 1] as Call, "Enter", objectStore.Variable)) return false; @@ -114,7 +118,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// bool TransformLockV2(Block block, int i) { - if (i < 2) return false; + if (i < 2) + return false; if (!(block.Instructions[i] is TryFinally body) || !(block.Instructions[i - 2] is StLoc objectStore) || !objectStore.Value.MatchLdLoc(out var tempVar) || !MatchCall(block.Instructions[i - 1] as Call, "Enter", tempVar)) return false; @@ -159,7 +164,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// bool TransformLockV4(Block block, int i) { - if (i < 1) return false; + if (i < 1) + return false; if (!(block.Instructions[i] is TryFinally body) || !(block.Instructions[i - 1] is StLoc flagStore)) return false; if (!flagStore.Variable.Type.IsKnownType(KnownTypeCode.Boolean) || !flagStore.Value.MatchLdcI4(0)) @@ -204,7 +210,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// bool TransformLockRoslyn(Block block, int i) { - if (i < 2) return false; + if (i < 2) + return false; if (!(block.Instructions[i] is TryFinally body) || !(block.Instructions[i - 1] is StLoc flagStore) || !(block.Instructions[i - 2] is StLoc objectStore)) return false; if (!objectStore.Variable.IsSingleDefinition || !flagStore.Variable.Type.IsKnownType(KnownTypeCode.Boolean) || !flagStore.Value.MatchLdcI4(0)) @@ -227,12 +234,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (entryPoint.Instructions.Count != 2 || entryPoint.IncomingEdgeCount != 1) return false; - if (flag != null) { + if (flag != null) + { if (!entryPoint.Instructions[0].MatchIfInstruction(out var cond, out var trueInst) || !(trueInst is Block trueBlock)) return false; if (!(cond.MatchLdLoc(flag) || (cond.MatchCompNotEquals(out var left, out var right) && left.MatchLdLoc(flag) && right.MatchLdcI4(0))) || !MatchExitBlock(trueBlock, obj)) return false; - } else { + } + else + { if (!MatchCall(entryPoint.Instructions[0] as Call, "Exit", obj)) return false; } @@ -290,7 +300,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!call.Arguments[0].MatchLdLoc(variables[0])) return false; - if (variables.Length == 2) { + if (variables.Length == 2) + { if (!call.Arguments[1].MatchLdLoca(variables[1])) return false; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs index 3b4c2c3dd..5bad499c3 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms @@ -21,16 +22,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms return FindResult.Stop; // cannot use named arg for operators or accessors if (call.Method is VarArgInstanceMethod) return FindResult.Stop; // CallBuilder doesn't support named args when using varargs - if (call.Method.IsConstructor) { + if (call.Method.IsConstructor) + { IType type = call.Method.DeclaringType; if (type.Kind == TypeKind.Delegate || type.IsAnonymousType()) return FindResult.Stop; } if (call.Method.Parameters.Any(p => string.IsNullOrEmpty(p.Name))) return FindResult.Stop; // cannot use named arguments - for (int i = child.ChildIndex; i < call.Arguments.Count; i++) { + for (int i = child.ChildIndex; i < call.Arguments.Count; i++) + { var r = ILInlining.FindLoadInNext(call.Arguments[i], v, expressionBeingMoved, InliningOptions.None); - if (r.Type == FindResultType.Found) { + if (r.Type == FindResultType.Found) + { return FindResult.NamedArgument(r.LoadInst, call.Arguments[i]); } } @@ -42,29 +46,36 @@ namespace ICSharpCode.Decompiler.IL.Transforms Debug.Assert(block.Kind == BlockKind.CallWithNamedArgs); var firstArg = ((StLoc)block.Instructions[0]).Value; var r = ILInlining.FindLoadInNext(firstArg, v, expressionBeingMoved, InliningOptions.IntroduceNamedArguments); - if (r.Type == FindResultType.Found || r.Type == FindResultType.NamedArgument) { + if (r.Type == FindResultType.Found || r.Type == FindResultType.NamedArgument) + { return r; // OK, inline into first instruction of block } var call = (CallInstruction)block.FinalInstruction; - if (call.IsInstanceCall) { + if (call.IsInstanceCall) + { // For instance calls, block.Instructions[0] is the argument // for the 'this' pointer. We can only insert at position 1. - if (r.Type == FindResultType.Stop) { + if (r.Type == FindResultType.Stop) + { // error: can't move expressionBeingMoved after block.Instructions[0] return FindResult.Stop; } // Because we always ensure block.Instructions[0] is the 'this' argument, // it's possible that the place we actually need to inline into // is within block.Instructions[1]: - if (block.Instructions.Count > 1) { + if (block.Instructions.Count > 1) + { r = ILInlining.FindLoadInNext(block.Instructions[1], v, expressionBeingMoved, InliningOptions.IntroduceNamedArguments); - if (r.Type == FindResultType.Found || r.Type == FindResultType.NamedArgument) { + if (r.Type == FindResultType.Found || r.Type == FindResultType.NamedArgument) + { return r; // OK, inline into block.Instructions[1] } } } - foreach (var arg in call.Arguments) { - if (arg.MatchLdLoc(v)) { + foreach (var arg in call.Arguments) + { + if (arg.MatchLdLoc(v)) + { return FindResult.NamedArgument(arg, arg); } } @@ -81,14 +92,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms Debug.Assert(context.Function == call.Ancestors.OfType().First()); var v = context.Function.RegisterVariable(VariableKind.NamedArgument, arg.ResultType); context.Step($"Introduce named argument '{v.Name}'", arg); - if (!(call.Parent is Block namedArgBlock) || namedArgBlock.Kind != BlockKind.CallWithNamedArgs) { + if (!(call.Parent is Block namedArgBlock) || namedArgBlock.Kind != BlockKind.CallWithNamedArgs) + { // create namedArgBlock: namedArgBlock = new Block(BlockKind.CallWithNamedArgs); call.ReplaceWith(namedArgBlock); namedArgBlock.FinalInstruction = call; - if (call.IsInstanceCall) { + if (call.IsInstanceCall) + { IType thisVarType = call.Method.DeclaringType; - if (CallInstruction.ExpectedTypeForThisPointer(thisVarType) == StackType.Ref) { + if (CallInstruction.ExpectedTypeForThisPointer(thisVarType) == StackType.Ref) + { thisVarType = new ByReferenceType(thisVarType); } var thisArgVar = context.Function.RegisterVariable(VariableKind.NamedArgument, thisVarType, "this_arg"); diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs index e251c23cd..9db4ce286 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms @@ -35,7 +36,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { public void Run(Block block, int pos, StatementTransformContext context) { - if (!TransformRefTypes(block, pos, context)) { + if (!TransformRefTypes(block, pos, context)) + { TransformThrowExpressionValueTypes(block, pos, context); } } @@ -60,7 +62,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // } // => // stloc s(if.notnull(valueInst, fallbackInst)) - if (trueInst.MatchStLoc(stloc.Variable, out var fallbackValue)) { + if (trueInst.MatchStLoc(stloc.Variable, out var fallbackValue)) + { context.Step("NullCoalescingTransform: simple (reference types)", stloc); stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, fallbackValue); block.Instructions.RemoveAt(pos + 1); // remove if instruction @@ -78,7 +81,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms && trueBlock.Instructions[0].MatchStLoc(out var temporary, out fallbackValue) && temporary.IsSingleDefinition && temporary.LoadCount == 1 && trueBlock.Instructions[1].MatchStLoc(stloc.Variable, out var useOfTemporary) - && useOfTemporary.MatchLdLoc(temporary)) { + && useOfTemporary.MatchLdLoc(temporary)) + { context.Step("NullCoalescingTransform: with temporary variable (reference types)", stloc); stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, fallbackValue); block.Instructions.RemoveAt(pos + 1); // remove if instruction @@ -91,7 +95,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // } // => // stloc obj(if.notnull(valueInst, throw(...))) - if (context.Settings.ThrowExpressions && trueInst is Throw throwInst) { + if (context.Settings.ThrowExpressions && trueInst is Throw throwInst) + { context.Step("NullCoalescingTransform (reference types + throw expression)", stloc); throwInst.resultType = StackType.O; stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, throwInst); @@ -143,7 +148,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms result.LoadInst.Parent.ReplaceWith(nullCoalescingWithThrow); block.Instructions.RemoveRange(pos, 2); // remove store(s) and if instruction return true; - } else { + } + else + { // reset the primary position (see remarks on ILInstruction.Parent) stloc.Value = stloc.Value; var children = throwInstParent.Children; diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs index 798c03f19..cda3652af 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms @@ -73,20 +74,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms { Debug.Assert(context.Settings.NullPropagation); Debug.Assert(!condition.MatchLogicNot(out _), "Caller should pass in positive condition"); - if (condition is Comp comp && comp.Left.MatchLdLoc(out var testedVar) && comp.Right.MatchLdNull()) { + if (condition is Comp comp && comp.Left.MatchLdLoc(out var testedVar) && comp.Right.MatchLdNull()) + { if (comp.LiftingKind != ComparisonLiftingKind.None) return null; - if (comp.Kind == ComparisonKind.Equality) { + if (comp.Kind == ComparisonKind.Equality) + { // testedVar == null ? trueInst : falseInst return TryNullPropagation(testedVar, falseInst, trueInst, Mode.ReferenceType); - } else if (comp.Kind == ComparisonKind.Inequality) { + } + else if (comp.Kind == ComparisonKind.Inequality) + { return TryNullPropagation(testedVar, trueInst, falseInst, Mode.ReferenceType); } - } else if (NullableLiftingTransform.MatchHasValueCall(condition, out ILInstruction loadInst)) { + } + else if (NullableLiftingTransform.MatchHasValueCall(condition, out ILInstruction loadInst)) + { // loadInst.HasValue ? trueInst : falseInst - if (loadInst.MatchLdLoca(out testedVar)) { + if (loadInst.MatchLdLoca(out testedVar)) + { return TryNullPropagation(testedVar, trueInst, falseInst, Mode.NullableByValue); - } else if (loadInst.MatchLdLoc(out testedVar)) { + } + else if (loadInst.MatchLdLoc(out testedVar)) + { return TryNullPropagation(testedVar, trueInst, falseInst, Mode.NullableByReference); } } @@ -100,10 +110,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms Mode mode) { bool removedRewrapOrNullableCtor = false; - if (NullableLiftingTransform.MatchNullableCtor(nonNullInst, out _, out var arg)) { + if (NullableLiftingTransform.MatchNullableCtor(nonNullInst, out _, out var arg)) + { nonNullInst = arg; removedRewrapOrNullableCtor = true; - } else if (nonNullInst.MatchNullableRewrap(out arg)) { + } + else if (nonNullInst.MatchNullableRewrap(out arg)) + { nonNullInst = arg; removedRewrapOrNullableCtor = true; } @@ -111,19 +124,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms return null; // note: InferType will be accurate in this case because the access chain consists of calls and field accesses IType returnType = nonNullInst.InferType(context.TypeSystem); - if (nullInst.MatchLdNull()) { + if (nullInst.MatchLdNull()) + { context.Step($"Null propagation (mode={mode}, output=reference type)", nonNullInst); // testedVar != null ? testedVar.AccessChain : null // => testedVar?.AccessChain IntroduceUnwrap(testedVar, varLoad, mode); return new NullableRewrap(nonNullInst); - } else if (nullInst.MatchDefaultValue(out var type) && type.IsKnownType(KnownTypeCode.NullableOfT)) { + } + else if (nullInst.MatchDefaultValue(out var type) && type.IsKnownType(KnownTypeCode.NullableOfT)) + { context.Step($"Null propagation (mode={mode}, output=value type)", nonNullInst); // testedVar != null ? testedVar.AccessChain : default(T?) // => testedVar?.AccessChain IntroduceUnwrap(testedVar, varLoad, mode); return new NullableRewrap(nonNullInst); - } else if (!removedRewrapOrNullableCtor && NullableType.IsNonNullableValueType(returnType)) { + } + else if (!removedRewrapOrNullableCtor && NullableType.IsNonNullableValueType(returnType)) + { context.Step($"Null propagation (mode={mode}, output=null coalescing)", nonNullInst); // testedVar != null ? testedVar.AccessChain : nullInst // => testedVar?.AccessChain ?? nullInst @@ -146,25 +164,34 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// internal void RunStatements(Block block, int pos) { - if (block.Instructions[pos] is IfInstruction ifInst && ifInst.FalseInst.MatchNop()) { + if (block.Instructions[pos] is IfInstruction ifInst && ifInst.FalseInst.MatchNop()) + { if (ifInst.Condition is Comp comp && comp.Kind == ComparisonKind.Inequality - && comp.Left.MatchLdLoc(out var testedVar) && comp.Right.MatchLdNull()) { + && comp.Left.MatchLdLoc(out var testedVar) && comp.Right.MatchLdNull()) + { TryNullPropForVoidCall(testedVar, Mode.ReferenceType, ifInst.TrueInst as Block, ifInst); - } else if (NullableLiftingTransform.MatchHasValueCall(ifInst.Condition, out ILInstruction arg)) { - if (arg.MatchLdLoca(out testedVar)) { + } + else if (NullableLiftingTransform.MatchHasValueCall(ifInst.Condition, out ILInstruction arg)) + { + if (arg.MatchLdLoca(out testedVar)) + { TryNullPropForVoidCall(testedVar, Mode.NullableByValue, ifInst.TrueInst as Block, ifInst); - } else if (arg.MatchLdLoc(out testedVar)) { + } + else if (arg.MatchLdLoc(out testedVar)) + { TryNullPropForVoidCall(testedVar, Mode.NullableByReference, ifInst.TrueInst as Block, ifInst); } } } - if (TransformNullPropagationOnUnconstrainedGenericExpression(block, pos, out var testedVariable, out var nonNullInst, out var nullInst, out var endBlock)) { + if (TransformNullPropagationOnUnconstrainedGenericExpression(block, pos, out var testedVariable, out var nonNullInst, out var nullInst, out var endBlock)) + { var parentInstruction = nonNullInst.Parent; var replacement = TryNullPropagation(testedVariable, nonNullInst, nullInst, Mode.UnconstrainedType); if (replacement == null) return; context.Step("TransformNullPropagationOnUnconstrainedGenericExpression", block); - switch (parentInstruction) { + switch (parentInstruction) + { case StLoc stloc: stloc.Value = replacement; break; @@ -180,7 +207,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms block.Instructions.RemoveRange(pos + 1, 2); // if the endBlock is only reachable through the current block, // combine both blocks. - if (endBlock?.IncomingEdgeCount == 1) { + if (endBlock?.IncomingEdgeCount == 1) + { block.Instructions.AddRange(endBlock.Instructions); block.Instructions.RemoveAt(pos + 2); endBlock.Remove(); @@ -194,7 +222,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (body == null || body.Instructions.Count != 1) return; var bodyInst = body.Instructions[0]; - if (bodyInst.MatchNullableRewrap(out var arg)) { + if (bodyInst.MatchNullableRewrap(out var arg)) + { bodyInst = arg; } if (!IsValidAccessChain(testedVar, mode, bodyInst, out var varLoad)) @@ -212,59 +241,89 @@ namespace ICSharpCode.Decompiler.IL.Transforms { finalLoad = null; int chainLength = 0; - while (true) { - if (IsValidEndOfChain()) { + while (true) + { + if (IsValidEndOfChain()) + { // valid end of chain finalLoad = inst; return chainLength >= 1; - } else if (inst.MatchLdFld(out var target, out _)) { + } + else if (inst.MatchLdFld(out var target, out _)) + { inst = target; - } else if (inst.MatchLdFlda(out target, out var f)) { - if (target is AddressOf addressOf && f.DeclaringType.Kind == TypeKind.Struct) { + } + else if (inst.MatchLdFlda(out target, out var f)) + { + if (target is AddressOf addressOf && f.DeclaringType.Kind == TypeKind.Struct) + { inst = addressOf.Value; - } else { + } + else + { inst = target; } - } else if (inst is CallInstruction call && call.OpCode != OpCode.NewObj) { - if (call.Arguments.Count == 0) { + } + else if (inst is CallInstruction call && call.OpCode != OpCode.NewObj) + { + if (call.Arguments.Count == 0) + { return false; } - if (call.Method.IsStatic && (!call.Method.IsExtensionMethod || !CanTransformToExtensionMethodCall(call, context))) { + if (call.Method.IsStatic && (!call.Method.IsExtensionMethod || !CanTransformToExtensionMethodCall(call, context))) + { return false; // only instance or extension methods can be called with ?. syntax } - if (call.Method.IsAccessor && !IsGetter(call.Method)) { + if (call.Method.IsAccessor && !IsGetter(call.Method)) + { return false; // setter/adder/remover cannot be called with ?. syntax } inst = call.Arguments[0]; - if ((call.ConstrainedTo ?? call.Method.DeclaringType).IsReferenceType == false && inst.MatchAddressOf(out var arg, out _)) { + if ((call.ConstrainedTo ?? call.Method.DeclaringType).IsReferenceType == false && inst.MatchAddressOf(out var arg, out _)) + { inst = arg; } // ensure the access chain does not contain any 'nullable.unwrap' that aren't directly part of the chain if (ArgumentsAfterFirstMayUnwrapNull(call.Arguments)) return false; - } else if (inst is LdLen ldLen) { + } + else if (inst is LdLen ldLen) + { inst = ldLen.Array; - } else if (inst is LdElema ldElema) { + } + else if (inst is LdElema ldElema) + { inst = ldElema.Array; // ensure the access chain does not contain any 'nullable.unwrap' that aren't directly part of the chain if (ldElema.Indices.Any(i => i.HasFlag(InstructionFlags.MayUnwrapNull))) return false; - } else if (inst is NullableUnwrap unwrap) { + } + else if (inst is NullableUnwrap unwrap) + { inst = unwrap.Argument; - if (unwrap.RefInput && inst is AddressOf addressOf) { + if (unwrap.RefInput && inst is AddressOf addressOf) + { inst = addressOf.Value; } - } else if (inst is DynamicGetMemberInstruction dynGetMember) { + } + else if (inst is DynamicGetMemberInstruction dynGetMember) + { inst = dynGetMember.Target; - } else if (inst is DynamicInvokeMemberInstruction dynInvokeMember) { + } + else if (inst is DynamicInvokeMemberInstruction dynInvokeMember) + { inst = dynInvokeMember.Arguments[0]; if (ArgumentsAfterFirstMayUnwrapNull(dynInvokeMember.Arguments)) return false; - } else if (inst is DynamicGetIndexInstruction dynGetIndex) { + } + else if (inst is DynamicGetIndexInstruction dynGetIndex) + { inst = dynGetIndex.Arguments[0]; if (ArgumentsAfterFirstMayUnwrapNull(dynGetIndex.Arguments)) return false; - } else { + } + else + { // unknown node -> invalid chain return false; } @@ -274,8 +333,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool ArgumentsAfterFirstMayUnwrapNull(InstructionCollection arguments) { // ensure the access chain does not contain any 'nullable.unwrap' that aren't directly part of the chain - for (int i = 1; i < arguments.Count; ++i) { - if (arguments[i].HasFlag(InstructionFlags.MayUnwrapNull)) { + for (int i = 1; i < arguments.Count; ++i) + { + if (arguments[i].HasFlag(InstructionFlags.MayUnwrapNull)) + { return true; } } @@ -284,7 +345,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool IsValidEndOfChain() { - switch (mode) { + switch (mode) + { case Mode.ReferenceType: // either reference type (expect: ldloc(testedVar)) or unconstrained generic type (expect: ldloca(testedVar)). return inst.MatchLdLocRef(testedVar); @@ -321,7 +383,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var oldParentChildren = varLoad.Parent.Children; var oldChildIndex = varLoad.ChildIndex; ILInstruction replacement; - switch (mode) { + switch (mode) + { case Mode.ReferenceType: case Mode.UnconstrainedType: // Wrap varLoad in nullable.unwrap: @@ -472,14 +535,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms // br endBlock // } var fallbackInst = Block.Unwrap(tmp); - if (fallbackInst is Block fallbackBlock && endBlockOrLeaveContainer is Block endBlock) { + if (fallbackInst is Block fallbackBlock && endBlockOrLeaveContainer is Block endBlock) + { if (!(fallbackBlock.Instructions.Count == 2)) return false; if (!fallbackBlock.Instructions[0].MatchStLoc(resultTemporary, out nullInst)) return false; if (!fallbackBlock.Instructions[1].MatchBranch(endBlock)) return false; - } else { + } + else + { if (!(fallbackInst is Leave fallbackLeave && endBlockOrLeaveContainer is BlockContainer leaveContainer && fallbackLeave.TargetContainer == leaveContainer && !fallbackLeave.Value.MatchNop())) return false; diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs index 80775465c..45be72188 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -57,7 +58,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms public bool Run(IfInstruction ifInst) { var lifted = Lift(ifInst, ifInst.Condition, ifInst.TrueInst, ifInst.FalseInst); - if (lifted != null) { + if (lifted != null) + { ifInst.ReplaceWith(lifted); return true; } @@ -76,7 +78,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms Debug.Assert(!bni.IsLifted && bni.Operator == BinaryNumericOperator.BitAnd); // caller ensures that bni.Left/bni.Right are booleans var lifted = Lift(bni, bni.Left, bni.Right, new LdcI4(0)); - if (lifted != null) { + if (lifted != null) + { bni.ReplaceWith(lifted); return true; } @@ -105,7 +108,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; var lifted = Lift(ifInst, ifInst.Condition, thenLeave.Value, elseLeave.Value); - if (lifted != null) { + if (lifted != null) + { thenLeave.Value = lifted; ifInst.ReplaceWith(thenLeave); block.Instructions.Remove(elseLeave); @@ -118,12 +122,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms #region AnalyzeCondition bool AnalyzeCondition(ILInstruction condition) { - if (MatchHasValueCall(condition, out ILVariable v)) { + if (MatchHasValueCall(condition, out ILVariable v)) + { if (nullableVars == null) nullableVars = new List(); nullableVars.Add(v); return true; - } else if (condition is BinaryNumericInstruction bitand) { + } + else if (condition is BinaryNumericInstruction bitand) + { if (!(bitand.Operator == BinaryNumericOperator.BitAnd && bitand.ResultType == StackType.I4)) return false; return AnalyzeCondition(bitand.Left) && AnalyzeCondition(bitand.Right); @@ -141,11 +148,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms { // ifInst is usually the IfInstruction to which condition belongs; // but can also be a BinaryNumericInstruction. - while (condition.MatchLogicNot(out var arg)) { + while (condition.MatchLogicNot(out var arg)) + { condition = arg; ExtensionMethods.Swap(ref trueInst, ref falseInst); } - if (context.Settings.NullPropagation && !NullPropagationTransform.IsProtectedIfInst(ifInst as IfInstruction)) { + if (context.Settings.NullPropagation && !NullPropagationTransform.IsProtectedIfInst(ifInst as IfInstruction)) + { var nullPropagated = new NullPropagationTransform(context) .Run(condition, trueInst, falseInst)?.WithILRange(ifInst); if (nullPropagated != null) @@ -153,43 +162,57 @@ namespace ICSharpCode.Decompiler.IL.Transforms } if (!context.Settings.LiftNullables) return null; - if (AnalyzeCondition(condition)) { + if (AnalyzeCondition(condition)) + { // (v1 != null && ... && vn != null) ? trueInst : falseInst // => normal lifting return LiftNormal(trueInst, falseInst)?.WithILRange(ifInst); } - if (MatchCompOrDecimal(condition, out var comp)) { + if (MatchCompOrDecimal(condition, out var comp)) + { // This might be a C#-style lifted comparison // (C# checks the underlying value before checking the HasValue bits) - if (comp.Kind.IsEqualityOrInequality()) { + if (comp.Kind.IsEqualityOrInequality()) + { // for equality/inequality, the HasValue bits must also compare equal/inequal - if (comp.Kind == ComparisonKind.Inequality) { + if (comp.Kind == ComparisonKind.Inequality) + { // handle inequality by swapping one last time ExtensionMethods.Swap(ref trueInst, ref falseInst); } - if (falseInst.MatchLdcI4(0)) { + if (falseInst.MatchLdcI4(0)) + { // (a.GetValueOrDefault() == b.GetValueOrDefault()) ? (a.HasValue == b.HasValue) : false // => a == b return LiftCSharpEqualityComparison(comp, ComparisonKind.Equality, trueInst) ?? LiftCSharpUserEqualityComparison(comp, ComparisonKind.Equality, trueInst); - } else if (falseInst.MatchLdcI4(1)) { + } + else if (falseInst.MatchLdcI4(1)) + { // (a.GetValueOrDefault() == b.GetValueOrDefault()) ? (a.HasValue != b.HasValue) : true // => a != b return LiftCSharpEqualityComparison(comp, ComparisonKind.Inequality, trueInst) ?? LiftCSharpUserEqualityComparison(comp, ComparisonKind.Inequality, trueInst); - } else if (IsGenericNewPattern(comp.Left, comp.Right, trueInst, falseInst)) { + } + else if (IsGenericNewPattern(comp.Left, comp.Right, trueInst, falseInst)) + { // (default(T) == null) ? Activator.CreateInstance() : default(T) // => Activator.CreateInstance() return trueInst; } - } else { + } + else + { // Not (in)equality, but one of < <= > >=. // Returns false unless all HasValue bits are true. - if (falseInst.MatchLdcI4(0) && AnalyzeCondition(trueInst)) { + if (falseInst.MatchLdcI4(0) && AnalyzeCondition(trueInst)) + { // comp(lhs, rhs) ? (v1 != null && ... && vn != null) : false // => comp.lifted[C#](lhs, rhs) return LiftCSharpComparison(comp, comp.Kind); - } else if (trueInst.MatchLdcI4(0) && AnalyzeCondition(falseInst)) { + } + else if (trueInst.MatchLdcI4(0) && AnalyzeCondition(falseInst)) + { // comp(lhs, rhs) ? false : (v1 != null && ... && vn != null) return LiftCSharpComparison(comp, comp.Kind.Negate()); } @@ -200,7 +223,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (MatchGetValueOrDefault(condition, out v) && NullableType.GetUnderlyingType(v.Type).IsKnownType(KnownTypeCode.Boolean)) { - if (MatchHasValueCall(trueInst, v) && falseInst.MatchLdcI4(0)) { + if (MatchHasValueCall(trueInst, v) && falseInst.MatchLdcI4(0)) + { // v.GetValueOrDefault() ? v.HasValue : false // ==> v == true context.Step("NullableLiftingTransform: v == true", ifInst); @@ -209,7 +233,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms new LdLoc(v).WithILRange(trueInst), new LdcI4(1).WithILRange(falseInst) ).WithILRange(ifInst); - } else if (trueInst.MatchLdcI4(0) && MatchHasValueCall(falseInst, v)) { + } + else if (trueInst.MatchLdcI4(0) && MatchHasValueCall(falseInst, v)) + { // v.GetValueOrDefault() ? false : v.HasValue // ==> v == false context.Step("NullableLiftingTransform: v == false", ifInst); @@ -218,7 +244,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms new LdLoc(v).WithILRange(falseInst), trueInst // LdcI4(0) ).WithILRange(ifInst); - } else if (MatchNegatedHasValueCall(trueInst, v) && falseInst.MatchLdcI4(1)) { + } + else if (MatchNegatedHasValueCall(trueInst, v) && falseInst.MatchLdcI4(1)) + { // v.GetValueOrDefault() ? !v.HasValue : true // ==> v != true context.Step("NullableLiftingTransform: v != true", ifInst); @@ -227,7 +255,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms new LdLoc(v).WithILRange(trueInst), falseInst // LdcI4(1) ).WithILRange(ifInst); - } else if (trueInst.MatchLdcI4(1) && MatchNegatedHasValueCall(falseInst, v)) { + } + else if (trueInst.MatchLdcI4(1) && MatchNegatedHasValueCall(falseInst, v)) + { // v.GetValueOrDefault() ? true : !v.HasValue // ==> v != false context.Step("NullableLiftingTransform: v != false", ifInst); @@ -239,7 +269,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } // Handle & and | on bool?: - if (trueInst.MatchLdLoc(out v)) { + if (trueInst.MatchLdLoc(out v)) + { if (MatchNullableCtor(falseInst, out var utype, out var arg) && utype.IsKnownType(KnownTypeCode.Boolean) && arg.MatchLdcI4(0)) { @@ -248,22 +279,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step("NullableLiftingTransform: 3vl.bool.and(bool, bool?)", ifInst); return new ThreeValuedBoolAnd(condition, trueInst).WithILRange(ifInst); } - if (falseInst.MatchLdLoc(out var v2)) { + if (falseInst.MatchLdLoc(out var v2)) + { // condition ? v : v2 - if (MatchThreeValuedLogicConditionPattern(condition, out var nullable1, out var nullable2)) { + if (MatchThreeValuedLogicConditionPattern(condition, out var nullable1, out var nullable2)) + { // (nullable1.GetValueOrDefault() || (!nullable2.GetValueOrDefault() && !nullable1.HasValue)) ? v : v2 - if (v == nullable1 && v2 == nullable2) { + if (v == nullable1 && v2 == nullable2) + { context.Step("NullableLiftingTransform: 3vl.bool.or(bool?, bool?)", ifInst); return new ThreeValuedBoolOr(trueInst, falseInst).WithILRange(ifInst); - } else if (v == nullable2 && v2 == nullable1) { + } + else if (v == nullable2 && v2 == nullable1) + { context.Step("NullableLiftingTransform: 3vl.bool.and(bool?, bool?)", ifInst); return new ThreeValuedBoolAnd(falseInst, trueInst).WithILRange(ifInst); } } } - } else if (falseInst.MatchLdLoc(out v)) { + } + else if (falseInst.MatchLdLoc(out v)) + { if (MatchNullableCtor(trueInst, out var utype, out var arg) - && utype.IsKnownType(KnownTypeCode.Boolean) && arg.MatchLdcI4(1)) { + && utype.IsKnownType(KnownTypeCode.Boolean) && arg.MatchLdcI4(1)) + { // condition ? (bool?)true : v // => condition | v context.Step("NullableLiftingTransform: 3vl.logic.or(bool, bool?)", ifInst); @@ -314,13 +353,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms { result = default(CompOrDecimal); result.Instruction = inst; - if (inst is Comp comp && !comp.IsLifted) { + if (inst is Comp comp && !comp.IsLifted) + { result.Kind = comp.Kind; result.Left = comp.Left; result.Right = comp.Right; return true; - } else if (inst is Call call && call.Method.IsOperator && call.Arguments.Count == 2 && !call.IsLifted) { - switch (call.Method.Name) { + } + else if (inst is Call call && call.Method.IsOperator && call.Arguments.Count == 2 && !call.IsLifted) + { + switch (call.Method.Name) + { case "op_Equality": result.Kind = ComparisonKind.Equality; break; @@ -361,9 +404,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms public IType LeftExpectedType { get { - if (Instruction is Call call) { + if (Instruction is Call call) + { return call.Method.Parameters[0].Type; - } else { + } + else + { return SpecialType.UnknownType; } } @@ -371,9 +417,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms public IType RightExpectedType { get { - if (Instruction is Call call) { + if (Instruction is Call call) + { return call.Method.Parameters[1].Type; - } else { + } + else + { return SpecialType.UnknownType; } } @@ -381,18 +430,26 @@ namespace ICSharpCode.Decompiler.IL.Transforms internal ILInstruction MakeLifted(ComparisonKind newComparisonKind, ILInstruction left, ILInstruction right) { - if (Instruction is Comp comp) { + if (Instruction is Comp comp) + { return new Comp(newComparisonKind, ComparisonLiftingKind.CSharp, comp.InputType, comp.Sign, left, right).WithILRange(Instruction); - } else if (Instruction is Call call) { + } + else if (Instruction is Call call) + { IMethod method; - if (newComparisonKind == Kind) { + if (newComparisonKind == Kind) + { method = call.Method; - } else if (newComparisonKind == ComparisonKind.Inequality && call.Method.Name == "op_Equality") { + } + else if (newComparisonKind == ComparisonKind.Inequality && call.Method.Name == "op_Equality") + { method = call.Method.DeclaringType.GetMethods(m => m.Name == "op_Inequality") .FirstOrDefault(m => ParameterListComparer.Instance.Equals(m.Parameters, call.Method.Parameters)); if (method == null) return null; - } else { + } + else + { return null; } return new Call(CSharp.Resolver.CSharpOperators.LiftUserDefinedOperator(method)) { @@ -401,7 +458,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILStackWasEmpty = call.ILStackWasEmpty, IsTail = call.IsTail }.WithILRange(call); - } else { + } + else + { return null; } } @@ -413,12 +472,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms { Debug.Assert(newComparisonKind.IsEqualityOrInequality()); bool hasValueTestNegated = false; - while (hasValueTest.MatchLogicNot(out var arg)) { + while (hasValueTest.MatchLogicNot(out var arg)) + { hasValueTest = arg; hasValueTestNegated = !hasValueTestNegated; } // The HasValue comparison must be the same operator as the Value comparison. - if (hasValueTest is Comp hasValueComp) { + if (hasValueTest is Comp hasValueComp) + { // Comparing two nullables: HasValue comparison must be the same operator as the Value comparison if ((hasValueTestNegated ? hasValueComp.Kind.Negate() : hasValueComp.Kind) != newComparisonKind) return null; @@ -432,15 +493,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms var (right, rightBits) = DoLift(valueComp.Right); if (left != null && right != null && leftBits[0] && rightBits[0] && SemanticHelper.IsPure(left.Flags) && SemanticHelper.IsPure(right.Flags) - ) { + ) + { context.Step("NullableLiftingTransform: C# (in)equality comparison", valueComp.Instruction); return valueComp.MakeLifted(newComparisonKind, left, right); } - } else if (newComparisonKind == ComparisonKind.Equality && !hasValueTestNegated && MatchHasValueCall(hasValueTest, out ILVariable v)) { + } + else if (newComparisonKind == ComparisonKind.Equality && !hasValueTestNegated && MatchHasValueCall(hasValueTest, out ILVariable v)) + { // Comparing nullable with non-nullable -> we can fall back to the normal comparison code. nullableVars = new List { v }; return LiftCSharpComparison(valueComp, newComparisonKind); - } else if (newComparisonKind == ComparisonKind.Inequality && hasValueTestNegated && MatchHasValueCall(hasValueTest, out v)) { + } + else if (newComparisonKind == ComparisonKind.Inequality && hasValueTestNegated && MatchHasValueCall(hasValueTest, out v)) + { // Comparing nullable with non-nullable -> we can fall back to the normal comparison code. nullableVars = new List { v }; return LiftCSharpComparison(valueComp, newComparisonKind); @@ -465,8 +531,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms var (left, right, bits) = DoLiftBinary(comp.Left, comp.Right, comp.LeftExpectedType, comp.RightExpectedType); // due to the restrictions on side effects, we only allow instructions that are pure after lifting. // (we can't check this before lifting due to the calls to GetValueOrDefault()) - if (left != null && right != null && SemanticHelper.IsPure(left.Flags) && SemanticHelper.IsPure(right.Flags)) { - if (!bits.All(0, nullableVars.Count)) { + if (left != null && right != null && SemanticHelper.IsPure(left.Flags) && SemanticHelper.IsPure(right.Flags)) + { + if (!bits.All(0, nullableVars.Count)) + { // don't lift if a nullableVar doesn't contribute to the result return null; } @@ -523,7 +591,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var (right, rightBits) = DoLift(call.Arguments[1]); if (left != null && right != null && leftBits[0] && rightBits[0] && SemanticHelper.IsPure(left.Flags) && SemanticHelper.IsPure(right.Flags) - ) { + ) + { context.Step("NullableLiftingTransform: C# user-defined (in)equality comparison", nestedIfInst); return new Call(liftedOperator) { Arguments = { left, right }, @@ -547,43 +616,51 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// ILInstruction LiftNormal(ILInstruction trueInst, ILInstruction falseInst) { - if (trueInst.MatchIfInstructionPositiveCondition(out var nestedCondition, out var nestedTrue, out var nestedFalse)) { + if (trueInst.MatchIfInstructionPositiveCondition(out var nestedCondition, out var nestedTrue, out var nestedFalse)) + { // Sometimes Roslyn generates pointless conditions like: // if (nullable.HasValue && (!nullable.HasValue || nullable.GetValueOrDefault() == b)) - if (MatchHasValueCall(nestedCondition, out ILVariable v) && nullableVars.Contains(v)) { + if (MatchHasValueCall(nestedCondition, out ILVariable v) && nullableVars.Contains(v)) + { trueInst = nestedTrue; } } bool isNullCoalescingWithNonNullableFallback = false; - if (!MatchNullableCtor(trueInst, out var utype, out var exprToLift)) { + if (!MatchNullableCtor(trueInst, out var utype, out var exprToLift)) + { isNullCoalescingWithNonNullableFallback = true; utype = context.TypeSystem.FindType(trueInst.ResultType.ToKnownTypeCode()); exprToLift = trueInst; - if (nullableVars.Count == 1 && exprToLift.MatchLdLoc(nullableVars[0])) { + if (nullableVars.Count == 1 && exprToLift.MatchLdLoc(nullableVars[0])) + { // v.HasValue ? ldloc v : fallback // => v ?? fallback context.Step("v.HasValue ? v : fallback => v ?? fallback", trueInst); return new NullCoalescingInstruction(NullCoalescingKind.Nullable, trueInst, falseInst) { UnderlyingResultType = NullableType.GetUnderlyingType(nullableVars[0].Type).GetStackType() }; - } else if (trueInst is Call call && !call.IsLifted - && CSharp.Resolver.CSharpOperators.IsComparisonOperator(call.Method) - && falseInst.MatchLdcI4(call.Method.Name == "op_Inequality" ? 1 : 0)) + } + else if (trueInst is Call call && !call.IsLifted + && CSharp.Resolver.CSharpOperators.IsComparisonOperator(call.Method) + && falseInst.MatchLdcI4(call.Method.Name == "op_Inequality" ? 1 : 0)) { // (v1 != null && ... && vn != null) ? call op_LessThan(lhs, rhs) : ldc.i4(0) var liftedOperator = CSharp.Resolver.CSharpOperators.LiftUserDefinedOperator(call.Method); - if ((call.Method.Name == "op_Equality" || call.Method.Name == "op_Inequality") && nullableVars.Count != 1) { + if ((call.Method.Name == "op_Equality" || call.Method.Name == "op_Inequality") && nullableVars.Count != 1) + { // Equality is special (returns true if both sides are null), only handle it // in the normal code path if we're dealing with only a single nullable var // (comparing nullable with non-nullable). liftedOperator = null; } - if (liftedOperator != null) { + if (liftedOperator != null) + { context.Step("Lift user-defined comparison operator", trueInst); var (left, right, bits) = DoLiftBinary(call.Arguments[0], call.Arguments[1], call.Method.Parameters[0].Type, call.Method.Parameters[1].Type); - if (left != null && right != null && bits.All(0, nullableVars.Count)) { + if (left != null && right != null && bits.All(0, nullableVars.Count)) + { return new Call(liftedOperator) { Arguments = { left, right }, ConstrainedTo = call.ConstrainedTo, @@ -595,7 +672,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } ILInstruction lifted; - if (nullableVars.Count == 1 && MatchGetValueOrDefault(exprToLift, nullableVars[0])) { + if (nullableVars.Count == 1 && MatchGetValueOrDefault(exprToLift, nullableVars[0])) + { // v.HasValue ? call GetValueOrDefault(ldloca v) : fallback // => conv.nop.lifted(ldloc v) ?? fallback // This case is handled separately from DoLift() because @@ -603,7 +681,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step("v.HasValue ? v.GetValueOrDefault() : fallback => v ?? fallback", trueInst); var inputUType = NullableType.GetUnderlyingType(nullableVars[0].Type); lifted = new LdLoc(nullableVars[0]); - if (!inputUType.Equals(utype) && utype.ToPrimitiveType() != PrimitiveType.None) { + if (!inputUType.Equals(utype) && utype.ToPrimitiveType() != PrimitiveType.None) + { // While the ILAst allows implicit conversions between short and int // (because both map to I4); it does not allow implicit conversions // between short? and int? (structs of different types). @@ -615,25 +694,32 @@ namespace ICSharpCode.Decompiler.IL.Transforms isLifted: true ); } - } else { + } + else + { context.Step("NullableLiftingTransform.DoLift", trueInst); BitSet bits; (lifted, bits) = DoLift(exprToLift); - if (lifted == null) { + if (lifted == null) + { return null; } - if (!bits.All(0, nullableVars.Count)) { + if (!bits.All(0, nullableVars.Count)) + { // don't lift if a nullableVar doesn't contribute to the result return null; } Debug.Assert(lifted is ILiftableInstruction liftable && liftable.IsLifted && liftable.UnderlyingResultType == exprToLift.ResultType); } - if (isNullCoalescingWithNonNullableFallback) { + if (isNullCoalescingWithNonNullableFallback) + { lifted = new NullCoalescingInstruction(NullCoalescingKind.NullableWithValueFallback, lifted, falseInst) { UnderlyingResultType = exprToLift.ResultType }; - } else if (!MatchNull(falseInst, utype)) { + } + else if (!MatchNull(falseInst, utype)) + { // Normal lifting, but the falseInst isn't `default(utype?)` // => use the `??` operator to provide the fallback value. lifted = new NullCoalescingInstruction(NullCoalescingKind.Nullable, lifted, falseInst) { @@ -662,11 +748,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// (ILInstruction, BitSet) DoLift(ILInstruction inst) { - if (MatchGetValueOrDefault(inst, out ILVariable inputVar)) { + if (MatchGetValueOrDefault(inst, out ILVariable inputVar)) + { // n.GetValueOrDefault() lifted => n. BitSet foundIndices = new BitSet(nullableVars.Count); - for (int i = 0; i < nullableVars.Count; i++) { - if (nullableVars[i] == inputVar) { + for (int i = 0; i < nullableVars.Count; i++) + { + if (nullableVars[i] == inputVar) + { foundIndices[i] = true; } } @@ -674,10 +763,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms return (new LdLoc(inputVar).WithILRange(inst), foundIndices); else return (null, null); - } else if (inst is Conv conv) { + } + else if (inst is Conv conv) + { var (arg, bits) = DoLift(conv.Argument); - if (arg != null) { - if (conv.HasDirectFlag(InstructionFlags.MayThrow) && !bits.All(0, nullableVars.Count)) { + if (arg != null) + { + if (conv.HasDirectFlag(InstructionFlags.MayThrow) && !bits.All(0, nullableVars.Count)) + { // Cannot execute potentially-throwing instruction unless all // the nullableVars are arguments to the instruction // (thus causing it not to throw when any of them is null). @@ -686,16 +779,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms var newInst = new Conv(arg, conv.InputType, conv.InputSign, conv.TargetType, conv.CheckForOverflow, isLifted: true).WithILRange(conv); return (newInst, bits); } - } else if (inst is BitNot bitnot) { + } + else if (inst is BitNot bitnot) + { var (arg, bits) = DoLift(bitnot.Argument); - if (arg != null) { + if (arg != null) + { var newInst = new BitNot(arg, isLifted: true, stackType: bitnot.ResultType).WithILRange(bitnot); return (newInst, bits); } - } else if (inst is BinaryNumericInstruction binary) { + } + else if (inst is BinaryNumericInstruction binary) + { var (left, right, bits) = DoLiftBinary(binary.Left, binary.Right, SpecialType.UnknownType, SpecialType.UnknownType); - if (left != null && right != null) { - if (binary.HasDirectFlag(InstructionFlags.MayThrow) && !bits.All(0, nullableVars.Count)) { + if (left != null && right != null) + { + if (binary.HasDirectFlag(InstructionFlags.MayThrow) && !bits.All(0, nullableVars.Count)) + { // Cannot execute potentially-throwing instruction unless all // the nullableVars are arguments to the instruction // (thus causing it not to throw when any of them is null). @@ -709,37 +809,47 @@ namespace ICSharpCode.Decompiler.IL.Transforms ).WithILRange(binary); return (newInst, bits); } - } else if (inst is Comp comp && !comp.IsLifted && comp.Kind == ComparisonKind.Equality - && MatchGetValueOrDefault(comp.Left, out ILVariable v) && nullableVars.Contains(v) - && NullableType.GetUnderlyingType(v.Type).IsKnownType(KnownTypeCode.Boolean) - && comp.Right.MatchLdcI4(0) - ) { + } + else if (inst is Comp comp && !comp.IsLifted && comp.Kind == ComparisonKind.Equality + && MatchGetValueOrDefault(comp.Left, out ILVariable v) && nullableVars.Contains(v) + && NullableType.GetUnderlyingType(v.Type).IsKnownType(KnownTypeCode.Boolean) + && comp.Right.MatchLdcI4(0) + ) + { // C# doesn't support ComparisonLiftingKind.ThreeValuedLogic, // except for operator! on bool?. var (arg, bits) = DoLift(comp.Left); Debug.Assert(arg != null); var newInst = new Comp(comp.Kind, ComparisonLiftingKind.ThreeValuedLogic, comp.InputType, comp.Sign, arg, comp.Right.Clone()).WithILRange(comp); return (newInst, bits); - } else if (inst is Call call && call.Method.IsOperator) { + } + else if (inst is Call call && call.Method.IsOperator) + { // Lifted user-defined operators, except for comparison operators (as those return bool, not bool?) var liftedOperator = CSharp.Resolver.CSharpOperators.LiftUserDefinedOperator(call.Method); if (liftedOperator == null || !NullableType.IsNullable(liftedOperator.ReturnType)) return (null, null); ILInstruction[] newArgs; BitSet newBits; - if (call.Arguments.Count == 1) { + if (call.Arguments.Count == 1) + { var (arg, bits) = DoLift(call.Arguments[0]); newArgs = new[] { arg }; newBits = bits; - } else if (call.Arguments.Count == 2) { + } + else if (call.Arguments.Count == 2) + { var (left, right, bits) = DoLiftBinary(call.Arguments[0], call.Arguments[1], call.Method.Parameters[0].Type, call.Method.Parameters[1].Type); newArgs = new[] { left, right }; newBits = bits; - } else { + } + else + { return (null, null); } - if (newBits == null || !newBits.All(0, nullableVars.Count)) { + if (newBits == null || !newBits.All(0, nullableVars.Count)) + { // all nullable vars must be involved when calling a method (side effect) return (null, null); } @@ -758,20 +868,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms { var (left, leftBits) = DoLift(lhs); var (right, rightBits) = DoLift(rhs); - if (left != null && right == null && SemanticHelper.IsPure(rhs.Flags)) { + if (left != null && right == null && SemanticHelper.IsPure(rhs.Flags)) + { // Embed non-nullable pure expression in lifted expression. right = NewNullable(rhs.Clone(), rightExpectedType); } - if (left == null && right != null && SemanticHelper.IsPure(lhs.Flags)) { + if (left == null && right != null && SemanticHelper.IsPure(lhs.Flags)) + { // Embed non-nullable pure expression in lifted expression. left = NewNullable(lhs.Clone(), leftExpectedType); } - if (left != null && right != null) { + if (left != null && right != null) + { var bits = leftBits ?? rightBits; if (rightBits != null) bits.UnionWith(rightBits); return (left, right, bits); - } else { + } + else + { return (null, null, null); } } @@ -782,10 +897,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms return inst; var nullable = context.TypeSystem.FindType(KnownTypeCode.NullableOfT).GetDefinition(); var ctor = nullable?.Methods.FirstOrDefault(m => m.IsConstructor && m.Parameters.Count == 1); - if (ctor != null) { + if (ctor != null) + { ctor = ctor.Specialize(new TypeParameterSubstitution(new[] { underlyingType }, null)); return new NewObj(ctor) { Arguments = { inst } }; - } else { + } + else + { return inst; } } @@ -815,7 +933,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// internal static bool MatchHasValueCall(ILInstruction inst, out ILVariable v) { - if (MatchHasValueCall(inst, out ILInstruction arg)) { + if (MatchHasValueCall(inst, out ILInstruction arg)) + { return arg.MatchLdLoca(out v); } v = null; @@ -893,7 +1012,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool MatchNull(ILInstruction inst, out IType underlyingType) { underlyingType = null; - if (inst.MatchDefaultValue(out IType type)) { + if (inst.MatchDefaultValue(out IType type)) + { underlyingType = NullableType.GetUnderlyingType(type); return NullableType.IsNullable(type); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs b/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs index 9415a9fea..2d82abd29 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs @@ -18,6 +18,7 @@ using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms @@ -28,7 +29,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (!context.Settings.AsyncAwait) return; - foreach (var inst in function.Descendants.OfType()) { + foreach (var inst in function.Descendants.OfType()) + { Run(inst, context); } } @@ -63,7 +65,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var block = blockContainer.Blocks[0]; Call call; ILInstruction returnValue; - switch (block.Instructions.Count) { + switch (block.Instructions.Count) + { case 1: // leave IL_0000 (call Test(ldloc this, ldloc A_1)) if (!block.Instructions[0].MatchLeave(blockContainer, out returnValue)) @@ -82,18 +85,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms default: return; } - if (call == null || call.Method.IsConstructor) { + if (call == null || call.Method.IsConstructor) + { return; } - if (call.Method.IsStatic || call.Method.Parameters.Count != inst.Method.Parameters.Count) { + if (call.Method.IsStatic || call.Method.Parameters.Count != inst.Method.Parameters.Count) + { return; } // check if original arguments are only correct ldloc calls - for (int i = 0; i < call.Arguments.Count; i++) { + for (int i = 0; i < call.Arguments.Count; i++) + { var originalArg = call.Arguments[i]; if (!originalArg.MatchLdLoc(out ILVariable var) || var.Kind != VariableKind.Parameter || - var.Index != i - 1) { + var.Index != i - 1) + { return; } } @@ -112,7 +119,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool IsDefinedInCurrentOrOuterClass(IMethod method, ITypeDefinition declaringTypeDefinition) { - while (declaringTypeDefinition != null) { + while (declaringTypeDefinition != null) + { if (method.DeclaringTypeDefinition == declaringTypeDefinition) return true; declaringTypeDefinition = declaringTypeDefinition.DeclaringTypeDefinition; diff --git a/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs index d73cf222f..062b1cd68 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.IL.ControlFlow; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Util; @@ -47,14 +48,16 @@ namespace ICSharpCode.Decompiler.IL this.context = context; Visit((BlockContainer)function.Body, null); - foreach (var node in function.Descendants.OfType()) { + foreach (var node in function.Descendants.OfType()) + { EliminateRedundantTryFinally(node, context); } } private void Visit(BlockContainer container, Block continueTarget) { - switch (container.Kind) { + switch (container.Kind) + { case ContainerKind.Loop: case ContainerKind.While: continueTarget = container.EntryPoint; @@ -65,7 +68,8 @@ namespace ICSharpCode.Decompiler.IL break; } - for (int i = 0; i < container.Blocks.Count; i++) { + for (int i = 0; i < container.Blocks.Count; i++) + { var block = container.Blocks[i]; // Note: it's possible for additional blocks to be appended to the container // by the Visit() call; but there should be no other changes to the Blocks collection. @@ -83,16 +87,18 @@ namespace ICSharpCode.Decompiler.IL private void Visit(Block block, Block continueTarget, ILInstruction nextInstruction = null) { Debug.Assert(block.HasFlag(InstructionFlags.EndPointUnreachable) || nextInstruction != null); - + // process each instruction in the block. - for (int i = 0; i < block.Instructions.Count; i++) { + for (int i = 0; i < block.Instructions.Count; i++) + { // Transformations may be applied to the current and following instructions but already processed instructions will not be changed var inst = block.Instructions[i]; // the next instruction to be executed. Transformations will change the next instruction, so this is a method instead of a variable ILInstruction NextInsn() => i + 1 < block.Instructions.Count ? block.Instructions[i + 1] : nextInstruction; - - switch (inst) { + + switch (inst) + { case BlockContainer container: // visit the contents of the container Visit(container, continueTarget); @@ -100,23 +106,26 @@ namespace ICSharpCode.Decompiler.IL // reduce nesting in switch blocks if (container.Kind == ContainerKind.Switch && CanDuplicateExit(NextInsn(), continueTarget, out var keywordExit1) && - ReduceSwitchNesting(block, container, keywordExit1)) { + ReduceSwitchNesting(block, container, keywordExit1)) + { RemoveRedundantExit(block, nextInstruction); } break; case IfInstruction ifInst: ImproveILOrdering(block, ifInst, continueTarget); - + // reduce nesting in if/else blocks if (CanDuplicateExit(NextInsn(), continueTarget, out var keywordExit2) && ReduceNesting(block, ifInst, keywordExit2)) RemoveRedundantExit(block, nextInstruction); - + // visit content blocks if (ifInst.TrueInst is Block trueBlock) Visit(trueBlock, continueTarget, NextInsn()); - - if (ifInst.FalseInst is Block falseBlock) { - if (ifInst.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable)) { + + if (ifInst.FalseInst is Block falseBlock) + { + if (ifInst.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable)) + { ExtractElseBlock(ifInst); break; } @@ -131,7 +140,8 @@ namespace ICSharpCode.Decompiler.IL // reducing nesting inside Try/Using/Lock etc, may make the endpoint unreachable. // This should only happen by replacing a Leave with the exit instruction we're about to delete, but I can't see a good way to assert this // This would be better placed in ReduceNesting, but it's more difficult to find the affected instructions/blocks there than here - if (i == block.Instructions.Count - 2 && inst.HasFlag(InstructionFlags.EndPointUnreachable)) { + if (i == block.Instructions.Count - 2 && inst.HasFlag(InstructionFlags.EndPointUnreachable)) + { context.Step("Remove unreachable exit", block.Instructions.Last()); block.Instructions.RemoveLast(); @@ -146,7 +156,8 @@ namespace ICSharpCode.Decompiler.IL // search for child containers to reduce nesting in private void VisitContainers(ILInstruction inst, Block continueTarget) { - switch (inst) { + switch (inst) + { case ILFunction _: break; // assume inline ILFunctions are already transformed case BlockContainer cont: @@ -177,7 +188,8 @@ namespace ICSharpCode.Decompiler.IL if (trueRangeIsEmpty || falseRangeIsEmpty || falseRangeStart >= trueRangeStart) return; - if (block.Instructions.Last() is Leave leave && !leave.IsLeavingFunction && leave.TargetContainer.Kind == ContainerKind.Normal) { + if (block.Instructions.Last() is Leave leave && !leave.IsLeavingFunction && leave.TargetContainer.Kind == ContainerKind.Normal) + { // non-keyword leave. Can't move out of the last position in the block (fall-through) without introducing goto, unless it can be replaced with a keyword (return/continue) if (!CanDuplicateExit(block.Instructions.Last(), continueTarget, out var keywordExit)) return; @@ -200,7 +212,8 @@ namespace ICSharpCode.Decompiler.IL UpdateStats(ifInst.TrueInst, ref maxStatements, ref maxDepth); // if (cond) { ... } exit; - if (ifInst.FalseInst.MatchNop()) { + if (ifInst.FalseInst.MatchNop()) + { // a separate heuristic to ShouldReduceNesting as there is visual balancing to be performed based on number of statments if (maxDepth < 2) return false; @@ -210,14 +223,15 @@ namespace ICSharpCode.Decompiler.IL // ...; exit; EnsureEndPointUnreachable(block, exitInst); Debug.Assert(ifInst == block.Instructions.SecondToLastOrDefault()); - + // use the same exit the block has. If the block already has one (such as a leave from a try), keep it in place EnsureEndPointUnreachable(ifInst.TrueInst, block.Instructions.Last()); ConditionDetection.InvertIf(block, ifInst, context); // ensure the exit inst of the if instruction is a keyword Debug.Assert(!(ifInst.TrueInst is Block)); - if (!ifInst.TrueInst.Match(exitInst).Success) { + if (!ifInst.TrueInst.Match(exitInst).Success) + { Debug.Assert(ifInst.TrueInst is Leave); context.Step("Replace leave with keyword exit", ifInst.TrueInst); ifInst.TrueInst.ReplaceWith(exitInst.Clone()); @@ -228,30 +242,34 @@ namespace ICSharpCode.Decompiler.IL // else-if trees are considered as a single group from the root IfInstruction if (GetElseIfParent(ifInst) != null) return false; - + // find the else block and tally stats for each else-if block - while (Block.Unwrap(ifInst.FalseInst) is IfInstruction elseIfInst) { + while (Block.Unwrap(ifInst.FalseInst) is IfInstruction elseIfInst) + { UpdateStats(elseIfInst.TrueInst, ref maxStatements, ref maxDepth); ifInst = elseIfInst; } if (!ShouldReduceNesting(ifInst.FalseInst, maxStatements, maxDepth)) return false; - + // extract the else block and insert exit points all the way up the else-if tree - do { + do + { var elseIfInst = GetElseIfParent(ifInst); - + // if (cond) { ... } else { ... } exit; // -> // if (cond) { ...; exit; } // ...; exit; EnsureEndPointUnreachable(ifInst.TrueInst, exitInst); - if (ifInst.FalseInst.HasFlag(InstructionFlags.EndPointUnreachable)) { + if (ifInst.FalseInst.HasFlag(InstructionFlags.EndPointUnreachable)) + { Debug.Assert(ifInst.HasFlag(InstructionFlags.EndPointUnreachable)); Debug.Assert(ifInst.Parent == block); int removeAfter = ifInst.ChildIndex + 1; - if (removeAfter < block.Instructions.Count) { + if (removeAfter < block.Instructions.Count) + { // Remove all instructions that ended up dead // (this should just be exitInst itself) Debug.Assert(block.Instructions.SecondToLastOrDefault() == ifInst); @@ -265,7 +283,7 @@ namespace ICSharpCode.Decompiler.IL return true; } - + /// /// Reduce Nesting in switch statements by replacing break; in cases with the block exit, and extracting the default case /// Does not affect IL order @@ -283,7 +301,7 @@ namespace ICSharpCode.Decompiler.IL return false; if (defaultBlock.Parent != switchContainer) return false; - + // tally stats for heuristic from each case block int maxStatements = 0, maxDepth = 0; foreach (var section in switchInst.Sections) @@ -292,7 +310,7 @@ namespace ICSharpCode.Decompiler.IL if (!ShouldReduceNesting(defaultBlock, maxStatements, maxDepth)) return false; - + Debug.Assert(defaultBlock.HasFlag(InstructionFlags.EndPointUnreachable)); // ensure the default case dominator tree has no exits (branches to other cases) @@ -310,10 +328,11 @@ namespace ICSharpCode.Decompiler.IL // if the switch container is followed by an instruction, it must be a Leave from a try/pinned/etc or exitInst // When it's a leave from a container, it's better to let the extracted default block 'fall through' rather than duplicating whatever // instruction eventually follows the container - if (parentBlock.Instructions.SecondToLastOrDefault() == switchContainer) { + if (parentBlock.Instructions.SecondToLastOrDefault() == switchContainer) + { if (defaultBlock.Instructions.Last().MatchLeave(switchContainer)) defaultBlock.Instructions.Last().ReplaceWith(parentBlock.Instructions.Last()); - + parentBlock.Instructions.RemoveLast(); } @@ -335,7 +354,8 @@ namespace ICSharpCode.Decompiler.IL // add any additional blocks from the default case to the parent container Debug.Assert(defaultBlocks[0] == defaultBlock); - if (defaultBlocks.Count > 1) { + if (defaultBlocks.Count > 1) + { var parentContainer = (BlockContainer)parentBlock.Parent; int insertAt = parentContainer.Blocks.IndexOf(parentBlock) + 1; foreach (var block in defaultBlocks.Skip(1)) @@ -363,18 +383,23 @@ namespace ICSharpCode.Decompiler.IL // leave from a try/pinned/lock etc, check if the target (the instruction following the target container) is duplicable, if so, set keywordExit to that ILInstruction leavingInst = leave.TargetContainer; Debug.Assert(!leavingInst.HasFlag(InstructionFlags.EndPointUnreachable)); - while (!(leavingInst.Parent is Block b) || leavingInst == b.Instructions.Last()) { - if (leavingInst.Parent is TryFinally tryFinally) { - if (leavingInst.SlotInfo == TryFinally.FinallyBlockSlot) { // cannot duplicate leaves from finally containers + while (!(leavingInst.Parent is Block b) || leavingInst == b.Instructions.Last()) + { + if (leavingInst.Parent is TryFinally tryFinally) + { + if (leavingInst.SlotInfo == TryFinally.FinallyBlockSlot) + { // cannot duplicate leaves from finally containers Debug.Assert(leave.TargetContainer == tryFinally.FinallyBlock); //finally cannot have control flow return false; } - if (tryFinally.HasFlag(InstructionFlags.EndPointUnreachable)) { // finally block changes return value/throws an exception? Yikes. Lets leave it alone + if (tryFinally.HasFlag(InstructionFlags.EndPointUnreachable)) + { // finally block changes return value/throws an exception? Yikes. Lets leave it alone Debug.Assert(tryFinally.FinallyBlock.HasFlag(InstructionFlags.EndPointUnreachable)); return false; } } - else if (leavingInst.Parent is TryFault tryFault && leavingInst.SlotInfo == TryFault.FaultBlockSlot) { // cannot duplicate leaves from fault containers either + else if (leavingInst.Parent is TryFault tryFault && leavingInst.SlotInfo == TryFault.FaultBlockSlot) + { // cannot duplicate leaves from fault containers either Debug.Assert(leave.TargetContainer == tryFault.FaultBlock); return false; } @@ -385,7 +410,7 @@ namespace ICSharpCode.Decompiler.IL } var block = (Block)leavingInst.Parent; - var targetInst = block.Instructions[block.Instructions.IndexOf(leavingInst)+1]; + var targetInst = block.Instructions[block.Instructions.IndexOf(leavingInst) + 1]; return CanDuplicateExit(targetInst, continueTarget, out keywordExit); } @@ -396,12 +421,14 @@ namespace ICSharpCode.Decompiler.IL /// The next instruction to be executed (provided inst does not exit) private void EnsureEndPointUnreachable(ILInstruction inst, ILInstruction fallthroughExit) { - if (!(inst is Block block)) { + if (!(inst is Block block)) + { Debug.Assert(inst.HasFlag(InstructionFlags.EndPointUnreachable)); return; } - if (!block.HasFlag(InstructionFlags.EndPointUnreachable)) { + if (!block.HasFlag(InstructionFlags.EndPointUnreachable)) + { context.Step("Duplicate block exit", fallthroughExit); block.Instructions.Add(fallthroughExit.Clone()); } @@ -412,7 +439,8 @@ namespace ICSharpCode.Decompiler.IL /// private void RemoveRedundantExit(Block block, ILInstruction implicitExit) { - if (block.Instructions.Last().Match(implicitExit).Success) { + if (block.Instructions.Last().Match(implicitExit).Success) + { context.Step("Remove redundant exit", block.Instructions.Last()); block.Instructions.RemoveLast(); } @@ -443,7 +471,7 @@ namespace ICSharpCode.Decompiler.IL ComputeStats(inst, ref numStatements, ref maxDepth, 0); maxStatements = Math.Max(numStatements, maxStatements); } - + /// /// Recursively computes the number of statements and maximum nested depth of an instruction /// @@ -452,13 +480,15 @@ namespace ICSharpCode.Decompiler.IL if (isStatement) numStatements++; - if (currentDepth > maxDepth) { + if (currentDepth > maxDepth) + { Debug.Assert(isStatement); maxDepth = currentDepth; } // enumerate children statements and containers - switch (inst) { + switch (inst) + { case Block block: if (isStatement) numStatements--; // don't count blocks as statements @@ -475,7 +505,8 @@ namespace ICSharpCode.Decompiler.IL numStatements++; //always add a statement for a container in an expression var containerBody = container.EntryPoint; - if (container.Kind == ContainerKind.For || container.Kind == ContainerKind.While) { + if (container.Kind == ContainerKind.For || container.Kind == ContainerKind.While) + { Debug.Assert(isStatement); if (!container.MatchConditionBlock(container.EntryPoint, out _, out containerBody)) @@ -489,7 +520,7 @@ namespace ICSharpCode.Decompiler.IL container.Kind == ContainerKind.Normal && lastInst.MatchLeave(container) || container.Kind == ContainerKind.Switch) // SwitchInstructyion always counts as a statement anyway, so no need to count the container as well numStatements--; - + // add the nested body ComputeStats(containerBody, ref numStatements, ref maxDepth, currentDepth + 1); break; @@ -500,12 +531,13 @@ namespace ICSharpCode.Decompiler.IL // include all nested else-if instructions at the same depth var elseInst = ifInst.FalseInst; - while (Block.Unwrap(elseInst) is IfInstruction elseIfInst) { + while (Block.Unwrap(elseInst) is IfInstruction elseIfInst) + { numStatements++; ComputeStats(elseIfInst.TrueInst, ref numStatements, ref maxDepth, currentDepth + 1); elseInst = elseIfInst.FalseInst; } - + // include all nested else instruction ComputeStats(elseInst, ref numStatements, ref maxDepth, currentDepth + 1); break; @@ -525,7 +557,8 @@ namespace ICSharpCode.Decompiler.IL int bodyStatements = 0; int bodyMaxDepth = maxDepth; ComputeStats(func.Body, ref bodyStatements, ref bodyMaxDepth, currentDepth); - if (bodyStatements >= 2) { // don't count inline functions + if (bodyStatements >= 2) + { // don't count inline functions numStatements += bodyStatements; maxDepth = bodyMaxDepth; } @@ -558,7 +591,7 @@ namespace ICSharpCode.Decompiler.IL // if the max depth is 2, always reduce nesting (total depth 3 or more) // if the max depth is 1, reduce nesting if this block is the largest // otherwise reduce nesting only if this block is twice as large as any other - return maxDepth2 >= 2 || maxDepth2 >= 1 && maxStatements2 > maxStatements || maxStatements2 >= 2*maxStatements; + return maxDepth2 >= 2 || maxDepth2 >= 1 && maxStatements2 > maxStatements || maxStatements2 >= 2 * maxStatements; } /// @@ -606,7 +639,8 @@ namespace ICSharpCode.Decompiler.IL // Finally is empty and redundant. But we'll delete the block only if there's a PinnedRegion. if (!(tryFinally.TryBlock is BlockContainer tryContainer)) return; - if (tryContainer.SingleInstruction() is PinnedRegion pinnedRegion) { + if (tryContainer.SingleInstruction() is PinnedRegion pinnedRegion) + { context.Step("Removing try-finally around PinnedRegion", pinnedRegion); tryFinally.ReplaceWith(pinnedRegion); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs b/ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs index 43cb2e577..6a95e4c3d 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.TypeSystem; @@ -41,9 +42,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms // This is necessary to remove useless stores generated by some compilers, e.g., the F# compiler. // In yield return + async, the C# compiler tends to store null/default(T) to variables // when the variable goes out of scope. - if (function.IsAsync || function.IsIterator || context.Settings.RemoveDeadStores) { + if (function.IsAsync || function.IsIterator || context.Settings.RemoveDeadStores) + { var variableQueue = new Queue(function.Variables); - while (variableQueue.Count > 0) { + while (variableQueue.Count > 0) + { var v = variableQueue.Dequeue(); if (v.Kind != VariableKind.Local && v.Kind != VariableKind.StackSlot) continue; @@ -53,14 +56,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms continue; if (v.LoadCount != 0 || v.AddressCount != 0) continue; - foreach (var stloc in v.StoreInstructions.OfType().ToArray()) { - if (stloc.Parent is Block block) { - if (SemanticHelper.IsPure(stloc.Value.Flags)) { + foreach (var stloc in v.StoreInstructions.OfType().ToArray()) + { + if (stloc.Parent is Block block) + { + if (SemanticHelper.IsPure(stloc.Value.Flags)) + { block.Instructions.Remove(stloc); - } else { + } + else + { stloc.ReplaceWith(stloc.Value); } - if (stloc.Value is LdLoc ldloc) { + if (stloc.Value is LdLoc ldloc) + { variableQueue.Enqueue(ldloc.Variable); } } @@ -69,14 +78,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms } // Try to infer IType of stack slots that are of StackType.Ref: - foreach (var v in function.Variables) { - if (v.Kind == VariableKind.StackSlot && v.StackType == StackType.Ref && v.AddressCount == 0) { + foreach (var v in function.Variables) + { + if (v.Kind == VariableKind.StackSlot && v.StackType == StackType.Ref && v.AddressCount == 0) + { IType newType = null; // Multiple store are possible in case of (c ? ref a : ref b) += 1, for example. - foreach (var stloc in v.StoreInstructions.OfType()) { + foreach (var stloc in v.StoreInstructions.OfType()) + { var inferredType = stloc.Value.InferType(context.TypeSystem); // cancel, if types of values do not match exactly - if (newType != null && !newType.Equals(inferredType)) { + if (newType != null && !newType.Equals(inferredType)) + { newType = SpecialType.UnknownType; break; } @@ -93,8 +106,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms { var visitor = new DefiniteAssignmentVisitor(function, context.CancellationToken); function.AcceptVisitor(visitor); - foreach (var v in function.Variables) { - if (v.Kind != VariableKind.Parameter && !visitor.IsPotentiallyUsedUninitialized(v)) { + foreach (var v in function.Variables) + { + if (v.Kind != VariableKind.Parameter && !visitor.IsPotentiallyUsedUninitialized(v)) + { v.HasInitialValue = false; } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs b/ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs index 5f7473fb1..18216219c 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs @@ -18,10 +18,11 @@ using System.Collections.Generic; using System.Linq; -using ICSharpCode.Decompiler.FlowAnalysis; -using ICSharpCode.Decompiler.Util; using System.Threading; + +using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL.Transforms { @@ -35,8 +36,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms var groupStores = new GroupStores(function, context.CancellationToken); function.Body.AcceptVisitor(groupStores); // Replace analyzed variables with their split versions: - foreach (var inst in function.Descendants.OfType()) { - if (groupStores.IsAnalyzedVariable(inst.Variable)) { + foreach (var inst in function.Descendants.OfType()) + { + if (groupStores.IsAnalyzedVariable(inst.Variable)) + { inst.Variable = groupStores.GetNewVariable(inst); } } @@ -45,10 +48,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool IsCandidateVariable(ILVariable v) { - switch (v.Kind) { + switch (v.Kind) + { case VariableKind.Local: - foreach (var ldloca in v.AddressInstructions) { - if (DetermineAddressUse(ldloca, ldloca.Variable) == AddressUse.Unknown) { + foreach (var ldloca in v.AddressInstructions) + { + if (DetermineAddressUse(ldloca, ldloca.Variable) == AddressUse.Unknown) + { // If we don't understand how the address is being used, // we can't split the variable. return false; @@ -95,7 +101,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static AddressUse DetermineAddressUse(ILInstruction addressLoadingInstruction, ILVariable targetVar) { - switch (addressLoadingInstruction.Parent) { + switch (addressLoadingInstruction.Parent) + { case LdObj ldobj: return AddressUse.Immediate; case LdFlda ldflda: @@ -110,15 +117,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!(stloc.Variable.Kind == VariableKind.StackSlot || stloc.Variable.Kind == VariableKind.Local)) return AddressUse.Unknown; var value = stloc.Value; - while (value is LdFlda ldFlda) { + while (value is LdFlda ldFlda) + { value = ldFlda.Target; } - if (value.OpCode != OpCode.LdLoca) { + if (value.OpCode != OpCode.LdLoca) + { // GroupStores only handles ref-locals correctly when they are supported by GetAddressLoadForRefLocalUse(), // which only works for ldflda*(ldloca) return AddressUse.Unknown; } - foreach (var load in stloc.Variable.LoadInstructions) { + foreach (var load in stloc.Variable.LoadInstructions) + { if (DetermineAddressUse(load, targetVar) != AddressUse.Immediate) return AddressUse.Unknown; } @@ -134,20 +144,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms // We'll assume the method only uses the address locally, // unless we can see an address being returned from the method: IType returnType = (call is NewObj) ? call.Method.DeclaringType : call.Method.ReturnType; - if (returnType.IsByRefLike) { + if (returnType.IsByRefLike) + { // If the address is returned from the method, it check whether it's consumed immediately. // This can still be fine, as long as we also check the consumer's other arguments for 'stloc targetVar'. if (DetermineAddressUse(call, targetVar) != AddressUse.Immediate) return AddressUse.Unknown; } - foreach (var p in call.Method.Parameters) { + foreach (var p in call.Method.Parameters) + { // catch "out Span" and similar if (p.Type.SkipModifiers() is ByReferenceType brt && brt.ElementType.IsByRefLike) return AddressUse.Unknown; } // ensure there's no 'stloc target' in between the ldloca and the call consuming the address - for (int i = addressLoadingInstruction.ChildIndex + 1; i < call.Arguments.Count; i++) { - foreach (var inst in call.Arguments[i].Descendants) { + for (int i = addressLoadingInstruction.ChildIndex + 1; i < call.Arguments.Count; i++) + { + foreach (var inst in call.Arguments[i].Descendants) + { if (inst is StLoc store && store.Variable == targetVar) return AddressUse.Unknown; } @@ -164,9 +178,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!ldloc.Variable.IsSingleDefinition) return null; // only single-definition variables can be supported ref locals var store = ldloc.Variable.StoreInstructions.SingleOrDefault(); - if (store is StLoc stloc) { + if (store is StLoc stloc) + { var value = stloc.Value; - while (value is LdFlda ldFlda) { + while (value is LdFlda ldFlda) + { value = ldFlda.Target; } return value as LdLoca; @@ -190,7 +206,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// Used to merge together all such loads of the same uninitialized value. /// readonly Dictionary uninitVariableUsage = new Dictionary(); - + public GroupStores(ILFunction scope, CancellationToken cancellationToken) : base(scope, IsCandidateVariable, cancellationToken) { } @@ -200,7 +216,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms base.VisitLdLoc(inst); HandleLoad(inst); var refLocalAddressLoad = GetAddressLoadForRefLocalUse(inst); - if (refLocalAddressLoad != null) { + if (refLocalAddressLoad != null) + { // SupportedRefLocal: act as if we copy-propagated the ldloca // to the point of use: HandleLoad(refLocalAddressLoad); @@ -215,23 +232,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms void HandleLoad(IInstructionWithVariableOperand inst) { - if (IsAnalyzedVariable(inst.Variable)) { - if (IsPotentiallyUninitialized(state, inst.Variable)) { + if (IsAnalyzedVariable(inst.Variable)) + { + if (IsPotentiallyUninitialized(state, inst.Variable)) + { // merge all uninit loads together: - if (uninitVariableUsage.TryGetValue(inst.Variable, out var uninitLoad)) { + if (uninitVariableUsage.TryGetValue(inst.Variable, out var uninitLoad)) + { unionFind.Merge(inst, uninitLoad); - } else { + } + else + { uninitVariableUsage.Add(inst.Variable, inst); } } - foreach (var store in GetStores(state, inst.Variable)) { + foreach (var store in GetStores(state, inst.Variable)) + { unionFind.Merge(inst, (IInstructionWithVariableOperand)store); } } } - + readonly Dictionary newVariables = new Dictionary(); - + /// /// Gets the new variable for a LdLoc, StLoc or TryCatchHandler instruction. /// @@ -239,7 +262,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { var representative = unionFind.Find(inst); ILVariable v; - if (!newVariables.TryGetValue(representative, out v)) { + if (!newVariables.TryGetValue(representative, out v)) + { v = new ILVariable(inst.Variable.Kind, inst.Variable.Type, inst.Variable.StackType, inst.Variable.Index); v.Name = inst.Variable.Name; v.HasGeneratedName = inst.Variable.HasGeneratedName; @@ -248,7 +272,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms newVariables.Add(representative, v); inst.Variable.Function.Variables.Add(v); } - if (inst.Variable.HasInitialValue && uninitVariableUsage.TryGetValue(inst.Variable, out var uninitLoad) && uninitLoad == inst) { + if (inst.Variable.HasInitialValue && uninitVariableUsage.TryGetValue(inst.Variable, out var uninitLoad) && uninitLoad == inst) + { v.HasInitialValue = true; } return v; diff --git a/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs index 27d83877f..d19643ca6 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs @@ -80,7 +80,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// public void RequestRerun(int pos) { - if (rerunPosition == null || pos > rerunPosition) { + if (rerunPosition == null || pos > rerunPosition) + { rerunPosition = pos; } } @@ -101,7 +102,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms public class StatementTransform : IBlockTransform { readonly IStatementTransform[] children; - + public StatementTransform(params IStatementTransform[] children) { this.children = children; @@ -112,11 +113,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms var ctx = new StatementTransformContext(context); int pos = 0; ctx.rerunPosition = block.Instructions.Count - 1; - while (pos >= 0) { - if (ctx.rerunPosition != null) { + while (pos >= 0) + { + if (ctx.rerunPosition != null) + { Debug.Assert(ctx.rerunPosition >= pos); #if DEBUG - for (; pos < ctx.rerunPosition; ++pos) { + for (; pos < ctx.rerunPosition; ++pos) + { block.Instructions[pos].ResetDirty(); } #else @@ -125,26 +129,32 @@ namespace ICSharpCode.Decompiler.IL.Transforms Debug.Assert(pos == ctx.rerunPosition); ctx.rerunPosition = null; } - foreach (var transform in children) { + foreach (var transform in children) + { Debug.Assert(block.HasFlag(InstructionFlags.EndPointUnreachable)); transform.Run(block, pos, ctx); #if DEBUG block.Instructions[pos].CheckInvariant(ILPhase.Normal); - for (int i = Math.Max(0, pos - 100); i < pos; ++i) { - if (block.Instructions[i].IsDirty) { + for (int i = Math.Max(0, pos - 100); i < pos; ++i) + { + if (block.Instructions[i].IsDirty) + { Debug.Fail($"{transform.GetType().Name} modified an instruction before pos"); } } #endif - if (ctx.rerunCurrentPosition) { + if (ctx.rerunCurrentPosition) + { ctx.rerunCurrentPosition = false; ctx.RequestRerun(pos); } - if (ctx.rerunPosition != null) { + if (ctx.rerunPosition != null) + { break; } } - if (ctx.rerunPosition == null) { + if (ctx.rerunPosition == null) + { pos--; } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/Stepper.cs b/ICSharpCode.Decompiler/IL/Transforms/Stepper.cs index 0645066bc..76aa63ff0 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/Stepper.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/Stepper.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL.Transforms @@ -80,7 +81,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms steps = new List(); groups = new Stack(); } - + /// /// Call this method immediately before performing a transform step. /// Used for debugging the IL transforms. Has no effect in release mode. @@ -94,7 +95,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms private Node StepInternal(string description, ILInstruction near) { - if (step == StepLimit) { + if (step == StepLimit) + { if (IsDebug) Debugger.Break(); else @@ -123,7 +125,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms public void EndGroup(bool keepIfEmpty = false) { var node = groups.Pop(); - if (!keepIfEmpty && node.Children.Count == 0) { + if (!keepIfEmpty && node.Children.Count == 0) + { var col = groups.PeekOrDefault()?.Children ?? steps; Debug.Assert(col.Last() == node); col.RemoveAt(col.Count - 1); diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs index 9d022a3c8..7490a3206 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.IL.ControlFlow; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -37,11 +38,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms HashSet changedContainers = new HashSet(); - foreach (var block in function.Descendants.OfType()) { + foreach (var block in function.Descendants.OfType()) + { bool changed = false; - for (int i = block.Instructions.Count - 1; i >= 0; i--) { + for (int i = block.Instructions.Count - 1; i >= 0; i--) + { SwitchInstruction newSwitch; - if (MatchSwitchOnNullable(block.Instructions, i, out newSwitch)) { + if (MatchSwitchOnNullable(block.Instructions, i, out newSwitch)) + { newSwitch.AddILRange(block.Instructions[i - 2]); block.Instructions[i + 1].ReplaceWith(newSwitch); block.Instructions.RemoveRange(i - 2, 3); @@ -49,7 +53,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms changed = true; continue; } - if (MatchRoslynSwitchOnNullable(block.Instructions, i, out newSwitch)) { + if (MatchRoslynSwitchOnNullable(block.Instructions, i, out newSwitch)) + { newSwitch.AddILRange(block.Instructions[i]); newSwitch.AddILRange(block.Instructions[i + 1]); block.Instructions[i].ReplaceWith(newSwitch); @@ -58,7 +63,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms continue; } } - if (!changed) continue; + if (!changed) + continue; SwitchDetection.SimplifySwitchInstruction(block, context); if (block.Parent is BlockContainer container) changedContainers.Add(container); @@ -79,7 +85,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // stloc switchVariable(call GetValueOrDefault(ldloc tmp)) // if (logic.not(call get_HasValue(ldloc tmp))) br nullCaseBlock // br switchBlock - if (i < 2) return false; + if (i < 2) + return false; if (!instructions[i - 2].MatchStLoc(out var tmp, out var ldloca) || !instructions[i - 1].MatchStLoc(out var switchVariable, out var getValueOrDefault) || !instructions[i].MatchIfInstruction(out var condition, out var trueInst)) @@ -149,8 +156,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (switchBlock.IncomingEdgeCount != 1) return false; SwitchInstruction switchInst; - switch (switchBlock.Instructions.Count) { - case 2: { + switch (switchBlock.Instructions.Count) + { + case 2: + { // this is the normal case described by the pattern above if (!switchBlock.Instructions[0].MatchStLoc(out var switchVar, out var getValueOrDefault)) return false; @@ -163,7 +172,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms switchInst = si; break; } - case 1: { + case 1: + { // this is the special case where `call GetValueOrDefault(ldloca tmp)` is inlined into the switch. if (!(switchBlock.Instructions[0] is SwitchInstruction si)) return false; @@ -172,7 +182,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms switchInst = si; break; } - default: { + default: + { return false; } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs index 45757c3e3..0fffa2a28 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs @@ -46,33 +46,41 @@ namespace ICSharpCode.Decompiler.IL.Transforms HashSet changedContainers = new HashSet(); - foreach (var block in function.Descendants.OfType()) { + foreach (var block in function.Descendants.OfType()) + { bool changed = false; if (block.IncomingEdgeCount == 0) continue; - for (int i = block.Instructions.Count - 1; i >= 0; i--) { - if (SimplifyCascadingIfStatements(block.Instructions, ref i)) { + for (int i = block.Instructions.Count - 1; i >= 0; i--) + { + if (SimplifyCascadingIfStatements(block.Instructions, ref i)) + { changed = true; continue; } - if (SimplifyCSharp1CascadingIfStatements(block.Instructions, ref i)) { + if (SimplifyCSharp1CascadingIfStatements(block.Instructions, ref i)) + { changed = true; continue; } - if (MatchLegacySwitchOnStringWithHashtable(block, hashtableInitializers, ref i)) { + if (MatchLegacySwitchOnStringWithHashtable(block, hashtableInitializers, ref i)) + { changed = true; continue; } - if (MatchLegacySwitchOnStringWithDict(block.Instructions, ref i)) { + if (MatchLegacySwitchOnStringWithDict(block.Instructions, ref i)) + { changed = true; continue; } - if (MatchRoslynSwitchOnString(block.Instructions, ref i)) { + if (MatchRoslynSwitchOnString(block.Instructions, ref i)) + { changed = true; continue; } } - if (!changed) continue; + if (!changed) + continue; SwitchDetection.SimplifySwitchInstruction(block, context); if (block.Parent is BlockContainer container) changedContainers.Add(container); @@ -81,13 +89,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms var omittedBlocks = new Dictionary(); // Remove all transformed hashtable initializers from the entrypoint. - foreach (var item in hashtableInitializers) { + foreach (var item in hashtableInitializers) + { var (labels, jumpToNext, containingBlock, previous, next, transformed) = item.Value; - if (!transformed) continue; + if (!transformed) + continue; if (!omittedBlocks.TryGetValue(previous, out var actual)) actual = previous; context.Step("Remove hashtable initializer", actual); - if (jumpToNext != null) { + if (jumpToNext != null) + { actual.Instructions.SecondToLastOrDefault().ReplaceWith(jumpToNext); } actual.Instructions.LastOrDefault().ReplaceWith(new Branch(next)); @@ -96,9 +107,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms } // If all initializer where removed, remove the initial null check as well. - if (hashtableInitializers.Count > 0 && omittedBlocks.Count == hashtableInitializers.Count && body.EntryPoint.Instructions.Count == 2) { + if (hashtableInitializers.Count > 0 && omittedBlocks.Count == hashtableInitializers.Count && body.EntryPoint.Instructions.Count == 2) + { if (body.EntryPoint.Instructions[0] is IfInstruction ifInst - && ifInst.TrueInst.MatchBranch(out var beginOfMethod) && body.EntryPoint.Instructions[1].MatchBranch(beginOfMethod)) { + && ifInst.TrueInst.MatchBranch(out var beginOfMethod) && body.EntryPoint.Instructions[1].MatchBranch(beginOfMethod)) + { context.Step("Remove initial null check", body); body.EntryPoint.Instructions.RemoveAt(0); } @@ -134,7 +147,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (tableInitBlock.IncomingEdgeCount != 1 || tableInitBlock.Instructions.Count < 3) return hashtables; Block previousBlock = entryPoint; - while (tableInitBlock != null) { + while (tableInitBlock != null) + { if (!ExtractStringValuesFromInitBlock(tableInitBlock, out var stringValues, out var blockAfterThisInitBlock, dictionaryType, dictField, true)) break; var nextHashtableInitHead = tableInitBlock.Instructions.SecondToLastOrDefault() as IfInstruction; @@ -142,7 +156,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms previousBlock = tableInitBlock; // if there is another IfInstruction before the end of the block, it might be a jump to the next hashtable init block. // if (comp(volatile.ldobj System.Collections.Hashtable(ldsflda $$method0x600003f-2) != ldnull)) br switchHeadBlock - if (nextHashtableInitHead != null) { + if (nextHashtableInitHead != null) + { if (!(nextHashtableInitHead.Condition.MatchCompNotEquals(out left, out right) && right.MatchLdNull() && MatchDictionaryFieldLoad(left, IsNonGenericHashtable, out var nextDictField, out _))) break; @@ -150,7 +165,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms break; tableInitBlock = blockAfterThisInitBlock; dictField = nextDictField; - } else { + } + else + { break; } } @@ -166,23 +183,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!instructions[i].MatchIfInstruction(out var condition, out var firstBlockOrDefaultJump)) return false; var nextCaseJump = instructions[i + 1]; - while (condition.MatchLogicNot(out var arg)) { + while (condition.MatchLogicNot(out var arg)) + { condition = arg; ExtensionMethods.Swap(ref firstBlockOrDefaultJump, ref nextCaseJump); } // match call to operator ==(string, string) if (!MatchStringEqualityComparison(condition, out var switchValueVar, out string firstBlockValue, out bool isVBCompareString)) return false; - if (isVBCompareString) { + if (isVBCompareString) + { ExtensionMethods.Swap(ref firstBlockOrDefaultJump, ref nextCaseJump); } - if (firstBlockOrDefaultJump.MatchBranch(out var firstBlock)) { + if (firstBlockOrDefaultJump.MatchBranch(out var firstBlock)) + { // success - } else if (firstBlockOrDefaultJump.MatchLeave(out _)) { + } + else if (firstBlockOrDefaultJump.MatchLeave(out _)) + { firstBlock = null; // success - } else { + } + else + { return false; } @@ -200,30 +224,38 @@ namespace ICSharpCode.Decompiler.IL.Transforms } ILInstruction switchValue = null; - if (isVBCompareString && string.IsNullOrEmpty(firstBlockValue)) { + if (isVBCompareString && string.IsNullOrEmpty(firstBlockValue)) + { if (!AddSwitchSection(null, firstBlock ?? firstBlockOrDefaultJump)) return false; if (!AddSwitchSection(string.Empty, firstBlock ?? firstBlockOrDefaultJump)) return false; - } else { + } + else + { if (!AddSwitchSection(firstBlockValue, firstBlock ?? firstBlockOrDefaultJump)) return false; } bool removeExtraLoad = false; bool keepAssignmentBefore = false; - if (i >= 1 && instructions[i - 1].MatchStLoc(switchValueVar, out switchValue)) { + if (i >= 1 && instructions[i - 1].MatchStLoc(switchValueVar, out switchValue)) + { // stloc switchValueVar(switchValue) // if (call op_Equality(ldloc switchValueVar, ldstr value)) br firstBlock // Newer versions of Roslyn use extra variables: if (i >= 2 && switchValue.MatchLdLoc(out var otherSwitchValueVar) && otherSwitchValueVar.IsSingleDefinition && otherSwitchValueVar.LoadCount == 1 - && instructions[i - 2].MatchStLoc(otherSwitchValueVar, out var newSwitchValue)) { + && instructions[i - 2].MatchStLoc(otherSwitchValueVar, out var newSwitchValue)) + { switchValue = newSwitchValue; removeExtraLoad = true; } - } else if (i >= 1 && instructions[i - 1] is StLoc stloc) { - if (stloc.Value.MatchLdLoc(switchValueVar)) { + } + else if (i >= 1 && instructions[i - 1] is StLoc stloc) + { + if (stloc.Value.MatchLdLoc(switchValueVar)) + { // in case of optimized legacy code there are two stlocs: // stloc otherSwitchValueVar(ldloc switchValue) // stloc switchValueVar(ldloc otherSwitchValueVar) @@ -232,17 +264,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms switchValueVar = stloc.Variable; numberOfUniqueMatchesWithCurrentVariable = 0; if (i >= 2 && instructions[i - 2].MatchStLoc(otherSwitchValueVar, out switchValue) - && otherSwitchValueVar.IsSingleDefinition && otherSwitchValueVar.LoadCount == 2) { + && otherSwitchValueVar.IsSingleDefinition && otherSwitchValueVar.LoadCount == 2) + { removeExtraLoad = true; - } else { + } + else + { switchValue = new LdLoc(otherSwitchValueVar); } - } else { + } + else + { // Variable before the start of the switch is not related to the switch. keepAssignmentBefore = true; switchValue = new LdLoc(switchValueVar); } - } else { + } + else + { // Instruction before the start of the switch is not related to the switch. keepAssignmentBefore = true; switchValue = new LdLoc(switchValueVar); @@ -252,16 +291,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; // extract all cases and add them to the values list. ILInstruction nextCaseBlock; - do { + do + { nextCaseBlock = MatchCaseBlock(currentCaseBlock, switchValueVar, out string value, out bool emptyStringEqualsNull, out ILInstruction block); if (nextCaseBlock == null) break; - if (emptyStringEqualsNull && string.IsNullOrEmpty(value)) { + if (emptyStringEqualsNull && string.IsNullOrEmpty(value)) + { if (!AddSwitchSection(null, block)) return false; if (!AddSwitchSection(string.Empty, block)) return false; - } else { + } + else + { if (!AddSwitchSection(value, block)) return false; } @@ -273,7 +316,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; context.Step(nameof(SimplifyCascadingIfStatements), instructions[i]); // if the switchValueVar is used in other places as well, do not eliminate the store. - if (switchValueVar.LoadCount > numberOfUniqueMatchesWithCurrentVariable) { + if (switchValueVar.LoadCount > numberOfUniqueMatchesWithCurrentVariable) + { keepAssignmentBefore = true; removeExtraLoad = false; // prevent loads from being deleted after detecting that // we have to keep the assignment before the switch statement @@ -285,17 +329,23 @@ namespace ICSharpCode.Decompiler.IL.Transforms var stringToInt = new StringToInt(switchValue, values.Skip(offset).Select(item => item.Item1).ToArray()); var inst = new SwitchInstruction(stringToInt); inst.Sections.AddRange(sections); - if (removeExtraLoad) { + if (removeExtraLoad) + { inst.AddILRange(instructions[i - 2]); instructions[i - 2].ReplaceWith(inst); instructions.RemoveRange(i - 1, 3); i -= 2; - } else { - if (keepAssignmentBefore) { + } + else + { + if (keepAssignmentBefore) + { inst.AddILRange(instructions[i]); instructions[i].ReplaceWith(inst); instructions.RemoveAt(i + 1); - } else { + } + else + { inst.AddILRange(instructions[i - 1]); instructions[i - 1].ReplaceWith(inst); instructions.RemoveRange(i, 2); @@ -307,7 +357,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool SimplifyCSharp1CascadingIfStatements(InstructionCollection instructions, ref int i) { - if (i < 1) return false; + if (i < 1) + return false; // match first block: // stloc switchValueVar(ldloc temp) // if (comp(ldloc temp == ldnull)) br defaultBlock @@ -344,7 +395,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // if (comp(ldloc switchValueVar == ldstr "case label")) br caseBlock // br currentCaseBlock - while (currentCaseBlock.Instructions[conditionOffset].MatchIfInstruction(out condition, out var caseBlockJump)) { + while (currentCaseBlock.Instructions[conditionOffset].MatchIfInstruction(out condition, out var caseBlockJump)) + { if (currentCaseBlock.Instructions.Count != conditionOffset + 2) break; if (!condition.MatchCompEquals(out var left, out var right)) @@ -366,7 +418,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step(nameof(SimplifyCSharp1CascadingIfStatements), instructions[i]); // switch contains case null: - if (currentCaseBlock != defaultOrNullBlock) { + if (currentCaseBlock != defaultOrNullBlock) + { values.Add((null, new Branch(defaultOrNullBlock))); } @@ -390,7 +443,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms && call.Method.DeclaringType.IsKnownType(KnownTypeCode.String) && call.Method.IsStatic && call.Method.Name == "IsInterned" - && call.Arguments.Count == 1) { + && call.Arguments.Count == 1) + { argument = call.Arguments[0]; return true; } @@ -423,27 +477,39 @@ namespace ICSharpCode.Decompiler.IL.Transforms return null; if (!currentBlock.MatchIfAtEndOfBlock(out var condition, out var caseBlockBranch, out var nextBlockBranch)) return null; - if (!MatchStringEqualityComparison(condition, switchVariable, out value, out bool isVBCompareString)) { + if (!MatchStringEqualityComparison(condition, switchVariable, out value, out bool isVBCompareString)) + { return null; } - if (isVBCompareString) { + if (isVBCompareString) + { ExtensionMethods.Swap(ref caseBlockBranch, ref nextBlockBranch); emptyStringEqualsNull = true; } - if (caseBlockBranch.MatchBranch(out var caseBlock)) { + if (caseBlockBranch.MatchBranch(out var caseBlock)) + { caseBlockOrLeave = caseBlock; - } else if (caseBlockBranch.MatchLeave(out _)) { + } + else if (caseBlockBranch.MatchLeave(out _)) + { caseBlockOrLeave = caseBlockBranch; - } else { + } + else + { return null; } - if (nextBlockBranch.MatchBranch(out Block nextBlock)) { + if (nextBlockBranch.MatchBranch(out Block nextBlock)) + { // success return nextBlock; - } else if (nextBlockBranch.MatchLeave(out BlockContainer blockContainer)) { + } + else if (nextBlockBranch.MatchLeave(out BlockContainer blockContainer)) + { // success return blockContainer; - } else { + } + else + { return null; } } @@ -464,10 +530,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; // The initial store can be omitted in some cases. If there is no initial store or the switch value variable is reused later, // we do not inline the "switch value", but create an extra load later on. - if (i > 0 && instructions[i - 1].MatchStLoc(out var switchValueVar, out var switchValue)) { + if (i > 0 && instructions[i - 1].MatchStLoc(out var switchValueVar, out var switchValue)) + { if (!(switchValueVar.IsSingleDefinition && ((SemanticHelper.IsPure(switchValue.Flags) && left.Match(switchValue).Success) || left.MatchLdLoc(switchValueVar)))) return false; - } else { + } + else + { if (!left.MatchLdLoc(out switchValueVar)) return false; switchValue = null; @@ -533,7 +602,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (switchBlock.IncomingEdgeCount != 1 || switchBlock.Instructions.Count == 0) return false; var sections = new List(); - switch (switchBlock.Instructions[0]) { + switch (switchBlock.Instructions[0]) + { case SwitchInstruction switchInst: if (switchBlock.Instructions.Count != 1) return false; @@ -558,14 +628,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!FixCasesWithoutValue(sections, stringValues)) return false; // switch contains case null: - if (nullValueCaseBlock != defaultBlock) { - if (!AddNullSection(sections, stringValues, nullValueCaseBlock)) { + if (nullValueCaseBlock != defaultBlock) + { + if (!AddNullSection(sections, stringValues, nullValueCaseBlock)) + { return false; } } context.Step(nameof(MatchLegacySwitchOnStringWithDict), instructions[i]); bool keepAssignmentBefore = false; - if (switchValueVar.LoadCount > 2 || switchValue == null) { + if (switchValueVar.LoadCount > 2 || switchValue == null) + { switchValue = new LdLoc(switchValueVar); keepAssignmentBefore = true; } @@ -573,12 +646,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms var inst = new SwitchInstruction(stringToInt); inst.Sections.AddRange(sections); instructions[i + 1].ReplaceWith(inst); - if (keepAssignmentBefore) { + if (keepAssignmentBefore) + { // delete if (comp(ldloc switchValueVar == ldnull)) inst.AddILRange(instructions[i]); instructions.RemoveAt(i); i--; - } else { + } + else + { // delete both the if and the assignment before inst.AddILRange(instructions[i - 1]); instructions.RemoveRange(i - 1, 2); @@ -598,9 +674,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms // And collect all sections that have no value mapped to them. SwitchSection defaultSection = sections.First(); List sectionsWithoutLabels = new List(); - foreach (var section in sections) { - if (section == defaultSection) continue; - if (section.Labels.Count() > defaultSection.Labels.Count()) { + foreach (var section in sections) + { + if (section == defaultSection) + continue; + if (section.Labels.Count() > defaultSection.Labels.Count()) + { if (!HasLabel(defaultSection)) sectionsWithoutLabels.Add(defaultSection); defaultSection = section; @@ -610,7 +689,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms sectionsWithoutLabels.Add(section); } - foreach (var section in sectionsWithoutLabels) { + foreach (var section in sectionsWithoutLabels) + { if (!section.Body.Match(defaultSection.Body).Success) return false; defaultSection.Labels = defaultSection.Labels.UnionWith(section.Labels); @@ -628,7 +708,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var possibleConflicts = sections.Where(sec => sec.Labels.Overlaps(label)).ToArray(); if (possibleConflicts.Length > 1) return false; - else if (possibleConflicts.Length == 1) { + else if (possibleConflicts.Length == 1) + { if (possibleConflicts[0].Labels.Count() == 1) return false; // cannot remove only label possibleConflicts[0].Labels = possibleConflicts[0].Labels.ExceptWith(label); @@ -666,18 +747,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!newObj.Method.DeclaringType.Equals(dictionaryType)) return false; int valuesLength = 0; - if (newObj.Arguments.Count == 2) { + if (newObj.Arguments.Count == 2) + { if (!newObj.Arguments[0].MatchLdcI4(out valuesLength)) return false; if (!newObj.Arguments[1].MatchLdcF4(0.5f)) return false; - } else if (newObj.Arguments.Count == 1) { + } + else if (newObj.Arguments.Count == 1) + { if (!newObj.Arguments[0].MatchLdcI4(out valuesLength)) return false; } values = new List<(string, int)>(valuesLength); int i = 0; - while (MatchAddCall(dictionaryType, block.Instructions[i + 1], dictVar, out var index, out var value)) { + while (MatchAddCall(dictionaryType, block.Instructions[i + 1], dictVar, out var index, out var value)) + { values.Add((value, index)); i++; } @@ -687,7 +772,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms dictType.Equals(dictionaryType) && loadField.MatchLdsFlda(out var dictField) && dictField.Equals(dictionaryField) && dictVarLoad.MatchLdLoc(dictVar))) return false; - if (isHashtablePattern && block.Instructions[i + 2] is IfInstruction) { + if (isHashtablePattern && block.Instructions[i + 2] is IfInstruction) + { return block.Instructions[i + 3].MatchBranch(out blockAfterInit); } return block.Instructions[i + 2].MatchBranch(out blockAfterInit); @@ -706,10 +792,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!c.Arguments[0].MatchLdLoc(dictVar)) return false; - if (!c.Arguments[1].MatchLdStr(out value)) { - if (c.Arguments[1].MatchLdsFld(out var field) && field.DeclaringType.IsKnownType(KnownTypeCode.String) && field.Name == "Empty") { + if (!c.Arguments[1].MatchLdStr(out value)) + { + if (c.Arguments[1].MatchLdsFld(out var field) && field.DeclaringType.IsKnownType(KnownTypeCode.String) && field.Name == "Empty") + { value = ""; - } else { + } + else + { return false; } } @@ -794,8 +884,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; var sections = new List(switchInst.Sections); // switch contains case null: - if (!(nullCaseBlockBranch is Leave) && nullCaseBlock != defaultBlock) { - if (!AddNullSection(sections, stringValues, nullCaseBlock)) { + if (!(nullCaseBlockBranch is Leave) && nullCaseBlock != defaultBlock) + { + if (!AddNullSection(sections, stringValues, nullCaseBlock)) + { return false; } } @@ -845,7 +937,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; // if there is another IfInstruction before the end of the block, it might be a jump to the next hashtable init block. // if (comp(volatile.ldobj System.Collections.Hashtable(ldsflda $$method0x600003f-2) != ldnull)) br switchHeadBlock - if (tableInitBlock.Instructions.SecondToLastOrDefault() is IfInstruction nextHashtableInitHead) { + if (tableInitBlock.Instructions.SecondToLastOrDefault() is IfInstruction nextHashtableInitHead) + { if (!(nextHashtableInitHead.Condition.MatchCompNotEquals(out left, out right) && right.MatchLdNull() && MatchDictionaryFieldLoad(left, IsNonGenericHashtable, out var nextSwitchInitField, out _))) return false; @@ -858,7 +951,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool MatchRoslynSwitchOnString(InstructionCollection instructions, ref int i) { - if (i >= instructions.Count - 1) return false; + if (i >= instructions.Count - 1) + return false; // stloc switchValueVar(switchValue) // if (comp(ldloc switchValueVar == ldnull)) br nullCase // br nextBlock @@ -867,7 +961,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms Block nullValueCaseBlock = null; ILInstruction instForNullCheck = null; if (instructions[i].MatchIfInstruction(out var condition, out var exitBlockJump) - && condition.MatchCompEqualsNull(out instForNullCheck)) { + && condition.MatchCompEqualsNull(out instForNullCheck)) + { var nextBlockJump = instructions[i + 1] as Branch; if (nextBlockJump == null || nextBlockJump.TargetBlock.IncomingEdgeCount != 1) return false; @@ -886,7 +981,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms MatchComputeStringHashCall(switchBlockInstructions[switchBlockInstructionsOffset], switchValueVar, out LdLoc switchValueLoad))) return false; - if (instForNullCheck != null && !instForNullCheck.MatchLdLoc(switchValueLoad.Variable)) { + if (instForNullCheck != null && !instForNullCheck.MatchLdLoc(switchValueLoad.Variable)) + { return false; } @@ -894,55 +990,70 @@ namespace ICSharpCode.Decompiler.IL.Transforms SwitchSection defaultSection = switchInst.Sections.MaxBy(s => s.Labels.Count()); if (!(defaultSection.Body.MatchBranch(out Block exitOrDefaultBlock) || defaultSection.Body.MatchLeave(out _))) return false; - foreach (var section in switchInst.Sections) { - if (section == defaultSection) continue; + foreach (var section in switchInst.Sections) + { + if (section == defaultSection) + continue; // extract target block if (!section.Body.MatchBranch(out Block target)) return false; string stringValue; bool emptyStringEqualsNull; - if (MatchRoslynEmptyStringCaseBlockHead(target, switchValueLoad.Variable, out ILInstruction targetOrLeave, out Block currentExitBlock)) { + if (MatchRoslynEmptyStringCaseBlockHead(target, switchValueLoad.Variable, out ILInstruction targetOrLeave, out Block currentExitBlock)) + { stringValue = ""; emptyStringEqualsNull = false; - } else if (!MatchRoslynCaseBlockHead(target, switchValueLoad.Variable, out targetOrLeave, out currentExitBlock, out stringValue, out emptyStringEqualsNull)) { + } + else if (!MatchRoslynCaseBlockHead(target, switchValueLoad.Variable, out targetOrLeave, out currentExitBlock, out stringValue, out emptyStringEqualsNull)) + { return false; } if (currentExitBlock != exitOrDefaultBlock) return false; - if (emptyStringEqualsNull && string.IsNullOrEmpty(stringValue)) { + if (emptyStringEqualsNull && string.IsNullOrEmpty(stringValue)) + { stringValues.Add((null, targetOrLeave)); stringValues.Add((string.Empty, targetOrLeave)); - } else { + } + else + { stringValues.Add((stringValue, targetOrLeave)); } } - if (nullValueCaseBlock != null && exitOrDefaultBlock != nullValueCaseBlock) { + if (nullValueCaseBlock != null && exitOrDefaultBlock != nullValueCaseBlock) + { stringValues.Add((null, nullValueCaseBlock)); } // In newer Roslyn versions (>=3.7) the null check appears in the default case, not prior to the switch. - if (!stringValues.Any(pair => pair.Value == null) && IsNullCheckInDefaultBlock(ref exitOrDefaultBlock, switchValueLoad.Variable, out nullValueCaseBlock)) { + if (!stringValues.Any(pair => pair.Value == null) && IsNullCheckInDefaultBlock(ref exitOrDefaultBlock, switchValueLoad.Variable, out nullValueCaseBlock)) + { stringValues.Add((null, nullValueCaseBlock)); } context.Step(nameof(MatchRoslynSwitchOnString), switchValueLoad); - if (exitOrDefaultBlock != null) { + if (exitOrDefaultBlock != null) + { // change TargetBlock in case it was modified by IsNullCheckInDefaultBlock() ((Branch)defaultSection.Body).TargetBlock = exitOrDefaultBlock; } ILInstruction switchValueInst = switchValueLoad; - if (instructions == switchBlockInstructions) { + if (instructions == switchBlockInstructions) + { // stloc switchValueLoadVariable(switchValue) // stloc switchValueVar(call ComputeStringHash(ldloc switchValueLoadVariable)) // switch (ldloc switchValueVar) { bool keepAssignmentBefore; // if the switchValueLoad.Variable is only used in the compiler generated case equality checks, we can remove it. if (i >= 1 && instructions[i - 1].MatchStLoc(switchValueLoad.Variable, out var switchValueTmp) && - switchValueLoad.Variable.IsSingleDefinition && switchValueLoad.Variable.LoadCount == switchInst.Sections.Count) { + switchValueLoad.Variable.IsSingleDefinition && switchValueLoad.Variable.LoadCount == switchInst.Sections.Count) + { switchValueInst = switchValueTmp; keepAssignmentBefore = false; - } else { + } + else + { keepAssignmentBefore = true; } // replace stloc switchValueVar(call ComputeStringHash(...)) with new switch instruction @@ -951,18 +1062,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms newSwitch.AddILRange(instructions[i + 1]); instructions.RemoveAt(i + 1); // remove extra assignment - if (!keepAssignmentBefore) { + if (!keepAssignmentBefore) + { newSwitch.AddILRange(instructions[i - 1]); instructions.RemoveRange(i - 1, 1); i -= 1; } - } else { + } + else + { bool keepAssignmentBefore; // if the switchValueLoad.Variable is only used in the compiler generated case equality checks, we can remove it. - if (i >= 2 && instructions[i - 2].MatchStLoc(out var temporary, out var temporaryValue) && instructions[i - 1].MatchStLoc(switchValueLoad.Variable, out var tempLoad) && tempLoad.MatchLdLoc(temporary)) { + if (i >= 2 && instructions[i - 2].MatchStLoc(out var temporary, out var temporaryValue) && instructions[i - 1].MatchStLoc(switchValueLoad.Variable, out var tempLoad) && tempLoad.MatchLdLoc(temporary)) + { switchValueInst = temporaryValue; keepAssignmentBefore = false; - } else { + } + else + { keepAssignmentBefore = true; } // replace null check with new switch instruction @@ -972,7 +1089,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms newSwitch.AddILRange(instructions[i + 1]); instructions.RemoveAt(i + 1); // remove extra assignment - if (!keepAssignmentBefore) { + if (!keepAssignmentBefore) + { newSwitch.AddILRange(instructions[i - 2]); instructions.RemoveRange(i - 2, 2); i -= 2; @@ -986,7 +1104,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var defaultLabel = new LongSet(new LongInterval(0, stringValues.Count)).Invert(); var values = new string[stringValues.Count]; var sections = new SwitchSection[stringValues.Count]; - foreach (var (idx, (value, bodyInstruction)) in stringValues.WithIndex()) { + foreach (var (idx, (value, bodyInstruction)) in stringValues.WithIndex()) + { values[idx] = value; var body = bodyInstruction is Block b ? new Branch(b) : bodyInstruction; sections[idx] = new SwitchSection { Labels = new LongSet(idx), Body = body }; @@ -1044,23 +1163,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; ILInstruction exitBranch = target.Instructions[1]; // Handle negated conditions first: - while (condition.MatchLogicNot(out var expr)) { + while (condition.MatchLogicNot(out var expr)) + { ExtensionMethods.Swap(ref exitBranch, ref bodyBranch); condition = expr; } if (!MatchStringEqualityComparison(condition, switchValueVar, out stringValue, out bool isVBCompareString)) return false; - if (isVBCompareString) { + if (isVBCompareString) + { ExtensionMethods.Swap(ref exitBranch, ref bodyBranch); emptyStringEqualsNull = true; } if (!(exitBranch.MatchBranch(out defaultOrExitBlock) || exitBranch.MatchLeave(out _))) return false; - if (bodyBranch.MatchLeave(out _)) { + if (bodyBranch.MatchLeave(out _)) + { bodyOrLeave = bodyBranch; return true; } - if (bodyBranch.MatchBranch(out var bodyBlock)) { + if (bodyBranch.MatchBranch(out var bodyBlock)) + { bodyOrLeave = bodyBlock; return true; } @@ -1095,11 +1218,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!lengthCheckBlock.Instructions[0].MatchIfInstruction(out var lengthCheckCondition, out var exitBranch2)) return false; ILInstruction bodyBranch; - if (lengthCheckCondition.MatchLogicNot(out arg)) { + if (lengthCheckCondition.MatchLogicNot(out arg)) + { bodyBranch = exitBranch2; exitBranch2 = lengthCheckBlock.Instructions[1]; lengthCheckCondition = arg; - } else { + } + else + { bodyBranch = lengthCheckBlock.Instructions[1]; } if (!(exitBranch2.MatchBranch(out defaultOrExitBlock) || exitBranch2.MatchLeave(out _))) @@ -1108,11 +1234,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!exitBranch.Match(exitBranch2).Success) return false; - if (bodyBranch.MatchLeave(out _)) { + if (bodyBranch.MatchLeave(out _)) + { bodyOrLeave = bodyBranch; return true; } - if (bodyBranch.MatchBranch(out var bodyBlock)) { + if (bodyBranch.MatchBranch(out var bodyBlock)) + { bodyOrLeave = bodyBlock; return true; } @@ -1167,36 +1295,48 @@ namespace ICSharpCode.Decompiler.IL.Transforms stringValue = null; variable = null; isVBCompareString = false; - while (condition is Comp comp && comp.Kind == ComparisonKind.Inequality && comp.Right.MatchLdcI4(0)) { + while (condition is Comp comp && comp.Kind == ComparisonKind.Inequality && comp.Right.MatchLdcI4(0)) + { // if (x != 0) == if (x) condition = comp.Left; } - if (condition is Call c) { + if (condition is Call c) + { ILInstruction left, right; if (c.Method.IsOperator && c.Method.Name == "op_Equality" - && c.Method.DeclaringType.IsKnownType(KnownTypeCode.String) && c.Arguments.Count == 2) { + && c.Method.DeclaringType.IsKnownType(KnownTypeCode.String) && c.Arguments.Count == 2) + { left = c.Arguments[0]; right = c.Arguments[1]; - } else if (c.Method.IsStatic && c.Method.Name == "CompareString" - && c.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" - && c.Arguments.Count == 3) { + } + else if (c.Method.IsStatic && c.Method.Name == "CompareString" + && c.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" + && c.Arguments.Count == 3) + { left = c.Arguments[0]; right = c.Arguments[1]; // VB CompareString(): return 0 on equality -> condition is effectively negated. // Also, the empty string is considered equal to null. isVBCompareString = true; - if (!c.Arguments[2].MatchLdcI4(0)) { + if (!c.Arguments[2].MatchLdcI4(0)) + { // Option Compare Text: case insensitive comparison is not supported in C# return false; } - } else { + } + else + { return false; } return left.MatchLdLoc(out variable) && right.MatchLdStr(out stringValue); - } else if (condition.MatchCompEqualsNull(out var arg)) { + } + else if (condition.MatchCompEqualsNull(out var arg)) + { stringValue = null; return arg.MatchLdLoc(out variable); - } else { + } + else + { return false; } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs index 2f949c756..3f371468b 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -32,13 +33,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms public class TransformArrayInitializers : IStatementTransform { StatementTransformContext context; - + void IStatementTransform.Run(Block block, int pos, StatementTransformContext context) { if (!context.Settings.ArrayInitializers) return; this.context = context; - try { + try + { if (DoTransform(context.Function, block, pos)) return; if (DoTransformMultiDim(context.Function, block, pos)) @@ -47,7 +49,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; if (DoTransformInlineRuntimeHelpersInitializeArray(block, pos)) return; - } finally { + } + finally + { this.context = null; } } @@ -57,8 +61,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (pos >= body.Instructions.Count - 2) return false; ILInstruction inst = body.Instructions[pos]; - if (inst.MatchStLoc(out var v, out var newarrExpr) && MatchNewArr(newarrExpr, out var elementType, out var arrayLength)) { - if (HandleRuntimeHelpersInitializeArray(body, pos + 1, v, elementType, arrayLength, out var values, out var initArrayPos)) { + if (inst.MatchStLoc(out var v, out var newarrExpr) && MatchNewArr(newarrExpr, out var elementType, out var arrayLength)) + { + if (HandleRuntimeHelpersInitializeArray(body, pos + 1, v, elementType, arrayLength, out var values, out var initArrayPos)) + { context.Step("HandleRuntimeHelperInitializeArray: single-dim", inst); var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type); var block = BlockFromInitializer(tempStore, elementType, arrayLength, values); @@ -67,8 +73,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInlining.InlineIfPossible(body, pos, context); return true; } - if (arrayLength.Length == 1) { - if (HandleSimpleArrayInitializer(function, body, pos + 1, v, elementType, arrayLength, out var arrayValues, out var instructionsToRemove)) { + if (arrayLength.Length == 1) + { + if (HandleSimpleArrayInitializer(function, body, pos + 1, v, elementType, arrayLength, out var arrayValues, out var instructionsToRemove)) + { context.Step("HandleSimpleArrayInitializer: single-dim", inst); var block = new Block(BlockKind.ArrayInitializer); var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type); @@ -87,7 +95,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInlining.InlineIfPossible(body, pos, context); return true; } - if (HandleJaggedArrayInitializer(body, pos + 1, v, elementType, arrayLength[0], out ILVariable finalStore, out values, out instructionsToRemove)) { + if (HandleJaggedArrayInitializer(body, pos + 1, v, elementType, arrayLength[0], out ILVariable finalStore, out values, out instructionsToRemove)) + { context.Step("HandleJaggedArrayInitializer: single-dim", inst); var block = new Block(BlockKind.ArrayInitializer); var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type); @@ -107,11 +116,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms internal static bool TransformSpanTArrayInitialization(NewObj inst, StatementTransformContext context, out Block block) { block = null; - if (MatchSpanTCtorWithPointerAndSize(inst, context, out var elementType, out var field, out var size)) { - if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) { + if (MatchSpanTCtorWithPointerAndSize(inst, context, out var elementType, out var field, out var size)) + { + if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) + { var valuesList = new List(); var initialValue = field.GetInitialValue(context.PEFile.Reader, context.TypeSystem); - if (DecodeArrayInitializer(elementType, initialValue, new[] { size }, valuesList)) { + if (DecodeArrayInitializer(elementType, initialValue, new[] { size }, valuesList)) + { var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, new ArrayType(context.TypeSystem, elementType)); block = BlockFromInitializer(tempStore, elementType, new[] { size }, valuesList.ToArray()); return true; @@ -147,8 +159,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (pos >= body.Instructions.Count - 2) return false; ILInstruction inst = body.Instructions[pos]; - if (inst.MatchStLoc(out var v, out var newarrExpr) && MatchNewArr(newarrExpr, out var elementType, out var length)) { - if (HandleRuntimeHelpersInitializeArray(body, pos + 1, v, elementType, length, out var values, out var initArrayPos)) { + if (inst.MatchStLoc(out var v, out var newarrExpr) && MatchNewArr(newarrExpr, out var elementType, out var length)) + { + if (HandleRuntimeHelpersInitializeArray(body, pos + 1, v, elementType, length, out var values, out var initArrayPos)) + { context.Step("HandleRuntimeHelpersInitializeArray: multi-dim", inst); var block = BlockFromInitializer(v, elementType, length, values); body.Instructions[pos].ReplaceWith(new StLoc(v, block)); @@ -156,7 +170,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInlining.InlineIfPossible(body, pos, context); return true; } - if (HandleSimpleArrayInitializer(function, body, pos + 1, v, elementType, length, out var arrayValues, out var instructionsToRemove)) { + if (HandleSimpleArrayInitializer(function, body, pos + 1, v, elementType, length, out var arrayValues, out var instructionsToRemove)) + { context.Step("HandleSimpleArrayInitializer: multi-dim", inst); var block = new Block(BlockKind.ArrayInitializer); var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type); @@ -184,14 +199,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (pos >= body.Instructions.Count - 2) return false; ILInstruction inst = body.Instructions[pos]; - if (inst.MatchStLoc(out var v, out var locallocExpr) && locallocExpr.MatchLocAlloc(out var lengthInst)) { - if (lengthInst.MatchLdcI(out var lengthInBytes) && HandleCpblkInitializer(body, pos + 1, v, lengthInBytes, out var blob, out var elementType)) { + if (inst.MatchStLoc(out var v, out var locallocExpr) && locallocExpr.MatchLocAlloc(out var lengthInst)) + { + if (lengthInst.MatchLdcI(out var lengthInBytes) && HandleCpblkInitializer(body, pos + 1, v, lengthInBytes, out var blob, out var elementType)) + { context.Step("HandleCpblkInitializer", inst); var block = new Block(BlockKind.StackAllocInitializer); var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, new PointerType(elementType)); block.Instructions.Add(new StLoc(tempStore, locallocExpr)); - while (blob.RemainingBytes > 0) { + while (blob.RemainingBytes > 0) + { block.Instructions.Add(StElemPtr(tempStore, blob.Offset, new LdcI4(blob.ReadByte()), elementType)); } @@ -202,7 +220,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms ExpressionTransforms.RunOnSingleStatement(body.Instructions[pos], context); return true; } - if (HandleSequentialLocAllocInitializer(body, pos + 1, v, locallocExpr, out elementType, out StObj[] values, out int instructionsToRemove)) { + if (HandleSequentialLocAllocInitializer(body, pos + 1, v, locallocExpr, out elementType, out StObj[] values, out int instructionsToRemove)) + { context.Step("HandleSequentialLocAllocInitializer", inst); var block = new Block(BlockKind.StackAllocInitializer); var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, new PointerType(elementType)); @@ -231,7 +250,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (field.MetadataToken.IsNil) return false; - if (!block.Instructions[pos + 1].MatchStLoc(out var finalStore, out var value)) { + if (!block.Instructions[pos + 1].MatchStLoc(out var finalStore, out var value)) + { var otherLoadOfV = v.LoadInstructions.FirstOrDefault(l => !(l.Parent is Cpblk)); if (otherLoadOfV == null) return false; @@ -243,15 +263,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms var fd = context.PEFile.Metadata.GetFieldDefinition((FieldDefinitionHandle)field.MetadataToken); if (!fd.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) return false; - if (value.MatchLdLoc(v)) { + if (value.MatchLdLoc(v)) + { elementType = ((PointerType)finalStore.Type).ElementType; - } else if (value is NewObj { Arguments: { Count: 2 } } newObj - && newObj.Method.DeclaringType.IsKnownType(KnownTypeCode.SpanOfT) - && newObj.Arguments[0].MatchLdLoc(v) - && newObj.Arguments[1].MatchLdcI4((int)length)) + } + else if (value is NewObj { Arguments: { Count: 2 } } newObj + && newObj.Method.DeclaringType.IsKnownType(KnownTypeCode.SpanOfT) + && newObj.Arguments[0].MatchLdLoc(v) + && newObj.Arguments[1].MatchLdcI4((int)length)) { elementType = ((ParameterizedType)newObj.Method.DeclaringType).TypeArguments[0]; - } else { + } + else + { return false; } blob = fd.GetInitialValue(context.PEFile.Reader, context.TypeSystem); @@ -278,7 +302,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms pos++; } - for (int i = pos; i < block.Instructions.Count; i++) { + for (int i = pos; i < block.Instructions.Count; i++) + { // match the basic stobj pattern if (!block.Instructions[i].MatchStObj(out ILInstruction target, out value, out var currentType) || value.Descendants.OfType().Any(inst => inst.Variable == store)) @@ -289,7 +314,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // match the target // should be either ldloc store (at offset 0) // or binary.add(ldloc store, offset) where offset is either 'elementSize' or 'i * elementSize' - if (!target.MatchLdLoc(store)) { + if (!target.MatchLdLoc(store)) + { if (!target.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out var left, out var right)) return false; if (!left.MatchLdLoc(store)) @@ -301,7 +327,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms break; minExpectedOffset = offset; } - if (values == null) { + if (values == null) + { var countInstruction = PointerArithmeticOffset.Detect(lengthInstruction, elementType, checkForOverflow: true); if (countInstruction == null || !countInstruction.MatchLdcI(out long valuesLength) || valuesLength < 1) return false; @@ -317,7 +344,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms || store.AddressCount != 0 || store.LoadCount > values.Length + 1) return false; - if (store.LoadInstructions.Last().Parent is StLoc finalStore) { + if (store.LoadInstructions.Last().Parent is StLoc finalStore) + { elementType = ((PointerType)finalStore.Variable.Type).ElementType; } instructionsToRemove += elementCount; @@ -330,11 +358,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInstruction targetInst; if (storeInstruction.Target.MatchLdLoc(out _)) targetInst = new LdLoc(target); - else if (storeInstruction.Target.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out var left, out var right)) { + else if (storeInstruction.Target.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out var left, out var right)) + { var old = (BinaryNumericInstruction)storeInstruction.Target; targetInst = new BinaryNumericInstruction(BinaryNumericOperator.Add, new LdLoc(target), right, old.CheckForOverflow, old.Sign); - } else + } + else throw new NotSupportedException("This should never happen: Bug in HandleSequentialLocAllocInitializer!"); return new StObj(targetInst, storeInstruction.Value, storeInstruction.Type); @@ -368,13 +398,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms { var nextIndices = new ILInstruction[arrayLength.Length]; exactMatch = true; - if (indices == null) { - for (int k = 0; k < nextIndices.Length; k++) { + if (indices == null) + { + for (int k = 0; k < nextIndices.Length; k++) + { nextIndices[k] = new LdcI4(nextMinimumIndex[k]); } - } else { + } + else + { bool previousComponentWasGreater = false; - for (int k = 0; k < indices.Count; k++) { + for (int k = 0; k < indices.Count; k++) + { if (!indices[k].MatchLdcI4(out int index)) return null; // index must be in range [0..length[ and must be greater than or equal to nextMinimumIndex @@ -384,7 +419,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (index < 0 || index >= arrayLength[k] || (!previousComponentWasGreater && index < nextMinimumIndex[k])) return null; nextIndices[k] = new LdcI4(nextMinimumIndex[k]); - if (index != nextMinimumIndex[k]) { + if (index != nextMinimumIndex[k]) + { exactMatch = false; // this flag allows us to check whether the whole set of indices is smaller: // [3, 3] should be smaller than [4, 0] even though 3 > 0. @@ -394,7 +430,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } - for (int k = nextMinimumIndex.Length - 1; k >= 0; k--) { + for (int k = nextMinimumIndex.Length - 1; k >= 0; k--) + { nextMinimumIndex[k]++; if (nextMinimumIndex[k] < arrayLength[k]) break; @@ -407,17 +444,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms int j = 0; int i = pos; int step; - while (i < block.Instructions.Count) { + while (i < block.Instructions.Count) + { InstructionCollection indices; // stobj elementType(ldelema elementType(ldloc store, indices), value) - if (block.Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out IType type)) { + if (block.Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out IType type)) + { if (!(target is LdElema ldelem && ldelem.Array.MatchLdLoc(store))) break; indices = ldelem.Indices; step = 1; // stloc s(ldelema elementType(ldloc store, indices)) // stobj elementType(ldloc s, value) - } else if (block.Instructions[i].MatchStLoc(out var addressTemporary, out var addressValue)) { + } + else if (block.Instructions[i].MatchStLoc(out var addressTemporary, out var addressValue)) + { if (!(addressTemporary.IsSingleDefinition && addressTemporary.LoadCount == 1)) break; if (!(addressValue is LdElema ldelem && ldelem.Array.MatchLdLoc(store))) @@ -430,7 +471,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms break; indices = ldelem.Indices; step = 2; - } else { + } + else + { break; } if (value.Descendants.OfType().Any(inst => inst.Variable == store)) @@ -440,30 +483,37 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool exact; if (j >= values.Length) break; - do { + do + { var nextIndices = CalculateNextIndices(indices, out exact); if (nextIndices == null) return false; - if (exact) { + if (exact) + { values[j] = (nextIndices, value); elementCount++; instructionsToRemove += step; - } else { + } + else + { values[j] = (nextIndices, null); } j++; } while (j < values.Length && !exact); i += step; } - if (i < block.Instructions.Count) { - if (block.Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out IType type)) { + if (i < block.Instructions.Count) + { + if (block.Instructions[i].MatchStObj(out ILInstruction target, out ILInstruction value, out IType type)) + { // An element of the array is modified directly after the initializer: // Abort transform, so that partial initializers are not constructed. if (target is LdElema ldelem && ldelem.Array.MatchLdLoc(store)) return false; } } - while (j < values.Length) { + while (j < values.Length) + { var nextIndices = CalculateNextIndices(null, out _); if (nextIndices == null) return false; @@ -491,16 +541,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms instructionsToRemove = 0; finalStore = null; values = new ILInstruction[length]; - + ILInstruction initializer; IType type; - for (int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) + { // 1. Instruction: (optional) temporary copy of store bool hasTemporaryCopy = block.Instructions[pos].MatchStLoc(out var temp, out var storeLoad) && storeLoad.MatchLdLoc(store); - if (hasTemporaryCopy) { + if (hasTemporaryCopy) + { if (!MatchJaggedArrayStore(block, pos + 1, temp, i, out initializer, out type)) return false; - } else { + } + else + { if (!MatchJaggedArrayStore(block, pos, store, i, out initializer, out type)) return false; } @@ -511,7 +565,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms } // In case there is an extra copy of the store variable // Remove it and use its value instead. - if (block.Instructions[pos].MatchStLoc(out finalStore, out var array)) { + if (block.Instructions[pos].MatchStLoc(out finalStore, out var array)) + { instructionsToRemove++; return array.MatchLdLoc(store); } @@ -541,17 +596,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms && nextInstruction.MatchStLoc(initializerStore, out initializer) && initializer.OpCode == OpCode.Block; } - + static Block BlockFromInitializer(ILVariable v, IType elementType, int[] arrayLength, ILInstruction[] values) { var block = new Block(BlockKind.ArrayInitializer); block.Instructions.Add(new StLoc(v, new NewArr(elementType, arrayLength.Select(l => new LdcI4(l)).ToArray()))); int step = arrayLength.Length + 1; - for (int i = 0; i < values.Length / step; i++) { + for (int i = 0; i < values.Length / step; i++) + { // values array is filled backwards var value = values[step * i]; var indices = new List(); - for (int j = step - 1; j >= 1; j--) { + for (int j = step - 1; j >= 1; j--) + { indices.Add(values[step * i + j]); } block.Instructions.Add(StElem(new LdLoc(v), indices.ToArray(), value, elementType)); @@ -559,7 +616,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms block.FinalInstruction = new LdLoc(v); return block; } - + static bool MatchNewArr(ILInstruction instruction, out IType arrayType, out int[] length) { length = null; @@ -569,8 +626,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms arrayType = newArr.Type; var args = newArr.Indices; length = new int[args.Count]; - for (int i = 0; i < args.Count; i++) { - if (!args[i].MatchLdcI4(out int value) || value <= 0) return false; + for (int i = 0; i < args.Count; i++) + { + if (!args[i].MatchLdcI4(out int value) || value <= 0) + return false; length[i] = value; } return true; @@ -602,11 +661,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool HandleRuntimeHelpersInitializeArray(Block body, int pos, ILVariable array, IType arrayType, int[] arrayLength, out ILInstruction[] values, out int foundPos) { - if (MatchInitializeArrayCall(body.Instructions[pos], out var arrayInst, out var field) && arrayInst.MatchLdLoc(array)) { - if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) { + if (MatchInitializeArrayCall(body.Instructions[pos], out var arrayInst, out var field) && arrayInst.MatchLdLoc(array)) + { + if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) + { var valuesList = new List(); var initialValue = field.GetInitialValue(context.PEFile.Reader, context.TypeSystem); - if (DecodeArrayInitializer(arrayType, initialValue, arrayLength, valuesList)) { + if (DecodeArrayInitializer(arrayType, initialValue, arrayLength, valuesList)) + { values = valuesList.ToArray(); foundPos = pos; return true; @@ -651,7 +713,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool DecodeArrayInitializer(IType type, BlobReader initialValue, int[] arrayLength, List output) { TypeCode typeCode = ReflectionHelper.GetTypeCode(type); - switch (typeCode) { + switch (typeCode) + { case TypeCode.Boolean: case TypeCode.Byte: return DecodeArrayInitializer(initialValue, arrayLength, output, typeCode, (ref BlobReader r) => new LdcI4(r.ReadByte())); @@ -693,10 +756,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (initialValue.RemainingBytes < (totalLength * elementSize)) return false; - for (int i = 0; i < totalLength; i++) { + for (int i = 0; i < totalLength; i++) + { output.Add(decoder(ref initialValue)); int next = i; - for (int j = arrayLength.Length - 1; j >= 0; j--) { + for (int j = arrayLength.Length - 1; j >= 0; j--) + { output.Add(new LdcI4(next % arrayLength[j])); next /= arrayLength[j]; } @@ -704,11 +769,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; } - + static ILInstruction StElem(ILInstruction array, ILInstruction[] indices, ILInstruction value, IType type) { - if (type.GetStackType() != value.ResultType) { - value = new Conv(value, type.ToPrimitiveType(), false, Sign.None); + if (type.GetStackType() != value.ResultType) + { + value = new Conv(value, type.ToPrimitiveType(), false, Sign.None); } return new StObj(new LdElema(type, array, indices) { DelayExceptions = true }, value, type); } @@ -718,7 +784,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms ITypeDefinition typeDef = elementType.GetEnumUnderlyingType().GetDefinition(); if (typeDef == null) return new DefaultValue(elementType); - switch (typeDef.KnownTypeCode) { + switch (typeDef.KnownTypeCode) + { case KnownTypeCode.Boolean: case KnownTypeCode.Char: case KnownTypeCode.SByte: @@ -748,7 +815,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static int ElementSizeOf(TypeCode elementType) { - switch (elementType) { + switch (elementType) + { case TypeCode.Boolean: case TypeCode.Byte: case TypeCode.SByte: diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index 50df2c861..48954ab05 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; @@ -40,16 +41,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms void IStatementTransform.Run(Block block, int pos, StatementTransformContext context) { this.context = context; - if (context.Settings.MakeAssignmentExpressions) { - if (TransformInlineAssignmentStObjOrCall(block, pos) || TransformInlineAssignmentLocal(block, pos)) { + if (context.Settings.MakeAssignmentExpressions) + { + if (TransformInlineAssignmentStObjOrCall(block, pos) || TransformInlineAssignmentLocal(block, pos)) + { // both inline assignments create a top-level stloc which might affect inlining context.RequestRerun(); return; - } + } } - if (context.Settings.IntroduceIncrementAndDecrement) { + if (context.Settings.IntroduceIncrementAndDecrement) + { if (TransformPostIncDecOperatorWithInlineStore(block, pos) - || TransformPostIncDecOperator(block, pos)) { + || TransformPostIncDecOperator(block, pos)) + { // again, new top-level stloc might need inlining: context.RequestRerun(); return; @@ -95,13 +100,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms // in some cases it can be a compiler-generated local if (inst == null || (inst.Variable.Kind != VariableKind.StackSlot && inst.Variable.Kind != VariableKind.Local)) return false; - if (IsImplicitTruncation(inst.Value, inst.Variable.Type, context.TypeSystem)) { + if (IsImplicitTruncation(inst.Value, inst.Variable.Type, context.TypeSystem)) + { // 'stloc s' is implicitly truncating the value return false; } ILVariable local; int nextPos; - if (block.Instructions[pos + 1] is StLoc localStore) { // with extra local + if (block.Instructions[pos + 1] is StLoc localStore) + { // with extra local if (localStore.Variable.Kind != VariableKind.Local || !localStore.Value.MatchLdLoc(inst.Variable)) return false; // if we're using an extra local, we'll delete "s", so check that that doesn't have any additional uses @@ -109,25 +116,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; local = localStore.Variable; nextPos = pos + 2; - } else { + } + else + { local = inst.Variable; localStore = null; nextPos = pos + 1; } - if (block.Instructions[nextPos] is StObj stobj) { + if (block.Instructions[nextPos] is StObj stobj) + { if (!stobj.Value.MatchLdLoc(inst.Variable)) return false; if (!SemanticHelper.IsPure(stobj.Target.Flags) || inst.Variable.IsUsedWithin(stobj.Target)) return false; var pointerType = stobj.Target.InferType(context.TypeSystem); IType newType = stobj.Type; - if (TypeUtils.IsCompatiblePointerTypeForMemoryAccess(pointerType, stobj.Type)) { + if (TypeUtils.IsCompatiblePointerTypeForMemoryAccess(pointerType, stobj.Type)) + { if (pointerType is ByReferenceType byref) newType = byref.ElementType; else if (pointerType is PointerType pointer) newType = pointer.ElementType; } - if (IsImplicitTruncation(inst.Value, newType, context.TypeSystem)) { + if (IsImplicitTruncation(inst.Value, newType, context.TypeSystem)) + { // 'stobj' is implicitly truncating the value return false; } @@ -139,7 +151,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms inst.ReplaceWith(new StLoc(local, stobj)); // note: our caller will trigger a re-run, which will call HandleStObjCompoundAssign if applicable return true; - } else if (block.Instructions[nextPos] is CallInstruction call) { + } + else if (block.Instructions[nextPos] is CallInstruction call) + { // call must be a setter call: if (!(call.OpCode == OpCode.Call || call.OpCode == OpCode.CallVirt)) return false; @@ -150,18 +164,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!call.Method.Equals(property.Setter)) return false; - if (!(property.IsIndexer || property.Setter.Parameters.Count == 1)) { + if (!(property.IsIndexer || property.Setter.Parameters.Count == 1)) + { // this is a parameterized property, which cannot be expressed as C# code. // setter calls are not valid in expression context, if property syntax cannot be used. return false; } if (!call.Arguments.Last().MatchLdLoc(inst.Variable)) return false; - foreach (var arg in call.Arguments.SkipLast(1)) { + foreach (var arg in call.Arguments.SkipLast(1)) + { if (!SemanticHelper.IsPure(arg.Flags) || inst.Variable.IsUsedWithin(arg)) return false; } - if (IsImplicitTruncation(inst.Value, call.Method.Parameters.Last().Type, context.TypeSystem)) { + if (IsImplicitTruncation(inst.Value, call.Method.Parameters.Last().Type, context.TypeSystem)) + { // setter call is implicitly truncating the value return false; } @@ -177,12 +194,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms }; inst.ReplaceWith(new StLoc(local, inlineBlock)); // because the ExpressionTransforms don't look into inline blocks, manually trigger HandleCallCompoundAssign - if (HandleCompoundAssign(call, context)) { + if (HandleCompoundAssign(call, context)) + { // if we did construct a compound assignment, it should have made our inline block redundant: Debug.Assert(!inlineBlock.IsConnected); } return true; - } else { + } + else + { return false; } } @@ -190,10 +210,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms static ILInstruction UnwrapSmallIntegerConv(ILInstruction inst, out Conv conv) { conv = inst as Conv; - if (conv != null && conv.Kind == ConversionKind.Truncate && conv.TargetType.IsSmallIntegerType()) { + if (conv != null && conv.Kind == ConversionKind.Truncate && conv.TargetType.IsSmallIntegerType()) + { // for compound assignments to small integers, the compiler emits a "conv" instruction return conv.Argument; - } else { + } + else + { return inst; } } @@ -220,11 +243,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (setterCall.Arguments.Count != getterCall.Arguments.Count + 1) return false; // Ensure that same arguments are passed to getterCall and setterCall: - for (int j = 0; j < getterCall.Arguments.Count; j++) { - if (setterCall.Arguments[j].MatchStLoc(out var v) && v.IsSingleDefinition && v.LoadCount == 1) { - if (getterCall.Arguments[j].MatchLdLoc(v)) { + for (int j = 0; j < getterCall.Arguments.Count; j++) + { + if (setterCall.Arguments[j].MatchStLoc(out var v) && v.IsSingleDefinition && v.LoadCount == 1) + { + if (getterCall.Arguments[j].MatchLdLoc(v)) + { // OK, setter call argument is saved in temporary that is re-used for getter call - if (finalizeMatch == null) { + if (finalizeMatch == null) + { finalizeMatch = AdjustArguments; } continue; @@ -240,8 +267,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms void AdjustArguments(ILTransformContext context) { Debug.Assert(setterCall.Arguments.Count == getterCall.Arguments.Count + 1); - for (int j = 0; j < getterCall.Arguments.Count; j++) { - if (setterCall.Arguments[j].MatchStLoc(out var v, out var value)) { + for (int j = 0; j < getterCall.Arguments.Count; j++) + { + if (setterCall.Arguments[j].MatchStLoc(out var v, out var value)) + { Debug.Assert(v.IsSingleDefinition && v.LoadCount == 1); Debug.Assert(getterCall.Arguments[j].MatchLdLoc(v)); getterCall.Arguments[j] = value; @@ -273,7 +302,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (!context.Settings.MakeAssignmentExpressions || !context.Settings.IntroduceIncrementAndDecrement) return false; - if (compoundStore is CallInstruction && compoundStore.SlotInfo != Block.InstructionSlot) { + if (compoundStore is CallInstruction && compoundStore.SlotInfo != Block.InstructionSlot) + { // replacing 'call set_Property' with a compound assignment instruction // changes the return value of the expression, so this is only valid on block-level. return false; @@ -283,12 +313,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms // targetType = The type of the property/field/etc. being stored to. // setterValue = The value being stored. var storeInSetter = setterValue as StLoc; - if (storeInSetter != null) { + if (storeInSetter != null) + { // We'll move the stloc to top-level: // callvirt set_Property(ldloc S_1, stloc v(binary.op(callvirt get_Property(ldloc S_1), value))) // ==> stloc v(compound.op.new(callvirt get_Property(ldloc S_1), value)) setterValue = storeInSetter.Value; - if (storeInSetter.Variable.Type.IsSmallIntegerType()) { + if (storeInSetter.Variable.Type.IsSmallIntegerType()) + { // 'stloc v' implicitly truncates the value. // Ensure that type of 'v' matches the type of the property: if (storeInSetter.Variable.Type.GetSize() != targetType.GetSize()) @@ -298,8 +330,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } ILInstruction newInst; - if (UnwrapSmallIntegerConv(setterValue, out var smallIntConv) is BinaryNumericInstruction binary) { - if (compoundStore is StLoc) { + if (UnwrapSmallIntegerConv(setterValue, out var smallIntConv) is BinaryNumericInstruction binary) + { + if (compoundStore is StLoc) + { // transform local variables only for user-defined operators return false; } @@ -312,22 +346,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms newInst = new NumericCompoundAssign( binary, target, targetKind, binary.Right, targetType, CompoundEvalMode.EvaluatesToNewValue); - } else if (setterValue is Call operatorCall && operatorCall.Method.IsOperator) { + } + else if (setterValue is Call operatorCall && operatorCall.Method.IsOperator) + { if (operatorCall.Arguments.Count == 0) return false; if (!IsMatchingCompoundLoad(operatorCall.Arguments[0], compoundStore, out var target, out var targetKind, out var finalizeMatch, forbiddenVariable: storeInSetter?.Variable)) return false; ILInstruction rhs; - if (operatorCall.Arguments.Count == 2) { + if (operatorCall.Arguments.Count == 2) + { if (CSharp.ExpressionBuilder.GetAssignmentOperatorTypeFromMetadataName(operatorCall.Method.Name) == null) return false; rhs = operatorCall.Arguments[1]; - } else if (operatorCall.Arguments.Count == 1) { + } + else if (operatorCall.Arguments.Count == 1) + { if (!(operatorCall.Method.Name == "op_Increment" || operatorCall.Method.Name == "op_Decrement")) return false; // use a dummy node so that we don't need a dedicated instruction for user-defined unary operator calls rhs = new LdcI4(1); - } else { + } + else + { return false; } if (operatorCall.IsLifted) @@ -336,15 +377,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms finalizeMatch?.Invoke(context); newInst = new UserDefinedCompoundAssign(operatorCall.Method, CompoundEvalMode.EvaluatesToNewValue, target, targetKind, rhs); - } else if (setterValue is DynamicBinaryOperatorInstruction dynamicBinaryOp) { + } + else if (setterValue is DynamicBinaryOperatorInstruction dynamicBinaryOp) + { if (!IsMatchingCompoundLoad(dynamicBinaryOp.Left, compoundStore, out var target, out var targetKind, out var finalizeMatch, forbiddenVariable: storeInSetter?.Variable)) return false; context.Step($"Compound assignment (dynamic binary)", compoundStore); finalizeMatch?.Invoke(context); newInst = new DynamicCompoundAssign(dynamicBinaryOp.Operation, dynamicBinaryOp.BinderFlags, target, dynamicBinaryOp.LeftArgumentInfo, dynamicBinaryOp.Right, dynamicBinaryOp.RightArgumentInfo, targetKind); - } else if (setterValue is Call concatCall && UserDefinedCompoundAssign.IsStringConcat(concatCall.Method)) { + } + else if (setterValue is Call concatCall && UserDefinedCompoundAssign.IsStringConcat(concatCall.Method)) + { // setterValue is a string.Concat() invocation - if (compoundStore is StLoc) { + if (compoundStore is StLoc) + { // transform local variables only for user-defined operators return false; } @@ -358,17 +404,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms finalizeMatch?.Invoke(context); newInst = new UserDefinedCompoundAssign(concatCall.Method, CompoundEvalMode.EvaluatesToNewValue, target, targetKind, concatCall.Arguments[1]); - } else { + } + else + { return false; } newInst.AddILRange(setterValue); - if (storeInSetter != null) { + if (storeInSetter != null) + { storeInSetter.Value = newInst; newInst = storeInSetter; context.RequestRerun(); // moving stloc to top-level might trigger inlining } compoundStore.ReplaceWith(newInst); - if (newInst.Parent is Block inlineAssignBlock && inlineAssignBlock.Kind == BlockKind.CallInlineAssign) { + if (newInst.Parent is Block inlineAssignBlock && inlineAssignBlock.Kind == BlockKind.CallInlineAssign) + { // It's possible that we first replaced the instruction in an inline-assign helper block. // In such a situation, we know from the block invariant that we're have a storeInSetter. Debug.Assert(storeInSetter != null); @@ -381,7 +431,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } return true; } - + /// /// stloc s(value) /// stloc l(ldloc s) @@ -401,15 +451,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!nextInst.Value.MatchLdLoc(inst.Variable)) return false; - if (IsImplicitTruncation(inst.Value, inst.Variable.Type, context.TypeSystem)) { + if (IsImplicitTruncation(inst.Value, inst.Variable.Type, context.TypeSystem)) + { // 'stloc s' is implicitly truncating the stack value return false; } - if (IsImplicitTruncation(inst.Value, nextInst.Variable.Type, context.TypeSystem)) { + if (IsImplicitTruncation(inst.Value, nextInst.Variable.Type, context.TypeSystem)) + { // 'stloc l' is implicitly truncating the stack value return false; } - if (nextInst.Variable.StackType == StackType.Ref) { + if (nextInst.Variable.StackType == StackType.Ref) + { // ref locals need to be initialized when they are declared, so // we can only use inline assignments when we know that the // ref local is definitely assigned. @@ -432,7 +485,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// static internal bool IsImplicitTruncation(ILInstruction value, IType type, ICompilation compilation, bool allowNullableValue = false) { - if (!type.IsSmallIntegerType()) { + if (!type.IsSmallIntegerType()) + { // Implicit truncation in ILAst only happens for small integer types; // other types of implicit truncation in IL cause the ILReader to insert // conv instructions. @@ -441,8 +495,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms // With small integer types, test whether the value might be changed by // truncation (based on type.GetSize()) followed by sign/zero extension (based on type.GetSign()). // (it's OK to have false-positives here if we're unsure) - if (value.MatchLdcI4(out int val)) { - switch (type.GetEnumUnderlyingType().GetDefinition()?.KnownTypeCode) { + if (value.MatchLdcI4(out int val)) + { + switch (type.GetEnumUnderlyingType().GetDefinition()?.KnownTypeCode) + { case KnownTypeCode.Boolean: return !(val == 0 || val == 1); case KnownTypeCode.Byte: @@ -455,12 +511,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms case KnownTypeCode.Char: return !(val >= ushort.MinValue && val <= ushort.MaxValue); } - } else if (value is Conv conv) { + } + else if (value is Conv conv) + { return conv.TargetType != type.ToPrimitiveType(); - } else if (value is Comp) { + } + else if (value is Comp) + { return false; // comp returns 0 or 1, which always fits - } else if (value is BinaryNumericInstruction bni) { - switch (bni.Operator) { + } + else if (value is BinaryNumericInstruction bni) + { + switch (bni.Operator) + { case BinaryNumericOperator.BitAnd: case BinaryNumericOperator.BitOr: case BinaryNumericOperator.BitXor: @@ -469,15 +532,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms return IsImplicitTruncation(bni.Left, type, compilation, allowNullableValue) || IsImplicitTruncation(bni.Right, type, compilation, allowNullableValue); } - } else if (value is IfInstruction ifInst) { + } + else if (value is IfInstruction ifInst) + { return IsImplicitTruncation(ifInst.TrueInst, type, compilation, allowNullableValue) || IsImplicitTruncation(ifInst.FalseInst, type, compilation, allowNullableValue); - } else { + } + else + { IType inferredType = value.InferType(compilation); - if (allowNullableValue) { + if (allowNullableValue) + { inferredType = NullableType.GetUnderlyingType(inferredType); } - if (inferredType.Kind != TypeKind.Unknown) { + if (inferredType.Kind != TypeKind.Unknown) + { return !(inferredType.GetSize() <= type.GetSize() && inferredType.GetSign() == type.GetSign()); } } @@ -494,52 +563,74 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// Every IsCompoundStore() call should be followed by an IsMatchingCompoundLoad() call. /// - static bool IsCompoundStore(ILInstruction inst, out IType storeType, + static bool IsCompoundStore(ILInstruction inst, out IType storeType, out ILInstruction value, ICompilation compilation) { value = null; storeType = null; - if (inst is StObj stobj) { + if (inst is StObj stobj) + { // stobj.Type may just be 'int' (due to stind.i4) when we're actually operating on a 'ref MyEnum'. // Try to determine the real type of the object we're modifying: storeType = stobj.Target.InferType(compilation); - if (storeType is ByReferenceType refType) { - if (TypeUtils.IsCompatibleTypeForMemoryAccess(refType.ElementType, stobj.Type)) { + if (storeType is ByReferenceType refType) + { + if (TypeUtils.IsCompatibleTypeForMemoryAccess(refType.ElementType, stobj.Type)) + { storeType = refType.ElementType; - } else { + } + else + { storeType = stobj.Type; } - } else if (storeType is PointerType pointerType) { - if (TypeUtils.IsCompatibleTypeForMemoryAccess(pointerType.ElementType, stobj.Type)) { + } + else if (storeType is PointerType pointerType) + { + if (TypeUtils.IsCompatibleTypeForMemoryAccess(pointerType.ElementType, stobj.Type)) + { storeType = pointerType.ElementType; - } else { + } + else + { storeType = stobj.Type; } - } else { + } + else + { storeType = stobj.Type; } value = stobj.Value; return SemanticHelper.IsPure(stobj.Target.Flags); - } else if (inst is CallInstruction call && (call.OpCode == OpCode.Call || call.OpCode == OpCode.CallVirt)) { - if (call.Method.Parameters.Count == 0) { + } + else if (inst is CallInstruction call && (call.OpCode == OpCode.Call || call.OpCode == OpCode.CallVirt)) + { + if (call.Method.Parameters.Count == 0) + { return false; } - foreach (var arg in call.Arguments.SkipLast(1)) { - if (arg.MatchStLoc(out var v) && v.IsSingleDefinition && v.LoadCount == 1) { + foreach (var arg in call.Arguments.SkipLast(1)) + { + if (arg.MatchStLoc(out var v) && v.IsSingleDefinition && v.LoadCount == 1) + { continue; // OK, IsMatchingCompoundLoad can perform an adjustment in this special case } - if (!SemanticHelper.IsPure(arg.Flags)) { + if (!SemanticHelper.IsPure(arg.Flags)) + { return false; } } storeType = call.Method.Parameters.Last().Type; value = call.Arguments.Last(); return IsSameMember(call.Method, (call.Method.AccessorOwner as IProperty)?.Setter); - } else if (inst is StLoc stloc && (stloc.Variable.Kind == VariableKind.Local || stloc.Variable.Kind == VariableKind.Parameter)) { + } + else if (inst is StLoc stloc && (stloc.Variable.Kind == VariableKind.Local || stloc.Variable.Kind == VariableKind.Parameter)) + { storeType = stloc.Variable.Type; value = stloc.Value; return true; - } else { + } + else + { return false; } } @@ -569,7 +660,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms target = null; targetKind = 0; finalizeMatch = null; - if (load is LdObj ldobj && store is StObj stobj) { + if (load is LdObj ldobj && store is StObj stobj) + { Debug.Assert(SemanticHelper.IsPure(stobj.Target.Flags)); if (!SemanticHelper.IsPure(ldobj.Target.Flags)) return false; @@ -577,30 +669,41 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; target = ldobj.Target; targetKind = CompoundTargetKind.Address; - if (ldobj.Target.Match(stobj.Target).Success) { + if (ldobj.Target.Match(stobj.Target).Success) + { return true; - } else if (IsDuplicatedAddressComputation(stobj.Target, ldobj.Target)) { + } + else if (IsDuplicatedAddressComputation(stobj.Target, ldobj.Target)) + { // Use S_0 as target, so that S_0 can later be eliminated by inlining. // (we can't eliminate previousInstruction right now, because it's before the transform's starting instruction) target = stobj.Target; return true; - } else { + } + else + { return false; } - } else if (MatchingGetterAndSetterCalls(load as CallInstruction, store as CallInstruction, out finalizeMatch)) { + } + else if (MatchingGetterAndSetterCalls(load as CallInstruction, store as CallInstruction, out finalizeMatch)) + { if (forbiddenVariable != null && forbiddenVariable.IsUsedWithin(load)) return false; target = load; targetKind = CompoundTargetKind.Property; return true; - } else if (load is LdLoc ldloc && store is StLoc stloc && ILVariableEqualityComparer.Instance.Equals(ldloc.Variable, stloc.Variable)) { + } + else if (load is LdLoc ldloc && store is StLoc stloc && ILVariableEqualityComparer.Instance.Equals(ldloc.Variable, stloc.Variable)) + { if (ILVariableEqualityComparer.Instance.Equals(ldloc.Variable, forbiddenVariable)) return false; target = new LdLoca(ldloc.Variable).WithILRange(ldloc); targetKind = CompoundTargetKind.Address; finalizeMatch = context => context.Function.RecombineVariables(ldloc.Variable, stloc.Variable); return true; - } else { + } + else + { return false; } @@ -610,7 +713,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // stloc S_0(ldloc refParam) // stloc V_0(ldobj System.Int32(ldloc refParam)) // stobj System.Int32(ldloc S_0, binary.add.i4(ldloc V_0, ldc.i4 1)) - while (storeTarget is LdFlda storeLdFlda && loadTarget is LdFlda loadLdFlda) { + while (storeTarget is LdFlda storeLdFlda && loadTarget is LdFlda loadLdFlda) + { if (!storeLdFlda.Field.Equals(loadLdFlda.Field)) return false; storeTarget = storeLdFlda.Target; @@ -648,24 +752,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool TransformPostIncDecOperatorWithInlineStore(Block block, int pos) { var store = block.Instructions[pos]; - if (!IsCompoundStore(store, out var targetType, out var value, context.TypeSystem)) { + if (!IsCompoundStore(store, out var targetType, out var value, context.TypeSystem)) + { return false; } StLoc stloc; var binary = UnwrapSmallIntegerConv(value, out var conv) as BinaryNumericInstruction; - if (binary != null && (binary.Right.MatchLdcI(1) || binary.Right.MatchLdcF4(1) || binary.Right.MatchLdcF8(1))) { + if (binary != null && (binary.Right.MatchLdcI(1) || binary.Right.MatchLdcF4(1) || binary.Right.MatchLdcF8(1))) + { if (!(binary.Operator == BinaryNumericOperator.Add || binary.Operator == BinaryNumericOperator.Sub)) return false; if (!ValidateCompoundAssign(binary, conv, targetType, context.Settings)) return false; stloc = binary.Left as StLoc; - } else if (value is Call operatorCall && operatorCall.Method.IsOperator && operatorCall.Arguments.Count == 1) { + } + else if (value is Call operatorCall && operatorCall.Method.IsOperator && operatorCall.Arguments.Count == 1) + { if (!(operatorCall.Method.Name == "op_Increment" || operatorCall.Method.Name == "op_Decrement")) return false; if (operatorCall.IsLifted) return false; // TODO: add tests and think about whether nullables need special considerations stloc = operatorCall.Arguments[0] as StLoc; - } else { + } + else + { return false; } if (stloc == null) @@ -678,10 +788,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; context.Step("TransformPostIncDecOperatorWithInlineStore", store); finalizeMatch?.Invoke(context); - if (binary != null) { + if (binary != null) + { block.Instructions[pos] = new StLoc(stloc.Variable, new NumericCompoundAssign( binary, target, targetKind, binary.Right, targetType, CompoundEvalMode.EvaluatesToOldValue)); - } else { + } + else + { Call operatorCall = (Call)value; block.Instructions[pos] = new StLoc(stloc.Variable, new UserDefinedCompoundAssign( operatorCall.Method, CompoundEvalMode.EvaluatesToOldValue, target, targetKind, new LdcI4(1))); @@ -717,16 +830,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms var tmpVar = inst.Variable; if (!IsCompoundStore(store, out var targetType, out var value, context.TypeSystem)) return false; - if (IsImplicitTruncation(inst.Value, targetType, context.TypeSystem)) { + if (IsImplicitTruncation(inst.Value, targetType, context.TypeSystem)) + { // 'stloc tmp' is implicitly truncating the value return false; } if (!IsMatchingCompoundLoad(inst.Value, store, out var target, out var targetKind, out var finalizeMatch, forbiddenVariable: inst.Variable, - previousInstruction: block.Instructions.ElementAtOrDefault(i - 1))) { + previousInstruction: block.Instructions.ElementAtOrDefault(i - 1))) + { return false; } - if (UnwrapSmallIntegerConv(value, out var conv) is BinaryNumericInstruction binary) { + if (UnwrapSmallIntegerConv(value, out var conv) is BinaryNumericInstruction binary) + { if (!binary.Left.MatchLdLoc(tmpVar) || !(binary.Right.MatchLdcI(1) || binary.Right.MatchLdcF4(1) || binary.Right.MatchLdcF8(1))) return false; if (!(binary.Operator == BinaryNumericOperator.Add || binary.Operator == BinaryNumericOperator.Sub)) @@ -737,7 +853,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms finalizeMatch?.Invoke(context); inst.Value = new NumericCompoundAssign(binary, target, targetKind, binary.Right, targetType, CompoundEvalMode.EvaluatesToOldValue); - } else if (value is Call operatorCall && operatorCall.Method.IsOperator && operatorCall.Arguments.Count == 1) { + } + else if (value is Call operatorCall && operatorCall.Method.IsOperator && operatorCall.Arguments.Count == 1) + { if (!operatorCall.Arguments[0].MatchLdLoc(tmpVar)) return false; if (!(operatorCall.Method.Name == "op_Increment" || operatorCall.Method.Name == "op_Decrement")) @@ -748,17 +866,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms finalizeMatch?.Invoke(context); inst.Value = new UserDefinedCompoundAssign(operatorCall.Method, CompoundEvalMode.EvaluatesToOldValue, target, targetKind, new LdcI4(1)); - } else { + } + else + { return false; } block.Instructions.RemoveAt(i + 1); - if (inst.Variable.IsSingleDefinition && inst.Variable.LoadCount == 0) { + if (inst.Variable.IsSingleDefinition && inst.Variable.LoadCount == 0) + { // dead store -> it was a statement-level post-increment inst.ReplaceWith(inst.Value); } return true; } - + static bool IsSameMember(IMember a, IMember b) { if (a == null || b == null) diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs index 42edf5183..1adcb5fe6 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.Semantics; @@ -36,11 +37,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms void IStatementTransform.Run(Block block, int pos, StatementTransformContext context) { - if (!context.Settings.ObjectOrCollectionInitializers) return; + if (!context.Settings.ObjectOrCollectionInitializers) + return; this.context = context; - try { + try + { DoTransform(block, pos); - } finally { + } + finally + { this.context = null; } } @@ -49,11 +54,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms { ILInstruction inst = body.Instructions[pos]; // Match stloc(v, newobj) - if (inst.MatchStLoc(out var v, out var initInst) && (v.Kind == VariableKind.Local || v.Kind == VariableKind.StackSlot)) { + if (inst.MatchStLoc(out var v, out var initInst) && (v.Kind == VariableKind.Local || v.Kind == VariableKind.StackSlot)) + { IType instType; - switch (initInst) { + switch (initInst) + { case NewObj newObjInst: - if (newObjInst.ILStackWasEmpty && v.Kind == VariableKind.Local && !context.Function.Method.IsConstructor && !context.Function.Method.IsCompilerGeneratedOrIsInCompilerGeneratedClass()) { + if (newObjInst.ILStackWasEmpty && v.Kind == VariableKind.Local && !context.Function.Method.IsConstructor && !context.Function.Method.IsCompilerGeneratedOrIsInCompilerGeneratedClass()) + { // on statement level (no other expressions on IL stack), // prefer to keep local variables (but not stack slots), // unless we are in a constructor (where inlining object initializers might be critical @@ -71,7 +79,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms instType = newObjInst.Method.DeclaringType; break; case DefaultValue defaultVal: - if (defaultVal.ILStackWasEmpty && v.Kind == VariableKind.Local && !context.Function.Method.IsConstructor) { + if (defaultVal.ILStackWasEmpty && v.Kind == VariableKind.Local && !context.Function.Method.IsConstructor) + { // on statement level (no other expressions on IL stack), // prefer to keep local variables (but not stack slots), // unless we are in a constructor (where inlining object initializers might be critical @@ -95,7 +104,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // if the method is a setter we're dealing with an object initializer // if the method is named Add and has at least 2 arguments we're dealing with a collection/dictionary initializer while (pos + initializerItemsCount + 1 < body.Instructions.Count - && IsPartOfInitializer(body.Instructions, pos + initializerItemsCount + 1, v, instType, ref blockKind)) { + && IsPartOfInitializer(body.Instructions, pos + initializerItemsCount + 1, v, instType, ref blockKind)) + { initializerItemsCount++; } // Do not convert the statements into an initializer if there's an incompatible usage of the initializer variable @@ -107,7 +117,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // We fetch the first unused variable from the list and remove all instructions after its // first usage (i.e. the init store) from the initializer. var index = possibleIndexVariables.Where(info => info.Value.Index > -1).Min(info => (int?)info.Value.Index); - if (index != null) { + if (index != null) + { initializerItemsCount = index.Value - pos - 1; } // The initializer would be empty, there's nothing to do here. @@ -120,10 +131,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms initializerBlock.FinalInstruction = new LdLoc(finalSlot); initializerBlock.Instructions.Add(new StLoc(finalSlot, initInst.Clone())); // Move all instructions to the initializer block. - for (int i = 1; i <= initializerItemsCount; i++) { - switch (body.Instructions[i + pos]) { + for (int i = 1; i <= initializerItemsCount; i++) + { + switch (body.Instructions[i + pos]) + { case CallInstruction call: - if (!(call is CallVirt || call is Call)) continue; + if (!(call is CallVirt || call is Call)) + continue; var newCall = call; var newTarget = newCall.Arguments[0]; foreach (var load in newTarget.Descendants.OfType()) @@ -172,7 +186,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // Include any stores to local variables that are single-assigned and do not reference the initializer-variable // in the list of possible index variables. // Index variables are used to implement dictionary initializers. - if (instructions[pos] is StLoc stloc && stloc.Variable.Kind == VariableKind.Local && stloc.Variable.IsSingleDefinition) { + if (instructions[pos] is StLoc stloc && stloc.Variable.Kind == VariableKind.Local && stloc.Variable.IsSingleDefinition) + { if (!context.Settings.DictionaryInitializers) return false; if (stloc.Value.Descendants.OfType().Any(ld => ld.Variable == target && (ld is LdLoc || ld is LdLoca))) @@ -193,19 +208,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms int firstDifferenceIndex = 0; while (firstDifferenceIndex < minLen && newPath[firstDifferenceIndex] == currentPath[firstDifferenceIndex]) firstDifferenceIndex++; - while (currentPath.Count > firstDifferenceIndex) { + while (currentPath.Count > firstDifferenceIndex) + { isCollection = false; currentPath.RemoveAt(currentPath.Count - 1); pathStack.Pop(); } - while (currentPath.Count < newPath.Count) { + while (currentPath.Count < newPath.Count) + { AccessPathElement newElement = newPath[currentPath.Count]; currentPath.Add(newElement); if (isCollection || !pathStack.Peek().Add(newElement)) return false; pathStack.Push(new HashSet()); } - switch (kind) { + switch (kind) + { case AccessPathKind.Adder: isCollection = true; if (pathStack.Peek().Count != 0) @@ -268,35 +286,50 @@ namespace ICSharpCode.Decompiler.IL.Transforms List values = null; IMethod method; var inst = instruction; - while (instruction != null) { - switch (instruction) { + while (instruction != null) + { + switch (instruction) + { case CallInstruction call: - if (!(call is CallVirt || call is Call)) goto default; + if (!(call is CallVirt || call is Call)) + goto default; method = call.Method; - if (resolveContext != null && !IsMethodApplicable(method, call.Arguments, rootType, resolveContext, settings)) goto default; + if (resolveContext != null && !IsMethodApplicable(method, call.Arguments, rootType, resolveContext, settings)) + goto default; instruction = call.Arguments[0]; - if (method.IsAccessor) { + if (method.IsAccessor) + { var property = method.AccessorOwner as IProperty; - if (!CanBeUsedInInitializer(property, resolveContext, kind, path)) goto default; + if (!CanBeUsedInInitializer(property, resolveContext, kind, path)) + goto default; var isGetter = method.Equals(property?.Getter); var indices = call.Arguments.Skip(1).Take(call.Arguments.Count - (isGetter ? 1 : 2)).ToArray(); - if (indices.Length > 0 && settings?.DictionaryInitializers == false) goto default; - if (possibleIndexVariables != null) { + if (indices.Length > 0 && settings?.DictionaryInitializers == false) + goto default; + if (possibleIndexVariables != null) + { // Mark all index variables as used - foreach (var index in indices.OfType()) { + foreach (var index in indices.OfType()) + { if (possibleIndexVariables.TryGetValue(index.Variable, out var info)) possibleIndexVariables[index.Variable] = (-1, info.Value); } } path.Insert(0, new AccessPathElement(call.OpCode, method.AccessorOwner, indices)); - } else { + } + else + { path.Insert(0, new AccessPathElement(call.OpCode, method)); } - if (values == null) { - if (method.IsAccessor) { + if (values == null) + { + if (method.IsAccessor) + { kind = AccessPathKind.Setter; values = new List { call.Arguments.Last() }; - } else { + } + else + { kind = AccessPathKind.Adder; values = new List(call.Arguments.Skip(1)); if (values.Count == 0) @@ -304,19 +337,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } break; - case LdObj ldobj: { - if (ldobj.Target is LdFlda ldflda && (kind != AccessPathKind.Setter || !ldflda.Field.IsReadOnly)) { + case LdObj ldobj: + { + if (ldobj.Target is LdFlda ldflda && (kind != AccessPathKind.Setter || !ldflda.Field.IsReadOnly)) + { path.Insert(0, new AccessPathElement(ldobj.OpCode, ldflda.Field)); instruction = ldflda.Target; break; } goto default; } - case StObj stobj: { - if (stobj.Target is LdFlda ldflda) { + case StObj stobj: + { + if (stobj.Target is LdFlda ldflda) + { path.Insert(0, new AccessPathElement(stobj.OpCode, ldflda.Field)); instruction = ldflda.Target; - if (values == null) { + if (values == null) + { values = new List(new[] { stobj.Value }); kind = AccessPathKind.Setter; } @@ -400,9 +438,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms static IType GetReturnTypeFromInstruction(ILInstruction instruction) { - switch (instruction) { + switch (instruction) + { case CallInstruction call: - if (!(call is CallVirt || call is Call)) goto default; + if (!(call is CallVirt || call is Call)) + goto default; return call.Method.ReturnType; case LdObj ldobj: if (ldobj.Target is LdFlda ldflda) @@ -427,7 +467,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms public override int GetHashCode() { int hashCode = 0; - unchecked { + unchecked + { if (Member != null) hashCode += 1000000007 * Member.GetHashCode(); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs index 8af899362..60c7984a9 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -108,12 +109,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (this.context != null) throw new InvalidOperationException("Reentrancy in " + nameof(TransformDisplayClassUsage)); - try { + try + { this.context = context; this.decompilationContext = new SimpleTypeResolveContext(context.Function.Method); AnalyzeFunction(function); Transform(function); - } finally { + } + finally + { ClearState(); } } @@ -129,7 +133,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { void VisitFunction(ILFunction f) { - foreach (var v in f.Variables.ToArray()) { + foreach (var v in f.Variables.ToArray()) + { var result = AnalyzeVariable(v); if (result == null || displayClasses.ContainsKey(result.Variable)) continue; @@ -140,14 +145,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms void VisitChildren(ILInstruction inst) { - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { Visit(child); } } void Visit(ILInstruction inst) { - switch (inst) { + switch (inst) + { case ILFunction f: VisitFunction(f); VisitChildren(inst); @@ -160,14 +167,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms Visit(function); - foreach (var (v, displayClass) in displayClasses.ToArray()) { + foreach (var (v, displayClass) in displayClasses.ToArray()) + { if (!ValidateDisplayClassUses(v, displayClass)) displayClasses.Remove(v); } - foreach (var displayClass in displayClasses.Values) { - foreach (var v in displayClass.VariablesToDeclare.Values) { - if (v.CanPropagate) { + foreach (var displayClass in displayClasses.Values) + { + foreach (var v in displayClass.VariablesToDeclare.Values) + { + if (v.CanPropagate) + { var variableToPropagate = v.GetOrDeclare(); if (variableToPropagate.Kind != VariableKind.Parameter && !displayClasses.ContainsKey(variableToPropagate)) v.Propagate(null); @@ -179,11 +190,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool ValidateDisplayClassUses(ILVariable v, DisplayClass displayClass) { Debug.Assert(v == displayClass.Variable); - foreach (var ldloc in v.LoadInstructions) { + foreach (var ldloc in v.LoadInstructions) + { if (!ValidateUse(displayClass, ldloc)) return false; } - foreach (var ldloca in v.AddressInstructions) { + foreach (var ldloca in v.AddressInstructions) + { if (!ValidateUse(displayClass, ldloca)) return false; } @@ -192,16 +205,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool ValidateUse(DisplayClass container, ILInstruction use) { IField field; - switch (use.Parent) { + switch (use.Parent) + { case LdFlda ldflda when ldflda.MatchLdFlda(out var target, out field) && target == use: var keyField = (IField)field.MemberDefinition; - if (!container.VariablesToDeclare.TryGetValue(keyField, out VariableToDeclare variable) || variable == null) { + if (!container.VariablesToDeclare.TryGetValue(keyField, out VariableToDeclare variable) || variable == null) + { variable = AddVariable(container, null, field); } container.VariablesToDeclare[keyField] = variable; return true; case StObj stobj when stobj.MatchStObj(out var target, out ILInstruction value, out _) && value == use: - if (target.MatchLdFlda(out var load, out field) && load.MatchLdLocRef(out var otherVariable) && displayClasses.TryGetValue(otherVariable, out var otherDisplayClass)) { + if (target.MatchLdFlda(out var load, out field) && load.MatchLdLocRef(out var otherVariable) && displayClasses.TryGetValue(otherVariable, out var otherDisplayClass)) + { if (otherDisplayClass.VariablesToDeclare.TryGetValue((IField)field.MemberDefinition, out var declaredVar)) return declaredVar.CanPropagate; } @@ -214,7 +230,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms private DisplayClass AnalyzeVariable(ILVariable v) { - switch (v.Kind) { + switch (v.Kind) + { case VariableKind.Parameter: if (context.Settings.YieldReturn && v.Function.StateMachineCompiledWithMono && v.IsThis()) return HandleMonoStateMachine(v.Function, v); @@ -233,28 +250,37 @@ namespace ICSharpCode.Decompiler.IL.Transforms DisplayClass DetectDisplayClass(ILVariable v) { ITypeDefinition definition; - if (v.Kind != VariableKind.StackSlot) { + if (v.Kind != VariableKind.StackSlot) + { definition = v.Type.GetDefinition(); - } else if (v.StoreInstructions.Count > 0 && v.StoreInstructions[0] is StLoc stloc) { + } + else if (v.StoreInstructions.Count > 0 && v.StoreInstructions[0] is StLoc stloc) + { definition = stloc.Value.InferType(context.TypeSystem).GetDefinition(); - } else { + } + else + { definition = null; } if (!ValidateDisplayClassDefinition(definition)) return null; DisplayClass result; - switch (definition.Kind) { + switch (definition.Kind) + { case TypeKind.Class: if (!v.IsSingleDefinition) return null; if (!(v.StoreInstructions.SingleOrDefault() is StLoc stloc)) return null; - if (stloc.Value is NewObj newObj && ValidateConstructor(newObj.Method)) { + if (stloc.Value is NewObj newObj && ValidateConstructor(newObj.Method)) + { result = new DisplayClass(v, definition) { CaptureScope = v.CaptureScope, Initializer = stloc }; - } else { + } + else + { return null; } @@ -273,7 +299,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return null; } - if (IsMonoNestedCaptureScope(definition)) { + if (IsMonoNestedCaptureScope(definition)) + { result.CaptureScope = null; } return result; @@ -283,7 +310,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (initBlock == null) return; - for (int i = startIndex; i < initBlock.Instructions.Count; i++) { + for (int i = startIndex; i < initBlock.Instructions.Count; i++) + { var init = initBlock.Instructions[i]; if (!init.MatchStFld(out var target, out var field, out _)) break; @@ -304,7 +332,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // Try to find a common ancestor of all uses of the variable v. ILInstruction Visit(ILInstruction inst) { - switch (inst) { + switch (inst) + { case LdLoc l when l.Variable == v: return l; case StLoc s when s.Variable == v: @@ -320,13 +349,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms { // Visit all children of the instruction ILInstruction result = null; - foreach (var child in inst.Children) { + foreach (var child in inst.Children) + { var newResult = Visit(child); // As soon as there is a second use of v in this sub-tree, // we can skip all other children and just return this node. - if (result == null) { + if (result == null) + { result = newResult; - } else if (newResult != null) { + } + else if (newResult != null) + { return inst; } } @@ -367,7 +400,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (definition.ParentModule.PEFile != context.PEFile) return false; - if (!context.Settings.AggressiveScalarReplacementOfAggregates) { + if (!context.Settings.AggressiveScalarReplacementOfAggregates) + { if (definition.DeclaringTypeDefinition == null) return false; if (!IsPotentialClosure(context, definition)) @@ -378,7 +412,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms private bool ValidateConstructor(IMethod method) { - try { + try + { if (method.Parameters.Count != 0) return false; var handle = (MethodDefinitionHandle)method.MetadataToken; @@ -399,7 +434,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // IL_0001: call instance void [mscorlib]System.Object::.ctor() // IL_0006: ret var opCode = DecodeOpCodeSkipNop(ref reader); - switch (opCode) { + switch (opCode) + { case ILOpCode.Ldarg: case ILOpCode.Ldarg_s: if (reader.DecodeIndex(opCode) != 0) @@ -422,7 +458,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!objectCtor.IsConstructor || objectCtor.Parameters.Count != 0) return false; return DecodeOpCodeSkipNop(ref reader) == ILOpCode.Ret; - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { return false; } } @@ -430,7 +468,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILOpCode DecodeOpCodeSkipNop(ref BlobReader reader) { ILOpCode code; - do { + do + { code = reader.DecodeOpCode(); } while (code == ILOpCode.Nop); return code; @@ -439,7 +478,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms VariableToDeclare AddVariable(DisplayClass result, StObj statement, IField field) { VariableToDeclare variable = new VariableToDeclare(result, field); - if (statement != null) { + if (statement != null) + { variable.Propagate(ResolveVariableToPropagate(statement.Value, field.Type)); variable.Initializers.Add(statement); } @@ -454,23 +494,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILVariable ResolveVariableToPropagate(ILInstruction value, IType expectedType = null) { ILVariable v; - switch (value) { + switch (value) + { case LdLoc load: v = load.Variable; - if (v.Kind == VariableKind.Parameter) { - if (v.LoadCount != 1 && !v.IsThis()) { + if (v.Kind == VariableKind.Parameter) + { + if (v.LoadCount != 1 && !v.IsThis()) + { // If the variable is a parameter and it is used elsewhere, we cannot propagate it. // "dc.field = v; dc.field.mutate(); use(v);" cannot turn to "v.mutate(); use(v)" return null; } - } else { + } + else + { // Non-parameter propagation will later be checked, and will only be allowed for display classes - if (v.Type.IsReferenceType != true) { + if (v.Type.IsReferenceType != true) + { // don't allow propagation for display structs (as used with local functions) return null; } } - if (!v.IsSingleDefinition) { + if (!v.IsSingleDefinition) + { // "dc.field = v; v = 42; use(dc.field)" cannot turn to "v = 42; use(v);" return null; } @@ -479,14 +526,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms return v; case LdObj ldfld: DisplayClass currentDisplayClass = null; - foreach (var item in ldfld.Target.Descendants) { - if (IsDisplayClassLoad(item, out v)) { + foreach (var item in ldfld.Target.Descendants) + { + if (IsDisplayClassLoad(item, out v)) + { if (!displayClasses.TryGetValue(v, out currentDisplayClass)) return null; } if (currentDisplayClass == null) return null; - if (item is LdFlda ldf && currentDisplayClass.VariablesToDeclare.TryGetValue((IField)ldf.Field.MemberDefinition, out var vd)) { + if (item is LdFlda ldf && currentDisplayClass.VariablesToDeclare.TryGetValue((IField)ldf.Field.MemberDefinition, out var vd)) + { if (!vd.CanPropagate) return null; if (!displayClasses.TryGetValue(vd.GetOrDeclare(), out currentDisplayClass)) @@ -503,7 +553,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { VisitILFunction(function); context.Step($"ResetHasInitialValueFlag", function); - foreach (var f in TreeTraversal.PostOrder(function, f => f.LocalFunctions)) { + foreach (var f in TreeTraversal.PostOrder(function, f => f.LocalFunctions)) + { RemoveDeadVariableInit.ResetHasInitialValueFlag(f, context); f.CapturedVariables.RemoveWhere(v => v.IsDead); } @@ -513,14 +564,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms { closureType = null; initializer = null; - if (variable.IsSingleDefinition && variable.StoreInstructions.SingleOrDefault() is StLoc inst) { + if (variable.IsSingleDefinition && variable.StoreInstructions.SingleOrDefault() is StLoc inst) + { initializer = inst; - if (IsClosureInit(context, inst, out closureType)) { + if (IsClosureInit(context, inst, out closureType)) + { return true; } } closureType = variable.Type.GetDefinition(); - if (context.Settings.LocalFunctions && closureType?.Kind == TypeKind.Struct && variable.HasInitialValue && IsPotentialClosure(context, closureType)) { + if (context.Settings.LocalFunctions && closureType?.Kind == TypeKind.Struct && variable.HasInitialValue && IsPotentialClosure(context, closureType)) + { initializer = LocalFunctionDecompiler.GetStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First()); return true; } @@ -529,7 +583,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool IsClosureInit(ILTransformContext context, StLoc inst, out ITypeDefinition closureType) { - if (inst.Value is NewObj newObj) { + if (inst.Value is NewObj newObj) + { closureType = newObj.Method.DeclaringTypeDefinition; return closureType != null && IsPotentialClosure(context, newObj); } @@ -561,16 +616,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms var displayClass = new DisplayClass(thisVariable, thisVariable.Type.GetDefinition()); displayClass.CaptureScope = (BlockContainer)function.Body; - foreach (var stateMachineVariable in function.Variables) { + foreach (var stateMachineVariable in function.Variables) + { if (stateMachineVariable.StateMachineField == null || displayClass.VariablesToDeclare.ContainsKey(stateMachineVariable.StateMachineField)) continue; VariableToDeclare variableToDeclare = new VariableToDeclare(displayClass, stateMachineVariable.StateMachineField, stateMachineVariable); displayClass.VariablesToDeclare.Add(stateMachineVariable.StateMachineField, variableToDeclare); } - if (!function.Method.IsStatic && FindThisField(out var thisField)) { + if (!function.Method.IsStatic && FindThisField(out var thisField)) + { var thisVar = function.Variables .FirstOrDefault(t => t.IsThis() && t.Type.GetDefinition() == decompilationContext.CurrentTypeDefinition); - if (thisVar == null) { + if (thisVar == null) + { thisVar = new ILVariable(VariableKind.Parameter, decompilationContext.CurrentTypeDefinition, -1) { Name = "this" }; function.Variables.Add(thisVar); } @@ -582,7 +640,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool FindThisField(out IField foundField) { foundField = null; - foreach (var field in closureType.GetFields(f2 => !f2.IsStatic && !displayClass.VariablesToDeclare.ContainsKey(f2) && f2.Type.GetDefinition() == decompilationContext.CurrentTypeDefinition)) { + foreach (var field in closureType.GetFields(f2 => !f2.IsStatic && !displayClass.VariablesToDeclare.ContainsKey(f2) && f2.Type.GetDefinition() == decompilationContext.CurrentTypeDefinition)) + { thisField = field; return true; } @@ -606,13 +665,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (potentialDisplayClass == null || !potentialDisplayClass.IsCompilerGeneratedOrIsInCompilerGeneratedClass()) return false; - switch (potentialDisplayClass.Kind) { + switch (potentialDisplayClass.Kind) + { case TypeKind.Struct: break; case TypeKind.Class: if (!potentialDisplayClass.IsSealed) return false; - if (!allowTypeImplementingInterfaces) { + if (!allowTypeImplementingInterfaces) + { if (!potentialDisplayClass.DirectBaseTypes.All(t => t.IsKnownType(KnownTypeCode.Object))) return false; } @@ -620,8 +681,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms default: return false; } - - while (potentialDisplayClass != decompiledTypeDefinition) { + + while (potentialDisplayClass != decompiledTypeDefinition) + { potentialDisplayClass = potentialDisplayClass.DeclaringTypeDefinition; if (potentialDisplayClass == null) return false; @@ -634,10 +696,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitILFunction(ILFunction function) { context.StepStartGroup("Visit " + function.Name); - try { + try + { this.currentFunctions.Push(function); base.VisitILFunction(function); - } finally { + } + finally + { this.currentFunctions.Pop(); context.StepEndGroup(keepIfEmpty: true); } @@ -646,7 +711,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected override void Default(ILInstruction inst) { ILInstruction next; - for (var child = inst.Children.FirstOrDefault(); child != null; child = next) { + for (var child = inst.Children.FirstOrDefault(); child != null; child = next) + { next = child.GetNextSibling(); child.AcceptVisitor(this); } @@ -655,21 +721,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitStLoc(StLoc inst) { DisplayClass displayClass; - if (inst.Parent is Block parentBlock && inst.Variable.IsSingleDefinition) { - if ((inst.Variable.Kind == VariableKind.Local || inst.Variable.Kind == VariableKind.StackSlot) && inst.Variable.LoadCount == 0) { + if (inst.Parent is Block parentBlock && inst.Variable.IsSingleDefinition) + { + if ((inst.Variable.Kind == VariableKind.Local || inst.Variable.Kind == VariableKind.StackSlot) && inst.Variable.LoadCount == 0) + { // traverse pre-order, so that we do not have to deal with more special cases afterwards base.VisitStLoc(inst); - if (inst.Value is StLoc || inst.Value is CompoundAssignmentInstruction) { + if (inst.Value is StLoc || inst.Value is CompoundAssignmentInstruction) + { context.Step($"Remove unused variable assignment {inst.Variable.Name}", inst); inst.ReplaceWith(inst.Value); } return; } - if (displayClasses.TryGetValue(inst.Variable, out displayClass) && displayClass.Initializer == inst) { + if (displayClasses.TryGetValue(inst.Variable, out displayClass) && displayClass.Initializer == inst) + { // inline contents of object initializer block - if (inst.Value is Block initBlock && initBlock.Kind == BlockKind.ObjectInitializer) { + if (inst.Value is Block initBlock && initBlock.Kind == BlockKind.ObjectInitializer) + { context.Step($"Remove initializer of {inst.Variable.Name}", inst); - for (int i = 1; i < initBlock.Instructions.Count; i++) { + for (int i = 1; i < initBlock.Instructions.Count; i++) + { var stobj = (StObj)initBlock.Instructions[i]; var variable = displayClass.VariablesToDeclare[(IField)((LdFlda)stobj.Target).Field.MemberDefinition]; parentBlock.Instructions.Insert(inst.ChildIndex + i, new StLoc(variable.GetOrDeclare(), stobj.Value).WithILRange(stobj)); @@ -679,14 +751,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms parentBlock.Instructions.Remove(inst); return; } - if (inst.Value is LdLoc || inst.Value is LdObj) { + if (inst.Value is LdLoc || inst.Value is LdObj) + { // in some cases (e.g. if inlining fails), there can be a reference to a display class in a stack slot, // in that case it is necessary to resolve the reference and iff it can be propagated, replace all loads // of the single-definition. var referencedDisplayClass = ResolveVariableToPropagate(inst.Value); - if (referencedDisplayClass != null && displayClasses.TryGetValue(referencedDisplayClass, out _)) { + if (referencedDisplayClass != null && displayClasses.TryGetValue(referencedDisplayClass, out _)) + { context.Step($"Propagate reference to {referencedDisplayClass.Name} in {inst.Variable}", inst); - foreach (var ld in inst.Variable.LoadInstructions.ToArray()) { + foreach (var ld in inst.Variable.LoadInstructions.ToArray()) + { ld.ReplaceWith(new LdLoc(referencedDisplayClass).WithILRange(ld)); } parentBlock.Instructions.Remove(inst); @@ -699,10 +774,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitStObj(StObj inst) { - if (IsDisplayClassFieldAccess(inst.Target, out var v, out var displayClass, out var field)) { + if (IsDisplayClassFieldAccess(inst.Target, out var v, out var displayClass, out var field)) + { VariableToDeclare vd = displayClass.VariablesToDeclare[(IField)field.MemberDefinition]; - if (vd.CanPropagate && vd.Initializers.Contains(inst)) { - if (inst.Parent is Block containingBlock) { + if (vd.CanPropagate && vd.Initializers.Contains(inst)) + { + if (inst.Parent is Block containingBlock) + { context.Step($"Remove initializer of {v.Name}.{vd.Name} due to propagation", inst); containingBlock.Instructions.Remove(inst); return; @@ -751,7 +829,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILVariable variable = v.GetOrDeclare(); inst.ReplaceWith(new LdLoca(variable).WithILRange(inst)); // add captured variable to all descendant functions from the declaring function to this use-site function - foreach (var f in currentFunctions) { + foreach (var f in currentFunctions) + { if (f == variable.Function) break; f.CapturedVariables.Add(variable); diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs index 014a785c4..15ebee413 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.TypeSystem; @@ -97,7 +98,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms public void Run(Block block, int pos, StatementTransformContext context) { - if (!context.Settings.ExpressionTrees) return; + if (!context.Settings.ExpressionTrees) + return; this.context = context; this.conversions = CSharpConversions.Get(context.TypeSystem); this.resolver = new CSharpResolver(context.TypeSystem); @@ -105,12 +107,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms this.parameterMapping = new Dictionary(); this.instructionsToRemove = new List(); this.lambdaStack = new Stack(); - for (int i = pos; i < block.Instructions.Count; i++) { - if (MatchParameterVariableAssignment(block.Instructions[i], out var v, out var type, out var name)) { + for (int i = pos; i < block.Instructions.Count; i++) + { + if (MatchParameterVariableAssignment(block.Instructions[i], out var v, out var type, out var name)) + { parameters.Add(v, (type, name)); continue; } - if (TryConvertExpressionTree(block.Instructions[i], block.Instructions[i])) { + if (TryConvertExpressionTree(block.Instructions[i], block.Instructions[i])) + { foreach (var inst in instructionsToRemove) block.Instructions.Remove(inst); instructionsToRemove.Clear(); @@ -121,9 +126,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool TryConvertExpressionTree(ILInstruction instruction, ILInstruction statement) { - if (MightBeExpressionTree(instruction, statement)) { + if (MightBeExpressionTree(instruction, statement)) + { var (lambda, type) = ConvertLambda((CallInstruction)instruction); - if (lambda != null) { + if (lambda != null) + { context.Step("Convert Expression Tree", instruction); var newLambda = (ILFunction)lambda(); SetExpressionTreeFlag(newLambda, (CallInstruction)instruction); @@ -134,7 +141,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms } if (instruction is Block block && block.Kind == BlockKind.ControlFlow) return false; // don't look into nested blocks - foreach (var child in instruction.Children) { + foreach (var child in instruction.Children) + { if (TryConvertExpressionTree(child, statement)) return true; } @@ -177,8 +185,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms container.ExpectedResultType = convertedBody.ResultType; container.Blocks.Add(new Block() { Instructions = { new Leave(container, convertedBody) } }); // Replace all other usages of the parameter variable - foreach (var mapping in parameterMapping) { - foreach (var load in mapping.Key.LoadInstructions.ToArray()) { + foreach (var mapping in parameterMapping) + { + foreach (var load in mapping.Key.LoadInstructions.ToArray()) + { if (load.IsDescendantOf(instruction)) continue; load.ReplaceWith(new LdLoc(mapping.Value)); @@ -193,9 +203,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (invocation.Arguments.Count != 1) return (null, SpecialType.UnknownType); var argument = invocation.Arguments.Single(); - if (argument is ILFunction function) { + if (argument is ILFunction function) + { return (() => function, function.DelegateType); - } else { + } + else + { var (converted, type) = ConvertInstruction(argument); if (converted == null) return (converted, type); @@ -204,7 +217,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInstruction BuildQuote() { var f = converted(); - if (f is ILFunction lambda && argument is CallInstruction call) { + if (f is ILFunction lambda && argument is CallInstruction call) + { SetExpressionTreeFlag(lambda, call); } @@ -221,12 +235,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool ReadParameters(ILInstruction initializer, IList parameters, IList parameterVariables, ITypeResolveContext resolveContext) { - switch (initializer) { + switch (initializer) + { case Block initializerBlock: if (initializerBlock.Kind != BlockKind.ArrayInitializer) return false; int i = 0; - foreach (var inst in initializerBlock.Instructions.OfType()) { + foreach (var inst in initializerBlock.Instructions.OfType()) + { if (i >= this.parameters.Count) return false; if (!inst.Value.MatchLdLoc(out var v)) @@ -262,8 +278,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms var result = inst(); Debug.Assert(type != null, "IType must be non-null!"); Debug.Assert(result.ResultType == type.GetStackType(), "StackTypes must match!"); - if (typeHint != null) { - if (result.ResultType != typeHint.GetStackType()) { + if (typeHint != null) + { + if (result.ResultType != typeHint.GetStackType()) + { return new Conv(result, typeHint.GetStackType().ToPrimitiveType(), false, typeHint.GetSign()); } } @@ -271,13 +289,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms } return (DoConvert, typeHint ?? type); - (Func, IType) Convert() { - switch (instruction) { + (Func, IType) Convert() + { + switch (instruction) + { case CallInstruction invocation: if (invocation.Method.DeclaringType.FullName != "System.Linq.Expressions.Expression") return (null, SpecialType.UnknownType); - switch (invocation.Method.Name) { + switch (invocation.Method.Name) + { case "Add": return ConvertBinaryNumericOperator(invocation, BinaryNumericOperator.Add, false); case "AddChecked": @@ -314,7 +335,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms case "GreaterThan": return ConvertComparison(invocation, ComparisonKind.GreaterThan); case "GreaterThanOrEqual": - return ConvertComparison(invocation, ComparisonKind.GreaterThanOrEqual); + return ConvertComparison(invocation, ComparisonKind.GreaterThanOrEqual); case "Invoke": return ConvertInvoke(invocation); case "Lambda": @@ -374,7 +395,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms case ILFunction function: ILFunction ApplyChangesToILFunction() { - if (function.Kind == ILFunctionKind.ExpressionTree) { + if (function.Kind == ILFunctionKind.ExpressionTree) + { function.DelegateType = UnwrapExpressionTree(function.DelegateType); function.Kind = ILFunctionKind.Delegate; } @@ -382,10 +404,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms } return (ApplyChangesToILFunction, function.DelegateType); case LdLoc ldloc: - if (IsExpressionTreeParameter(ldloc.Variable)) { + if (IsExpressionTreeParameter(ldloc.Variable)) + { // Replace an already mapped parameter with the actual ILVariable, // we generated earlier. - if (parameterMapping.TryGetValue(ldloc.Variable, out var v)) { + if (parameterMapping.TryGetValue(ldloc.Variable, out var v)) + { if (typeHint.SkipModifiers() is ByReferenceType && !v.Type.IsByRefLike) return (() => new LdLoca(v), typeHint); return (() => new LdLoc(v), v.Type); @@ -396,7 +420,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // so our transform can continue normally. // Later, we will replace all references to unmapped variables, // with references to mapped parameters. - if (ldloc.Variable.IsSingleDefinition && ldloc.Variable.StoreInstructions[0] is ILInstruction instr) { + if (ldloc.Variable.IsSingleDefinition && ldloc.Variable.StoreInstructions[0] is ILInstruction instr) + { if (MatchParameterVariableAssignment(instr, out _, out var t, out _)) return (() => new ExpressionTreeCast(t, ldloc, false), t); } @@ -414,7 +439,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms IType UnwrapExpressionTree(IType delegateType) { - if (delegateType is ParameterizedType pt && pt.FullName == "System.Linq.Expressions.Expression" && pt.TypeArguments.Count == 1) { + if (delegateType is ParameterizedType pt && pt.FullName == "System.Linq.Expressions.Expression" && pt.TypeArguments.Count == 1) + { return pt.TypeArguments[0]; } return delegateType; @@ -435,7 +461,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInstruction Convert() { Func[] toBeConverted = new Func[arguments.Count]; - for (int i = 0; i < arguments.Count; i++) { + for (int i = 0; i < arguments.Count; i++) + { var (converted, indexType) = ConvertInstruction(arguments[i]); if (converted == null) return null; @@ -467,12 +494,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (right == null) return (null, SpecialType.UnknownType); IMember method; - switch (invocation.Arguments.Count) { + switch (invocation.Arguments.Count) + { case 2: - if (op == BinaryNumericOperator.ShiftLeft || op == BinaryNumericOperator.ShiftRight) { + if (op == BinaryNumericOperator.ShiftLeft || op == BinaryNumericOperator.ShiftRight) + { if (!rightType.IsKnownType(KnownTypeCode.Int32)) return (null, SpecialType.UnknownType); - } else { + } + else + { if (!rightType.Equals(leftType)) return (null, SpecialType.UnknownType); } @@ -505,16 +536,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms var (value, typeValue) = ConvertInstruction(invocation.Arguments[1]); if (value == null) return (null, SpecialType.UnknownType); - if (MatchGetMethodFromHandle(invocation.Arguments[0], out var member)) { - } else if (MatchGetFieldFromHandle(invocation.Arguments[0], out member)) { - } else { + if (MatchGetMethodFromHandle(invocation.Arguments[0], out var member)) + { + } + else if (MatchGetFieldFromHandle(invocation.Arguments[0], out member)) + { + } + else + { return (null, SpecialType.UnknownType); } - switch (member) { + switch (member) + { case IMethod method: if (method.IsStatic) return (targetVariable => new Call(method) { Arguments = { new LdLoc(targetVariable), value() } }, method.ReturnType); - else + else return (targetVariable => new CallVirt(method) { Arguments = { new LdLoc(targetVariable), value() } }, method.ReturnType); case IField field: return (targetVariable => new StObj(new LdFlda(new LdLoc(targetVariable), (IField)member) { DelayExceptions = true }, value(), member.ReturnType), field.ReturnType); @@ -529,16 +566,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms IList arguments = null; Func targetConverter = null; IType targetType = null; - if (MatchGetMethodFromHandle(invocation.Arguments[0], out var member)) { + if (MatchGetMethodFromHandle(invocation.Arguments[0], out var member)) + { // static method - if (invocation.Arguments.Count != 2 || !MatchArgumentList(invocation.Arguments[1], out arguments)) { + if (invocation.Arguments.Count != 2 || !MatchArgumentList(invocation.Arguments[1], out arguments)) + { arguments = new List(invocation.Arguments.Skip(1)); } - } else if (MatchGetMethodFromHandle(invocation.Arguments[1], out member)) { - if (invocation.Arguments.Count != 3 || !MatchArgumentList(invocation.Arguments[2], out arguments)) { + } + else if (MatchGetMethodFromHandle(invocation.Arguments[1], out member)) + { + if (invocation.Arguments.Count != 3 || !MatchArgumentList(invocation.Arguments[2], out arguments)) + { arguments = new List(invocation.Arguments.Skip(2)); } - if (!invocation.Arguments[0].MatchLdNull()) { + if (!invocation.Arguments[0].MatchLdNull()) + { (targetConverter, targetType) = ConvertInstruction(invocation.Arguments[0]); if (targetConverter == null) return (null, SpecialType.UnknownType); @@ -550,7 +593,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var convertedArguments = ConvertCallArguments(arguments, method); if (convertedArguments == null) return (null, SpecialType.UnknownType); - if (method.FullName == "System.Reflection.MethodInfo.CreateDelegate" && method.Parameters.Count == 2) { + if (method.FullName == "System.Reflection.MethodInfo.CreateDelegate" && method.Parameters.Count == 2) + { if (!MatchGetMethodFromHandle(UnpackConstant(invocation.Arguments[0]), out var targetMethod)) return (null, SpecialType.UnknownType); if (!MatchGetTypeFromHandle(UnpackConstant(arguments[0]), out var delegateType)) @@ -563,12 +607,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms CallInstruction BuildCall() { CallInstruction call; - if (method.IsStatic) { + if (method.IsStatic) + { call = new Call(method); - } else { + } + else + { call = new CallVirt(method); } - if (targetConverter != null) { + if (targetConverter != null) + { call.Arguments.Add(PrepareCallTarget(method.DeclaringType, targetConverter(), targetType)); } call.Arguments.AddRange(convertedArguments.Select(f => f())); @@ -579,20 +627,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInstruction PrepareCallTarget(IType expectedType, ILInstruction target, IType targetType) { - switch (CallInstruction.ExpectedTypeForThisPointer(expectedType)) { + switch (CallInstruction.ExpectedTypeForThisPointer(expectedType)) + { case StackType.Ref: if (target.ResultType == StackType.Ref) return target; else return new AddressOf(target, expectedType); case StackType.O: - if (targetType.IsReferenceType == false) { + if (targetType.IsReferenceType == false) + { return new Box(target, targetType); - } else { + } + else + { return target; } default: - if (expectedType.Kind == TypeKind.Unknown && target.ResultType != StackType.Unknown) { + if (expectedType.Kind == TypeKind.Unknown && target.ResultType != StackType.Unknown) + { return new Conv(target, PrimitiveType.Unknown, false, Sign.None); } return target; @@ -610,7 +663,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { var converted = new Func[arguments.Count]; Debug.Assert(arguments.Count == method.Parameters.Count); - for (int i = 0; i < arguments.Count; i++) { + for (int i = 0; i < arguments.Count; i++) + { var expectedType = method.Parameters[i].Type; var argument = ConvertInstruction(arguments[i], expectedType).Item1; if (argument == null) @@ -647,16 +701,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms var kind = NullCoalescingKind.Ref; var trueInstTypeNonNullable = NullableType.GetUnderlyingType(trueInstType); IType targetType; - if (NullableType.IsNullable(trueInstType) && conversions.ImplicitConversion(fallbackInstType, trueInstTypeNonNullable).IsValid) { + if (NullableType.IsNullable(trueInstType) && conversions.ImplicitConversion(fallbackInstType, trueInstTypeNonNullable).IsValid) + { targetType = trueInstTypeNonNullable; kind = NullableType.IsNullable(fallbackInstType) ? NullCoalescingKind.Nullable : NullCoalescingKind.NullableWithValueFallback; - } else if (conversions.ImplicitConversion(fallbackInstType, trueInstType).IsValid) { + } + else if (conversions.ImplicitConversion(fallbackInstType, trueInstType).IsValid) + { targetType = trueInstType; - } else { + } + else + { targetType = fallbackInstType; } - return (() => new NullCoalescingInstruction(kind, trueInst(), fallbackInst()) { - UnderlyingResultType = trueInstTypeNonNullable.GetStackType() + return (() => new NullCoalescingInstruction(kind, trueInst(), fallbackInst()) { + UnderlyingResultType = trueInstTypeNonNullable.GetStackType() }, targetType); } @@ -670,19 +729,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms var (right, rightType) = ConvertInstruction(invocation.Arguments[1]); if (right == null) return (null, SpecialType.UnknownType); - if (invocation.Arguments.Count == 4 && invocation.Arguments[2].MatchLdcI4(out var isLifted) && MatchGetMethodFromHandle(invocation.Arguments[3], out var method)) { - if (isLifted != 0) { + if (invocation.Arguments.Count == 4 && invocation.Arguments[2].MatchLdcI4(out var isLifted) && MatchGetMethodFromHandle(invocation.Arguments[3], out var method)) + { + if (isLifted != 0) + { method = CSharpOperators.LiftUserDefinedOperator((IMethod)method); } return (() => new Call((IMethod)method) { Arguments = { left(), right() } }, method.ReturnType); } var rr = resolver.ResolveBinaryOperator(kind.ToBinaryOperatorType(), new ResolveResult(leftType), new ResolveResult(rightType)) as OperatorResolveResult; - if (rr != null && !rr.IsError && rr.UserDefinedOperatorMethod != null) { + if (rr != null && !rr.IsError && rr.UserDefinedOperatorMethod != null) + { return (() => new Call(rr.UserDefinedOperatorMethod) { Arguments = { left(), right() } }, rr.UserDefinedOperatorMethod.ReturnType); } - if (leftType.IsKnownType(KnownTypeCode.String) && rightType.IsKnownType(KnownTypeCode.String)) { + if (leftType.IsKnownType(KnownTypeCode.String) && rightType.IsKnownType(KnownTypeCode.String)) + { IMethod operatorMethod; - switch (kind) { + switch (kind) + { case ComparisonKind.Equality: operatorMethod = leftType.GetMethods(m => m.IsOperator && m.Name == "op_Equality" && m.Parameters.Count == 2).FirstOrDefault(m => m.Parameters[0].Type.IsKnownType(KnownTypeCode.String) && m.Parameters[1].Type.IsKnownType(KnownTypeCode.String)); if (operatorMethod == null) @@ -726,7 +790,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (!MatchConstantCall(invocation, out var value, out var type)) return (null, SpecialType.UnknownType); - if (value.MatchBox(out var arg, out var boxType)) { + if (value.MatchBox(out var arg, out var boxType)) + { if (boxType.Kind == TypeKind.Enum || boxType.IsKnownType(KnownTypeCode.Boolean)) return (() => new ExpressionTreeCast(boxType, ConvertValue(arg, invocation), false), boxType); return (() => ConvertValue(arg, invocation), type); @@ -743,7 +808,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!MatchArgumentList(invocation.Arguments[1], out var arguments)) return (null, SpecialType.UnknownType); var args = new Func[arguments.Count]; - for (int i = 0; i < arguments.Count; i++) { + for (int i = 0; i < arguments.Count; i++) + { var arg = ConvertInstruction(arguments[i]).Item1; if (arg == null) return (null, SpecialType.UnknownType); @@ -766,7 +832,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (invocation.Arguments.Count != 2) return (null, SpecialType.UnknownType); Func targetConverter = null; - if (!invocation.Arguments[0].MatchLdNull()) { + if (!invocation.Arguments[0].MatchLdNull()) + { targetConverter = ConvertInstruction(invocation.Arguments[0]).Item1; if (targetConverter == null) return (null, SpecialType.UnknownType); @@ -774,7 +841,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!MatchGetFieldFromHandle(invocation.Arguments[1], out var member)) return (null, SpecialType.UnknownType); IType type = member.ReturnType; - if (typeHint.SkipModifiers() is ByReferenceType && !member.ReturnType.IsByRefLike) { + if (typeHint.SkipModifiers() is ByReferenceType && !member.ReturnType.IsByRefLike) + { type = typeHint; } return (BuildField, type); @@ -782,17 +850,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInstruction BuildField() { ILInstruction inst; - if (targetConverter == null) { + if (targetConverter == null) + { inst = new LdsFlda((IField)member); - } else { + } + else + { var target = targetConverter(); - if (member.DeclaringType.IsReferenceType == true) { + if (member.DeclaringType.IsReferenceType == true) + { inst = new LdFlda(target, (IField)member) { DelayExceptions = true }; - } else { + } + else + { inst = new LdFlda(new AddressOf(target, member.DeclaringType), (IField)member) { DelayExceptions = true }; } } - if (!(typeHint.SkipModifiers() is ByReferenceType && !member.ReturnType.IsByRefLike)) { + if (!(typeHint.SkipModifiers() is ByReferenceType && !member.ReturnType.IsByRefLike)) + { inst = new LdObj(inst, member.ReturnType); } return inst; @@ -835,24 +910,31 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!MatchNew((CallInstruction)invocation.Arguments[0], out var ctor)) return (null, SpecialType.UnknownType); IList arguments; - if (!MatchGetMethodFromHandle(invocation.Arguments[1], out var member)) { + if (!MatchGetMethodFromHandle(invocation.Arguments[1], out var member)) + { if (!MatchArgumentList(invocation.Arguments[1], out arguments)) return (null, SpecialType.UnknownType); - } else { + } + else + { if (invocation.Arguments.Count != 3 || !MatchArgumentList(invocation.Arguments[2], out arguments)) return (null, SpecialType.UnknownType); } if (arguments == null || arguments.Count == 0) return (null, SpecialType.UnknownType); Func[] convertedArguments = new Func[arguments.Count]; - for (int i = 0; i < arguments.Count; i++) { - if (arguments[i] is CallInstruction elementInit && elementInit.Method.FullName == "System.Linq.Expressions.Expression.ElementInit") { + for (int i = 0; i < arguments.Count; i++) + { + if (arguments[i] is CallInstruction elementInit && elementInit.Method.FullName == "System.Linq.Expressions.Expression.ElementInit") + { var arg = ConvertElementInit(elementInit).Item1; if (arg == null) return (null, SpecialType.UnknownType); - + convertedArguments[i] = v => { var a = arg(); ((CallInstruction)a).Arguments.Insert(0, new LdLoc(v)); return a; }; - } else { + } + else + { var arg = ConvertInstruction(arguments[i]).Item1; if (arg == null) return (null, SpecialType.UnknownType); @@ -885,7 +967,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (right == null) return (null, SpecialType.UnknownType); IMember method; - switch (invocation.Arguments.Count) { + switch (invocation.Arguments.Count) + { case 2: var resultType = context.TypeSystem.FindType(KnownTypeCode.Boolean); return (() => and ? IfInstruction.LogicAnd(left(), right()) : IfInstruction.LogicOr(left(), right()), resultType); @@ -925,13 +1008,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms return (null, SpecialType.UnknownType); Func[] convertedArguments = new Func[arguments.Count]; - for (int i = 0; i < arguments.Count; i++) { + for (int i = 0; i < arguments.Count; i++) + { Func arg; - if (arguments[i] is CallInstruction bind && bind.Method.FullName == "System.Linq.Expressions.Expression.Bind") { + if (arguments[i] is CallInstruction bind && bind.Method.FullName == "System.Linq.Expressions.Expression.Bind") + { arg = ConvertBind(bind).Item1; if (arg == null) return (null, SpecialType.UnknownType); - } else { + } + else + { return (null, SpecialType.UnknownType); } convertedArguments[i] = arg; @@ -965,7 +1052,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (arguments.Count == 0) return (null, SpecialType.UnknownType); var indices = new Func[arguments.Count]; - for (int i = 0; i < arguments.Count; i++) { + for (int i = 0; i < arguments.Count; i++) + { var index = ConvertInstruction(arguments[i]).Item1; if (index == null) return (null, SpecialType.UnknownType); @@ -986,7 +1074,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (arguments.Count == 0) return (() => new NewArr(type, new LdcI4(0)), arrayType); var convertedArguments = new Func[arguments.Count]; - for (int i = 0; i < arguments.Count; i++) { + for (int i = 0; i < arguments.Count; i++) + { ILInstruction item = arguments[i]; var value = ConvertInstruction(item).Item1; if (value == null) @@ -1001,7 +1090,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var variable = function.RegisterVariable(VariableKind.InitializerTarget, arrayType); Block initializer = new Block(BlockKind.ArrayInitializer); initializer.Instructions.Add(new StLoc(variable, new NewArr(type, new LdcI4(convertedArguments.Length)))); - for (int i = 0; i < convertedArguments.Length; i++) { + for (int i = 0; i < convertedArguments.Length; i++) + { initializer.Instructions.Add(new StObj(new LdElema(type, new LdLoc(variable), new LdcI4(i)) { DelayExceptions = true }, convertedArguments[i](), type)); } initializer.FinalInstruction = new LdLoc(variable); @@ -1016,13 +1106,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms ctor = null; if (invocation.Method.Name != "New") return false; - switch (invocation.Arguments.Count) { + switch (invocation.Arguments.Count) + { case 1: - if (MatchGetTypeFromHandle(invocation.Arguments[0], out var type)) { + if (MatchGetTypeFromHandle(invocation.Arguments[0], out var type)) + { ctor = type.GetConstructors(c => c.Parameters.Count == 0).FirstOrDefault(); return ctor != null; } - if (MatchGetConstructorFromHandle(invocation.Arguments[0], out var member)) { + if (MatchGetConstructorFromHandle(invocation.Arguments[0], out var member)) + { ctor = (IMethod)member; return true; } @@ -1040,15 +1133,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms (Func, IType) ConvertNewObject(CallInstruction invocation) { - switch (invocation.Arguments.Count) { + switch (invocation.Arguments.Count) + { case 1: - if (MatchGetTypeFromHandle(invocation.Arguments[0], out var type)) { + if (MatchGetTypeFromHandle(invocation.Arguments[0], out var type)) + { var ctor = type.GetConstructors(c => c.Parameters.Count == 0).FirstOrDefault(); if (ctor == null) return (null, SpecialType.UnknownType); return (() => new NewObj(ctor), type); } - if (MatchGetConstructorFromHandle(invocation.Arguments[0], out var member)) { + if (MatchGetConstructorFromHandle(invocation.Arguments[0], out var member)) + { return (() => new NewObj((IMethod)member), member.DeclaringType); } return (null, SpecialType.UnknownType); @@ -1091,7 +1187,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var (argument, argumentType) = ConvertInstruction(invocation.Arguments[0]); if (argument == null) return (null, SpecialType.UnknownType); - switch (invocation.Arguments.Count) { + switch (invocation.Arguments.Count) + { case 1: return (() => argumentType.IsKnownType(KnownTypeCode.Boolean) ? Comp.LogicNot(argument()) : (ILInstruction)new BitNot(argument()), argumentType); case 2: @@ -1111,7 +1208,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return (null, SpecialType.UnknownType); Func targetConverter = null; IType targetType = null; - if (!invocation.Arguments[0].MatchLdNull()) { + if (!invocation.Arguments[0].MatchLdNull()) + { (targetConverter, targetType) = ConvertInstruction(invocation.Arguments[0]); if (targetConverter == null) return (null, SpecialType.UnknownType); @@ -1119,7 +1217,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!MatchGetMethodFromHandle(invocation.Arguments[1], out var member)) return (null, SpecialType.UnknownType); IList arguments; - if (invocation.Arguments.Count != 3 || !MatchArgumentList(invocation.Arguments[2], out arguments)) { + if (invocation.Arguments.Count != 3 || !MatchArgumentList(invocation.Arguments[2], out arguments)) + { arguments = new List(); } var convertedArguments = ConvertCallArguments(arguments, (IMethod)member); @@ -1128,12 +1227,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInstruction BuildProperty() { CallInstruction call; - if (member.IsStatic) { + if (member.IsStatic) + { call = new Call((IMethod)member); - } else { + } + else + { call = new CallVirt((IMethod)member); } - if (targetConverter != null) { + if (targetConverter != null) + { call.Arguments.Add(PrepareCallTarget(member.DeclaringType, targetConverter(), targetType)); } call.Arguments.AddRange(convertedArguments.Select(f => f())); @@ -1183,10 +1286,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms var (argument, argumentType) = ConvertInstruction(invocation.Arguments[0]); if (argument == null) return (null, SpecialType.UnknownType); - switch (invocation.Arguments.Count) { + switch (invocation.Arguments.Count) + { case 1: ILInstruction left; - switch (argumentType.GetStackType()) { + switch (argumentType.GetStackType()) + { case StackType.I4: left = new LdcI4(0); break; @@ -1218,9 +1323,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInstruction ConvertValue(ILInstruction value, ILInstruction context) { - switch (value) { + switch (value) + { case LdLoc ldloc: - if (IsExpressionTreeParameter(ldloc.Variable)) { + if (IsExpressionTreeParameter(ldloc.Variable)) + { if (!parameterMapping.TryGetValue(ldloc.Variable, out var v)) return ldloc.Clone(); if (context is CallInstruction parentCall @@ -1228,19 +1335,26 @@ namespace ICSharpCode.Decompiler.IL.Transforms && v.StackType.IsIntegerType()) return new LdLoca(v).WithILRange(ldloc); return null; - } else if (IsClosureReference(ldloc.Variable)) { - if (ldloc.Variable.Kind == VariableKind.Local) { + } + else if (IsClosureReference(ldloc.Variable)) + { + if (ldloc.Variable.Kind == VariableKind.Local) + { ldloc.Variable.Kind = VariableKind.DisplayClassLocal; } - if (ldloc.Variable.CaptureScope == null) { + if (ldloc.Variable.CaptureScope == null) + { ldloc.Variable.CaptureScope = BlockContainer.FindClosestContainer(context); var f = ldloc.Variable.CaptureScope.Ancestors.OfType().FirstOrDefault(); - if (f != null) { + if (f != null) + { f.CapturedVariables.Add(ldloc.Variable); } } return ldloc; - } else { + } + else + { return ldloc; } default: @@ -1266,7 +1380,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { value = null; type = null; - if (inst is CallInstruction call && call.Method.FullName == "System.Linq.Expressions.Expression.Constant") { + if (inst is CallInstruction call && call.Method.FullName == "System.Linq.Expressions.Expression.Constant") + { value = call.Arguments[0]; if (call.Arguments.Count == 2) return MatchGetTypeFromHandle(call.Arguments[1], out type); @@ -1322,7 +1437,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms static bool MatchFromHandleParameterList(CallInstruction call, out IMember member) { member = null; - switch (call.Arguments.Count) { + switch (call.Arguments.Count) + { case 1: if (!call.Arguments[0].MatchLdMemberToken(out member)) return false; @@ -1342,8 +1458,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool MatchArgumentList(ILInstruction inst, out IList arguments) { arguments = null; - if (!(inst is Block block && block.Kind == BlockKind.ArrayInitializer)) { - if (IsEmptyParameterList(inst)) { + if (!(inst is Block block && block.Kind == BlockKind.ArrayInitializer)) + { + if (IsEmptyParameterList(inst)) + { arguments = new List(); return true; } @@ -1351,7 +1469,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms } int i = 0; arguments = new List(); - foreach (var item in block.Instructions.OfType()) { + foreach (var item in block.Instructions.OfType()) + { if (!(item.Target is LdElema ldelem && ldelem.Indices.Single().MatchLdcI4(i))) return false; arguments.Add(item.Value); diff --git a/ICSharpCode.Decompiler/IL/Transforms/TupleTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/TupleTransform.cs index 6e61499f1..7b6f5cdbe 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TupleTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TupleTransform.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL @@ -36,7 +37,8 @@ namespace ICSharpCode.Decompiler.IL { tupleType = inst.Field.DeclaringType; target = inst.Target; - if (!inst.Field.Name.StartsWith("Item", StringComparison.Ordinal)) { + if (!inst.Field.Name.StartsWith("Item", StringComparison.Ordinal)) + { position = 0; return false; } @@ -44,7 +46,8 @@ namespace ICSharpCode.Decompiler.IL return false; if (!TupleType.IsTupleCompatible(tupleType, out _)) return false; - while (target is LdFlda ldflda && ldflda.Field.Name == "Rest" && TupleType.IsTupleCompatible(ldflda.Field.DeclaringType, out _)) { + while (target is LdFlda ldflda && ldflda.Field.Name == "Rest" && TupleType.IsTupleCompatible(ldflda.Field.DeclaringType, out _)) + { tupleType = ldflda.Field.DeclaringType; target = ldflda.Target; position += TupleType.RestPosition - 1; @@ -65,11 +68,13 @@ namespace ICSharpCode.Decompiler.IL return false; arguments = new ILInstruction[elementCount]; int outIndex = 0; - while (elementCount >= TupleType.RestPosition) { + while (elementCount >= TupleType.RestPosition) + { if (newobj.Arguments.Count != TupleType.RestPosition) return false; - for (int pos = 1; pos < TupleType.RestPosition; pos++) { - arguments[outIndex++] = newobj.Arguments[pos-1]; + for (int pos = 1; pos < TupleType.RestPosition; pos++) + { + arguments[outIndex++] = newobj.Arguments[pos - 1]; } elementCount -= TupleType.RestPosition - 1; Debug.Assert(outIndex + elementCount == arguments.Length); @@ -84,7 +89,8 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(outIndex + elementCount == arguments.Length); if (newobj.Arguments.Count != elementCount) return false; - for (int i = 0; i < elementCount; i++) { + for (int i = 0; i < elementCount; i++) + { arguments[outIndex++] = newobj.Arguments[i]; } return true; diff --git a/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs index ec6eeaf91..9f1221385 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -45,19 +46,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms // user.logic op_BitwiseAnd(ldloc lhsVar, rhsInst) if (!block.Instructions[pos].MatchIfInstructionPositiveCondition(out var condition, out var trueInst, out var falseInst)) return false; - if (trueInst.OpCode == OpCode.Nop) { + if (trueInst.OpCode == OpCode.Nop) + { trueInst = block.Instructions[pos + 1]; - } else if (falseInst.OpCode == OpCode.Nop) { + } + else if (falseInst.OpCode == OpCode.Nop) + { falseInst = block.Instructions[pos + 1]; - } else { + } + else + { return false; } - if (trueInst.MatchReturn(out var trueValue) && falseInst.MatchReturn(out var falseValue)) { + if (trueInst.MatchReturn(out var trueValue) && falseInst.MatchReturn(out var falseValue)) + { var transformed = Transform(condition, trueValue, falseValue); - if (transformed == null) { + if (transformed == null) + { transformed = TransformDynamic(condition, trueValue, falseValue); } - if (transformed != null) { + if (transformed != null) + { context.Step("User-defined short-circuiting logic operator (optimized return)", condition); ((Leave)block.Instructions[pos + 1]).Value = transformed; block.Instructions.RemoveAt(pos); @@ -91,7 +100,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms var trueInst = Block.Unwrap(ifInst.TrueInst); if (!trueInst.MatchStLoc(s, out var storeValue)) return false; - if (storeValue is Call call) { + if (storeValue is Call call) + { if (!MatchBitwiseCall(call, s, conditionMethodName)) return false; if (s.IsUsedWithin(call.Arguments[1])) @@ -152,83 +162,117 @@ namespace ICSharpCode.Decompiler.IL.Transforms result.AddILRange(call); return result; } - + public static ILInstruction TransformDynamic(ILInstruction condition, ILInstruction trueInst, ILInstruction falseInst) { // Check condition: System.Linq.Expressions.ExpressionType unaryOp; - if (condition.MatchLdLoc(out var lhsVar)) { + if (condition.MatchLdLoc(out var lhsVar)) + { // if (ldloc lhsVar) box bool(ldloc lhsVar) else dynamic.binary.operator.logic Or(ldloc lhsVar, rhsInst) // -> dynamic.logic.operator OrElse(ldloc lhsVar, rhsInst) - if (trueInst is Box box && box.Type.IsKnownType(KnownTypeCode.Boolean)) { + if (trueInst is Box box && box.Type.IsKnownType(KnownTypeCode.Boolean)) + { unaryOp = System.Linq.Expressions.ExpressionType.IsTrue; trueInst = box.Argument; - } else if (falseInst is Box box2 && box2.Type.IsKnownType(KnownTypeCode.Boolean)) { + } + else if (falseInst is Box box2 && box2.Type.IsKnownType(KnownTypeCode.Boolean)) + { // negate condition and swap true/false unaryOp = System.Linq.Expressions.ExpressionType.IsFalse; falseInst = trueInst; trueInst = box2.Argument; - } else { + } + else + { return null; } - } else if (condition is DynamicUnaryOperatorInstruction unary) { + } + else if (condition is DynamicUnaryOperatorInstruction unary) + { // if (dynamic.unary.operator IsFalse(ldloc lhsVar)) ldloc lhsVar else dynamic.binary.operator.logic And(ldloc lhsVar, rhsInst) // -> dynamic.logic.operator AndAlso(ldloc lhsVar, rhsInst) unaryOp = unary.Operation; if (!unary.Operand.MatchLdLoc(out lhsVar)) return null; - } else if (MatchCondition(condition, out lhsVar, out string operatorMethodName)) { + } + else if (MatchCondition(condition, out lhsVar, out string operatorMethodName)) + { // if (call op_False(ldloc s)) box S(ldloc s) else dynamic.binary.operator.logic And(ldloc s, rhsInst)) - if (operatorMethodName == "op_True") { + if (operatorMethodName == "op_True") + { unaryOp = System.Linq.Expressions.ExpressionType.IsTrue; - } else { + } + else + { Debug.Assert(operatorMethodName == "op_False"); unaryOp = System.Linq.Expressions.ExpressionType.IsFalse; } var callParamType = ((Call)condition).Method.Parameters.Single().Type.SkipModifiers(); - if (callParamType.IsReferenceType == false) { + if (callParamType.IsReferenceType == false) + { // If lhs is a value type, eliminate the boxing instruction. - if (trueInst is Box box && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(box.Type, callParamType)) { + if (trueInst is Box box && NormalizeTypeVisitor.TypeErasure.EquivalentTypes(box.Type, callParamType)) + { trueInst = box.Argument; - } else if (trueInst.OpCode == OpCode.LdcI4) { + } + else if (trueInst.OpCode == OpCode.LdcI4) + { // special case, handled below in 'check trueInst' - } else { + } + else + { return null; } } - } else { + } + else + { return null; } // Check trueInst: DynamicUnaryOperatorInstruction rhsUnary; - if (trueInst.MatchLdLoc(lhsVar)) { + if (trueInst.MatchLdLoc(lhsVar)) + { // OK, typical pattern where the expression evaluates to 'dynamic' rhsUnary = null; - } else if (trueInst.MatchLdcI4(1) && unaryOp == System.Linq.Expressions.ExpressionType.IsTrue) { + } + else if (trueInst.MatchLdcI4(1) && unaryOp == System.Linq.Expressions.ExpressionType.IsTrue) + { // logic.or(IsTrue(lhsVar), IsTrue(lhsVar | rhsInst)) // => IsTrue(lhsVar || rhsInst) rhsUnary = falseInst as DynamicUnaryOperatorInstruction; - if (rhsUnary != null) { + if (rhsUnary != null) + { if (rhsUnary.Operation != System.Linq.Expressions.ExpressionType.IsTrue) return null; falseInst = rhsUnary.Operand; - } else { + } + else + { return null; } - } else { + } + else + { return null; } System.Linq.Expressions.ExpressionType expectedBitop; System.Linq.Expressions.ExpressionType logicOp; - if (unaryOp == System.Linq.Expressions.ExpressionType.IsFalse) { + if (unaryOp == System.Linq.Expressions.ExpressionType.IsFalse) + { expectedBitop = System.Linq.Expressions.ExpressionType.And; logicOp = System.Linq.Expressions.ExpressionType.AndAlso; - } else if (unaryOp == System.Linq.Expressions.ExpressionType.IsTrue) { + } + else if (unaryOp == System.Linq.Expressions.ExpressionType.IsTrue) + { expectedBitop = System.Linq.Expressions.ExpressionType.Or; logicOp = System.Linq.Expressions.ExpressionType.OrElse; - } else { + } + else + { return null; } @@ -242,10 +286,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms var logicInst = new DynamicLogicOperatorInstruction(binary.BinderFlags, logicOp, binary.CallingContext, binary.LeftArgumentInfo, binary.Left, binary.RightArgumentInfo, binary.Right) .WithILRange(binary); - if (rhsUnary != null) { + if (rhsUnary != null) + { rhsUnary.Operand = logicInst; return rhsUnary; - } else { + } + else + { return logicInst; } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs index 88d8f70e3..53795a1d3 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL.Transforms @@ -31,9 +32,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms void IBlockTransform.Run(Block block, BlockTransformContext context) { - if (!context.Settings.UsingStatement) return; + if (!context.Settings.UsingStatement) + return; this.context = context; - for (int i = block.Instructions.Count - 1; i >= 0; i--) { + for (int i = block.Instructions.Count - 1; i >= 0; i--) + { if (!TransformUsing(block, i) && !TransformUsingVB(block, i) && !TransformAsyncUsing(block, i)) continue; // This happens in some cases: @@ -71,7 +74,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// bool TransformUsing(Block block, int i) { - if (i < 1) return false; + if (i < 1) + return false; if (!(block.Instructions[i] is TryFinally tryFinally) || !(block.Instructions[i - 1] is StLoc storeInst)) return false; if (!(storeInst.Value.MatchLdNull() || CheckResourceType(storeInst.Variable.Type))) @@ -181,7 +185,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms int castIndex = entryPoint.Instructions.Count == 3 ? 0 : -1; var checkInst = entryPoint.Instructions[checkIndex]; bool isReference = objVar.Type.IsReferenceType != false; - if (castIndex > -1) { + if (castIndex > -1) + { if (!entryPoint.Instructions[castIndex].MatchStLoc(out var tempVar, out var isinst)) return false; if (!isinst.MatchIsInst(out var load, out var disposableType) || !load.MatchLdLoc(objVar) || !disposableType.IsKnownType(disposeTypeCode)) @@ -193,7 +198,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (tempVar.LoadCount != numObjVarLoadsInCheck) return false; - } else { + } + else + { if (!MatchDisposeCheck(objVar, checkInst, isReference, usingNull, out _, disposeMethodFullName, disposeTypeCode)) return false; } @@ -207,19 +214,26 @@ namespace ICSharpCode.Decompiler.IL.Transforms numObjVarLoadsInCheck = 2; ILInstruction disposeInvocation; CallInstruction disposeCall; - if (objVar.Type.IsKnownType(KnownTypeCode.NullableOfT)) { - if (checkInst.MatchIfInstruction(out var condition, out var disposeInst)) { + if (objVar.Type.IsKnownType(KnownTypeCode.NullableOfT)) + { + if (checkInst.MatchIfInstruction(out var condition, out var disposeInst)) + { if (!NullableLiftingTransform.MatchHasValueCall(condition, objVar)) return false; if (!(disposeInst is Block disposeBlock) || disposeBlock.Instructions.Count != 1) return false; disposeInvocation = disposeBlock.Instructions[0]; - } else if (checkInst.MatchNullableRewrap(out disposeInst)) { + } + else if (checkInst.MatchNullableRewrap(out disposeInst)) + { disposeInvocation = disposeInst; - } else { + } + else + { return false; } - if (disposeTypeCode == KnownTypeCode.IAsyncDisposable) { + if (disposeTypeCode == KnownTypeCode.IAsyncDisposable) + { if (!UnwrapAwait(ref disposeInvocation)) return false; } @@ -233,22 +247,28 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (disposeCall.Arguments.Count != 1) return false; var firstArg = disposeCall.Arguments.FirstOrDefault(); - if (!(firstArg.MatchUnboxAny(out var innerArg1, out var unboxType) && unboxType.IsKnownType(disposeTypeCode))) { + if (!(firstArg.MatchUnboxAny(out var innerArg1, out var unboxType) && unboxType.IsKnownType(disposeTypeCode))) + { if (!firstArg.MatchAddressOf(out var innerArg2, out _)) return false; return NullableLiftingTransform.MatchGetValueOrDefault(innerArg2, objVar) || (innerArg2 is NullableUnwrap unwrap && unwrap.Argument.MatchLdLoc(objVar)); - } else { + } + else + { if (!(innerArg1.MatchBox(out firstArg, out var boxType) && boxType.IsKnownType(KnownTypeCode.NullableOfT) && NullableType.GetUnderlyingType(boxType).Equals(NullableType.GetUnderlyingType(objVar.Type)))) return false; return firstArg.MatchLdLoc(objVar); } - } else { + } + else + { ILInstruction target; bool boxedValue = false; - if (isReference && checkInst is NullableRewrap rewrap) { + if (isReference && checkInst is NullableRewrap rewrap) + { // the null check of reference types might have been transformed into "objVar?.Dispose();" if (!(rewrap.Argument is CallVirt cv)) return false; @@ -257,7 +277,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms numObjVarLoadsInCheck = 1; disposeCall = cv; target = unwrap.Argument; - } else if (isReference) { + } + else if (isReference) + { // reference types have a null check. if (!checkInst.MatchIfInstruction(out var condition, out var disposeInst)) return false; @@ -266,7 +288,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!(disposeInst is Block disposeBlock) || disposeBlock.Instructions.Count != 1) return false; disposeInvocation = disposeBlock.Instructions[0]; - if (disposeTypeCode == KnownTypeCode.IAsyncDisposable) { + if (disposeTypeCode == KnownTypeCode.IAsyncDisposable) + { if (!UnwrapAwait(ref disposeInvocation)) return false; } @@ -278,7 +301,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (target.MatchBox(out var newTarget, out var type) && type.Equals(objVar.Type)) target = newTarget; disposeCall = cv; - } else if (objVar.Type.Kind == TypeKind.Struct && objVar.Type.IsByRefLike) { + } + else if (objVar.Type.Kind == TypeKind.Struct && objVar.Type.IsByRefLike) + { if (!(checkInst is Call call && call.Method.DeclaringType == objVar.Type)) return false; target = call.Arguments.FirstOrDefault(); @@ -288,8 +313,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; disposeMethodFullName = call.Method.FullName; disposeCall = call; - } else { - if (disposeTypeCode == KnownTypeCode.IAsyncDisposable) { + } + else + { + if (disposeTypeCode == KnownTypeCode.IAsyncDisposable) + { if (!UnwrapAwait(ref checkInst)) return false; } @@ -298,7 +326,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms target = cv.Arguments.FirstOrDefault(); if (target == null) return false; - if (target.MatchBox(out var newTarget, out var type) && type.Equals(objVar.Type)) { + if (target.MatchBox(out var newTarget, out var type) && type.Equals(objVar.Type)) + { boxedValue = type.IsReferenceType != true; target = newTarget; } @@ -342,7 +371,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// private bool TransformAsyncUsing(Block block, int i) { - if (i < 1 || !context.Settings.AsyncUsingAndForEachStatement) return false; + if (i < 1 || !context.Settings.AsyncUsingAndForEachStatement) + return false; if (!(block.Instructions[i] is TryFinally tryFinally) || !(block.Instructions[i - 1] is StLoc storeInst)) return false; if (!CheckAsyncResourceType(storeInst.Variable.Type, out string disposeMethodFullName)) @@ -369,7 +399,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { disposeMethodFullName = null; IType t = NullableType.GetUnderlyingType(type); - if (t.GetAllBaseTypes().Any(b => b.IsKnownType(KnownTypeCode.IAsyncDisposable))) { + if (t.GetAllBaseTypes().Any(b => b.IsKnownType(KnownTypeCode.IAsyncDisposable))) + { disposeMethodFullName = "System.IAsyncDisposable.DisposeAsync"; return true; } @@ -377,7 +408,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms IMethod disposeMethod = t .GetMethods(m => m.Parameters.Count == 0 && m.TypeParameters.Count == 0 && m.Name == "DisposeAsync") .SingleOrDefault(); - if (disposeMethod != null) { + if (disposeMethod != null) + { disposeMethodFullName = disposeMethod.FullName; return true; } diff --git a/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs b/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs index d066778af..d2f16d675 100644 --- a/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs +++ b/ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs @@ -86,14 +86,18 @@ namespace ICSharpCode.Decompiler.Metadata builder.Append("PublicKeyToken="); var pk_token = PublicKeyToken; - if (pk_token != null && pk_token.Length > 0) { - for (int i = 0; i < pk_token.Length; i++) { + if (pk_token != null && pk_token.Length > 0) + { + for (int i = 0; i < pk_token.Length; i++) + { builder.Append(pk_token[i].ToString("x2")); } - } else + } + else builder.Append("null"); - if (IsRetargetable) { + if (IsRetargetable) + { builder.Append(sep); builder.Append("Retargetable=Yes"); } @@ -121,10 +125,12 @@ namespace ICSharpCode.Decompiler.Metadata var name = new AssemblyNameReference(); var tokens = fullName.Split(','); - for (int i = 0; i < tokens.Length; i++) { + for (int i = 0; i < tokens.Length; i++) + { var token = tokens[i].Trim(); - if (i == 0) { + if (i == 0) + { name.Name = token; continue; } @@ -133,7 +139,8 @@ namespace ICSharpCode.Decompiler.Metadata if (parts.Length != 2) throw new ArgumentException("Malformed name"); - switch (parts[0].ToLowerInvariant()) { + switch (parts[0].ToLowerInvariant()) + { case "version": name.Version = new Version(parts[1]); break; @@ -185,7 +192,8 @@ namespace ICSharpCode.Decompiler.Metadata if (entry.PublicKeyOrToken.IsNil) return null; var bytes = Metadata.GetBlobBytes(entry.PublicKeyOrToken); - if ((entry.Flags & AssemblyFlags.PublicKey) != 0) { + if ((entry.Flags & AssemblyFlags.PublicKey) != 0) + { return sha1.ComputeHash(bytes).Skip(12).ToArray(); } return bytes; diff --git a/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs b/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs index d6a949d7d..241996e0b 100644 --- a/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs +++ b/ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs @@ -87,7 +87,8 @@ namespace ICSharpCode.Decompiler.Metadata if (parents.ContainsKey(part)) return; parents.Add(part, parent); - if (!parts.TryGetValue(parent, out var list)) { + if (!parts.TryGetValue(parent, out var list)) + { list = new List(); parts.Add(parent, list); } diff --git a/ICSharpCode.Decompiler/Metadata/CustomAttributeDecoder.cs b/ICSharpCode.Decompiler/Metadata/CustomAttributeDecoder.cs index 254132f98..2212d32ad 100644 --- a/ICSharpCode.Decompiler/Metadata/CustomAttributeDecoder.cs +++ b/ICSharpCode.Decompiler/Metadata/CustomAttributeDecoder.cs @@ -26,13 +26,15 @@ namespace ICSharpCode.Decompiler.Metadata _provider = provider; _provideBoxingTypeInfo = provideBoxingTypeInfo; } - + public ImmutableArray> DecodeNamedArguments(ref BlobReader valueReader, int count) { var arguments = ImmutableArray.CreateBuilder>(count); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { CustomAttributeNamedArgumentKind kind = (CustomAttributeNamedArgumentKind)valueReader.ReadSerializationTypeCode(); - if (kind != CustomAttributeNamedArgumentKind.Field && kind != CustomAttributeNamedArgumentKind.Property) { + if (kind != CustomAttributeNamedArgumentKind.Field && kind != CustomAttributeNamedArgumentKind.Property) + { throw new BadImageFormatException(); } @@ -52,14 +54,15 @@ namespace ICSharpCode.Decompiler.Metadata public SerializationTypeCode TypeCode; public SerializationTypeCode ElementTypeCode; } - + private ArgumentTypeInfo DecodeNamedArgumentType(ref BlobReader valueReader, bool isElementType = false) { var info = new ArgumentTypeInfo { TypeCode = valueReader.ReadSerializationTypeCode(), }; - switch (info.TypeCode) { + switch (info.TypeCode) + { case SerializationTypeCode.Boolean: case SerializationTypeCode.Byte: case SerializationTypeCode.Char: @@ -85,7 +88,8 @@ namespace ICSharpCode.Decompiler.Metadata break; case SerializationTypeCode.SZArray: - if (isElementType) { + if (isElementType) + { // jagged arrays are not allowed. throw new BadImageFormatException(); } @@ -112,14 +116,16 @@ namespace ICSharpCode.Decompiler.Metadata private CustomAttributeTypedArgument DecodeArgument(ref BlobReader valueReader, ArgumentTypeInfo info) { var outer = info; - if (info.TypeCode == SerializationTypeCode.TaggedObject) { + if (info.TypeCode == SerializationTypeCode.TaggedObject) + { info = DecodeNamedArgumentType(ref valueReader); } // PERF_TODO: https://github.com/dotnet/corefx/issues/6533 // Cache /reuse common arguments to avoid boxing (small integers, true, false). object value; - switch (info.TypeCode) { + switch (info.TypeCode) + { case SerializationTypeCode.Boolean: value = valueReader.ReadBoolean(); break; @@ -185,7 +191,8 @@ namespace ICSharpCode.Decompiler.Metadata throw new BadImageFormatException(); } - if (_provideBoxingTypeInfo && outer.TypeCode == SerializationTypeCode.TaggedObject) { + if (_provideBoxingTypeInfo && outer.TypeCode == SerializationTypeCode.TaggedObject) + { return new CustomAttributeTypedArgument(outer.Type, new CustomAttributeTypedArgument(info.Type, value)); } @@ -195,15 +202,18 @@ namespace ICSharpCode.Decompiler.Metadata private ImmutableArray>? DecodeArrayArgument(ref BlobReader blobReader, ArgumentTypeInfo info) { int count = blobReader.ReadInt32(); - if (count == -1) { + if (count == -1) + { return null; } - if (count == 0) { + if (count == 0) + { return ImmutableArray>.Empty; } - if (count < 0) { + if (count < 0) + { throw new BadImageFormatException(); } @@ -214,7 +224,8 @@ namespace ICSharpCode.Decompiler.Metadata var array = ImmutableArray.CreateBuilder>(count); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { array.Add(DecodeArgument(ref blobReader, elementInfo)); } diff --git a/ICSharpCode.Decompiler/Metadata/Dom.cs b/ICSharpCode.Decompiler/Metadata/Dom.cs index 0425b4e5f..d9ed722ad 100644 --- a/ICSharpCode.Decompiler/Metadata/Dom.cs +++ b/ICSharpCode.Decompiler/Metadata/Dom.cs @@ -9,6 +9,7 @@ using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using System.Security.Cryptography; using System.Text; + using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs index c5c8722cf..6ef101115 100644 --- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs +++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs @@ -23,7 +23,9 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; + using ICSharpCode.Decompiler.Util; + using LightJson.Serialization; namespace ICSharpCode.Decompiler.Metadata @@ -70,9 +72,11 @@ namespace ICSharpCode.Decompiler.Metadata { this.targetFrameworkVersion = targetFrameworkVersion; - if (targetFramework == TargetFrameworkIdentifier.NETStandard) { + if (targetFramework == TargetFrameworkIdentifier.NETStandard) + { // .NET Standard 2.1 is implemented by .NET Core 3.0 or higher - if (targetFrameworkVersion.Major == 2 && targetFrameworkVersion.Minor == 1) { + if (targetFrameworkVersion.Major == 2 && targetFrameworkVersion.Minor == 1) + { this.targetFrameworkVersion = new Version(3, 0, 0); } } @@ -87,12 +91,16 @@ namespace ICSharpCode.Decompiler.Metadata searchPaths.Add(basePath); var depsJsonFileName = Path.Combine(basePath, $"{assemblyName}.deps.json"); - if (File.Exists(depsJsonFileName)) { + if (File.Exists(depsJsonFileName)) + { packages = LoadPackageInfos(depsJsonFileName, targetFrameworkIdString).ToArray(); - foreach (var path in LookupPaths) { - foreach (var p in packages) { - foreach (var item in p.RuntimeComponents) { + foreach (var path in LookupPaths) + { + foreach (var p in packages) + { + foreach (var item in p.RuntimeComponents) + { var itemPath = Path.GetDirectoryName(item); var fullPath = Path.Combine(path, p.Name, p.Version, itemPath).ToLowerInvariant(); if (Directory.Exists(fullPath)) @@ -100,7 +108,9 @@ namespace ICSharpCode.Decompiler.Metadata } } } - } else { + } + else + { loadInfo?.AddMessage(assemblyName, MessageKind.Warning, $"{assemblyName}.deps.json could not be found!"); } } @@ -117,10 +127,14 @@ namespace ICSharpCode.Decompiler.Metadata public string TryResolveDotNetCore(IAssemblyReference name) { - foreach (var basePath in searchPaths.Concat(packageBasePaths)) { - if (File.Exists(Path.Combine(basePath, name.Name + ".dll"))) { + foreach (var basePath in searchPaths.Concat(packageBasePaths)) + { + if (File.Exists(Path.Combine(basePath, name.Name + ".dll"))) + { return Path.Combine(basePath, name.Name + ".dll"); - } else if (File.Exists(Path.Combine(basePath, name.Name + ".exe"))) { + } + else if (File.Exists(Path.Combine(basePath, name.Name + ".exe"))) + { return Path.Combine(basePath, name.Name + ".exe"); } } @@ -132,7 +146,8 @@ namespace ICSharpCode.Decompiler.Metadata { var (tfi, version) = UniversalAssemblyResolver.ParseTargetFramework(targetFramework); string identifier, identifierExt; - switch (tfi) { + switch (tfi) + { case TargetFrameworkIdentifier.NETCoreApp: identifier = "Microsoft.NETCore.App"; identifierExt = "netcoreapp" + version.Major + "." + version.Minor; @@ -154,14 +169,17 @@ namespace ICSharpCode.Decompiler.Metadata var libraries = dependencies["libraries"].AsJsonObject; if (runtimeInfos == null || libraries == null) yield break; - foreach (var library in libraries) { + foreach (var library in libraries) + { var type = library.Value["type"].AsString; var path = library.Value["path"].AsString; var runtimeInfo = runtimeInfos[library.Key].AsJsonObject?["runtime"].AsJsonObject; string[] components = new string[runtimeInfo?.Count ?? 0]; - if (runtimeInfo != null) { + if (runtimeInfo != null) + { int i = 0; - foreach (var component in runtimeInfo) { + foreach (var component in runtimeInfo) + { components[i] = component.Key; i++; } @@ -175,13 +193,17 @@ namespace ICSharpCode.Decompiler.Metadata if (dotnetBasePath == null) return null; var basePaths = RuntimePacks.Select(pack => Path.Combine(dotnetBasePath, "shared", pack)); - foreach (var basePath in basePaths) { + foreach (var basePath in basePaths) + { if (!Directory.Exists(basePath)) continue; var closestVersion = GetClosestVersionFolder(basePath, targetFrameworkVersion); - if (File.Exists(Path.Combine(basePath, closestVersion, name.Name + ".dll"))) { + if (File.Exists(Path.Combine(basePath, closestVersion, name.Name + ".dll"))) + { return Path.Combine(basePath, closestVersion, name.Name + ".dll"); - } else if (File.Exists(Path.Combine(basePath, closestVersion, name.Name + ".exe"))) { + } + else if (File.Exists(Path.Combine(basePath, closestVersion, name.Name + ".exe"))) + { return Path.Combine(basePath, closestVersion, name.Name + ".exe"); } } @@ -193,7 +215,8 @@ namespace ICSharpCode.Decompiler.Metadata var foundVersions = new DirectoryInfo(basePath).GetDirectories() .Select(d => ConvertToVersion(d.Name)) .Where(v => v.version != null); - foreach (var folder in foundVersions.OrderBy(v => v.Item1)) { + foreach (var folder in foundVersions.OrderBy(v => v.Item1)) + { if (folder.version >= version) return folder.directoryName; } @@ -206,15 +229,19 @@ namespace ICSharpCode.Decompiler.Metadata { string shortName = name; int dashIndex = shortName.IndexOf('-'); - if (dashIndex > 0) { + if (dashIndex > 0) + { shortName = shortName.Remove(dashIndex); } return shortName; } - try { + try + { return (new Version(RemoveTrailingVersionInfo()), name); - } catch (Exception ex) { + } + catch (Exception ex) + { Trace.TraceWarning(ex.ToString()); return (null, null); } @@ -223,13 +250,17 @@ namespace ICSharpCode.Decompiler.Metadata public static string FindDotNetExeDirectory() { string dotnetExeName = (Environment.OSVersion.Platform == PlatformID.Unix) ? "dotnet" : "dotnet.exe"; - foreach (var item in Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator)) { - try { + foreach (var item in Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator)) + { + try + { string fileName = Path.Combine(item, dotnetExeName); if (!File.Exists(fileName)) continue; - if (Environment.OSVersion.Platform == PlatformID.Unix) { - if ((new FileInfo(fileName).Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint) { + if (Environment.OSVersion.Platform == PlatformID.Unix) + { + if ((new FileInfo(fileName).Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint) + { var sb = new StringBuilder(); realpath(fileName, sb); fileName = sb.ToString(); @@ -238,7 +269,8 @@ namespace ICSharpCode.Decompiler.Metadata } } return Path.GetDirectoryName(fileName); - } catch (ArgumentException) { } + } + catch (ArgumentException) { } } return null; } diff --git a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs index dd7aee077..aea9fea59 100644 --- a/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs @@ -19,9 +19,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; +using System.Text.RegularExpressions; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Metadata @@ -35,7 +36,7 @@ namespace ICSharpCode.Decompiler.Metadata @"|(NuGetFallbackFolder[/\\](?[^/\\]+)\\(?[^/\\]+)([/\\].*)?[/\\]ref[/\\])" + @"|(shared[/\\](?[^/\\]+)\\(?[^/\\]+)([/\\].*)?[/\\])" + @"|(packs[/\\](?[^/\\]+)\\(?[^/\\]+)\\ref([/\\].*)?[/\\])"; - + static readonly string RefPathPattern = @"(Reference Assemblies[/\\]Microsoft[/\\]Framework[/\\](?.NETFramework)[/\\]v(?[^/\\]+)[/\\])" + @"|(NuGetFallbackFolder[/\\](?[^/\\]+)\\(?[^/\\]+)([/\\].*)?[/\\]ref[/\\])" + @@ -54,27 +55,35 @@ namespace ICSharpCode.Decompiler.Metadata const string TargetFrameworkAttributeName = "System.Runtime.Versioning.TargetFrameworkAttribute"; var reader = assembly.GetMetadataReader(); - foreach (var h in reader.GetCustomAttributes(Handle.AssemblyDefinition)) { - try { + foreach (var h in reader.GetCustomAttributes(Handle.AssemblyDefinition)) + { + try + { var attribute = reader.GetCustomAttribute(h); if (attribute.GetAttributeType(reader).GetFullTypeName(reader).ToString() != TargetFrameworkAttributeName) continue; var blobReader = reader.GetBlobReader(attribute.Value); - if (blobReader.ReadUInt16() == 0x0001) { + if (blobReader.ReadUInt16() == 0x0001) + { return blobReader.ReadSerializedString(); } - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { // ignore malformed attributes } } - foreach (var h in reader.AssemblyReferences) { - try { + foreach (var h in reader.AssemblyReferences) + { + try + { var r = reader.GetAssemblyReference(h); if (r.PublicKeyOrToken.IsNil) continue; string version; - switch (reader.GetString(r.Name)) { + switch (reader.GetString(r.Name)) + { case "netstandard": version = r.Version.ToString(3); return $".NETStandard,Version=v{version}"; @@ -83,29 +92,37 @@ namespace ICSharpCode.Decompiler.Metadata // 4.2.0 => .NET Core 2.0 // 4.2.1 => .NET Core 2.1 / 3.0 // 4.2.2 => .NET Core 3.1 - if (r.Version >= new Version(4, 2, 0)) { + if (r.Version >= new Version(4, 2, 0)) + { version = "2.0"; - if (r.Version >= new Version(4, 2, 1)) { + if (r.Version >= new Version(4, 2, 1)) + { version = "3.0"; } - if (r.Version >= new Version(4, 2, 2)) { + if (r.Version >= new Version(4, 2, 2)) + { version = "3.1"; } return $".NETCoreApp,Version=v{version}"; - } else { + } + else + { continue; } case "mscorlib": version = r.Version.ToString(2); return $".NETFramework,Version=v{version}"; } - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { // ignore malformed references } } // Optionally try to detect target version through assembly path as a fallback (use case: reference assemblies) - if (assemblyPath != null) { + if (assemblyPath != null) + { /* * Detected path patterns (examples): * @@ -115,20 +132,28 @@ namespace ICSharpCode.Decompiler.Metadata */ var pathMatch = Regex.Match(assemblyPath, PathPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture); - if (pathMatch.Success) { + if (pathMatch.Success) + { var type = pathMatch.Groups["type"].Value; var version = pathMatch.Groups["version"].Value; if (string.IsNullOrEmpty(version)) version = reader.MetadataVersion; - if (type == "Microsoft.NET" || type == ".NETFramework") { + if (type == "Microsoft.NET" || type == ".NETFramework") + { return $".NETFramework,Version=v{version.TrimStart('v').Substring(0, 3)}"; - } else if (type.IndexOf("netcore", StringComparison.OrdinalIgnoreCase) >= 0) { + } + else if (type.IndexOf("netcore", StringComparison.OrdinalIgnoreCase) >= 0) + { return $".NETCoreApp,Version=v{version}"; - } else if (type.IndexOf("netstandard", StringComparison.OrdinalIgnoreCase) >= 0) { + } + else if (type.IndexOf("netstandard", StringComparison.OrdinalIgnoreCase) >= 0) + { return $".NETStandard,Version=v{version}"; } - } else { + } + else + { return $".NETFramework,Version={reader.MetadataVersion.Substring(0, 4)}"; } } @@ -162,8 +187,10 @@ namespace ICSharpCode.Decompiler.Metadata public void AddMessage(string fullName, MessageKind kind, string message) { - lock (loadedAssemblyReferences) { - if (!loadedAssemblyReferences.TryGetValue(fullName, out var referenceInfo)) { + lock (loadedAssemblyReferences) + { + if (!loadedAssemblyReferences.TryGetValue(fullName, out var referenceInfo)) + { referenceInfo = new UnresolvedAssemblyNameReference(fullName); loadedAssemblyReferences.Add(fullName, referenceInfo); } @@ -173,12 +200,16 @@ namespace ICSharpCode.Decompiler.Metadata public void AddMessageOnce(string fullName, MessageKind kind, string message) { - lock (loadedAssemblyReferences) { - if (!loadedAssemblyReferences.TryGetValue(fullName, out var referenceInfo)) { + lock (loadedAssemblyReferences) + { + if (!loadedAssemblyReferences.TryGetValue(fullName, out var referenceInfo)) + { referenceInfo = new UnresolvedAssemblyNameReference(fullName); loadedAssemblyReferences.Add(fullName, referenceInfo); referenceInfo.Messages.Add((kind, message)); - } else { + } + else + { var lastMsg = referenceInfo.Messages.LastOrDefault(); if (kind != lastMsg.Item1 && message != lastMsg.Item2) referenceInfo.Messages.Add((kind, message)); @@ -188,14 +219,16 @@ namespace ICSharpCode.Decompiler.Metadata public bool TryGetInfo(string fullName, out UnresolvedAssemblyNameReference info) { - lock (loadedAssemblyReferences) { + lock (loadedAssemblyReferences) + { return loadedAssemblyReferences.TryGetValue(fullName, out info); } } public IReadOnlyList Entries { get { - lock (loadedAssemblyReferences) { + lock (loadedAssemblyReferences) + { return loadedAssemblyReferences.Values.ToList(); } } @@ -203,7 +236,8 @@ namespace ICSharpCode.Decompiler.Metadata public bool HasErrors { get { - lock (loadedAssemblyReferences) { + lock (loadedAssemblyReferences) + { return loadedAssemblyReferences.Any(i => i.Value.HasErrors); } } diff --git a/ICSharpCode.Decompiler/Metadata/ILOpCodes.cs b/ICSharpCode.Decompiler/Metadata/ILOpCodes.cs index 3ca4a821a..43b2e2a97 100644 --- a/ICSharpCode.Decompiler/Metadata/ILOpCodes.cs +++ b/ICSharpCode.Decompiler/Metadata/ILOpCodes.cs @@ -25,8 +25,8 @@ namespace ICSharpCode.Decompiler.Metadata static partial class ILOpCodeExtensions { // We use a byte array instead of an enum array because it can be initialized more efficiently - static readonly byte[] operandTypes = { (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.ShortVariable, (byte)OperandType.ShortVariable, (byte)OperandType.ShortVariable, (byte)OperandType.ShortVariable, (byte)OperandType.ShortVariable, (byte)OperandType.ShortVariable, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.ShortI, (byte)OperandType.I, (byte)OperandType.I8, (byte)OperandType.ShortR, (byte)OperandType.R, 255, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Method, (byte)OperandType.Method, (byte)OperandType.Sig, (byte)OperandType.None, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.Switch, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Method, (byte)OperandType.Type, (byte)OperandType.Type, (byte)OperandType.String, (byte)OperandType.Method, (byte)OperandType.Type, (byte)OperandType.Type, (byte)OperandType.None, 255, 255, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.Field, (byte)OperandType.Field, (byte)OperandType.Field, (byte)OperandType.Field, (byte)OperandType.Field, (byte)OperandType.Field, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Type, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Type, (byte)OperandType.Type, (byte)OperandType.Type, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, 255, 255, 255, 255, 255, 255, 255, (byte)OperandType.Type, (byte)OperandType.None, 255, 255, (byte)OperandType.Type, 255, 255, 255, 255, 255, 255, 255, 255, 255, (byte)OperandType.Tok, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.BrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.None, (byte)OperandType.None, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Method, (byte)OperandType.Method, 255, (byte)OperandType.Variable, (byte)OperandType.Variable, (byte)OperandType.Variable, (byte)OperandType.Variable, (byte)OperandType.Variable, (byte)OperandType.Variable, (byte)OperandType.None, 255, (byte)OperandType.None, (byte)OperandType.ShortI, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Type, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.None, 255, (byte)OperandType.None, 255, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.None, }; + static readonly byte[] operandTypes = { (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.ShortVariable, (byte)OperandType.ShortVariable, (byte)OperandType.ShortVariable, (byte)OperandType.ShortVariable, (byte)OperandType.ShortVariable, (byte)OperandType.ShortVariable, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.ShortI, (byte)OperandType.I, (byte)OperandType.I8, (byte)OperandType.ShortR, (byte)OperandType.R, 255, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Method, (byte)OperandType.Method, (byte)OperandType.Sig, (byte)OperandType.None, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.BrTarget, (byte)OperandType.Switch, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Method, (byte)OperandType.Type, (byte)OperandType.Type, (byte)OperandType.String, (byte)OperandType.Method, (byte)OperandType.Type, (byte)OperandType.Type, (byte)OperandType.None, 255, 255, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.Field, (byte)OperandType.Field, (byte)OperandType.Field, (byte)OperandType.Field, (byte)OperandType.Field, (byte)OperandType.Field, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Type, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Type, (byte)OperandType.Type, (byte)OperandType.Type, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, 255, 255, 255, 255, 255, 255, 255, (byte)OperandType.Type, (byte)OperandType.None, 255, 255, (byte)OperandType.Type, 255, 255, 255, 255, 255, 255, 255, 255, 255, (byte)OperandType.Tok, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.BrTarget, (byte)OperandType.ShortBrTarget, (byte)OperandType.None, (byte)OperandType.None, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Method, (byte)OperandType.Method, 255, (byte)OperandType.Variable, (byte)OperandType.Variable, (byte)OperandType.Variable, (byte)OperandType.Variable, (byte)OperandType.Variable, (byte)OperandType.Variable, (byte)OperandType.None, 255, (byte)OperandType.None, (byte)OperandType.ShortI, (byte)OperandType.None, (byte)OperandType.None, (byte)OperandType.Type, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.None, 255, (byte)OperandType.None, 255, (byte)OperandType.Type, (byte)OperandType.None, (byte)OperandType.None, }; - static readonly string[] operandNames = { "nop", "break", "ldarg.0", "ldarg.1", "ldarg.2", "ldarg.3", "ldloc.0", "ldloc.1", "ldloc.2", "ldloc.3", "stloc.0", "stloc.1", "stloc.2", "stloc.3", "ldarg.s", "ldarga.s", "starg.s", "ldloc.s", "ldloca.s", "stloc.s", "ldnull", "ldc.i4.m1", "ldc.i4.0", "ldc.i4.1", "ldc.i4.2", "ldc.i4.3", "ldc.i4.4", "ldc.i4.5", "ldc.i4.6", "ldc.i4.7", "ldc.i4.8", "ldc.i4.s", "ldc.i4", "ldc.i8", "ldc.r4", "ldc.r8", "", "dup", "pop", "jmp", "call", "calli", "ret", "br.s", "brfalse.s", "brtrue.s", "beq.s", "bge.s", "bgt.s", "ble.s", "blt.s", "bne.un.s", "bge.un.s", "bgt.un.s", "ble.un.s", "blt.un.s", "br", "brfalse", "brtrue", "beq", "bge", "bgt", "ble", "blt", "bne.un", "bge.un", "bgt.un", "ble.un", "blt.un", "switch", "ldind.i1", "ldind.u1", "ldind.i2", "ldind.u2", "ldind.i4", "ldind.u4", "ldind.i8", "ldind.i", "ldind.r4", "ldind.r8", "ldind.ref", "stind.ref", "stind.i1", "stind.i2", "stind.i4", "stind.i8", "stind.r4", "stind.r8", "add", "sub", "mul", "div", "div.un", "rem", "rem.un", "and", "or", "xor", "shl", "shr", "shr.un", "neg", "not", "conv.i1", "conv.i2", "conv.i4", "conv.i8", "conv.r4", "conv.r8", "conv.u4", "conv.u8", "callvirt", "cpobj", "ldobj", "ldstr", "newobj", "castclass", "isinst", "conv.r.un", "", "", "unbox", "throw", "ldfld", "ldflda", "stfld", "ldsfld", "ldsflda", "stsfld", "stobj", "conv.ovf.i1.un", "conv.ovf.i2.un", "conv.ovf.i4.un", "conv.ovf.i8.un", "conv.ovf.u1.un", "conv.ovf.u2.un", "conv.ovf.u4.un", "conv.ovf.u8.un", "conv.ovf.i.un", "conv.ovf.u.un", "box", "newarr", "ldlen", "ldelema", "ldelem.i1", "ldelem.u1", "ldelem.i2", "ldelem.u2", "ldelem.i4", "ldelem.u4", "ldelem.i8", "ldelem.i", "ldelem.r4", "ldelem.r8", "ldelem.ref", "stelem.i", "stelem.i1", "stelem.i2", "stelem.i4", "stelem.i8", "stelem.r4", "stelem.r8", "stelem.ref", "ldelem", "stelem", "unbox.any", "", "", "", "", "", "", "", "", "", "", "", "", "", "conv.ovf.i1", "conv.ovf.u1", "conv.ovf.i2", "conv.ovf.u2", "conv.ovf.i4", "conv.ovf.u4", "conv.ovf.i8", "conv.ovf.u8", "", "", "", "", "", "", "", "refanyval", "ckfinite", "", "", "mkrefany", "", "", "", "", "", "", "", "", "", "ldtoken", "conv.u2", "conv.u1", "conv.i", "conv.ovf.i", "conv.ovf.u", "add.ovf", "add.ovf.un", "mul.ovf", "mul.ovf.un", "sub.ovf", "sub.ovf.un", "endfinally", "leave", "leave.s", "stind.i", "conv.u", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "prefix7", "prefix6", "prefix5", "prefix4", "prefix3", "prefix2", "prefix1", "prefixref", "arglist", "ceq", "cgt", "cgt.un", "clt", "clt.un", "ldftn", "ldvirtftn", "", "ldarg", "ldarga", "starg", "ldloc", "ldloca", "stloc", "localloc", "", "endfilter", "unaligned.", "volatile.", "tail.", "initobj", "constrained.", "cpblk", "initblk", "", "rethrow", "", "sizeof", "refanytype", "readonly.", }; + static readonly string[] operandNames = { "nop", "break", "ldarg.0", "ldarg.1", "ldarg.2", "ldarg.3", "ldloc.0", "ldloc.1", "ldloc.2", "ldloc.3", "stloc.0", "stloc.1", "stloc.2", "stloc.3", "ldarg.s", "ldarga.s", "starg.s", "ldloc.s", "ldloca.s", "stloc.s", "ldnull", "ldc.i4.m1", "ldc.i4.0", "ldc.i4.1", "ldc.i4.2", "ldc.i4.3", "ldc.i4.4", "ldc.i4.5", "ldc.i4.6", "ldc.i4.7", "ldc.i4.8", "ldc.i4.s", "ldc.i4", "ldc.i8", "ldc.r4", "ldc.r8", "", "dup", "pop", "jmp", "call", "calli", "ret", "br.s", "brfalse.s", "brtrue.s", "beq.s", "bge.s", "bgt.s", "ble.s", "blt.s", "bne.un.s", "bge.un.s", "bgt.un.s", "ble.un.s", "blt.un.s", "br", "brfalse", "brtrue", "beq", "bge", "bgt", "ble", "blt", "bne.un", "bge.un", "bgt.un", "ble.un", "blt.un", "switch", "ldind.i1", "ldind.u1", "ldind.i2", "ldind.u2", "ldind.i4", "ldind.u4", "ldind.i8", "ldind.i", "ldind.r4", "ldind.r8", "ldind.ref", "stind.ref", "stind.i1", "stind.i2", "stind.i4", "stind.i8", "stind.r4", "stind.r8", "add", "sub", "mul", "div", "div.un", "rem", "rem.un", "and", "or", "xor", "shl", "shr", "shr.un", "neg", "not", "conv.i1", "conv.i2", "conv.i4", "conv.i8", "conv.r4", "conv.r8", "conv.u4", "conv.u8", "callvirt", "cpobj", "ldobj", "ldstr", "newobj", "castclass", "isinst", "conv.r.un", "", "", "unbox", "throw", "ldfld", "ldflda", "stfld", "ldsfld", "ldsflda", "stsfld", "stobj", "conv.ovf.i1.un", "conv.ovf.i2.un", "conv.ovf.i4.un", "conv.ovf.i8.un", "conv.ovf.u1.un", "conv.ovf.u2.un", "conv.ovf.u4.un", "conv.ovf.u8.un", "conv.ovf.i.un", "conv.ovf.u.un", "box", "newarr", "ldlen", "ldelema", "ldelem.i1", "ldelem.u1", "ldelem.i2", "ldelem.u2", "ldelem.i4", "ldelem.u4", "ldelem.i8", "ldelem.i", "ldelem.r4", "ldelem.r8", "ldelem.ref", "stelem.i", "stelem.i1", "stelem.i2", "stelem.i4", "stelem.i8", "stelem.r4", "stelem.r8", "stelem.ref", "ldelem", "stelem", "unbox.any", "", "", "", "", "", "", "", "", "", "", "", "", "", "conv.ovf.i1", "conv.ovf.u1", "conv.ovf.i2", "conv.ovf.u2", "conv.ovf.i4", "conv.ovf.u4", "conv.ovf.i8", "conv.ovf.u8", "", "", "", "", "", "", "", "refanyval", "ckfinite", "", "", "mkrefany", "", "", "", "", "", "", "", "", "", "ldtoken", "conv.u2", "conv.u1", "conv.i", "conv.ovf.i", "conv.ovf.u", "add.ovf", "add.ovf.un", "mul.ovf", "mul.ovf.un", "sub.ovf", "sub.ovf.un", "endfinally", "leave", "leave.s", "stind.i", "conv.u", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "prefix7", "prefix6", "prefix5", "prefix4", "prefix3", "prefix2", "prefix1", "prefixref", "arglist", "ceq", "cgt", "cgt.un", "clt", "clt.un", "ldftn", "ldvirtftn", "", "ldarg", "ldarga", "starg", "ldloc", "ldloca", "stloc", "localloc", "", "endfilter", "unaligned.", "volatile.", "tail.", "initobj", "constrained.", "cpblk", "initblk", "", "rethrow", "", "sizeof", "refanytype", "readonly.", }; } } diff --git a/ICSharpCode.Decompiler/Metadata/LightJson/JsonArray.cs b/ICSharpCode.Decompiler/Metadata/LightJson/JsonArray.cs index 5b26d1863..28eb80355 100644 --- a/ICSharpCode.Decompiler/Metadata/LightJson/JsonArray.cs +++ b/ICSharpCode.Decompiler/Metadata/LightJson/JsonArray.cs @@ -32,11 +32,13 @@ namespace LightJson public JsonArray(params JsonValue[] values) : this() { - if (values == null) { + if (values == null) + { throw new ArgumentNullException(nameof(values)); } - foreach (var value in values) { + foreach (var value in values) + { this.items.Add(value); } } @@ -60,9 +62,12 @@ namespace LightJson /// public JsonValue this[int index] { get { - if (index >= 0 && index < this.items.Count) { + if (index >= 0 && index < this.items.Count) + { return this.items[index]; - } else { + } + else + { return JsonValue.Null; } } @@ -169,7 +174,8 @@ namespace LightJson get { var items = new JsonValue[this.jsonArray.Count]; - for (int i = 0; i < this.jsonArray.Count; i += 1) { + for (int i = 0; i < this.jsonArray.Count; i += 1) + { items[i] = this.jsonArray[i]; } diff --git a/ICSharpCode.Decompiler/Metadata/LightJson/JsonObject.cs b/ICSharpCode.Decompiler/Metadata/LightJson/JsonObject.cs index bf9a9cede..ddda8a1bc 100644 --- a/ICSharpCode.Decompiler/Metadata/LightJson/JsonObject.cs +++ b/ICSharpCode.Decompiler/Metadata/LightJson/JsonObject.cs @@ -45,9 +45,12 @@ namespace LightJson get { JsonValue value; - if (this.properties.TryGetValue(key, out value)) { + if (this.properties.TryGetValue(key, out value)) + { return value; - } else { + } + else + { return JsonValue.Null; } } @@ -114,14 +117,16 @@ namespace LightJson /// Returns this JsonObject. public JsonObject Rename(string oldKey, string newKey) { - if (oldKey == newKey) { + if (oldKey == newKey) + { // Renaming to the same name just does nothing return this; } JsonValue value; - if (this.properties.TryGetValue(oldKey, out value)) { + if (this.properties.TryGetValue(oldKey, out value)) + { this[newKey] = value; this.Remove(oldKey); } @@ -192,7 +197,8 @@ namespace LightJson var keys = new KeyValuePair[this.jsonObject.Count]; var i = 0; - foreach (var property in this.jsonObject) { + foreach (var property in this.jsonObject) + { keys[i] = new KeyValuePair(property.Key, property.Value); i += 1; } @@ -219,11 +225,16 @@ namespace LightJson [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public object View { get { - if (this.value.IsJsonObject) { + if (this.value.IsJsonObject) + { return (JsonObject)this.value; - } else if (this.value.IsJsonArray) { + } + else if (this.value.IsJsonArray) + { return (JsonArray)this.value; - } else { + } + else + { return this.value; } } diff --git a/ICSharpCode.Decompiler/Metadata/LightJson/JsonValue.cs b/ICSharpCode.Decompiler/Metadata/LightJson/JsonValue.cs index bde06c256..c79ac3459 100644 --- a/ICSharpCode.Decompiler/Metadata/LightJson/JsonValue.cs +++ b/ICSharpCode.Decompiler/Metadata/LightJson/JsonValue.cs @@ -8,6 +8,7 @@ namespace LightJson using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; + using LightJson.Serialization; /// @@ -32,13 +33,16 @@ namespace LightJson /// The value to be wrapped. public JsonValue(bool? value) { - if (value.HasValue) { + if (value.HasValue) + { this.reference = null; this.type = JsonValueType.Boolean; this.value = value.Value ? 1 : 0; - } else { + } + else + { this = JsonValue.Null; } } @@ -49,13 +53,16 @@ namespace LightJson /// The value to be wrapped. public JsonValue(double? value) { - if (value.HasValue) { + if (value.HasValue) + { this.reference = null; this.type = JsonValueType.Number; this.value = value.Value; - } else { + } + else + { this = JsonValue.Null; } } @@ -66,13 +73,16 @@ namespace LightJson /// The value to be wrapped. public JsonValue(string value) { - if (value != null) { + if (value != null) + { this.value = default(double); this.type = JsonValueType.String; this.reference = value; - } else { + } + else + { this = JsonValue.Null; } } @@ -83,13 +93,16 @@ namespace LightJson /// The value to be wrapped. public JsonValue(JsonObject value) { - if (value != null) { + if (value != null) + { this.value = default(double); this.type = JsonValueType.Object; this.reference = value; - } else { + } + else + { this = JsonValue.Null; } } @@ -100,13 +113,16 @@ namespace LightJson /// The value to be wrapped. public JsonValue(JsonArray value) { - if (value != null) { + if (value != null) + { this.value = default(double); this.type = JsonValueType.Array; this.reference = value; - } else { + } + else + { this = JsonValue.Null; } } @@ -166,7 +182,8 @@ namespace LightJson /// A value indicating whether this JsonValue is an Integer. public bool IsInteger { get { - if (!this.IsNumber) { + if (!this.IsNumber) + { return false; } @@ -231,7 +248,8 @@ namespace LightJson /// This value as a Boolean type. public bool AsBoolean { get { - switch (this.Type) { + switch (this.Type) + { case JsonValueType.Boolean: return this.value == 1; @@ -260,11 +278,13 @@ namespace LightJson var value = this.AsNumber; // Prevent overflow if the value doesn't fit. - if (value >= int.MaxValue) { + if (value >= int.MaxValue) + { return int.MaxValue; } - if (value <= int.MinValue) { + if (value <= int.MinValue) + { return int.MinValue; } @@ -278,7 +298,8 @@ namespace LightJson /// This value as a Number type. public double AsNumber { get { - switch (this.Type) { + switch (this.Type) + { case JsonValueType.Boolean: return (this.value == 1) ? 1 @@ -289,9 +310,12 @@ namespace LightJson case JsonValueType.String: double number; - if (double.TryParse((string)this.reference, NumberStyles.Float, CultureInfo.InvariantCulture, out number)) { + if (double.TryParse((string)this.reference, NumberStyles.Float, CultureInfo.InvariantCulture, out number)) + { return number; - } else { + } + else + { goto default; } @@ -307,7 +331,8 @@ namespace LightJson /// This value as a String type. public string AsString { get { - switch (this.Type) { + switch (this.Type) + { case JsonValueType.Boolean: return (this.value == 1) ? "true" @@ -357,9 +382,12 @@ namespace LightJson get { DateTime value; - if (this.IsString && DateTime.TryParse((string)this.reference, out value)) { + if (this.IsString && DateTime.TryParse((string)this.reference, out value)) + { return value; - } else { + } + else + { return null; } } @@ -371,7 +399,8 @@ namespace LightJson /// This (inner) value as a System.object. public object AsObject { get { - switch (this.Type) { + switch (this.Type) + { case JsonValueType.Boolean: case JsonValueType.Number: return this.value; @@ -396,17 +425,23 @@ namespace LightJson /// public JsonValue this[string key] { get { - if (this.IsJsonObject) { + if (this.IsJsonObject) + { return ((JsonObject)this.reference)[key]; - } else { + } + else + { throw new InvalidOperationException("This value does not represent a JsonObject."); } } set { - if (this.IsJsonObject) { + if (this.IsJsonObject) + { ((JsonObject)this.reference)[key] = value; - } else { + } + else + { throw new InvalidOperationException("This value does not represent a JsonObject."); } } @@ -421,17 +456,23 @@ namespace LightJson /// public JsonValue this[int index] { get { - if (this.IsJsonArray) { + if (this.IsJsonArray) + { return ((JsonArray)this.reference)[index]; - } else { + } + else + { throw new InvalidOperationException("This value does not represent a JsonArray."); } } set { - if (this.IsJsonArray) { + if (this.IsJsonArray) + { ((JsonArray)this.reference)[index] = value; - } else { + } + else + { throw new InvalidOperationException("This value does not represent a JsonArray."); } } @@ -492,7 +533,8 @@ namespace LightJson /// The value to be converted. public static implicit operator JsonValue(DateTime? value) { - if (value == null) { + if (value == null) + { return JsonValue.Null; } @@ -505,9 +547,12 @@ namespace LightJson /// The JsonValue to be converted. public static explicit operator int(JsonValue jsonValue) { - if (jsonValue.IsInteger) { + if (jsonValue.IsInteger) + { return jsonValue.AsInteger; - } else { + } + else + { return 0; } } @@ -520,11 +565,14 @@ namespace LightJson /// Throws System.InvalidCastException when the inner value type of the /// JsonValue is not the desired type of the conversion. /// - public static explicit operator int? (JsonValue jsonValue) + public static explicit operator int?(JsonValue jsonValue) { - if (jsonValue.IsNull) { + if (jsonValue.IsNull) + { return null; - } else { + } + else + { return (int)jsonValue; } } @@ -535,9 +583,12 @@ namespace LightJson /// The JsonValue to be converted. public static explicit operator bool(JsonValue jsonValue) { - if (jsonValue.IsBoolean) { + if (jsonValue.IsBoolean) + { return jsonValue.value == 1; - } else { + } + else + { return false; } } @@ -550,11 +601,14 @@ namespace LightJson /// Throws System.InvalidCastException when the inner value type of the /// JsonValue is not the desired type of the conversion. /// - public static explicit operator bool? (JsonValue jsonValue) + public static explicit operator bool?(JsonValue jsonValue) { - if (jsonValue.IsNull) { + if (jsonValue.IsNull) + { return null; - } else { + } + else + { return (bool)jsonValue; } } @@ -565,9 +619,12 @@ namespace LightJson /// The JsonValue to be converted. public static explicit operator double(JsonValue jsonValue) { - if (jsonValue.IsNumber) { + if (jsonValue.IsNumber) + { return jsonValue.value; - } else { + } + else + { return double.NaN; } } @@ -580,11 +637,14 @@ namespace LightJson /// Throws System.InvalidCastException when the inner value type of the /// JsonValue is not the desired type of the conversion. /// - public static explicit operator double? (JsonValue jsonValue) + public static explicit operator double?(JsonValue jsonValue) { - if (jsonValue.IsNull) { + if (jsonValue.IsNull) + { return null; - } else { + } + else + { return (double)jsonValue; } } @@ -595,9 +655,12 @@ namespace LightJson /// The JsonValue to be converted. public static explicit operator string(JsonValue jsonValue) { - if (jsonValue.IsString || jsonValue.IsNull) { + if (jsonValue.IsString || jsonValue.IsNull) + { return jsonValue.reference as string; - } else { + } + else + { return null; } } @@ -608,9 +671,12 @@ namespace LightJson /// The JsonValue to be converted. public static explicit operator JsonObject(JsonValue jsonValue) { - if (jsonValue.IsJsonObject || jsonValue.IsNull) { + if (jsonValue.IsJsonObject || jsonValue.IsNull) + { return jsonValue.reference as JsonObject; - } else { + } + else + { return null; } } @@ -621,9 +687,12 @@ namespace LightJson /// The JsonValue to be converted. public static explicit operator JsonArray(JsonValue jsonValue) { - if (jsonValue.IsJsonArray || jsonValue.IsNull) { + if (jsonValue.IsJsonArray || jsonValue.IsNull) + { return jsonValue.reference as JsonArray; - } else { + } + else + { return null; } } @@ -636,9 +705,12 @@ namespace LightJson { var dateTime = jsonValue.AsDateTime; - if (dateTime.HasValue) { + if (dateTime.HasValue) + { return dateTime.Value; - } else { + } + else + { return DateTime.MinValue; } } @@ -647,11 +719,14 @@ namespace LightJson /// Converts the given JsonValue into a nullable DateTime. /// /// The JsonValue to be converted. - public static explicit operator DateTime? (JsonValue jsonValue) + public static explicit operator DateTime?(JsonValue jsonValue) { - if (jsonValue.IsDateTime || jsonValue.IsNull) { + if (jsonValue.IsDateTime || jsonValue.IsNull) + { return jsonValue.AsDateTime; - } else { + } + else + { return null; } } @@ -691,14 +766,18 @@ namespace LightJson /// public override bool Equals(object obj) { - if (obj == null) { + if (obj == null) + { return this.IsNull; } var jsonValue = obj as JsonValue?; - if (jsonValue == null) { + if (jsonValue == null) + { return false; - } else { + } + else + { return this == jsonValue.Value; } } @@ -706,9 +785,12 @@ namespace LightJson /// public override int GetHashCode() { - if (this.IsNull) { + if (this.IsNull) + { return this.Type.GetHashCode(); - } else { + } + else + { return this.Type.GetHashCode() ^ this.value.GetHashCode() ^ EqualityComparer.Default.GetHashCode(this.reference); @@ -728,9 +810,12 @@ namespace LightJson [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public JsonObject ObjectView { get { - if (this.jsonValue.IsJsonObject) { + if (this.jsonValue.IsJsonObject) + { return (JsonObject)this.jsonValue.reference; - } else { + } + else + { return null; } } @@ -739,9 +824,12 @@ namespace LightJson [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public JsonArray ArrayView { get { - if (this.jsonValue.IsJsonArray) { + if (this.jsonValue.IsJsonArray) + { return (JsonArray)this.jsonValue.reference; - } else { + } + else + { return null; } } @@ -755,11 +843,16 @@ namespace LightJson public object Value { get { - if (this.jsonValue.IsJsonObject) { + if (this.jsonValue.IsJsonObject) + { return (JsonObject)this.jsonValue.reference; - } else if (this.jsonValue.IsJsonArray) { + } + else if (this.jsonValue.IsJsonArray) + { return (JsonArray)this.jsonValue.reference; - } else { + } + else + { return this.jsonValue; } } diff --git a/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonParseException.cs b/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonParseException.cs index 61d2c11bc..28aa1c9c1 100644 --- a/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonParseException.cs +++ b/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonParseException.cs @@ -84,7 +84,8 @@ namespace LightJson.Serialization private static string GetDefaultMessage(ErrorType type) { - switch (type) { + switch (type) + { case ErrorType.IncompleteMessage: return "The string ended before a value could be parsed."; diff --git a/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonReader.cs b/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonReader.cs index f63388e20..693f10a63 100644 --- a/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonReader.cs +++ b/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonReader.cs @@ -7,6 +7,7 @@ namespace LightJson.Serialization using System.Globalization; using System.IO; using System.Text; + using ErrorType = JsonParseException.ErrorType; /// @@ -28,7 +29,8 @@ namespace LightJson.Serialization /// The parsed . public static JsonValue Parse(TextReader reader) { - if (reader == null) { + if (reader == null) + { throw new ArgumentNullException(nameof(reader)); } @@ -42,11 +44,13 @@ namespace LightJson.Serialization /// The parsed . public static JsonValue Parse(string source) { - if (source == null) { + if (source == null) + { throw new ArgumentNullException(nameof(source)); } - using (var reader = new StringReader(source)) { + using (var reader = new StringReader(source)) + { return Parse(reader); } } @@ -62,11 +66,13 @@ namespace LightJson.Serialization var next = this.scanner.Peek(); - if (char.IsNumber(next)) { + if (char.IsNumber(next)) + { return this.ReadNumber(); } - switch (next) { + switch (next) + { case '{': return this.ReadObject(); @@ -101,7 +107,8 @@ namespace LightJson.Serialization private JsonValue ReadBoolean() { - switch (this.scanner.Peek()) { + switch (this.scanner.Peek()) + { case 't': this.scanner.Assert("true"); return true; @@ -114,9 +121,11 @@ namespace LightJson.Serialization private void ReadDigits(StringBuilder builder) { - while (true) { + while (true) + { int next = this.scanner.Peek(throwAtEndOfFile: false); - if (next == -1 || !char.IsNumber((char)next)) { + if (next == -1 || !char.IsNumber((char)next)) + { return; } @@ -128,27 +137,34 @@ namespace LightJson.Serialization { var builder = new StringBuilder(); - if (this.scanner.Peek() == '-') { + if (this.scanner.Peek() == '-') + { builder.Append(this.scanner.Read()); } - if (this.scanner.Peek() == '0') { + if (this.scanner.Peek() == '0') + { builder.Append(this.scanner.Read()); - } else { + } + else + { this.ReadDigits(builder); } - if (this.scanner.Peek(throwAtEndOfFile: false) == '.') { + if (this.scanner.Peek(throwAtEndOfFile: false) == '.') + { builder.Append(this.scanner.Read()); this.ReadDigits(builder); } - if (this.scanner.Peek(throwAtEndOfFile: false) == 'e' || this.scanner.Peek(throwAtEndOfFile: false) == 'E') { + if (this.scanner.Peek(throwAtEndOfFile: false) == 'e' || this.scanner.Peek(throwAtEndOfFile: false) == 'E') + { builder.Append(this.scanner.Read()); var next = this.scanner.Peek(); - switch (next) { + switch (next) + { case '+': case '-': builder.Append(this.scanner.Read()); @@ -169,15 +185,18 @@ namespace LightJson.Serialization this.scanner.Assert('"'); - while (true) { + while (true) + { var errorPosition = this.scanner.Position; var c = this.scanner.Read(); - if (c == '\\') { + if (c == '\\') + { errorPosition = this.scanner.Position; c = this.scanner.Read(); - switch (char.ToLower(c)) { + switch (char.ToLower(c)) + { case '"': case '\\': case '/': @@ -206,14 +225,21 @@ namespace LightJson.Serialization ErrorType.InvalidOrUnexpectedCharacter, errorPosition); } - } else if (c == '"') { + } + else if (c == '"') + { break; - } else { - if (char.IsControl(c)) { + } + else + { + if (char.IsControl(c)) + { throw new JsonParseException( ErrorType.InvalidOrUnexpectedCharacter, errorPosition); - } else { + } + else + { builder.Append(c); } } @@ -225,7 +251,8 @@ namespace LightJson.Serialization private int ReadHexDigit() { var errorPosition = this.scanner.Position; - switch (char.ToUpper(this.scanner.Read())) { + switch (char.ToUpper(this.scanner.Read())) + { case '0': return 0; @@ -304,16 +331,21 @@ namespace LightJson.Serialization this.scanner.SkipWhitespace(); - if (this.scanner.Peek() == '}') { + if (this.scanner.Peek() == '}') + { this.scanner.Read(); - } else { - while (true) { + } + else + { + while (true) + { this.scanner.SkipWhitespace(); var errorPosition = this.scanner.Position; var key = this.ReadJsonKey(); - if (jsonObject.ContainsKey(key)) { + if (jsonObject.ContainsKey(key)) + { throw new JsonParseException( ErrorType.DuplicateObjectKeys, errorPosition); @@ -333,19 +365,26 @@ namespace LightJson.Serialization errorPosition = this.scanner.Position; var next = this.scanner.Read(); - if (next == ',') { + if (next == ',') + { // Allow trailing commas in objects this.scanner.SkipWhitespace(); - if (this.scanner.Peek() == '}') { + if (this.scanner.Peek() == '}') + { next = this.scanner.Read(); } } - if (next == '}') { + if (next == '}') + { break; - } else if (next == ',') { + } + else if (next == ',') + { continue; - } else { + } + else + { throw new JsonParseException( ErrorType.InvalidOrUnexpectedCharacter, errorPosition); @@ -367,10 +406,14 @@ namespace LightJson.Serialization this.scanner.SkipWhitespace(); - if (this.scanner.Peek() == ']') { + if (this.scanner.Peek() == ']') + { this.scanner.Read(); - } else { - while (true) { + } + else + { + while (true) + { this.scanner.SkipWhitespace(); var value = this.ReadJsonValue(); @@ -381,19 +424,26 @@ namespace LightJson.Serialization var errorPosition = this.scanner.Position; var next = this.scanner.Read(); - if (next == ',') { + if (next == ',') + { // Allow trailing commas in arrays this.scanner.SkipWhitespace(); - if (this.scanner.Peek() == ']') { + if (this.scanner.Peek() == ']') + { next = this.scanner.Read(); } } - if (next == ']') { + if (next == ']') + { break; - } else if (next == ',') { + } + else if (next == ',') + { continue; - } else { + } + else + { throw new JsonParseException( ErrorType.InvalidOrUnexpectedCharacter, errorPosition); diff --git a/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/TextScanner.cs b/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/TextScanner.cs index 41a9e5a61..363e51d1e 100644 --- a/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/TextScanner.cs +++ b/ICSharpCode.Decompiler/Metadata/LightJson/Serialization/TextScanner.cs @@ -4,6 +4,7 @@ namespace LightJson.Serialization { using System.IO; + using ErrorType = JsonParseException.ErrorType; /// @@ -51,11 +52,14 @@ namespace LightJson.Serialization { var next = this.reader.Peek(); - if (next == -1 && throwAtEndOfFile) { + if (next == -1 && throwAtEndOfFile) + { throw new JsonParseException( ErrorType.IncompleteMessage, this.position); - } else { + } + else + { return next; } } @@ -68,15 +72,21 @@ namespace LightJson.Serialization { var next = this.reader.Read(); - if (next == -1) { + if (next == -1) + { throw new JsonParseException( ErrorType.IncompleteMessage, this.position); - } else { - if (next == '\n') { + } + else + { + if (next == '\n') + { this.position.Line += 1; this.position.Column = 0; - } else { + } + else + { this.position.Column += 1; } @@ -89,15 +99,21 @@ namespace LightJson.Serialization /// public void SkipWhitespace() { - while (true) { + while (true) + { char next = this.Peek(); - if (char.IsWhiteSpace(next)) { + if (char.IsWhiteSpace(next)) + { this.Read(); continue; - } else if (next == '/') { + } + else if (next == '/') + { this.SkipComment(); continue; - } else { + } + else + { break; } } @@ -111,7 +127,8 @@ namespace LightJson.Serialization public void Assert(char next) { var errorPosition = this.position; - if (this.Read() != next) { + if (this.Read() != next) + { throw new JsonParseException( string.Format("Parser expected '{0}'", next), ErrorType.InvalidOrUnexpectedCharacter, @@ -126,7 +143,8 @@ namespace LightJson.Serialization /// The expected string. public void Assert(string next) { - for (var i = 0; i < next.Length; i += 1) { + for (var i = 0; i < next.Length; i += 1) + { this.Assert(next[i]); } } @@ -135,7 +153,8 @@ namespace LightJson.Serialization { // First character is the first slash this.Read(); - switch (this.Peek()) { + switch (this.Peek()) + { case '/': this.SkipLineComment(); return; @@ -157,8 +176,10 @@ namespace LightJson.Serialization // First character is the second '/' of the opening '//' this.Read(); - while (true) { - switch (this.reader.Peek()) { + while (true) + { + switch (this.reader.Peek()) + { case '\n': // Reached the end of the line this.Read(); @@ -181,8 +202,10 @@ namespace LightJson.Serialization this.Read(); bool foundStar = false; - while (true) { - switch (this.reader.Peek()) { + while (true) + { + switch (this.reader.Peek()) + { case '*': this.Read(); foundStar = true; @@ -190,9 +213,12 @@ namespace LightJson.Serialization case '/': this.Read(); - if (foundStar) { + if (foundStar) + { return; - } else { + } + else + { foundStar = false; continue; } diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs index dcb2013bd..1759f4472 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs @@ -3,24 +3,27 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Reflection; -using SRM = System.Reflection.Metadata; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; +using SRM = System.Reflection.Metadata; + namespace ICSharpCode.Decompiler.Metadata { public static class MetadataExtensions { static HashAlgorithm GetHashAlgorithm(this MetadataReader reader) { - switch (reader.GetAssemblyDefinition().HashAlgorithm) { + switch (reader.GetAssemblyDefinition().HashAlgorithm) + { case AssemblyHashAlgorithm.None: // only for multi-module assemblies? return SHA1.Create(); @@ -55,7 +58,8 @@ namespace ICSharpCode.Decompiler.Metadata return string.Empty; var asm = reader.GetAssemblyDefinition(); string publicKey = "null"; - if (!asm.PublicKey.IsNil) { + if (!asm.PublicKey.IsNil) + { // AssemblyFlags.PublicKey does not apply to assembly definitions publicKey = CalculatePublicKeyToken(asm.PublicKey, reader); } @@ -77,10 +81,14 @@ namespace ICSharpCode.Decompiler.Metadata public static string GetFullAssemblyName(this SRM.AssemblyReference reference, MetadataReader reader) { string publicKey = "null"; - if (!reference.PublicKeyOrToken.IsNil) { - if ((reference.Flags & AssemblyFlags.PublicKey) != 0) { + if (!reference.PublicKeyOrToken.IsNil) + { + if ((reference.Flags & AssemblyFlags.PublicKey) != 0) + { publicKey = CalculatePublicKeyToken(reference.PublicKeyOrToken, reader); - } else { + } + else + { publicKey = reader.GetBlobBytes(reference.PublicKeyOrToken).ToHexString(8); } } @@ -107,7 +115,8 @@ namespace ICSharpCode.Decompiler.Metadata public static string ToHexString(this BlobReader reader) { StringBuilder sb = new StringBuilder(reader.Length * 3); - for (int i = 0; i < reader.Length; i++) { + for (int i = 0; i < reader.Length; i++) + { if (i == 0) sb.AppendFormat("{0:X2}", reader.ReadByte()); else @@ -118,7 +127,8 @@ namespace ICSharpCode.Decompiler.Metadata public static IEnumerable GetTopLevelTypeDefinitions(this MetadataReader reader) { - foreach (var handle in reader.TypeDefinitions) { + foreach (var handle in reader.TypeDefinitions) + { var td = reader.GetTypeDefinition(handle); if (td.GetDeclaringType().IsNil) yield return handle; @@ -128,9 +138,11 @@ namespace ICSharpCode.Decompiler.Metadata public static string ToILNameString(this FullTypeName typeName, bool omitGenerics = false) { string name; - if (typeName.IsNested) { + if (typeName.IsNested) + { name = typeName.Name; - if (!omitGenerics) { + if (!omitGenerics) + { int localTypeParameterCount = typeName.GetNestedTypeAdditionalTypeParameterCount(typeName.NestingLevel - 1); if (localTypeParameterCount > 0) name += "`" + localTypeParameterCount; @@ -138,11 +150,14 @@ namespace ICSharpCode.Decompiler.Metadata name = Disassembler.DisassemblerHelpers.Escape(name); return $"{typeName.GetDeclaringType().ToILNameString(omitGenerics)}/{name}"; } - if (!string.IsNullOrEmpty(typeName.TopLevelTypeName.Namespace)) { + if (!string.IsNullOrEmpty(typeName.TopLevelTypeName.Namespace)) + { name = $"{typeName.TopLevelTypeName.Namespace}.{typeName.Name}"; if (!omitGenerics && typeName.TypeParameterCount > 0) name += "`" + typeName.TypeParameterCount; - } else { + } + else + { name = typeName.Name; if (!omitGenerics && typeName.TypeParameterCount > 0) name += "`" + typeName.TypeParameterCount; @@ -154,7 +169,8 @@ namespace ICSharpCode.Decompiler.Metadata public static IModuleReference GetDeclaringModule(this TypeReferenceHandle handle, MetadataReader reader) { var tr = reader.GetTypeReference(handle); - switch (tr.ResolutionScope.Kind) { + switch (tr.ResolutionScope.Kind) + { case HandleKind.TypeReference: return ((TypeReferenceHandle)tr.ResolutionScope).GetDeclaringModule(reader); case HandleKind.AssemblyReference: @@ -185,7 +201,8 @@ namespace ICSharpCode.Decompiler.Metadata public static PrimitiveTypeCode ToPrimitiveTypeCode(this KnownTypeCode typeCode) { - switch (typeCode) { + switch (typeCode) + { case KnownTypeCode.Object: return PrimitiveTypeCode.Object; case KnownTypeCode.Boolean: @@ -229,7 +246,8 @@ namespace ICSharpCode.Decompiler.Metadata public static KnownTypeCode ToKnownTypeCode(this PrimitiveTypeCode typeCode) { - switch (typeCode) { + switch (typeCode) + { case PrimitiveTypeCode.Boolean: return KnownTypeCode.Boolean; case PrimitiveTypeCode.Byte: @@ -274,7 +292,8 @@ namespace ICSharpCode.Decompiler.Metadata public static IEnumerable GetModuleReferences(this MetadataReader metadata) { var rowCount = metadata.GetTableRowCount(TableIndex.ModuleRef); - for (int row = 1; row <= rowCount; row++) { + for (int row = 1; row <= rowCount; row++) + { yield return MetadataTokens.ModuleReferenceHandle(row); } } @@ -282,7 +301,8 @@ namespace ICSharpCode.Decompiler.Metadata public static IEnumerable GetTypeSpecifications(this MetadataReader metadata) { var rowCount = metadata.GetTableRowCount(TableIndex.TypeSpec); - for (int row = 1; row <= rowCount; row++) { + for (int row = 1; row <= rowCount; row++) + { yield return MetadataTokens.TypeSpecificationHandle(row); } } @@ -290,7 +310,8 @@ namespace ICSharpCode.Decompiler.Metadata public static IEnumerable GetMethodSpecifications(this MetadataReader metadata) { var rowCount = metadata.GetTableRowCount(TableIndex.MethodSpec); - for (int row = 1; row <= rowCount; row++) { + for (int row = 1; row <= rowCount; row++) + { yield return MetadataTokens.MethodSpecificationHandle(row); } } @@ -304,7 +325,8 @@ namespace ICSharpCode.Decompiler.Metadata bool methodSmall = metadata.GetTableRowCount(TableIndex.MethodDef) <= ushort.MaxValue; bool assocSmall = metadata.GetTableRowCount(TableIndex.Property) <= ushort.MaxValue && metadata.GetTableRowCount(TableIndex.Event) <= ushort.MaxValue; int assocOffset = (methodSmall ? 2 : 4) + 2; - for (int row = 0; row < rowCount; row++) { + for (int row = 0; row < rowCount; row++) + { yield return Read(row); } @@ -314,9 +336,12 @@ namespace ICSharpCode.Decompiler.Metadata int methodDef = methodSmall ? *(ushort*)(ptr + 2) : (int)*(uint*)(ptr + 2); int assocDef = assocSmall ? *(ushort*)(ptr + assocOffset) : (int)*(uint*)(ptr + assocOffset); EntityHandle propOrEvent; - if ((assocDef & 0x1) == 1) { + if ((assocDef & 0x1) == 1) + { propOrEvent = MetadataTokens.PropertyDefinitionHandle(assocDef >> 1); - } else { + } + else + { propOrEvent = MetadataTokens.EventDefinitionHandle(assocDef >> 1); } return (MetadataTokens.Handle(0x18000000 | (row + 1)), (MethodSemanticsAttributes)(*(ushort*)ptr), MetadataTokens.MethodDefinitionHandle(methodDef), propOrEvent); @@ -326,7 +351,8 @@ namespace ICSharpCode.Decompiler.Metadata public static IEnumerable GetFieldLayouts(this MetadataReader metadata) { var rowCount = metadata.GetTableRowCount(TableIndex.FieldLayout); - for (int row = 1; row <= rowCount; row++) { + for (int row = 1; row <= rowCount; row++) + { yield return MetadataTokens.EntityHandle(TableIndex.FieldLayout, row); } } @@ -337,13 +363,15 @@ namespace ICSharpCode.Decompiler.Metadata int offset = metadata.GetTableMetadataOffset(TableIndex.FieldLayout); int rowSize = metadata.GetTableRowSize(TableIndex.FieldLayout); int rowCount = metadata.GetTableRowCount(TableIndex.FieldLayout); - + int fieldRowNo = metadata.GetRowNumber(fieldLayoutHandle); bool small = metadata.GetTableRowCount(TableIndex.Field) <= ushort.MaxValue; - for (int row = rowCount - 1; row >= 0; row--) { + for (int row = rowCount - 1; row >= 0; row--) + { byte* ptr = startPointer + offset + rowSize * row; uint rowNo = small ? *(ushort*)(ptr + 4) : *(uint*)(ptr + 4); - if (fieldRowNo == rowNo) { + if (fieldRowNo == rowNo) + { return (*(int*)ptr, MetadataTokens.FieldDefinitionHandle(fieldRowNo)); } } diff --git a/ICSharpCode.Decompiler/Metadata/MetadataTokenHelpers.cs b/ICSharpCode.Decompiler/Metadata/MetadataTokenHelpers.cs index b0bfd4285..2f39cb832 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataTokenHelpers.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataTokenHelpers.cs @@ -32,9 +32,12 @@ namespace ICSharpCode.Decompiler.Metadata // but that causes problems later on. if (metadataToken < 0) return null; - try { + try + { return MetadataTokens.EntityHandle(metadataToken); - } catch (ArgumentException) { + } + catch (ArgumentException) + { return null; } } @@ -45,9 +48,12 @@ namespace ICSharpCode.Decompiler.Metadata // but that causes problems later on. if (metadataToken < 0) return MetadataTokens.EntityHandle(0); - try { + try + { return MetadataTokens.EntityHandle(metadataToken); - } catch (ArgumentException) { + } + catch (ArgumentException) + { return MetadataTokens.EntityHandle(0); } } diff --git a/ICSharpCode.Decompiler/Metadata/MethodSemanticsLookup.cs b/ICSharpCode.Decompiler/Metadata/MethodSemanticsLookup.cs index cd2220970..b457a73d3 100644 --- a/ICSharpCode.Decompiler/Metadata/MethodSemanticsLookup.cs +++ b/ICSharpCode.Decompiler/Metadata/MethodSemanticsLookup.cs @@ -22,6 +22,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.Metadata @@ -60,17 +61,20 @@ namespace ICSharpCode.Decompiler.Metadata public MethodSemanticsLookup(MetadataReader metadata, MethodSemanticsAttributes filter = csharpAccessors) { - if ((filter & MethodSemanticsAttributes.Other) != 0) { + if ((filter & MethodSemanticsAttributes.Other) != 0) + { throw new NotSupportedException("SRM doesn't provide access to 'other' accessors"); } entries = new List(metadata.GetTableRowCount(TableIndex.MethodSemantics)); - foreach (var propHandle in metadata.PropertyDefinitions) { + foreach (var propHandle in metadata.PropertyDefinitions) + { var prop = metadata.GetPropertyDefinition(propHandle); var accessors = prop.GetAccessors(); AddEntry(MethodSemanticsAttributes.Getter, accessors.Getter, propHandle); AddEntry(MethodSemanticsAttributes.Setter, accessors.Setter, propHandle); } - foreach (var eventHandle in metadata.EventDefinitions) { + foreach (var eventHandle in metadata.EventDefinitions) + { var ev = metadata.GetEventDefinition(eventHandle); var accessors = ev.GetAccessors(); AddEntry(MethodSemanticsAttributes.Adder, accessors.Adder, eventHandle); @@ -90,9 +94,12 @@ namespace ICSharpCode.Decompiler.Metadata public (EntityHandle, MethodSemanticsAttributes) GetSemantics(MethodDefinitionHandle method) { int pos = entries.BinarySearch(new Entry(0, method, default(EntityHandle))); - if (pos >= 0) { + if (pos >= 0) + { return (entries[pos].Association, entries[pos].Semantics); - } else { + } + else + { return (default(EntityHandle), 0); } } diff --git a/ICSharpCode.Decompiler/Metadata/OperandType.cs b/ICSharpCode.Decompiler/Metadata/OperandType.cs index 900cf1218..352e83272 100644 --- a/ICSharpCode.Decompiler/Metadata/OperandType.cs +++ b/ICSharpCode.Decompiler/Metadata/OperandType.cs @@ -105,7 +105,8 @@ namespace ICSharpCode.Decompiler.Metadata static HashSet BuildKeywordList(params string[] keywords) { HashSet s = new HashSet(keywords); - foreach (var inst in operandNames) { + foreach (var inst in operandNames) + { if (string.IsNullOrEmpty(inst)) continue; s.Add(inst); diff --git a/ICSharpCode.Decompiler/Metadata/PEFile.cs b/ICSharpCode.Decompiler/Metadata/PEFile.cs index 9b69c8a9a..a81258a10 100644 --- a/ICSharpCode.Decompiler/Metadata/PEFile.cs +++ b/ICSharpCode.Decompiler/Metadata/PEFile.cs @@ -24,6 +24,7 @@ using System.IO; using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -77,7 +78,8 @@ namespace ICSharpCode.Decompiler.Metadata string version = Metadata.MetadataVersion; if (version == null || version.Length <= 1) return TargetRuntime.Unknown; - switch (version[1]) { + switch (version[1]) + { case '1': if (version.Length <= 3) return TargetRuntime.Unknown; @@ -108,7 +110,8 @@ namespace ICSharpCode.Decompiler.Metadata IEnumerable GetResources() { var metadata = Metadata; - foreach (var h in metadata.ManifestResources) { + foreach (var h in metadata.ManifestResources) + { yield return new Resource(this, h); } } @@ -126,11 +129,14 @@ namespace ICSharpCode.Decompiler.Metadata public TypeDefinitionHandle GetTypeDefinition(TopLevelTypeName typeName) { var lookup = LazyInit.VolatileRead(ref typeLookup); - if (lookup == null) { + if (lookup == null) + { lookup = new Dictionary(); - foreach (var handle in Metadata.TypeDefinitions) { + foreach (var handle in Metadata.TypeDefinitions) + { var td = Metadata.GetTypeDefinition(handle); - if (!td.GetDeclaringType().IsNil) { + if (!td.GetDeclaringType().IsNil) + { continue; // nested type } var nsHandle = td.Namespace; @@ -154,9 +160,11 @@ namespace ICSharpCode.Decompiler.Metadata public ExportedTypeHandle GetTypeForwarder(FullTypeName typeName) { var lookup = LazyInit.VolatileRead(ref typeForwarderLookup); - if (lookup == null) { + if (lookup == null) + { lookup = new Dictionary(); - foreach (var handle in Metadata.ExportedTypes) { + foreach (var handle in Metadata.ExportedTypes) + { var td = Metadata.GetExportedType(handle); lookup[td.GetFullTypeName(Metadata)] = handle; } diff --git a/ICSharpCode.Decompiler/Metadata/SignatureBlobComparer.cs b/ICSharpCode.Decompiler/Metadata/SignatureBlobComparer.cs index 47f237834..22f2c7629 100644 --- a/ICSharpCode.Decompiler/Metadata/SignatureBlobComparer.cs +++ b/ICSharpCode.Decompiler/Metadata/SignatureBlobComparer.cs @@ -33,7 +33,8 @@ namespace ICSharpCode.Decompiler.Metadata // compare signature headers if (a.RemainingBytes == 0 || b.RemainingBytes == 0 || (header = a.ReadSignatureHeader()) != b.ReadSignatureHeader()) return false; - if (header.IsGeneric) { + if (header.IsGeneric) + { // read & compare generic parameter count if (!IsSameCompressedInteger(ref a, ref b, out _)) return false; @@ -46,7 +47,8 @@ namespace ICSharpCode.Decompiler.Metadata if (!TypesAreEqual(ref a, ref b, contextForA, contextForB, typeCode)) return false; int i = 0; - for (; i < totalParameterCount; i++) { + for (; i < totalParameterCount; i++) + { if (!IsSameCompressedInteger(ref a, ref b, out typeCode)) return false; // varargs sentinel @@ -55,7 +57,8 @@ namespace ICSharpCode.Decompiler.Metadata if (!TypesAreEqual(ref a, ref b, contextForA, contextForB, typeCode)) return false; } - for (; i < totalParameterCount; i++) { + for (; i < totalParameterCount; i++) + { if (!IsSameCompressedInteger(ref a, ref b, out typeCode)) return false; if (!TypesAreEqual(ref a, ref b, contextForA, contextForB, typeCode)) @@ -88,7 +91,8 @@ namespace ICSharpCode.Decompiler.Metadata static bool TypesAreEqual(ref BlobReader a, ref BlobReader b, MetadataReader contextForA, MetadataReader contextForB, int typeCode) { - switch (typeCode) { + switch (typeCode) + { case 0x1: // ELEMENT_TYPE_VOID case 0x2: // ELEMENT_TYPE_BOOLEAN case 0x3: // ELEMENT_TYPE_CHAR @@ -122,7 +126,7 @@ namespace ICSharpCode.Decompiler.Metadata return false; return true; case 0x14: // ELEMENT_TYPE_ARRAY - // element type + // element type if (!IsSameCompressedInteger(ref a, ref b, out typeCode)) return false; if (!TypesAreEqual(ref a, ref b, contextForA, contextForB, typeCode)) @@ -133,21 +137,23 @@ namespace ICSharpCode.Decompiler.Metadata // sizes if (!IsSameCompressedInteger(ref a, ref b, out int numOfSizes)) return false; - for (int i = 0; i < numOfSizes; i++) { + for (int i = 0; i < numOfSizes; i++) + { if (!IsSameCompressedInteger(ref a, ref b, out _)) return false; } // lower bounds if (!IsSameCompressedInteger(ref a, ref b, out int numOfLowerBounds)) return false; - for (int i = 0; i < numOfLowerBounds; i++) { + for (int i = 0; i < numOfLowerBounds; i++) + { if (!IsSameCompressedSignedInteger(ref a, ref b, out _)) return false; } return true; case 0x1F: // ELEMENT_TYPE_CMOD_REQD case 0x20: // ELEMENT_TYPE_CMOD_OPT - // modifier + // modifier if (!TypeHandleEquals(ref a, ref b, contextForA, contextForB)) return false; // unmodified type @@ -157,14 +163,15 @@ namespace ICSharpCode.Decompiler.Metadata return false; return true; case 0x15: // ELEMENT_TYPE_GENERICINST - // generic type + // generic type if (!IsSameCompressedInteger(ref a, ref b, out typeCode)) return false; if (!TypesAreEqual(ref a, ref b, contextForA, contextForB, typeCode)) return false; if (!IsSameCompressedInteger(ref a, ref b, out int numOfArguments)) return false; - for (int i = 0; i < numOfArguments; i++) { + for (int i = 0; i < numOfArguments; i++) + { if (!IsSameCompressedInteger(ref a, ref b, out typeCode)) return false; if (!TypesAreEqual(ref a, ref b, contextForA, contextForB, typeCode)) @@ -173,7 +180,7 @@ namespace ICSharpCode.Decompiler.Metadata return true; case 0x13: // ELEMENT_TYPE_VAR case 0x1E: // ELEMENT_TYPE_MVAR - // index + // index if (!IsSameCompressedInteger(ref a, ref b, out _)) return false; return true; diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index f5245a5a2..cdcf8c141 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -60,7 +60,7 @@ namespace ICSharpCode.Decompiler.Metadata DotNetCorePathFinder dotNetCorePathFinder; readonly bool throwOnError; readonly PEStreamOptions streamOptions; - readonly MetadataReaderOptions metadataOptions; + readonly MetadataReaderOptions metadataOptions; readonly string mainAssemblyFileName; readonly string baseDirectory; readonly List directories = new List(); @@ -99,7 +99,8 @@ namespace ICSharpCode.Decompiler.Metadata this.targetFramework = targetFramework ?? string.Empty; (targetFrameworkIdentifier, targetFrameworkVersion) = ParseTargetFramework(this.targetFramework); - if (mainAssemblyFileName != null) { + if (mainAssemblyFileName != null) + { string baseDirectory = Path.GetDirectoryName(mainAssemblyFileName); if (string.IsNullOrWhiteSpace(this.baseDirectory)) this.baseDirectory = Environment.CurrentDirectory; @@ -112,7 +113,8 @@ namespace ICSharpCode.Decompiler.Metadata string[] tokens = targetFramework.Split(','); TargetFrameworkIdentifier identifier; - switch (tokens[0].Trim().ToUpperInvariant()) { + switch (tokens[0].Trim().ToUpperInvariant()) + { case ".NETCOREAPP": identifier = TargetFrameworkIdentifier.NETCoreApp; break; @@ -129,13 +131,15 @@ namespace ICSharpCode.Decompiler.Metadata Version version = null; - for (int i = 1; i < tokens.Length; i++) { + for (int i = 1; i < tokens.Length; i++) + { var pair = tokens[i].Trim().Split('='); if (pair.Length != 2) continue; - switch (pair[0].Trim().ToUpperInvariant()) { + switch (pair[0].Trim().ToUpperInvariant()) + { case "VERSION": var versionString = pair[1].TrimStart('v', ' ', '\t'); if (identifier == TargetFrameworkIdentifier.NETCoreApp || @@ -156,7 +160,8 @@ namespace ICSharpCode.Decompiler.Metadata public PEFile Resolve(IAssemblyReference name) { var file = FindAssemblyFile(name); - if (file == null) { + if (file == null) + { if (throwOnError) throw new AssemblyResolutionException(name); return null; @@ -168,7 +173,8 @@ namespace ICSharpCode.Decompiler.Metadata { string baseDirectory = Path.GetDirectoryName(mainModule.FileName); string moduleFileName = Path.Combine(baseDirectory, moduleName); - if (!File.Exists(moduleFileName)) { + if (!File.Exists(moduleFileName)) + { if (throwOnError) throw new Exception($"Module {moduleName} could not be found!"); return null; @@ -183,22 +189,26 @@ namespace ICSharpCode.Decompiler.Metadata public string FindAssemblyFile(IAssemblyReference name) { - if (name.IsWindowsRuntime) { + if (name.IsWindowsRuntime) + { return FindWindowsMetadataFile(name); } string file = null; - switch (targetFrameworkIdentifier) { + switch (targetFrameworkIdentifier) + { case TargetFrameworkIdentifier.NETCoreApp: case TargetFrameworkIdentifier.NETStandard: if (IsZeroOrAllOnes(targetFrameworkVersion)) goto default; - if (dotNetCorePathFinder == null) { + if (dotNetCorePathFinder == null) + { if (mainAssemblyFileName == null) dotNetCorePathFinder = new DotNetCorePathFinder(targetFrameworkIdentifier, targetFrameworkVersion); else dotNetCorePathFinder = new DotNetCorePathFinder(mainAssemblyFileName, targetFramework, targetFrameworkIdentifier, targetFrameworkVersion); - foreach (var directory in directories) { + foreach (var directory in directories) + { dotNetCorePathFinder.AddSearchDirectory(directory); } } @@ -233,7 +243,8 @@ namespace ICSharpCode.Decompiler.Metadata // TODO : Find a way to detect the required Windows SDK version. var di = new DirectoryInfo(basePath); basePath = null; - foreach (var versionFolder in di.EnumerateDirectories()) { + foreach (var versionFolder in di.EnumerateDirectories()) + { basePath = versionFolder.FullName; } @@ -268,7 +279,8 @@ namespace ICSharpCode.Decompiler.Metadata void AddTargetFrameworkSearchPathIfExists(string path) { - if (targetFrameworkSearchPaths == null) { + if (targetFrameworkSearchPaths == null) + { targetFrameworkSearchPaths = new HashSet(); } if (Directory.Exists(path)) @@ -283,7 +295,8 @@ namespace ICSharpCode.Decompiler.Metadata AddTargetFrameworkSearchPathIfExists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Microsoft Silverlight")); AddTargetFrameworkSearchPathIfExists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Microsoft Silverlight")); - foreach (var baseDirectory in targetFrameworkSearchPaths) { + foreach (var baseDirectory in targetFrameworkSearchPaths) + { var versionDirectory = Path.Combine(baseDirectory, FindClosestVersionDirectory(baseDirectory, version)); var file = SearchDirectory(name, versionDirectory); if (file != null) @@ -296,7 +309,8 @@ namespace ICSharpCode.Decompiler.Metadata { string path = null; foreach (var folder in new DirectoryInfo(basePath).GetDirectories().Select(d => DotNetCorePathFinder.ConvertToVersion(d.Name)) - .Where(v => v.Item1 != null).OrderByDescending(v => v.Item1)) { + .Where(v => v.Item1 != null).OrderByDescending(v => v.Item1)) + { if (path == null || folder.Item1 >= version) path = folder.Item2; } @@ -317,13 +331,15 @@ namespace ICSharpCode.Decompiler.Metadata ? new[] { framework_dir, Path.Combine(framework_dir, "Facades") } : new[] { framework_dir }; - if (IsSpecialVersionOrRetargetable(name)) { + if (IsSpecialVersionOrRetargetable(name)) + { assembly = SearchDirectory(name, framework_dirs); if (assembly != null) return assembly; } - if (name.Name == "mscorlib") { + if (name.Name == "mscorlib") + { assembly = GetCorlib(name); if (assembly != null) return assembly; @@ -335,7 +351,8 @@ namespace ICSharpCode.Decompiler.Metadata // when decompiling assemblies that target frameworks prior to 4.0, we can fall back to the 4.0 assemblies in case the target framework is not installed. // but when looking for Microsoft.Build.Framework, Version=15.0.0.0 we should not use the version 4.0 assembly here so that the LoadedAssembly logic can instead fall back to version 15.1.0.0 - if (name.Version <= new Version(4, 0, 0, 0)) { + if (name.Version <= new Version(4, 0, 0, 0)) + { assembly = SearchDirectory(name, framework_dirs); if (assembly != null) return assembly; @@ -349,7 +366,8 @@ namespace ICSharpCode.Decompiler.Metadata #region .NET / mono GAC handling string SearchDirectory(IAssemblyReference name, IEnumerable directories) { - foreach (var directory in directories) { + foreach (var directory in directories) + { string file = SearchDirectory(name, directory); if (file != null) return file; @@ -366,13 +384,17 @@ namespace ICSharpCode.Decompiler.Metadata string SearchDirectory(IAssemblyReference name, string directory) { var extensions = name.IsWindowsRuntime ? new[] { ".winmd", ".dll" } : new[] { ".exe", ".dll" }; - foreach (var extension in extensions) { + foreach (var extension in extensions) + { string file = Path.Combine(directory, name.Name + extension); if (!File.Exists(file)) continue; - try { + try + { return file; - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { continue; } } @@ -386,14 +408,15 @@ namespace ICSharpCode.Decompiler.Metadata || (version.Major == 65535 && version.Minor == 65535 && version.Build == 65535 && version.Revision == 65535); } - internal static Version ZeroVersion = new Version(0,0,0,0); + internal static Version ZeroVersion = new Version(0, 0, 0, 0); string GetCorlib(IAssemblyReference reference) { var version = reference.Version; var corlib = typeof(object).Assembly.GetName(); - if (decompilerRuntime != DecompilerRuntime.NETCoreApp) { + if (decompilerRuntime != DecompilerRuntime.NETCoreApp) + { if (corlib.Version == version || IsSpecialVersionOrRetargetable(reference)) return typeof(object).Module.FullyQualifiedName; } @@ -402,9 +425,12 @@ namespace ICSharpCode.Decompiler.Metadata return null; string path; - if (decompilerRuntime == DecompilerRuntime.Mono) { + if (decompilerRuntime == DecompilerRuntime.Mono) + { path = GetMonoMscorlibBasePath(version); - } else { + } + else + { path = GetMscorlibBasePath(version, reference.PublicKeyToken.ToHexString(8)); } @@ -422,7 +448,8 @@ namespace ICSharpCode.Decompiler.Metadata { string GetSubFolderForVersion() { - switch (version.Major) { + switch (version.Major) + { case 1: if (version.MajorRevision == 3300) return "v1.0.3705"; @@ -438,7 +465,8 @@ namespace ICSharpCode.Decompiler.Metadata } } - if (publicKeyToken == "969db8053d3322ac") { + if (publicKeyToken == "969db8053d3322ac") + { string programFiles = Environment.Is64BitOperatingSystem ? Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) : Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); @@ -446,7 +474,9 @@ namespace ICSharpCode.Decompiler.Metadata string cfBasePath = Path.Combine(programFiles, cfPath); if (Directory.Exists(cfBasePath)) return cfBasePath; - } else { + } + else + { string rootPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "Microsoft.NET"); string[] frameworkPaths = new[] { Path.Combine(rootPath, "Framework"), @@ -455,8 +485,10 @@ namespace ICSharpCode.Decompiler.Metadata string folder = GetSubFolderForVersion(); - if (folder != null) { - foreach (var path in frameworkPaths) { + if (folder != null) + { + foreach (var path in frameworkPaths) + { var basePath = Path.Combine(path, folder); if (Directory.Exists(basePath)) return basePath; @@ -474,14 +506,17 @@ namespace ICSharpCode.Decompiler.Metadata var path = Directory.GetParent(typeof(object).Module.FullyQualifiedName).Parent.FullName; if (version.Major == 1) path = Path.Combine(path, "1.0"); - else if (version.Major == 2) { + else if (version.Major == 2) + { if (version.MajorRevision == 5) path = Path.Combine(path, "2.1"); else path = Path.Combine(path, "2.0"); - } else if (version.Major == 4) + } + else if (version.Major == 4) path = Path.Combine(path, "4.0"); - else { + else + { if (throwOnError) throw new NotSupportedException("Version not supported: " + version); return null; @@ -516,7 +551,8 @@ namespace ICSharpCode.Decompiler.Metadata return paths; var prefixes = gac_paths_env.Split(Path.PathSeparator); - foreach (var prefix in prefixes) { + foreach (var prefix in prefixes) + { if (string.IsNullOrEmpty(prefix)) continue; @@ -549,7 +585,8 @@ namespace ICSharpCode.Decompiler.Metadata static string GetAssemblyInMonoGac(IAssemblyReference reference) { - for (int i = 0; i < gac_paths.Count; i++) { + for (int i = 0; i < gac_paths.Count; i++) + { var gac_path = gac_paths[i]; var file = GetAssemblyFile(reference, string.Empty, gac_path); if (File.Exists(file)) @@ -564,8 +601,10 @@ namespace ICSharpCode.Decompiler.Metadata var gacs = new[] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" }; var prefixes = new[] { string.Empty, "v4.0_" }; - for (int i = 0; i < gac_paths.Count; i++) { - for (int j = 0; j < gacs.Length; j++) { + for (int i = 0; i < gac_paths.Count; i++) + { + for (int j = 0; j < gacs.Length; j++) + { var gac = Path.Combine(gac_paths[i], gacs[j]); var file = GetAssemblyFile(reference, prefixes[i], gac); if (Directory.Exists(gac) && File.Exists(file)) @@ -598,12 +637,15 @@ namespace ICSharpCode.Decompiler.Metadata public static IEnumerable EnumerateGac() { var gacs = new[] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" }; - foreach (var path in GetGacPaths()) { - foreach (var gac in gacs) { + foreach (var path in GetGacPaths()) + { + foreach (var gac in gacs) + { string rootPath = Path.Combine(path, gac); if (!Directory.Exists(rootPath)) continue; - foreach (var item in new DirectoryInfo(rootPath).EnumerateFiles("*.dll", SearchOption.AllDirectories)) { + foreach (var item in new DirectoryInfo(rootPath).EnumerateFiles("*.dll", SearchOption.AllDirectories)) + { string[] name = Path.GetDirectoryName(item.FullName).Substring(rootPath.Length + 1).Split(new[] { "\\" }, StringSplitOptions.RemoveEmptyEntries); if (name.Length != 2) continue; diff --git a/ICSharpCode.Decompiler/NRExtensions.cs b/ICSharpCode.Decompiler/NRExtensions.cs index 927af49cf..7d98e27b4 100644 --- a/ICSharpCode.Decompiler/NRExtensions.cs +++ b/ICSharpCode.Decompiler/NRExtensions.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.TypeSystem; @@ -26,12 +27,13 @@ namespace ICSharpCode.Decompiler { public static bool IsCompilerGenerated(this IEntity entity) { - if (entity != null) { + if (entity != null) + { return entity.HasAttribute(KnownAttribute.CompilerGenerated); } return false; } - + public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this IEntity entity) { if (entity == null) @@ -40,46 +42,48 @@ namespace ICSharpCode.Decompiler return true; return IsCompilerGeneratedOrIsInCompilerGeneratedClass(entity.DeclaringTypeDefinition); } - + public static bool HasGeneratedName(this IMember member) { return member.Name.StartsWith("<", StringComparison.Ordinal); } - + public static bool HasGeneratedName(this IType type) { return type.Name.StartsWith("<", StringComparison.Ordinal) || type.Name.Contains("<"); } - + public static bool IsAnonymousType(this IType type) { if (type == null) return false; - if (string.IsNullOrEmpty(type.Namespace) && type.HasGeneratedName() && (type.Name.Contains("AnonType") || type.Name.Contains("AnonymousType"))) { + if (string.IsNullOrEmpty(type.Namespace) && type.HasGeneratedName() + && (type.Name.Contains("AnonType") || type.Name.Contains("AnonymousType"))) + { ITypeDefinition td = type.GetDefinition(); return td != null && td.IsCompilerGenerated(); } return false; } - + public static bool ContainsAnonymousType(this IType type) { var visitor = new ContainsAnonTypeVisitor(); type.AcceptVisitor(visitor); return visitor.ContainsAnonType; } - + class ContainsAnonTypeVisitor : TypeVisitor { public bool ContainsAnonType; - + public override IType VisitOtherType(IType type) { if (IsAnonymousType(type)) ContainsAnonType = true; return base.VisitOtherType(type); } - + public override IType VisitTypeDefinition(ITypeDefinition type) { if (IsAnonymousType(type)) diff --git a/ICSharpCode.Decompiler/Output/IAmbience.cs b/ICSharpCode.Decompiler/Output/IAmbience.cs index a8b547f3c..4637ddc91 100644 --- a/ICSharpCode.Decompiler/Output/IAmbience.cs +++ b/ICSharpCode.Decompiler/Output/IAmbience.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Output @@ -31,19 +32,19 @@ namespace ICSharpCode.Decompiler.Output /// /// Show the parameter list /// - ShowParameterList = 1, + ShowParameterList = 1, /// /// Show names for parameters /// - ShowParameterNames = 2, + ShowParameterNames = 2, /// /// Show the accessibility (private, public, etc.) /// - ShowAccessibility = 4, + ShowAccessibility = 4, /// /// Show the definition key word (class, struct, Sub, Function, etc.) /// - ShowDefinitionKeyword = 8, + ShowDefinitionKeyword = 8, /// /// Show the declaring type for the type or member /// @@ -51,7 +52,7 @@ namespace ICSharpCode.Decompiler.Output /// /// Show modifiers (virtual, override, etc.) /// - ShowModifiers = 0x20, + ShowModifiers = 0x20, /// /// Show the return type /// @@ -109,21 +110,21 @@ namespace ICSharpCode.Decompiler.Output ShowTypeParameterVarianceModifier | ShowDefinitionKeyword | ShowBody, - + All = 0x7ffff, } - + /// /// Ambiences are used to convert type system symbols to text (usually for displaying the symbol to the user; e.g. in editor tooltips). /// public interface IAmbience { ConversionFlags ConversionFlags { get; set; } - + string ConvertSymbol(ISymbol symbol); string ConvertType(IType type); string ConvertConstantValue(object constantValue); - + string WrapComment(string comment); } } diff --git a/ICSharpCode.Decompiler/Output/ITextOutput.cs b/ICSharpCode.Decompiler/Output/ITextOutput.cs index 9b935cd9d..0a7bdc97f 100644 --- a/ICSharpCode.Decompiler/Output/ITextOutput.cs +++ b/ICSharpCode.Decompiler/Output/ITextOutput.cs @@ -18,6 +18,7 @@ using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; diff --git a/ICSharpCode.Decompiler/Output/PlainTextOutput.cs b/ICSharpCode.Decompiler/Output/PlainTextOutput.cs index ce6a7bf4a..5d2995c76 100644 --- a/ICSharpCode.Decompiler/Output/PlainTextOutput.cs +++ b/ICSharpCode.Decompiler/Output/PlainTextOutput.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; @@ -32,7 +33,7 @@ namespace ICSharpCode.Decompiler readonly TextWriter writer; int indent; bool needsIndent; - + int line = 1; int column = 1; @@ -44,58 +45,60 @@ namespace ICSharpCode.Decompiler throw new ArgumentNullException(nameof(writer)); this.writer = writer; } - + public PlainTextOutput() { this.writer = new StringWriter(); } - + public TextLocation Location { get { return new TextLocation(line, column + (needsIndent ? indent : 0)); } } - + public override string ToString() { return writer.ToString(); } - + public void Indent() { indent++; } - + public void Unindent() { indent--; } - + void WriteIndent() { - if (needsIndent) { + if (needsIndent) + { needsIndent = false; - for (int i = 0; i < indent; i++) { + for (int i = 0; i < indent; i++) + { writer.Write(IndentationString); } column += indent; } } - + public void Write(char ch) { WriteIndent(); writer.Write(ch); column++; } - + public void Write(string text) { WriteIndent(); writer.Write(text); column += text.Length; } - + public void WriteLine() { writer.WriteLine(); @@ -106,12 +109,16 @@ namespace ICSharpCode.Decompiler public void WriteReference(Disassembler.OpCodeInfo opCode, bool omitSuffix = false) { - if (omitSuffix) { + if (omitSuffix) + { int lastDot = opCode.Name.LastIndexOf('.'); - if (lastDot > 0) { + if (lastDot > 0) + { Write(opCode.Name.Remove(lastDot + 1)); } - } else { + } + else + { Write(opCode.Name); } } @@ -139,7 +146,7 @@ namespace ICSharpCode.Decompiler void ITextOutput.MarkFoldStart(string collapsedText, bool defaultCollapsed) { } - + void ITextOutput.MarkFoldEnd() { } @@ -167,7 +174,8 @@ namespace ICSharpCode.Decompiler public void Commit() { - foreach (var action in actions) { + foreach (var action in actions) + { action(target); } } diff --git a/ICSharpCode.Decompiler/Output/TextOutputWriter.cs b/ICSharpCode.Decompiler/Output/TextOutputWriter.cs index 36bc1cee8..afd84cbbc 100644 --- a/ICSharpCode.Decompiler/Output/TextOutputWriter.cs +++ b/ICSharpCode.Decompiler/Output/TextOutputWriter.cs @@ -25,28 +25,28 @@ namespace ICSharpCode.Decompiler public class TextOutputWriter : TextWriter { readonly ITextOutput output; - + public TextOutputWriter(ITextOutput output) { if (output == null) throw new ArgumentNullException(nameof(output)); this.output = output; } - + public override Encoding Encoding { get { return Encoding.UTF8; } } - + public override void Write(char value) { output.Write(value); } - + public override void Write(string value) { output.Write(value); } - + public override void WriteLine() { output.WriteLine(); diff --git a/ICSharpCode.Decompiler/Output/TextTokenWriter.cs b/ICSharpCode.Decompiler/Output/TextTokenWriter.cs index ce2f7c49b..5ec4e54b6 100644 --- a/ICSharpCode.Decompiler/Output/TextTokenWriter.cs +++ b/ICSharpCode.Decompiler/Output/TextTokenWriter.cs @@ -57,13 +57,15 @@ namespace ICSharpCode.Decompiler public override void WriteIdentifier(Identifier identifier) { - if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) { + if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) + { output.Write('@'); } var definition = GetCurrentDefinition(); string name = TextWriterTokenWriter.EscapeIdentifier(identifier.Name); - switch (definition) { + switch (definition) + { case IType t: output.WriteReference(t, name, true); return; @@ -73,7 +75,8 @@ namespace ICSharpCode.Decompiler } var member = GetCurrentMemberReference(); - switch (member) { + switch (member) + { case IType t: output.WriteReference(t, name, false); return; @@ -83,18 +86,21 @@ namespace ICSharpCode.Decompiler } var localDefinition = GetCurrentLocalDefinition(); - if (localDefinition != null) { + if (localDefinition != null) + { output.WriteLocalReference(name, localDefinition, isDefinition: true); return; } var localRef = GetCurrentLocalReference(); - if (localRef != null) { + if (localRef != null) + { output.WriteLocalReference(name, localRef); return; } - if (firstUsingDeclaration && !lastUsingDeclaration) { + if (firstUsingDeclaration && !lastUsingDeclaration) + { output.MarkFoldStart(defaultCollapsed: !settings.ExpandUsingDeclarations); firstUsingDeclaration = false; } @@ -106,14 +112,17 @@ namespace ICSharpCode.Decompiler { AstNode node = nodeStack.Peek(); var symbol = node.GetSymbol(); - if (symbol == null && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) { + if (symbol == null && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) + { symbol = node.Parent.GetSymbol(); } - if (symbol != null && node.Role == Roles.Type && node.Parent is ObjectCreateExpression) { + if (symbol != null && node.Role == Roles.Type && node.Parent is ObjectCreateExpression) + { symbol = node.Parent.GetSymbol(); } - if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) { + if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) + { var declaringType = member.DeclaringType; if (declaringType != null && declaringType.Kind == TypeKind.Delegate) return null; @@ -143,13 +152,15 @@ namespace ICSharpCode.Decompiler if (letClauseVariable != null) return letClauseVariable; - if (node is GotoStatement gotoStatement) { + if (node is GotoStatement gotoStatement) + { var method = nodeStack.Select(nd => nd.GetSymbol() as IMethod).FirstOrDefault(mr => mr != null); if (method != null) return method + gotoStatement.Label; } - if (node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) { + if (node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) + { var symbol = node.Parent.GetSymbol(); if (symbol is LocalFunctionMethod) return symbol; @@ -164,25 +175,29 @@ namespace ICSharpCode.Decompiler if (node is Identifier && node.Parent != null) node = node.Parent; - if (node is ParameterDeclaration || node is VariableInitializer || node is CatchClause || node is VariableDesignation) { + if (node is ParameterDeclaration || node is VariableInitializer || node is CatchClause || node is VariableDesignation) + { var variable = node.Annotation()?.Variable; if (variable != null) return variable; } - if (node is QueryLetClause) { + if (node is QueryLetClause) + { var variable = node.Annotation(); if (variable != null) return variable; } - if (node is LabelStatement label) { + if (node is LabelStatement label) + { var method = nodeStack.Select(nd => nd.GetSymbol() as IMethod).FirstOrDefault(mr => mr != null); if (method != null) return method + label.Label; } - if (node is MethodDeclaration && node.Parent is LocalFunctionDeclarationStatement) { + if (node is MethodDeclaration && node.Parent is LocalFunctionDeclarationStatement) + { var localFunction = node.Parent.GetResolveResult() as MemberResolveResult; if (localFunction != null) return localFunction.Member; @@ -208,8 +223,10 @@ namespace ICSharpCode.Decompiler public override void WriteKeyword(Role role, string keyword) { //To make reference for 'this' and 'base' keywords in the ClassName():this() expression - if (role == ConstructorInitializer.ThisKeywordRole || role == ConstructorInitializer.BaseKeywordRole) { - if (nodeStack.Peek() is ConstructorInitializer initializer && initializer.GetSymbol() is IMember member) { + if (role == ConstructorInitializer.ThisKeywordRole || role == ConstructorInitializer.BaseKeywordRole) + { + if (nodeStack.Peek() is ConstructorInitializer initializer && initializer.GetSymbol() is IMember member) + { output.WriteReference(member, keyword); return; } @@ -219,22 +236,26 @@ namespace ICSharpCode.Decompiler public override void WriteToken(Role role, string token) { - switch (token) { + switch (token) + { case "{": - if (role != Roles.LBrace) { + if (role != Roles.LBrace) + { output.Write("{"); break; } if (braceLevelWithinType >= 0 || nodeStack.Peek() is TypeDeclaration) braceLevelWithinType++; - if (nodeStack.OfType().Count() <= 1 || settings.FoldBraces) { + if (nodeStack.OfType().Count() <= 1 || settings.FoldBraces) + { output.MarkFoldStart(defaultCollapsed: !settings.ExpandMemberDefinitions && braceLevelWithinType == 1); } output.Write("{"); break; case "}": output.Write('}'); - if (role != Roles.RBrace) break; + if (role != Roles.RBrace) + break; if (nodeStack.OfType().Count() <= 1 || settings.FoldBraces) output.MarkFoldEnd(); if (braceLevelWithinType >= 0) @@ -244,8 +265,10 @@ namespace ICSharpCode.Decompiler // Attach member reference to token only if there's no identifier in the current node. var member = GetCurrentMemberReference(); var node = nodeStack.Peek(); - if (member != null && node.GetChildByRole(Roles.Identifier).IsNull) { - switch (member) { + if (member != null && node.GetChildByRole(Roles.Identifier).IsNull) + { + switch (member) + { case IType t: output.WriteReference(t, token, false); return; @@ -253,7 +276,8 @@ namespace ICSharpCode.Decompiler output.WriteReference(m, token, false); return; } - } else + } + else output.Write(token); break; } @@ -276,7 +300,8 @@ namespace ICSharpCode.Decompiler public override void NewLine() { - if (!firstUsingDeclaration && lastUsingDeclaration) { + if (!firstUsingDeclaration && lastUsingDeclaration) + { output.MarkFoldEnd(); lastUsingDeclaration = false; } @@ -285,7 +310,8 @@ namespace ICSharpCode.Decompiler public override void WriteComment(CommentType commentType, string content) { - switch (commentType) { + switch (commentType) + { case CommentType.SingleLine: output.Write("//"); output.WriteLine(content); @@ -297,13 +323,15 @@ namespace ICSharpCode.Decompiler break; case CommentType.Documentation: bool isLastLine = !(nodeStack.Peek().NextSibling is Comment); - if (!inDocumentationComment && !isLastLine) { + if (!inDocumentationComment && !isLastLine) + { inDocumentationComment = true; output.MarkFoldStart("///" + content, true); } output.Write("///"); output.Write(content); - if (inDocumentationComment && isLastLine) { + if (inDocumentationComment && isLastLine) + { inDocumentationComment = false; output.MarkFoldEnd(); } @@ -320,7 +348,8 @@ namespace ICSharpCode.Decompiler // pre-processor directive must start on its own line output.Write('#'); output.Write(type.ToString().ToLowerInvariant()); - if (!string.IsNullOrEmpty(argument)) { + if (!string.IsNullOrEmpty(argument)) + { output.Write(' '); output.Write(argument); } @@ -339,7 +368,8 @@ namespace ICSharpCode.Decompiler public override void WritePrimitiveType(string type) { - switch (type) { + switch (type) + { case "new": output.Write(type); output.Write("()"); @@ -361,13 +391,18 @@ namespace ICSharpCode.Decompiler case "object": var node = nodeStack.Peek(); ISymbol symbol; - if (node.Role == Roles.Type && node.Parent is ObjectCreateExpression) { + if (node.Role == Roles.Type && node.Parent is ObjectCreateExpression) + { symbol = node.Parent.GetSymbol(); - } else { + } + else + { symbol = nodeStack.Peek().GetSymbol(); } - if (symbol == null) goto default; - switch (symbol) { + if (symbol == null) + goto default; + switch (symbol) + { case IType t: output.WriteReference(t, type, false); return; @@ -384,11 +419,15 @@ namespace ICSharpCode.Decompiler public override void StartNode(AstNode node) { - if (nodeStack.Count == 0) { - if (IsUsingDeclaration(node)) { + if (nodeStack.Count == 0) + { + if (IsUsingDeclaration(node)) + { firstUsingDeclaration = !IsUsingDeclaration(node.PrevSibling); lastUsingDeclaration = !IsUsingDeclaration(node.NextSibling); - } else { + } + else + { firstUsingDeclaration = false; lastUsingDeclaration = false; } @@ -411,11 +450,13 @@ namespace ICSharpCode.Decompiler { if (node is EntityDeclaration && !(node.Parent is LocalFunctionDeclarationStatement)) return true; - if (node is VariableInitializer && node.Parent is FieldDeclaration) { + if (node is VariableInitializer && node.Parent is FieldDeclaration) + { node = node.Parent; return true; } - if (node is FixedVariableInitializer && node.Parent is FixedFieldDeclaration) { + if (node is FixedVariableInitializer && node.Parent is FixedFieldDeclaration) + { node = node.Parent; return true; } diff --git a/ICSharpCode.Decompiler/SRMExtensions.cs b/ICSharpCode.Decompiler/SRMExtensions.cs index 0803080f1..c9b33f8ed 100644 --- a/ICSharpCode.Decompiler/SRMExtensions.cs +++ b/ICSharpCode.Decompiler/SRMExtensions.cs @@ -2,25 +2,36 @@ using System.Collections.Immutable; using System.Reflection; using System.Reflection.Metadata; -using SRM = System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; -using System.Reflection.Metadata.Ecma335; + +using SRM = System.Reflection.Metadata; namespace ICSharpCode.Decompiler { public static partial class SRMExtensions { - public static bool HasFlag(this TypeDefinition typeDefinition, TypeAttributes attribute) => (typeDefinition.Attributes & attribute) == attribute; - public static bool HasFlag(this MethodDefinition methodDefinition, MethodAttributes attribute) => (methodDefinition.Attributes & attribute) == attribute; - public static bool HasFlag(this FieldDefinition fieldDefinition, FieldAttributes attribute) => (fieldDefinition.Attributes & attribute) == attribute; - public static bool HasFlag(this PropertyDefinition propertyDefinition, PropertyAttributes attribute) => (propertyDefinition.Attributes & attribute) == attribute; - public static bool HasFlag(this EventDefinition eventDefinition, EventAttributes attribute) => (eventDefinition.Attributes & attribute) == attribute; - - public static bool IsTypeKind(this HandleKind kind) => kind == HandleKind.TypeDefinition || kind == HandleKind.TypeReference || kind == HandleKind.TypeSpecification; - public static bool IsMemberKind(this HandleKind kind) => kind == HandleKind.MethodDefinition || kind == HandleKind.PropertyDefinition || kind == HandleKind.FieldDefinition - || kind == HandleKind.EventDefinition || kind == HandleKind.MemberReference || kind == HandleKind.MethodSpecification; + public static bool HasFlag(this TypeDefinition typeDefinition, TypeAttributes attribute) + => (typeDefinition.Attributes & attribute) == attribute; + public static bool HasFlag(this MethodDefinition methodDefinition, MethodAttributes attribute) + => (methodDefinition.Attributes & attribute) == attribute; + public static bool HasFlag(this FieldDefinition fieldDefinition, FieldAttributes attribute) + => (fieldDefinition.Attributes & attribute) == attribute; + public static bool HasFlag(this PropertyDefinition propertyDefinition, PropertyAttributes attribute) + => (propertyDefinition.Attributes & attribute) == attribute; + public static bool HasFlag(this EventDefinition eventDefinition, EventAttributes attribute) + => (eventDefinition.Attributes & attribute) == attribute; + + public static bool IsTypeKind(this HandleKind kind) => + kind == HandleKind.TypeDefinition || kind == HandleKind.TypeReference + || kind == HandleKind.TypeSpecification; + public static bool IsMemberKind(this HandleKind kind) => + kind == HandleKind.MethodDefinition || kind == HandleKind.PropertyDefinition + || kind == HandleKind.FieldDefinition || kind == HandleKind.EventDefinition + || kind == HandleKind.MemberReference || kind == HandleKind.MethodSpecification; public static bool IsValueType(this TypeDefinitionHandle handle, MetadataReader reader) { @@ -53,12 +64,14 @@ namespace ICSharpCode.Decompiler return baseType.IsKnownType(reader, KnownTypeCode.Enum); } - public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader, out PrimitiveTypeCode underlyingType) + public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader, + out PrimitiveTypeCode underlyingType) { return reader.GetTypeDefinition(handle).IsEnum(reader, out underlyingType); } - public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader, out PrimitiveTypeCode underlyingType) + public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader, + out PrimitiveTypeCode underlyingType) { underlyingType = 0; EntityHandle baseType = typeDefinition.GetBaseTypeOrNil(); @@ -66,7 +79,8 @@ namespace ICSharpCode.Decompiler return false; if (!baseType.IsKnownType(reader, KnownTypeCode.Enum)) return false; - foreach (var handle in typeDefinition.GetFields()) { + foreach (var handle in typeDefinition.GetFields()) + { var field = reader.GetFieldDefinition(handle); if ((field.Attributes & FieldAttributes.Static) != 0) continue; @@ -89,7 +103,7 @@ namespace ICSharpCode.Decompiler var baseType = typeDefinition.GetBaseTypeOrNil(); return !baseType.IsNil && baseType.IsKnownType(reader, KnownTypeCode.MulticastDelegate); } - + public static bool HasBody(this MethodDefinition methodDefinition) { const MethodAttributes noBodyAttrs = MethodAttributes.Abstract | MethodAttributes.PinvokeImpl; @@ -126,7 +140,8 @@ namespace ICSharpCode.Decompiler public static TypeDefinitionHandle GetDeclaringType(this EntityHandle entity, MetadataReader metadata) { - switch (entity.Kind) { + switch (entity.Kind) + { case HandleKind.TypeDefinition: var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity); return td.GetDeclaringType(); @@ -149,7 +164,8 @@ namespace ICSharpCode.Decompiler public static TypeReferenceHandle GetDeclaringType(this TypeReference tr) { - switch (tr.ResolutionScope.Kind) { + switch (tr.ResolutionScope.Kind) + { case HandleKind.TypeReference: return (TypeReferenceHandle)tr.ResolutionScope; default: @@ -161,7 +177,8 @@ namespace ICSharpCode.Decompiler { if (handle.IsNil) throw new ArgumentNullException(nameof(handle)); - switch (handle.Kind) { + switch (handle.Kind) + { case HandleKind.TypeDefinition: return ((TypeDefinitionHandle)handle).GetFullTypeName(reader); case HandleKind.TypeReference: @@ -173,14 +190,18 @@ namespace ICSharpCode.Decompiler } } - public static bool IsKnownType(this EntityHandle handle, MetadataReader reader, KnownTypeCode knownType) + public static bool IsKnownType(this EntityHandle handle, MetadataReader reader, + KnownTypeCode knownType) { - return !handle.IsNil && GetFullTypeName(handle, reader) == KnownTypeReference.Get(knownType).TypeName; + return !handle.IsNil + && GetFullTypeName(handle, reader) == KnownTypeReference.Get(knownType).TypeName; } - - internal static bool IsKnownType(this EntityHandle handle, MetadataReader reader, KnownAttribute knownType) + + internal static bool IsKnownType(this EntityHandle handle, MetadataReader reader, + KnownAttribute knownType) { - return !handle.IsNil && GetFullTypeName(handle, reader) == knownType.GetTypeName(); + return !handle.IsNil + && GetFullTypeName(handle, reader) == knownType.GetTypeName(); } public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader) @@ -197,27 +218,40 @@ namespace ICSharpCode.Decompiler throw new ArgumentNullException(nameof(handle)); var tr = reader.GetTypeReference(handle); string name; - try { + try + { name = reader.GetString(tr.Name); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { name = $"TR{reader.GetToken(handle):x8}"; } - name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out var typeParameterCount); + name = ReflectionHelper.SplitTypeParameterCountFromReflectionName( + name, out var typeParameterCount); TypeReferenceHandle declaringTypeHandle; - try { + try + { declaringTypeHandle = tr.GetDeclaringType(); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { declaringTypeHandle = default; } - if (declaringTypeHandle.IsNil) { + if (declaringTypeHandle.IsNil) + { string ns; - try { + try + { ns = tr.Namespace.IsNil ? "" : reader.GetString(tr.Namespace); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { ns = ""; } return new FullTypeName(new TopLevelTypeName(ns, name, typeParameterCount)); - } else { + } + else + { return declaringTypeHandle.GetFullTypeName(reader).NestedType(name, typeParameterCount); } } @@ -232,22 +266,30 @@ namespace ICSharpCode.Decompiler public static FullTypeName GetFullTypeName(this TypeDefinition td, MetadataReader reader) { TypeDefinitionHandle declaringTypeHandle; - string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(reader.GetString(td.Name), out var typeParameterCount); - if ((declaringTypeHandle = td.GetDeclaringType()).IsNil) { + string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName( + reader.GetString(td.Name), out var typeParameterCount); + if ((declaringTypeHandle = td.GetDeclaringType()).IsNil) + { string @namespace = td.Namespace.IsNil ? "" : reader.GetString(td.Namespace); return new FullTypeName(new TopLevelTypeName(@namespace, name, typeParameterCount)); - } else { + } + else + { return declaringTypeHandle.GetFullTypeName(reader).NestedType(name, typeParameterCount); } } public static FullTypeName GetFullTypeName(this ExportedType type, MetadataReader metadata) { - string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(type.Name), out int typeParameterCount); - if (type.Implementation.Kind == HandleKind.ExportedType) { + string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName( + metadata.GetString(type.Name), out int typeParameterCount); + if (type.Implementation.Kind == HandleKind.ExportedType) + { var outerType = metadata.GetExportedType((ExportedTypeHandle)type.Implementation); return outerType.GetFullTypeName(metadata).NestedType(name, typeParameterCount); - } else { + } + else + { string ns = type.Namespace.IsNil ? "" : metadata.GetString(type.Namespace); return new TopLevelTypeName(ns, name, typeParameterCount); } @@ -256,7 +298,9 @@ namespace ICSharpCode.Decompiler public static bool IsAnonymousType(this TypeDefinition type, MetadataReader metadata) { string name = metadata.GetString(type.Name); - if (type.Namespace.IsNil && type.HasGeneratedName(metadata) && (name.Contains("AnonType") || name.Contains("AnonymousType"))) { + if (type.Namespace.IsNil && type.HasGeneratedName(metadata) + && (name.Contains("AnonType") || name.Contains("AnonymousType"))) + { return type.IsCompilerGenerated(metadata); } return false; @@ -298,7 +342,8 @@ namespace ICSharpCode.Decompiler return metadata.GetMethodDefinition(handle).IsCompilerGenerated(metadata); } - public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this MethodDefinitionHandle handle, MetadataReader metadata) + public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this MethodDefinitionHandle handle, + MetadataReader metadata) { MethodDefinition method = metadata.GetMethodDefinition(handle); if (method.IsCompilerGenerated(metadata)) @@ -309,7 +354,8 @@ namespace ICSharpCode.Decompiler return false; } - public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this TypeDefinitionHandle handle, MetadataReader metadata) + public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this TypeDefinitionHandle handle, + MetadataReader metadata) { TypeDefinition type = metadata.GetTypeDefinition(handle); if (type.IsCompilerGenerated(metadata)) @@ -353,7 +399,8 @@ namespace ICSharpCode.Decompiler /// public static EntityHandle GetAttributeType(this SRM.CustomAttribute attribute, MetadataReader reader) { - switch (attribute.Constructor.Kind) { + switch (attribute.Constructor.Kind) + { case HandleKind.MethodDefinition: var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor); return md.GetDeclaringType(); @@ -361,40 +408,54 @@ namespace ICSharpCode.Decompiler var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor); return mr.Parent; default: - throw new BadImageFormatException("Unexpected token kind for attribute constructor: " + attribute.Constructor.Kind); + throw new BadImageFormatException("Unexpected token kind for attribute constructor: " + + attribute.Constructor.Kind); } } - - public static bool HasKnownAttribute(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata, KnownAttribute type) + + public static bool HasKnownAttribute(this CustomAttributeHandleCollection customAttributes, + MetadataReader metadata, KnownAttribute type) { - foreach (var handle in customAttributes) { + foreach (var handle in customAttributes) + { var customAttribute = metadata.GetCustomAttribute(handle); if (customAttribute.IsKnownAttribute(metadata, type)) return true; } return false; } - - internal static bool IsKnownAttribute(this SRM.CustomAttribute attr, MetadataReader metadata, KnownAttribute attrType) + + internal static bool IsKnownAttribute(this SRM.CustomAttribute attr, MetadataReader metadata, + KnownAttribute attrType) { return attr.GetAttributeType(metadata).IsKnownType(metadata, attrType); } - public static Nullability? GetNullableContext(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata) + public static Nullability? GetNullableContext(this CustomAttributeHandleCollection customAttributes, + MetadataReader metadata) { - foreach (var handle in customAttributes) { + foreach (var handle in customAttributes) + { var customAttribute = metadata.GetCustomAttribute(handle); - if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.NullableContext)) { + if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.NullableContext)) + { // Decode CustomAttributeValue value; - try { - value = customAttribute.DecodeValue(Metadata.MetadataExtensions.MinimalAttributeTypeProvider); - } catch (BadImageFormatException) { + try + { + value = customAttribute.DecodeValue( + Metadata.MetadataExtensions.MinimalAttributeTypeProvider); + } + catch (BadImageFormatException) + { continue; - } catch (Metadata.EnumUnderlyingTypeResolveException) { + } + catch (Metadata.EnumUnderlyingTypeResolveException) + { continue; } - if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is byte b && b <= 2) { + if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is byte b && b <= 2) + { return (Nullability)b; } } @@ -403,7 +464,8 @@ namespace ICSharpCode.Decompiler } #endregion - public static unsafe SRM.BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile, ICompilation typeSystem) + public static unsafe BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile, + ICompilation typeSystem) { if (!field.HasFlag(FieldAttributes.HasFieldRVA)) return default; @@ -413,7 +475,8 @@ namespace ICSharpCode.Decompiler int size = field.DecodeSignature(new FieldValueSizeDecoder(typeSystem), default); var sectionData = pefile.GetSectionData(rva); if (sectionData.Length == 0 && size != 0) - throw new BadImageFormatException($"Field data (rva=0x{rva:x}) could not be found in any section!"); + throw new BadImageFormatException($"Field data (rva=0x{rva:x}) could not be found" + + "in any section!"); if (size < 0 || size > sectionData.Length) throw new BadImageFormatException($"Invalid size {size} for field data!"); return sectionData.GetReader(0, size); @@ -433,20 +496,23 @@ namespace ICSharpCode.Decompiler this.pointerSize = module.PEFile.Reader.PEHeaders.PEHeader.Magic == PEMagic.PE32 ? 4 : 8; } - public int GetArrayType(int elementType, ArrayShape shape) => GetPrimitiveType(PrimitiveTypeCode.Object); + public int GetArrayType(int elementType, ArrayShape shape) => + GetPrimitiveType(PrimitiveTypeCode.Object); public int GetSZArrayType(int elementType) => GetPrimitiveType(PrimitiveTypeCode.Object); public int GetByReferenceType(int elementType) => pointerSize; public int GetFunctionPointerType(MethodSignature signature) => pointerSize; - public int GetGenericInstantiation(int genericType, ImmutableArray typeArguments) => genericType; + public int GetGenericInstantiation(int genericType, ImmutableArray typeArguments) + => genericType; public int GetGenericMethodParameter(GenericContext genericContext, int index) => 0; public int GetGenericTypeParameter(GenericContext genericContext, int index) => 0; public int GetModifiedType(int modifier, int unmodifiedType, bool isRequired) => unmodifiedType; public int GetPinnedType(int elementType) => elementType; public int GetPointerType(int elementType) => pointerSize; - public int GetPrimitiveType(PrimitiveTypeCode typeCode) + public int GetPrimitiveType(PrimitiveTypeCode typeCode) { - switch (typeCode) { + switch (typeCode) + { case PrimitiveTypeCode.Boolean: case PrimitiveTypeCode.Byte: case PrimitiveTypeCode.SByte: @@ -471,13 +537,15 @@ namespace ICSharpCode.Decompiler } } - public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) + public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, + byte rawTypeKind) { var td = reader.GetTypeDefinition(handle); return td.GetLayout().Size; } - public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) + public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, + byte rawTypeKind) { var typeDef = module?.ResolveType(handle, new GenericContext()).GetDefinition(); if (typeDef == null || typeDef.MetadataToken.IsNil) @@ -487,7 +555,8 @@ namespace ICSharpCode.Decompiler return td.GetLayout().Size; } - public int GetTypeFromSpecification(MetadataReader reader, GenericContext genericContext, TypeSpecificationHandle handle, byte rawTypeKind) + public int GetTypeFromSpecification(MetadataReader reader, GenericContext genericContext, + TypeSpecificationHandle handle, byte rawTypeKind) { return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext); } @@ -495,9 +564,12 @@ namespace ICSharpCode.Decompiler public static EntityHandle GetBaseTypeOrNil(this TypeDefinition definition) { - try { + try + { return definition.BaseType; - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { return default; } } diff --git a/ICSharpCode.Decompiler/SRMHacks.cs b/ICSharpCode.Decompiler/SRMHacks.cs index c2ba77b25..11d750fed 100644 --- a/ICSharpCode.Decompiler/SRMHacks.cs +++ b/ICSharpCode.Decompiler/SRMHacks.cs @@ -7,20 +7,25 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler { public static partial class SRMExtensions { - public static ImmutableArray GetMethodImplementations(this MethodDefinitionHandle handle, MetadataReader reader) + public static ImmutableArray GetMethodImplementations( + this MethodDefinitionHandle handle, MetadataReader reader) { var resultBuilder = ImmutableArray.CreateBuilder(); - var typeDefinition = reader.GetTypeDefinition(reader.GetMethodDefinition(handle).GetDeclaringType()); + var typeDefinition = reader.GetTypeDefinition(reader.GetMethodDefinition(handle) + .GetDeclaringType()); - foreach (var methodImplementationHandle in typeDefinition.GetMethodImplementations()) { + foreach (var methodImplementationHandle in typeDefinition.GetMethodImplementations()) + { var methodImplementation = reader.GetMethodImplementation(methodImplementationHandle); - if (methodImplementation.MethodBody == handle) { + if (methodImplementation.MethodBody == handle) + { resultBuilder.Add(methodImplementationHandle); } } diff --git a/ICSharpCode.Decompiler/Semantics/AmbiguousResolveResult.cs b/ICSharpCode.Decompiler/Semantics/AmbiguousResolveResult.cs index a339741e8..51e7435aa 100644 --- a/ICSharpCode.Decompiler/Semantics/AmbiguousResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/AmbiguousResolveResult.cs @@ -28,12 +28,12 @@ namespace ICSharpCode.Decompiler.Semantics public AmbiguousTypeResolveResult(IType type) : base(type) { } - + public override bool IsError { get { return true; } } } - + /// /// Represents an ambiguous field/property/event access. /// @@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.Semantics public AmbiguousMemberResolveResult(ResolveResult targetResult, IMember member) : base(targetResult, member) { } - + public override bool IsError { get { return true; } } diff --git a/ICSharpCode.Decompiler/Semantics/ArrayAccessResolveResult.cs b/ICSharpCode.Decompiler/Semantics/ArrayAccessResolveResult.cs index 5cd5a9a7d..f4a610ab4 100644 --- a/ICSharpCode.Decompiler/Semantics/ArrayAccessResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/ArrayAccessResolveResult.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -30,7 +31,7 @@ namespace ICSharpCode.Decompiler.Semantics { public readonly ResolveResult Array; public readonly IList Indexes; - + public ArrayAccessResolveResult(IType elementType, ResolveResult array, IList indexes) : base(elementType) { if (array == null) @@ -40,10 +41,10 @@ namespace ICSharpCode.Decompiler.Semantics this.Array = array; this.Indexes = indexes; } - + public override IEnumerable GetChildResults() { - return new [] { Array }.Concat(Indexes); + return new[] { Array }.Concat(Indexes); } } } diff --git a/ICSharpCode.Decompiler/Semantics/ArrayCreateResolveResult.cs b/ICSharpCode.Decompiler/Semantics/ArrayCreateResolveResult.cs index 9e4a2e1cb..624fce728 100644 --- a/ICSharpCode.Decompiler/Semantics/ArrayCreateResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/ArrayCreateResolveResult.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -32,13 +33,13 @@ namespace ICSharpCode.Decompiler.Semantics /// Gets the size arguments. /// public readonly IReadOnlyList SizeArguments; - + /// /// Gets the initializer elements. /// This field may be null if no initializer was specified. /// public readonly IReadOnlyList InitializerElements; - + public ArrayCreateResolveResult(IType arrayType, IReadOnlyList sizeArguments, IReadOnlyList initializerElements) : base(arrayType) { @@ -47,7 +48,7 @@ namespace ICSharpCode.Decompiler.Semantics this.SizeArguments = sizeArguments; this.InitializerElements = initializerElements; } - + public override IEnumerable GetChildResults() { if (InitializerElements != null) diff --git a/ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs b/ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs index bbb525ca3..97918b33a 100644 --- a/ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -34,23 +35,23 @@ namespace ICSharpCode.Decompiler.Semantics public bool IsIn => ReferenceKind == ReferenceKind.In; public readonly ResolveResult ElementResult; - + public ByReferenceResolveResult(ResolveResult elementResult, ReferenceKind kind) : this(elementResult.Type, kind) { this.ElementResult = elementResult; } - + public ByReferenceResolveResult(IType elementType, ReferenceKind kind) : base(new ByReferenceType(elementType)) { this.ReferenceKind = kind; } - + public IType ElementType { get { return ((ByReferenceType)this.Type).ElementType; } } - + public override IEnumerable GetChildResults() { if (ElementResult != null) @@ -58,7 +59,7 @@ namespace ICSharpCode.Decompiler.Semantics else return Enumerable.Empty(); } - + public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "[{0} {1} {2}]", GetType().Name, ReferenceKind.ToString().ToLowerInvariant(), ElementType); diff --git a/ICSharpCode.Decompiler/Semantics/ConstantResolveResult.cs b/ICSharpCode.Decompiler/Semantics/ConstantResolveResult.cs index 7efacf6db..d475de1ae 100644 --- a/ICSharpCode.Decompiler/Semantics/ConstantResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/ConstantResolveResult.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Globalization; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -32,20 +33,20 @@ namespace ICSharpCode.Decompiler.Semantics 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(CultureInfo.InvariantCulture, "[{0} {1} = {2}]", GetType().Name, this.Type, constantValue); diff --git a/ICSharpCode.Decompiler/Semantics/Conversion.cs b/ICSharpCode.Decompiler/Semantics/Conversion.cs index 030f7bde9..a92735b4f 100644 --- a/ICSharpCode.Decompiler/Semantics/Conversion.cs +++ b/ICSharpCode.Decompiler/Semantics/Conversion.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Immutable; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -33,41 +34,41 @@ namespace ICSharpCode.Decompiler.Semantics /// Not a valid conversion. /// public static readonly Conversion None = new InvalidConversion(); - + /// /// Identity conversion. /// public static readonly Conversion IdentityConversion = new BuiltinConversion(true, 0); - + public static readonly Conversion ImplicitNumericConversion = new NumericOrEnumerationConversion(true, false); public static readonly Conversion ExplicitNumericConversion = new NumericOrEnumerationConversion(false, false); public static readonly Conversion ImplicitLiftedNumericConversion = new NumericOrEnumerationConversion(true, true); public static readonly Conversion ExplicitLiftedNumericConversion = new NumericOrEnumerationConversion(false, true); - + public static Conversion EnumerationConversion(bool isImplicit, bool isLifted) { return new NumericOrEnumerationConversion(isImplicit, isLifted, true); } - + public static readonly Conversion NullLiteralConversion = new BuiltinConversion(true, 1); - + /// /// The numeric conversion of a constant expression. /// public static readonly Conversion ImplicitConstantExpressionConversion = new BuiltinConversion(true, 2); - + public static readonly Conversion ImplicitReferenceConversion = new BuiltinConversion(true, 3); public static readonly Conversion ExplicitReferenceConversion = new BuiltinConversion(false, 3); - + public static readonly Conversion ImplicitDynamicConversion = new BuiltinConversion(true, 4); public static readonly Conversion ExplicitDynamicConversion = new BuiltinConversion(false, 4); - + public static readonly Conversion ImplicitNullableConversion = new BuiltinConversion(true, 5); public static readonly Conversion ExplicitNullableConversion = new BuiltinConversion(false, 5); - + public static readonly Conversion ImplicitPointerConversion = new BuiltinConversion(true, 6); public static readonly Conversion ExplicitPointerConversion = new BuiltinConversion(false, 6); - + public static readonly Conversion BoxingConversion = new BuiltinConversion(true, 7); public static readonly Conversion UnboxingConversion = new BuiltinConversion(false, 8); @@ -92,14 +93,14 @@ namespace ICSharpCode.Decompiler.Semantics throw new ArgumentNullException(nameof(operatorMethod)); return new UserDefinedConv(isImplicit, operatorMethod, conversionBeforeUserDefinedOperator, conversionAfterUserDefinedOperator, isLifted, isAmbiguous); } - + public static Conversion MethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument) { if (chosenMethod == null) throw new ArgumentNullException(nameof(chosenMethod)); return new MethodGroupConv(chosenMethod, isVirtualMethodLookup, delegateCapturesFirstArgument, isValid: true); } - + public static Conversion InvalidMethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument) { if (chosenMethod == null) @@ -112,53 +113,53 @@ namespace ICSharpCode.Decompiler.Semantics return new TupleConv(conversions); } #endregion - + #region Inner classes sealed class InvalidConversion : Conversion { public override bool IsValid { get { return false; } } - + public override string ToString() { return "None"; } } - + sealed class NumericOrEnumerationConversion : Conversion { readonly bool isImplicit; readonly bool isLifted; readonly bool isEnumeration; - + public NumericOrEnumerationConversion(bool isImplicit, bool isLifted, bool isEnumeration = false) { this.isImplicit = isImplicit; this.isLifted = isLifted; this.isEnumeration = isEnumeration; } - + public override bool IsImplicit { get { return isImplicit; } } - + public override bool IsExplicit { get { return !isImplicit; } } - + public override bool IsNumericConversion { get { return !isEnumeration; } } - + public override bool IsEnumerationConversion { get { return isEnumeration; } } - + public override bool IsLifted { get { return isLifted; } } - + public override string ToString() { return (isImplicit ? "implicit" : "explicit") @@ -166,46 +167,46 @@ namespace ICSharpCode.Decompiler.Semantics + (isEnumeration ? " enumeration" : " numeric") + " conversion"; } - + public override bool Equals(Conversion other) { NumericOrEnumerationConversion o = other as NumericOrEnumerationConversion; return o != null && isImplicit == o.isImplicit && isLifted == o.isLifted && isEnumeration == o.isEnumeration; } - + public override int GetHashCode() { return (isImplicit ? 1 : 0) + (isLifted ? 2 : 0) + (isEnumeration ? 4 : 0); } } - + sealed class BuiltinConversion : Conversion { readonly bool isImplicit; readonly byte type; - + public BuiltinConversion(bool isImplicit, byte type) { this.isImplicit = isImplicit; this.type = type; } - + public override bool IsImplicit { get { return isImplicit; } } - + public override bool IsExplicit { get { return !isImplicit; } } - + public override bool IsIdentityConversion { get { return type == 0; } } - + public override bool IsNullLiteralConversion { get { return type == 1; } } - + public override bool IsConstantExpressionConversion { get { return type == 2; } } @@ -213,41 +214,42 @@ namespace ICSharpCode.Decompiler.Semantics public override bool IsReferenceConversion { get { return type == 3; } } - + public override bool IsDynamicConversion { get { return type == 4; } } - + public override bool IsNullableConversion { get { return type == 5; } } - + public override bool IsPointerConversion { get { return type == 6; } } - + public override bool IsBoxingConversion { get { return type == 7; } } - + public override bool IsUnboxingConversion { get { return type == 8; } } - + public override bool IsTryCast { get { return type == 9; } } public override bool IsInterpolatedStringConversion => type == 10; - + public override bool IsThrowExpressionConversion { get { return type == 11; } } - + public override string ToString() { string name = null; - switch (type) { + switch (type) + { case 0: return "identity conversion"; case 1: @@ -281,7 +283,7 @@ namespace ICSharpCode.Decompiler.Semantics return (isImplicit ? "implicit " : "explicit ") + name + " conversion"; } } - + sealed class UserDefinedConv : Conversion { readonly IMethod method; @@ -290,7 +292,7 @@ namespace ICSharpCode.Decompiler.Semantics readonly Conversion conversionAfterUserDefinedOperator; readonly bool isImplicit; readonly bool isValid; - + public UserDefinedConv(bool isImplicit, IMethod method, Conversion conversionBeforeUserDefinedOperator, Conversion conversionAfterUserDefinedOperator, bool isLifted, bool isAmbiguous) { this.method = method; @@ -300,31 +302,31 @@ namespace ICSharpCode.Decompiler.Semantics this.isImplicit = isImplicit; this.isValid = !isAmbiguous; } - + public override bool IsValid { get { return isValid; } } - + public override bool IsImplicit { get { return isImplicit; } } - + public override bool IsExplicit { get { return !isImplicit; } } - + public override bool IsLifted { get { return isLifted; } } - + public override bool IsUserDefined { get { return true; } } - + public override Conversion ConversionBeforeUserDefinedOperator { get { return conversionBeforeUserDefinedOperator; } } - + public override Conversion ConversionAfterUserDefinedOperator { get { return conversionAfterUserDefinedOperator; } } @@ -332,18 +334,18 @@ namespace ICSharpCode.Decompiler.Semantics public override IMethod Method { get { return method; } } - + public override bool Equals(Conversion other) { UserDefinedConv o = other as UserDefinedConv; return o != null && isLifted == o.isLifted && isImplicit == o.isImplicit && isValid == o.isValid && method.Equals(o.method); } - + public override int GetHashCode() { return unchecked(method.GetHashCode() + (isLifted ? 31 : 27) + (isImplicit ? 71 : 61) + (isValid ? 107 : 109)); } - + public override string ToString() { return (isImplicit ? "implicit" : "explicit") @@ -352,14 +354,14 @@ namespace ICSharpCode.Decompiler.Semantics + "user-defined conversion (" + method + ")"; } } - + sealed class MethodGroupConv : Conversion { readonly IMethod method; readonly bool isVirtualMethodLookup; readonly bool delegateCapturesFirstArgument; readonly bool isValid; - + public MethodGroupConv(IMethod method, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument, bool isValid) { this.method = method; @@ -367,23 +369,23 @@ namespace ICSharpCode.Decompiler.Semantics this.delegateCapturesFirstArgument = delegateCapturesFirstArgument; this.isValid = isValid; } - + public override bool IsValid { get { return isValid; } } - + public override bool IsImplicit { get { return true; } } - + public override bool IsMethodGroupConversion { get { return true; } } - + public override bool IsVirtualMethodLookup { get { return isVirtualMethodLookup; } } - + public override bool DelegateCapturesFirstArgument { get { return delegateCapturesFirstArgument; } } @@ -391,19 +393,19 @@ namespace ICSharpCode.Decompiler.Semantics public override IMethod Method { get { return method; } } - + public override bool Equals(Conversion other) { MethodGroupConv o = other as MethodGroupConv; return o != null && method.Equals(o.method); } - + public override int GetHashCode() { return method.GetHashCode(); } } - + sealed class TupleConv : Conversion { public override bool IsImplicit { get; } @@ -425,9 +427,11 @@ namespace ICSharpCode.Decompiler.Semantics public override int GetHashCode() { - unchecked { + unchecked + { int hash = 0; - foreach (var conv in ElementConversions) { + foreach (var conv in ElementConversions) + { hash *= 31; hash += conv.GetHashCode(); } @@ -441,22 +445,22 @@ namespace ICSharpCode.Decompiler.Semantics } } #endregion - + /// /// Gets whether the conversion is valid. /// public virtual bool IsValid { get { return true; } } - + public virtual bool IsImplicit { get { return false; } } - + public virtual bool IsExplicit { get { return false; } } - + /// /// Gets whether the conversion is an 'as' cast. /// @@ -471,11 +475,11 @@ namespace ICSharpCode.Decompiler.Semantics public virtual bool IsIdentityConversion { get { return false; } } - + public virtual bool IsNullLiteralConversion { get { return false; } } - + public virtual bool IsConstantExpressionConversion { get { return false; } } @@ -483,35 +487,35 @@ namespace ICSharpCode.Decompiler.Semantics public virtual bool IsNumericConversion { get { return false; } } - + /// /// Gets whether this conversion is a lifted version of another conversion. /// public virtual bool IsLifted { get { return false; } } - + /// /// Gets whether the conversion is dynamic. /// public virtual bool IsDynamicConversion { get { return false; } } - + /// /// Gets whether the conversion is a reference conversion. /// public virtual bool IsReferenceConversion { get { return false; } } - + /// /// Gets whether the conversion is an enumeration conversion. /// public virtual bool IsEnumerationConversion { get { return false; } } - + /// /// Gets whether the conversion is a nullable conversion /// (conversion between a nullable type and the regular type). @@ -533,7 +537,7 @@ namespace ICSharpCode.Decompiler.Semantics public virtual Conversion ConversionBeforeUserDefinedOperator { get { return null; } } - + /// /// The conversion that is applied to the result of the user-defined conversion operator. /// @@ -547,35 +551,35 @@ namespace ICSharpCode.Decompiler.Semantics public virtual bool IsBoxingConversion { get { return false; } } - + /// /// Gets whether this conversion is an unboxing conversion. /// public virtual bool IsUnboxingConversion { get { return false; } } - + /// /// Gets whether this conversion is a pointer conversion. /// public virtual bool IsPointerConversion { get { return false; } } - + /// /// Gets whether this conversion is a method group conversion. /// public virtual bool IsMethodGroupConversion { get { return false; } } - + /// /// For method-group conversions, gets whether to perform a virtual method lookup at runtime. /// public virtual bool IsVirtualMethodLookup { get { return false; } } - + /// /// For method-group conversions, gets whether the conversion captures the first argument. /// @@ -592,7 +596,7 @@ namespace ICSharpCode.Decompiler.Semantics public virtual bool IsAnonymousFunctionConversion { get { return false; } } - + /// /// Gets the method associated with this conversion. /// For user-defined conversions, this is the method being called. @@ -621,12 +625,12 @@ namespace ICSharpCode.Decompiler.Semantics { return Equals(obj as Conversion); } - + public override int GetHashCode() { return base.GetHashCode(); } - + public virtual bool Equals(Conversion other) { return this == other; diff --git a/ICSharpCode.Decompiler/Semantics/ConversionResolveResult.cs b/ICSharpCode.Decompiler/Semantics/ConversionResolveResult.cs index 388119b53..ad3b939a5 100644 --- a/ICSharpCode.Decompiler/Semantics/ConversionResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/ConversionResolveResult.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -32,12 +33,12 @@ namespace ICSharpCode.Decompiler.Semantics { public readonly ResolveResult Input; public readonly Conversion Conversion; - + /// /// For numeric conversions, specifies whether overflow checking is enabled. /// public readonly bool CheckForOverflow; - + public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion) : base(targetType) { @@ -48,20 +49,20 @@ namespace ICSharpCode.Decompiler.Semantics this.Input = input; this.Conversion = conversion; } - + public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion, bool checkForOverflow) : this(targetType, input, conversion) { this.CheckForOverflow = checkForOverflow; } - + public override bool IsError { get { return !Conversion.IsValid; } } - + public override IEnumerable GetChildResults() { - return new [] { Input }; + return new[] { Input }; } } diff --git a/ICSharpCode.Decompiler/Semantics/ErrorResolveResult.cs b/ICSharpCode.Decompiler/Semantics/ErrorResolveResult.cs index de993c555..271e62ad0 100644 --- a/ICSharpCode.Decompiler/Semantics/ErrorResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/ErrorResolveResult.cs @@ -34,23 +34,23 @@ namespace ICSharpCode.Decompiler.Semantics /// Gets an ErrorResolveResult instance with Type = SpecialType.UnknownType. /// public static readonly ErrorResolveResult UnknownError = new ErrorResolveResult(SpecialType.UnknownType); - + public ErrorResolveResult(IType type) : base(type) { } - + public ErrorResolveResult(IType type, string message, TextLocation location) : base(type) { this.Message = message; this.Location = location; } - + public override bool IsError { get { return true; } } - + public string Message { get; private set; } - + public TextLocation Location { get; private set; } } } diff --git a/ICSharpCode.Decompiler/Semantics/ForEachResolveResult.cs b/ICSharpCode.Decompiler/Semantics/ForEachResolveResult.cs index 5e8e30529..fb4edfcec 100644 --- a/ICSharpCode.Decompiler/Semantics/ForEachResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/ForEachResolveResult.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -30,36 +31,36 @@ namespace ICSharpCode.Decompiler.Semantics /// Gets the semantic tree for the call to GetEnumerator. /// public readonly ResolveResult GetEnumeratorCall; - + /// /// Gets the collection type. /// public readonly IType CollectionType; - + /// /// Gets the enumerator type. /// public readonly IType EnumeratorType; - + /// /// Gets the element type. /// This is the type that would be inferred for an implicitly-typed element variable. /// For explicitly-typed element variables, this type may differ from ElementVariable.Type. /// public readonly IType ElementType; - + /// /// Gets the Current property on the IEnumerator. /// Returns null if the property is not found. /// public readonly IProperty CurrentProperty; - + /// /// Gets the MoveNext() method on the IEnumerator. /// Returns null if the method is not found. /// public readonly IMethod MoveNextMethod; - + public ForEachResolveResult(ResolveResult getEnumeratorCall, IType collectionType, IType enumeratorType, IType elementType, IProperty currentProperty, IMethod moveNextMethod, IType voidType) : base(voidType) { diff --git a/ICSharpCode.Decompiler/Semantics/InterpolatedStringResolveResult.cs b/ICSharpCode.Decompiler/Semantics/InterpolatedStringResolveResult.cs index 65f6e0011..a3777ded4 100644 --- a/ICSharpCode.Decompiler/Semantics/InterpolatedStringResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/InterpolatedStringResolveResult.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics diff --git a/ICSharpCode.Decompiler/Semantics/InvocationResolveResult.cs b/ICSharpCode.Decompiler/Semantics/InvocationResolveResult.cs index 495001a9d..1b07b653f 100644 --- a/ICSharpCode.Decompiler/Semantics/InvocationResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/InvocationResolveResult.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -32,7 +33,7 @@ namespace ICSharpCode.Decompiler.Semantics /// Gets the arguments that are being passed to the method, in the order the arguments are being evaluated. /// public readonly IList Arguments; - + /// /// Gets the list of initializer statements that are appplied to the result of this invocation. /// This is used to represent object and collection initializers. @@ -40,32 +41,32 @@ namespace ICSharpCode.Decompiler.Semantics /// to refer to the result of this invocation. /// public readonly IList InitializerStatements; - + public InvocationResolveResult(ResolveResult targetResult, IParameterizedMember member, - IList arguments = null, - IList initializerStatements = null, - IType returnTypeOverride = null) + IList arguments = null, + IList initializerStatements = null, + IType returnTypeOverride = null) : base(targetResult, member, returnTypeOverride) { this.Arguments = arguments ?? EmptyList.Instance; this.InitializerStatements = initializerStatements ?? EmptyList.Instance; } - + public new IParameterizedMember Member { get { return (IParameterizedMember)base.Member; } } - + /// /// Gets the arguments in the order they are being passed to the method. /// For parameter arrays (params), this will return an ArrayCreateResolveResult. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", - Justification = "Derived methods may be expensive and create new lists")] + Justification = "Derived methods may be expensive and create new lists")] public virtual IList GetArgumentsForCall() { return Arguments; } - + public override IEnumerable GetChildResults() { return base.GetChildResults().Concat(this.Arguments).Concat(this.InitializerStatements); diff --git a/ICSharpCode.Decompiler/Semantics/LocalResolveResult.cs b/ICSharpCode.Decompiler/Semantics/LocalResolveResult.cs index 092746fda..ac8be7989 100644 --- a/ICSharpCode.Decompiler/Semantics/LocalResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/LocalResolveResult.cs @@ -18,6 +18,7 @@ using System; using System.Globalization; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -28,42 +29,43 @@ namespace ICSharpCode.Decompiler.Semantics public class LocalResolveResult : ResolveResult { readonly IVariable variable; - + public LocalResolveResult(IVariable variable) : base(UnpackTypeIfByRefParameter(variable)) { this.variable = variable; } - + static IType UnpackTypeIfByRefParameter(IVariable variable) { if (variable == null) throw new ArgumentNullException(nameof(variable)); IType type = variable.Type; - if (type.Kind == TypeKind.ByReference) { + if (type.Kind == TypeKind.ByReference) + { IParameter p = variable as IParameter; if (p != null && p.ReferenceKind != ReferenceKind.None) 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 IsParameter ? null : variable.GetConstantValue(); } } - + public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "[LocalResolveResult {0}]", variable); diff --git a/ICSharpCode.Decompiler/Semantics/MemberResolveResult.cs b/ICSharpCode.Decompiler/Semantics/MemberResolveResult.cs index 0953f9f06..358a84386 100644 --- a/ICSharpCode.Decompiler/Semantics/MemberResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/MemberResolveResult.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -35,7 +36,7 @@ namespace ICSharpCode.Decompiler.Semantics readonly object constantValue; readonly ResolveResult targetResult; readonly bool isVirtualCall; - + public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnTypeOverride = null) : base(returnTypeOverride ?? ComputeType(member)) { @@ -43,15 +44,16 @@ namespace ICSharpCode.Decompiler.Semantics this.member = member; var thisRR = targetResult as ThisResolveResult; this.isVirtualCall = member.IsOverridable && !(thisRR != null && thisRR.CausesNonVirtualInvocation); - + IField field = member as IField; - if (field != null) { + if (field != null) + { isConstant = field.IsConst; if (isConstant) constantValue = field.GetConstantValue(); } } - + public MemberResolveResult(ResolveResult targetResult, IMember member, bool isVirtualCall, IType returnTypeOverride = null) : base(returnTypeOverride ?? ComputeType(member)) { @@ -59,16 +61,18 @@ namespace ICSharpCode.Decompiler.Semantics this.member = member; this.isVirtualCall = isVirtualCall; IField field = member as IField; - if (field != null) { + if (field != null) + { isConstant = field.IsConst; if (isConstant) constantValue = field.GetConstantValue(); } } - + static IType ComputeType(IMember member) { - switch (member.SymbolKind) { + switch (member.SymbolKind) + { case SymbolKind.Constructor: return member.DeclaringType ?? SpecialType.UnknownType; case SymbolKind.Field: @@ -80,7 +84,7 @@ namespace ICSharpCode.Decompiler.Semantics return ((ByReferenceType)member.ReturnType).ElementType; return member.ReturnType; } - + public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType, bool isConstant, object constantValue) : base(returnType) { @@ -89,7 +93,7 @@ namespace ICSharpCode.Decompiler.Semantics this.isConstant = isConstant; this.constantValue = constantValue; } - + public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType, bool isConstant, object constantValue, bool isVirtualCall) : base(returnType) { @@ -99,11 +103,11 @@ namespace ICSharpCode.Decompiler.Semantics this.constantValue = constantValue; this.isVirtualCall = isVirtualCall; } - + public ResolveResult TargetResult { get { return targetResult; } } - + /// /// Gets the member. /// This property never returns null. @@ -111,22 +115,22 @@ namespace ICSharpCode.Decompiler.Semantics public IMember Member { get { return member; } } - + /// /// Gets whether this MemberResolveResult is a virtual call. /// public bool IsVirtualCall { get { return isVirtualCall; } } - + public override bool IsCompileTimeConstant { get { return isConstant; } } - + public override object ConstantValue { get { return constantValue; } } - + public override IEnumerable GetChildResults() { if (targetResult != null) @@ -134,7 +138,7 @@ namespace ICSharpCode.Decompiler.Semantics else return Enumerable.Empty(); } - + public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "[{0} {1}]", GetType().Name, member); diff --git a/ICSharpCode.Decompiler/Semantics/NamedArgumentResolveResult.cs b/ICSharpCode.Decompiler/Semantics/NamedArgumentResolveResult.cs index b988c862a..10f6d488f 100644 --- a/ICSharpCode.Decompiler/Semantics/NamedArgumentResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/NamedArgumentResolveResult.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -32,23 +33,23 @@ namespace ICSharpCode.Decompiler.Semantics /// This field can be null. /// public readonly IParameterizedMember Member; - + /// /// Gets the parameter. /// This field can be null. /// public readonly IParameter Parameter; - + /// /// Gets the parameter name. /// public readonly string ParameterName; - + /// /// Gets the argument passed to the parameter. /// public readonly ResolveResult Argument; - + public NamedArgumentResolveResult(IParameter parameter, ResolveResult argument, IParameterizedMember member = null) : base(argument.Type) { @@ -61,7 +62,7 @@ namespace ICSharpCode.Decompiler.Semantics this.ParameterName = parameter.Name; this.Argument = argument; } - + public NamedArgumentResolveResult(string parameterName, ResolveResult argument) : base(argument.Type) { @@ -72,10 +73,10 @@ namespace ICSharpCode.Decompiler.Semantics this.ParameterName = parameterName; this.Argument = argument; } - + public override IEnumerable GetChildResults() { - return new [] { Argument }; + return new[] { Argument }; } } } diff --git a/ICSharpCode.Decompiler/Semantics/NamespaceResolveResult.cs b/ICSharpCode.Decompiler/Semantics/NamespaceResolveResult.cs index f3891e297..f4df33c22 100644 --- a/ICSharpCode.Decompiler/Semantics/NamespaceResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/NamespaceResolveResult.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Globalization; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -27,20 +28,20 @@ namespace ICSharpCode.Decompiler.Semantics public class NamespaceResolveResult : ResolveResult { readonly INamespace ns; - + public NamespaceResolveResult(INamespace ns) : base(SpecialType.NoType) { this.ns = ns; } - + public INamespace Namespace { get { return ns; } } - + public string NamespaceName { get { return ns.FullName; } } - + public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "[{0} {1}]", GetType().Name, ns); diff --git a/ICSharpCode.Decompiler/Semantics/OperatorResolveResult.cs b/ICSharpCode.Decompiler/Semantics/OperatorResolveResult.cs index af5318c18..cd54d315e 100644 --- a/ICSharpCode.Decompiler/Semantics/OperatorResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/OperatorResolveResult.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -32,7 +33,7 @@ namespace ICSharpCode.Decompiler.Semantics readonly IMethod userDefinedOperatorMethod; readonly IList operands; readonly bool isLiftedOperator; - + public OperatorResolveResult(IType resultType, ExpressionType operatorType, params ResolveResult[] operands) : base(resultType) { @@ -41,7 +42,7 @@ namespace ICSharpCode.Decompiler.Semantics this.operatorType = operatorType; this.operands = operands; } - + public OperatorResolveResult(IType resultType, ExpressionType operatorType, IMethod userDefinedOperatorMethod, bool isLiftedOperator, IList operands) : base(resultType) { @@ -52,21 +53,21 @@ namespace ICSharpCode.Decompiler.Semantics this.isLiftedOperator = isLiftedOperator; this.operands = operands; } - + /// /// Gets the operator type. /// public ExpressionType OperatorType { get { return operatorType; } } - + /// /// Gets the operands. /// public IList Operands { get { return operands; } } - + /// /// Gets the user defined operator method. /// Returns null if this is a predefined operator. @@ -74,14 +75,14 @@ namespace ICSharpCode.Decompiler.Semantics public IMethod UserDefinedOperatorMethod { get { return userDefinedOperatorMethod; } } - + /// /// Gets whether this is a lifted operator. /// public bool IsLiftedOperator { get { return isLiftedOperator; } } - + public override IEnumerable GetChildResults() { return operands; diff --git a/ICSharpCode.Decompiler/Semantics/ResolveResult.cs b/ICSharpCode.Decompiler/Semantics/ResolveResult.cs index 593c83465..6ca0a177a 100644 --- a/ICSharpCode.Decompiler/Semantics/ResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/ResolveResult.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -29,42 +30,42 @@ namespace ICSharpCode.Decompiler.Semantics public class ResolveResult { readonly IType type; - + public ResolveResult(IType type) { if (type == null) throw new ArgumentNullException(nameof(type)); this.type = type; } - + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", - Justification = "Unrelated to object.GetType()")] + Justification = "Unrelated to object.GetType()")] 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 ResolveResult ShallowClone() { return (ResolveResult)MemberwiseClone(); diff --git a/ICSharpCode.Decompiler/Semantics/SizeOfResolveResult.cs b/ICSharpCode.Decompiler/Semantics/SizeOfResolveResult.cs index 34306afd8..48bbdc2f1 100644 --- a/ICSharpCode.Decompiler/Semantics/SizeOfResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/SizeOfResolveResult.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -28,7 +29,7 @@ namespace ICSharpCode.Decompiler.Semantics { readonly IType referencedType; readonly int? constantValue; - + public SizeOfResolveResult(IType int32, IType referencedType, int? constantValue) : base(int32) { @@ -37,7 +38,7 @@ namespace ICSharpCode.Decompiler.Semantics this.referencedType = referencedType; this.constantValue = constantValue; } - + /// /// The type referenced by the 'sizeof'. /// diff --git a/ICSharpCode.Decompiler/Semantics/ThisResolveResult.cs b/ICSharpCode.Decompiler/Semantics/ThisResolveResult.cs index c6de1a744..fa5f0650c 100644 --- a/ICSharpCode.Decompiler/Semantics/ThisResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/ThisResolveResult.cs @@ -27,12 +27,12 @@ namespace ICSharpCode.Decompiler.Semantics public class ThisResolveResult : ResolveResult { bool causesNonVirtualInvocation; - + public ThisResolveResult(IType type, bool causesNonVirtualInvocation = false) : base(type) { this.causesNonVirtualInvocation = causesNonVirtualInvocation; } - + /// /// Gets whether this resolve result causes member invocations to be non-virtual. /// diff --git a/ICSharpCode.Decompiler/Semantics/TupleResolveResult.cs b/ICSharpCode.Decompiler/Semantics/TupleResolveResult.cs index b93334d4e..59923dff4 100644 --- a/ICSharpCode.Decompiler/Semantics/TupleResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/TupleResolveResult.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; diff --git a/ICSharpCode.Decompiler/Semantics/TypeIsResolveResult.cs b/ICSharpCode.Decompiler/Semantics/TypeIsResolveResult.cs index 2d6b57e60..5d591c2d3 100644 --- a/ICSharpCode.Decompiler/Semantics/TypeIsResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/TypeIsResolveResult.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -32,7 +33,7 @@ namespace ICSharpCode.Decompiler.Semantics /// Type that is being compared with. /// public readonly IType TargetType; - + public TypeIsResolveResult(ResolveResult input, IType targetType, IType booleanType) : base(booleanType) { diff --git a/ICSharpCode.Decompiler/Semantics/TypeOfResolveResult.cs b/ICSharpCode.Decompiler/Semantics/TypeOfResolveResult.cs index b274558b5..2452bdf18 100644 --- a/ICSharpCode.Decompiler/Semantics/TypeOfResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/TypeOfResolveResult.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -27,7 +28,7 @@ namespace ICSharpCode.Decompiler.Semantics public class TypeOfResolveResult : ResolveResult { readonly IType referencedType; - + public TypeOfResolveResult(IType systemType, IType referencedType) : base(systemType) { @@ -35,7 +36,7 @@ namespace ICSharpCode.Decompiler.Semantics throw new ArgumentNullException(nameof(referencedType)); this.referencedType = referencedType; } - + /// /// The type referenced by the 'typeof'. /// diff --git a/ICSharpCode.Decompiler/Semantics/TypeResolveResult.cs b/ICSharpCode.Decompiler/Semantics/TypeResolveResult.cs index 8d54caa43..651033d1d 100644 --- a/ICSharpCode.Decompiler/Semantics/TypeResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/TypeResolveResult.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.Semantics : base(type) { } - + public override bool IsError { get { return this.Type.Kind == TypeKind.Unknown; } } diff --git a/ICSharpCode.Decompiler/Semantics/UnknownMemberResolveResult.cs b/ICSharpCode.Decompiler/Semantics/UnknownMemberResolveResult.cs index 0040caded..0a4d0d3ec 100644 --- a/ICSharpCode.Decompiler/Semantics/UnknownMemberResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/UnknownMemberResolveResult.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.Semantics @@ -33,7 +34,7 @@ namespace ICSharpCode.Decompiler.Semantics readonly IType targetType; readonly string memberName; readonly ReadOnlyCollection typeArguments; - + public UnknownMemberResolveResult(IType targetType, string memberName, IEnumerable typeArguments) : base(SpecialType.UnknownType) { @@ -43,50 +44,50 @@ namespace ICSharpCode.Decompiler.Semantics this.memberName = memberName; this.typeArguments = new ReadOnlyCollection(typeArguments.ToArray()); } - + /// /// The type on which the method is being called. /// public IType TargetType { get { return targetType; } } - + public string MemberName { get { return memberName; } } - + public ReadOnlyCollection TypeArguments { get { return typeArguments; } } - + public override bool IsError { get { return true; } } - + public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "[{0} {1}.{2}]", GetType().Name, targetType, memberName); } } - + /// /// Represents an unknown method. /// public class UnknownMethodResolveResult : UnknownMemberResolveResult { readonly ReadOnlyCollection parameters; - + public UnknownMethodResolveResult(IType targetType, string methodName, IEnumerable typeArguments, IEnumerable parameters) : base(targetType, methodName, typeArguments) { this.parameters = new ReadOnlyCollection(parameters.ToArray()); } - + public ReadOnlyCollection Parameters { get { return parameters; } } } - + /// /// Represents an unknown identifier. /// @@ -94,26 +95,26 @@ namespace ICSharpCode.Decompiler.Semantics { readonly string identifier; readonly int typeArgumentCount; - + public UnknownIdentifierResolveResult(string identifier, int typeArgumentCount = 0) : base(SpecialType.UnknownType) { this.identifier = identifier; this.typeArgumentCount = typeArgumentCount; } - + public string Identifier { get { return identifier; } } - + public int TypeArgumentCount { get { return typeArgumentCount; } } - + public override bool IsError { get { return true; } } - + public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "[{0} {1}]", GetType().Name, identifier); diff --git a/ICSharpCode.Decompiler/Solution/ProjectId.cs b/ICSharpCode.Decompiler/Solution/ProjectId.cs index e067babed..a4dda3da4 100644 --- a/ICSharpCode.Decompiler/Solution/ProjectId.cs +++ b/ICSharpCode.Decompiler/Solution/ProjectId.cs @@ -34,7 +34,8 @@ namespace ICSharpCode.Decompiler.Solution /// Thrown when is null or empty. public ProjectId(string projectPlatform, Guid projectGuid, Guid typeGuid) { - if (string.IsNullOrWhiteSpace(projectPlatform)) { + if (string.IsNullOrWhiteSpace(projectPlatform)) + { throw new ArgumentException("The platform cannot be null or empty.", nameof(projectPlatform)); } diff --git a/ICSharpCode.Decompiler/Solution/SolutionCreator.cs b/ICSharpCode.Decompiler/Solution/SolutionCreator.cs index 1e4d3619b..1619ea8f1 100644 --- a/ICSharpCode.Decompiler/Solution/SolutionCreator.cs +++ b/ICSharpCode.Decompiler/Solution/SolutionCreator.cs @@ -42,19 +42,23 @@ namespace ICSharpCode.Decompiler.Solution /// Thrown when contains no items. public static void WriteSolutionFile(string targetFile, IEnumerable projects) { - if (string.IsNullOrWhiteSpace(targetFile)) { + if (string.IsNullOrWhiteSpace(targetFile)) + { throw new ArgumentException("The target file cannot be null or empty.", nameof(targetFile)); } - if (projects == null) { + if (projects == null) + { throw new ArgumentNullException(nameof(projects)); } - if (!projects.Any()) { + if (!projects.Any()) + { throw new InvalidOperationException("At least one project is expected."); } - using (var writer = new StreamWriter(targetFile)) { + using (var writer = new StreamWriter(targetFile)) + { WriteSolutionFile(writer, projects, targetFile); } @@ -88,7 +92,8 @@ namespace ICSharpCode.Decompiler.Solution private static void WriteProjects(TextWriter writer, IEnumerable projects, string solutionFilePath) { - foreach (var project in projects) { + foreach (var project in projects) + { var projectRelativePath = GetRelativePath(solutionFilePath, project.FilePath); var typeGuid = project.TypeGuid.ToString("B").ToUpperInvariant(); var projectGuid = project.Guid.ToString("B").ToUpperInvariant(); @@ -105,11 +110,13 @@ namespace ICSharpCode.Decompiler.Solution platforms.Sort(); writer.WriteLine("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"); - foreach (var platform in platforms) { + foreach (var platform in platforms) + { writer.WriteLine($"\t\tDebug|{platform} = Debug|{platform}"); } - foreach (var platform in platforms) { + foreach (var platform in platforms) + { writer.WriteLine($"\t\tRelease|{platform} = Release|{platform}"); } @@ -125,15 +132,18 @@ namespace ICSharpCode.Decompiler.Solution { writer.WriteLine("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); - foreach (var project in projects) { + foreach (var project in projects) + { var projectGuid = project.Guid.ToString("B").ToUpperInvariant(); - foreach (var platform in solutionPlatforms) { + foreach (var platform in solutionPlatforms) + { writer.WriteLine($"\t\t{projectGuid}.Debug|{platform}.ActiveCfg = Debug|{project.PlatformName}"); writer.WriteLine($"\t\t{projectGuid}.Debug|{platform}.Build.0 = Debug|{project.PlatformName}"); } - foreach (var platform in solutionPlatforms) { + foreach (var platform in solutionPlatforms) + { writer.WriteLine($"\t\t{projectGuid}.Release|{platform}.ActiveCfg = Release|{project.PlatformName}"); writer.WriteLine($"\t\t{projectGuid}.Release|{platform}.Build.0 = Release|{project.PlatformName}"); } @@ -146,14 +156,16 @@ namespace ICSharpCode.Decompiler.Solution { var projectsMap = projects.ToDictionary(p => p.ProjectName, p => p); - foreach (var project in projects) { + foreach (var project in projects) + { XDocument projectDoc = XDocument.Load(project.FilePath); var referencesItemGroups = projectDoc.Root .Elements(ProjectFileNamespace + "ItemGroup") .Where(e => e.Elements(ProjectFileNamespace + "Reference").Any()); - foreach (var itemGroup in referencesItemGroups) { + foreach (var itemGroup in referencesItemGroups) + { FixProjectReferences(project.FilePath, itemGroup, projectsMap); } @@ -163,9 +175,11 @@ namespace ICSharpCode.Decompiler.Solution private static void FixProjectReferences(string projectFilePath, XElement itemGroup, IDictionary projects) { - foreach (var item in itemGroup.Elements(ProjectFileNamespace + "Reference").ToList()) { + foreach (var item in itemGroup.Elements(ProjectFileNamespace + "Reference").ToList()) + { var assemblyName = item.Attribute("Include")?.Value; - if (assemblyName != null && projects.TryGetValue(assemblyName, out var referencedProject)) { + if (assemblyName != null && projects.TryGetValue(assemblyName, out var referencedProject)) + { item.Remove(); var projectReference = new XElement(ProjectFileNamespace + "ProjectReference", @@ -183,14 +197,16 @@ namespace ICSharpCode.Decompiler.Solution Uri fromUri = new Uri(fromFilePath); Uri toUri = new Uri(toFilePath); - if (fromUri.Scheme != toUri.Scheme) { + if (fromUri.Scheme != toUri.Scheme) + { return toFilePath; } Uri relativeUri = fromUri.MakeRelativeUri(toUri); string relativePath = Uri.UnescapeDataString(relativeUri.ToString()); - if (string.Equals(toUri.Scheme, Uri.UriSchemeFile, StringComparison.OrdinalIgnoreCase)) { + if (string.Equals(toUri.Scheme, Uri.UriSchemeFile, StringComparison.OrdinalIgnoreCase)) + { relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); } diff --git a/ICSharpCode.Decompiler/TypeSystem/Accessibility.cs b/ICSharpCode.Decompiler/TypeSystem/Accessibility.cs index 25091ddc8..8c5035bdf 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Accessibility.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Accessibility.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Diagnostics; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem @@ -87,12 +88,16 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static Accessibility Intersect(this Accessibility a, Accessibility b) { - if (a > b) { + if (a > b) + { ExtensionMethods.Swap(ref a, ref b); } - if (a == Accessibility.Protected && b == Accessibility.Internal) { + if (a == Accessibility.Protected && b == Accessibility.Internal) + { return Accessibility.ProtectedAndInternal; - } else { + } + else + { Debug.Assert(!(a == Accessibility.Internal && b == Accessibility.Protected)); return a; } @@ -105,12 +110,16 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static Accessibility Union(this Accessibility a, Accessibility b) { - if (a > b) { + if (a > b) + { ExtensionMethods.Swap(ref a, ref b); } - if (a == Accessibility.Protected && b == Accessibility.Internal) { + if (a == Accessibility.Protected && b == Accessibility.Internal) + { return Accessibility.ProtectedOrInternal; - } else { + } + else + { Debug.Assert(!(a == Accessibility.Internal && b == Accessibility.Protected)); return b; } @@ -123,7 +132,8 @@ namespace ICSharpCode.Decompiler.TypeSystem public static Accessibility EffectiveAccessibility(this IEntity entity) { Accessibility accessibility = entity.Accessibility; - for (ITypeDefinition typeDef = entity.DeclaringTypeDefinition; typeDef != null; typeDef = typeDef.DeclaringTypeDefinition) { + for (ITypeDefinition typeDef = entity.DeclaringTypeDefinition; typeDef != null; typeDef = typeDef.DeclaringTypeDefinition) + { accessibility = Intersect(accessibility, typeDef.Accessibility); } return accessibility; diff --git a/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs b/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs index b024d4620..367e43b4b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs @@ -20,8 +20,10 @@ using System; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; + using SRM = System.Reflection.Metadata; namespace ICSharpCode.Decompiler.TypeSystem @@ -47,60 +49,82 @@ namespace ICSharpCode.Decompiler.TypeSystem string[] tupleElementNames = null; Nullability nullability; Nullability[] nullableAttributeData = null; - if ((options & TypeSystemOptions.NullabilityAnnotations) != 0) { + if ((options & TypeSystemOptions.NullabilityAnnotations) != 0) + { nullability = nullableContext; - } else { + } + else + { nullability = Nullability.Oblivious; } const TypeSystemOptions relevantOptions = TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple | TypeSystemOptions.NullabilityAnnotations | TypeSystemOptions.NativeIntegers; - if (attributes != null && (options & relevantOptions) != 0) { - foreach (var attrHandle in attributes.Value) { + if (attributes != null && (options & relevantOptions) != 0) + { + foreach (var attrHandle in attributes.Value) + { var attr = metadata.GetCustomAttribute(attrHandle); var attrType = attr.GetAttributeType(metadata); - if ((options & TypeSystemOptions.Dynamic) != 0 && attrType.IsKnownType(metadata, KnownAttribute.Dynamic)) { + if ((options & TypeSystemOptions.Dynamic) != 0 && attrType.IsKnownType(metadata, KnownAttribute.Dynamic)) + { hasDynamicAttribute = true; var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider); - if (ctor.FixedArguments.Length == 1) { + if (ctor.FixedArguments.Length == 1) + { var arg = ctor.FixedArguments[0]; if (arg.Value is ImmutableArray> values - && values.All(v => v.Value is bool)) { + && values.All(v => v.Value is bool)) + { dynamicAttributeData = values.SelectArray(v => (bool)v.Value); } } - } else if ((options & TypeSystemOptions.NativeIntegers) != 0 && attrType.IsKnownType(metadata, KnownAttribute.NativeInteger)) { + } + else if ((options & TypeSystemOptions.NativeIntegers) != 0 && attrType.IsKnownType(metadata, KnownAttribute.NativeInteger)) + { hasNativeIntegersAttribute = true; var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider); - if (ctor.FixedArguments.Length == 1) { + if (ctor.FixedArguments.Length == 1) + { var arg = ctor.FixedArguments[0]; if (arg.Value is ImmutableArray> values - && values.All(v => v.Value is bool)) { + && values.All(v => v.Value is bool)) + { nativeIntegersAttributeData = values.SelectArray(v => (bool)v.Value); } } - } else if ((options & TypeSystemOptions.Tuple) != 0 && attrType.IsKnownType(metadata, KnownAttribute.TupleElementNames)) { + } + else if ((options & TypeSystemOptions.Tuple) != 0 && attrType.IsKnownType(metadata, KnownAttribute.TupleElementNames)) + { var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider); - if (ctor.FixedArguments.Length == 1) { + if (ctor.FixedArguments.Length == 1) + { var arg = ctor.FixedArguments[0]; if (arg.Value is ImmutableArray> values - && values.All(v => v.Value is string || v.Value == null)) { + && values.All(v => v.Value is string || v.Value == null)) + { tupleElementNames = values.SelectArray(v => (string)v.Value); } } - } else if ((options & TypeSystemOptions.NullabilityAnnotations) != 0 && attrType.IsKnownType(metadata, KnownAttribute.Nullable)) { + } + else if ((options & TypeSystemOptions.NullabilityAnnotations) != 0 && attrType.IsKnownType(metadata, KnownAttribute.Nullable)) + { var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider); - if (ctor.FixedArguments.Length == 1) { + if (ctor.FixedArguments.Length == 1) + { var arg = ctor.FixedArguments[0]; if (arg.Value is ImmutableArray> values - && values.All(v => v.Value is byte b && b <= 2)) { + && values.All(v => v.Value is byte b && b <= 2)) + { nullableAttributeData = values.SelectArray(v => (Nullability)(byte)v.Value); - } else if (arg.Value is byte b && b <= 2) { + } + else if (arg.Value is byte b && b <= 2) + { nullability = (Nullability)b; } } } } } - if (hasDynamicAttribute || hasNativeIntegersAttribute || nullability != Nullability.Oblivious || nullableAttributeData != null + if (hasDynamicAttribute || hasNativeIntegersAttribute || nullability != Nullability.Oblivious || nullableAttributeData != null || (options & (TypeSystemOptions.Tuple | TypeSystemOptions.KeepModifiers)) != TypeSystemOptions.KeepModifiers) { var visitor = new ApplyAttributeTypeVisitor( @@ -109,12 +133,17 @@ namespace ICSharpCode.Decompiler.TypeSystem options, tupleElementNames, nullability, nullableAttributeData ); - if (typeChildrenOnly) { + if (typeChildrenOnly) + { return inputType.VisitChildren(visitor); - } else { + } + else + { return inputType.AcceptVisitor(visitor); } - } else { + } + else + { return inputType; } } @@ -132,7 +161,7 @@ namespace ICSharpCode.Decompiler.TypeSystem int tupleTypeIndex = 0; int nullabilityTypeIndex = 0; - private ApplyAttributeTypeVisitor(ICompilation compilation, + private ApplyAttributeTypeVisitor(ICompilation compilation, bool hasDynamicAttribute, bool[] dynamicAttributeData, bool hasNativeIntegersAttribute, bool[] nativeIntegersAttributeData, TypeSystemOptions options, string[] tupleElementNames, @@ -201,11 +230,14 @@ namespace ICSharpCode.Decompiler.TypeSystem public override IType VisitParameterizedType(ParameterizedType type) { bool useTupleTypes = (options & TypeSystemOptions.Tuple) != 0; - if (useTupleTypes && TupleType.IsTupleCompatible(type, out int tupleCardinality)) { - if (tupleCardinality > 1) { + if (useTupleTypes && TupleType.IsTupleCompatible(type, out int tupleCardinality)) + { + if (tupleCardinality > 1) + { var valueTupleAssembly = type.GetDefinition()?.ParentModule; ImmutableArray elementNames = default; - if (tupleElementNames != null && tupleTypeIndex < tupleElementNames.Length) { + if (tupleElementNames != null && tupleTypeIndex < tupleElementNames.Length) + { string[] extractedValues = new string[tupleCardinality]; Array.Copy(tupleElementNames, tupleTypeIndex, extractedValues, 0, Math.Min(tupleCardinality, tupleElementNames.Length - tupleTypeIndex)); @@ -214,23 +246,31 @@ namespace ICSharpCode.Decompiler.TypeSystem tupleTypeIndex += tupleCardinality; ExpectDummyNullabilityForGenericValueType(); var elementTypes = ImmutableArray.CreateBuilder(tupleCardinality); - do { + do + { int normalArgCount = Math.Min(type.TypeArguments.Count, TupleType.RestPosition - 1); - for (int i = 0; i < normalArgCount; i++) { + for (int i = 0; i < normalArgCount; i++) + { dynamicTypeIndex++; elementTypes.Add(type.TypeArguments[i].AcceptVisitor(this)); } - if (type.TypeArguments.Count == TupleType.RestPosition) { + if (type.TypeArguments.Count == TupleType.RestPosition) + { type = type.TypeArguments.Last() as ParameterizedType; ExpectDummyNullabilityForGenericValueType(); dynamicTypeIndex++; - if (type != null && TupleType.IsTupleCompatible(type, out int nestedCardinality)) { + if (type != null && TupleType.IsTupleCompatible(type, out int nestedCardinality)) + { tupleTypeIndex += nestedCardinality; - } else { + } + else + { Debug.Fail("TRest should be another value tuple"); type = null; } - } else { + } + else + { type = null; } } while (type != null); @@ -241,7 +281,9 @@ namespace ICSharpCode.Decompiler.TypeSystem elementNames, valueTupleAssembly ); - } else { + } + else + { // C# doesn't have syntax for tuples of cardinality <= 1 tupleTypeIndex += tupleCardinality; } @@ -249,12 +291,14 @@ namespace ICSharpCode.Decompiler.TypeSystem // Visit generic type and type arguments. // Like base implementation, except that it increments dynamicTypeIndex. var genericType = type.GenericType.AcceptVisitor(this); - if (genericType.IsReferenceType != true && !genericType.IsKnownType(KnownTypeCode.NullableOfT)) { + if (genericType.IsReferenceType != true && !genericType.IsKnownType(KnownTypeCode.NullableOfT)) + { ExpectDummyNullabilityForGenericValueType(); } bool changed = type.GenericType != genericType; var arguments = new IType[type.TypeArguments.Count]; - for (int i = 0; i < type.TypeArguments.Count; i++) { + for (int i = 0; i < type.TypeArguments.Count; i++) + { dynamicTypeIndex++; arguments[i] = type.TypeArguments[i].AcceptVisitor(this); changed = changed || arguments[i] != type.TypeArguments[i]; @@ -268,22 +312,28 @@ namespace ICSharpCode.Decompiler.TypeSystem { IType newType = type; var ktc = type.KnownTypeCode; - if (ktc == KnownTypeCode.Object && hasDynamicAttribute) { + if (ktc == KnownTypeCode.Object && hasDynamicAttribute) + { if (dynamicAttributeData == null || dynamicTypeIndex >= dynamicAttributeData.Length) newType = SpecialType.Dynamic; else if (dynamicAttributeData[dynamicTypeIndex]) newType = SpecialType.Dynamic; - } else if ((ktc == KnownTypeCode.IntPtr || ktc == KnownTypeCode.UIntPtr) && hasNativeIntegersAttribute) { + } + else if ((ktc == KnownTypeCode.IntPtr || ktc == KnownTypeCode.UIntPtr) && hasNativeIntegersAttribute) + { // native integers use the same indexing logic as 'dynamic' if (nativeIntegersAttributeData == null || dynamicTypeIndex > nativeIntegersAttributeData.Length) newType = (ktc == KnownTypeCode.IntPtr ? SpecialType.NInt : SpecialType.NUInt); else if (nativeIntegersAttributeData[dynamicTypeIndex]) newType = (ktc == KnownTypeCode.IntPtr ? SpecialType.NInt : SpecialType.NUInt); } - if (type.IsReferenceType == true) { + if (type.IsReferenceType == true) + { Nullability nullability = GetNullability(); return newType.ChangeNullability(nullability); - } else { + } + else + { return newType; } } @@ -291,7 +341,8 @@ namespace ICSharpCode.Decompiler.TypeSystem public override IType VisitOtherType(IType type) { type = base.VisitOtherType(type); - if (type.Kind == TypeKind.Unknown && type.IsReferenceType == true) { + if (type.Kind == TypeKind.Unknown && type.IsReferenceType == true) + { Nullability nullability = GetNullability(); type = type.ChangeNullability(nullability); } diff --git a/ICSharpCode.Decompiler/TypeSystem/ArrayType.cs b/ICSharpCode.Decompiler/TypeSystem/ArrayType.cs index 4f6fe6e5e..f10da4531 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ArrayType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ArrayType.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; @@ -41,20 +42,20 @@ namespace ICSharpCode.Decompiler.TypeSystem this.compilation = compilation; this.dimensions = dimensions; this.nullability = nullability; - + ICompilationProvider p = elementType as ICompilationProvider; if (p != null && p.Compilation != compilation) throw new InvalidOperationException("Cannot create an array type using a different compilation from the element type."); } - + public override TypeKind Kind { get { return TypeKind.Array; } } - + public ICompilation Compilation { get { return compilation; } } - + public int Dimensions { get { return dimensions; } } @@ -71,19 +72,19 @@ namespace ICSharpCode.Decompiler.TypeSystem public override string NameSuffix { get { - return "[" + new string(',', dimensions-1) + "]"; + return "[" + new string(',', dimensions - 1) + "]"; } } - + public override bool? IsReferenceType { get { return true; } } - + public override int GetHashCode() { return unchecked(elementType.GetHashCode() * 71681 + dimensions); } - + public override bool Equals(IType other) { ArrayType a = other as ArrayType; @@ -92,7 +93,8 @@ namespace ICSharpCode.Decompiler.TypeSystem public override string ToString() { - switch (nullability) { + switch (nullability) + { case Nullability.Nullable: return elementType.ToString() + NameSuffix + "?"; case Nullability.NotNullable: @@ -108,7 +110,8 @@ namespace ICSharpCode.Decompiler.TypeSystem IType t = compilation.FindType(KnownTypeCode.Array); if (t.Kind != TypeKind.Unknown) baseTypes.Add(t); - if (dimensions == 1 && elementType.Kind != TypeKind.Pointer) { + if (dimensions == 1 && elementType.Kind != TypeKind.Pointer) + { // single-dimensional arrays implement IList ITypeDefinition def = compilation.FindType(KnownTypeCode.IListOfT) as ITypeDefinition; if (def != null) @@ -121,7 +124,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return baseTypes; } } - + public override IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) @@ -129,7 +132,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return compilation.FindType(KnownTypeCode.Array).GetMethods(filter, options); } - + public override IEnumerable GetMethods(IReadOnlyList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) @@ -145,7 +148,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return compilation.FindType(KnownTypeCode.Array).GetAccessors(filter, options); } - + public override IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) @@ -153,15 +156,15 @@ namespace ICSharpCode.Decompiler.TypeSystem else return compilation.FindType(KnownTypeCode.Array).GetProperties(filter, options); } - + // NestedTypes, Events, Fields: System.Array doesn't have any; so we can use the AbstractType default implementation // that simply returns an empty list - + public override IType AcceptVisitor(TypeVisitor visitor) { return visitor.VisitArrayType(this); } - + public override IType VisitChildren(TypeVisitor visitor) { IType e = elementType.AcceptVisitor(visitor); @@ -171,13 +174,13 @@ namespace ICSharpCode.Decompiler.TypeSystem return new ArrayType(compilation, e, dimensions, nullability); } } - + [Serializable] public sealed class ArrayTypeReference : ITypeReference, ISupportsInterning { readonly ITypeReference elementType; readonly int dimensions; - + public ArrayTypeReference(ITypeReference elementType, int dimensions = 1) { if (elementType == null) @@ -187,30 +190,30 @@ namespace ICSharpCode.Decompiler.TypeSystem this.elementType = elementType; this.dimensions = dimensions; } - + public ITypeReference ElementType { get { return elementType; } } - + public int Dimensions { get { return dimensions; } } - + public IType Resolve(ITypeResolveContext context) { return new ArrayType(context.Compilation, elementType.Resolve(context), dimensions); } - + public override string ToString() { return elementType.ToString() + "[" + new string(',', dimensions - 1) + "]"; } - + int ISupportsInterning.GetHashCodeForInterning() { return elementType.GetHashCode() ^ dimensions; } - + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { ArrayTypeReference o = other as ArrayTypeReference; diff --git a/ICSharpCode.Decompiler/TypeSystem/AssemblyQualifiedTypeName.cs b/ICSharpCode.Decompiler/TypeSystem/AssemblyQualifiedTypeName.cs index 50d23c8df..2643842f1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/AssemblyQualifiedTypeName.cs +++ b/ICSharpCode.Decompiler/TypeSystem/AssemblyQualifiedTypeName.cs @@ -24,19 +24,19 @@ namespace ICSharpCode.Decompiler.TypeSystem { public readonly string AssemblyName; public readonly FullTypeName TypeName; - + public AssemblyQualifiedTypeName(FullTypeName typeName, string assemblyName) { this.AssemblyName = assemblyName; this.TypeName = typeName; } - + public AssemblyQualifiedTypeName(ITypeDefinition typeDefinition) { this.AssemblyName = typeDefinition.ParentModule.AssemblyName; this.TypeName = typeDefinition.FullTypeName; } - + public override string ToString() { if (string.IsNullOrEmpty(AssemblyName)) @@ -44,33 +44,34 @@ namespace ICSharpCode.Decompiler.TypeSystem else return TypeName.ToString() + ", " + AssemblyName; } - + public override bool Equals(object obj) { return (obj is AssemblyQualifiedTypeName) && Equals((AssemblyQualifiedTypeName)obj); } - + public bool Equals(AssemblyQualifiedTypeName other) { return this.AssemblyName == other.AssemblyName && this.TypeName == other.TypeName; } - + public override int GetHashCode() { int hashCode = 0; - unchecked { + unchecked + { if (AssemblyName != null) hashCode += 1000000007 * AssemblyName.GetHashCode(); hashCode += TypeName.GetHashCode(); } return hashCode; } - + public static bool operator ==(AssemblyQualifiedTypeName lhs, AssemblyQualifiedTypeName rhs) { return lhs.Equals(rhs); } - + public static bool operator !=(AssemblyQualifiedTypeName lhs, AssemblyQualifiedTypeName rhs) { return !lhs.Equals(rhs); diff --git a/ICSharpCode.Decompiler/TypeSystem/ByReferenceType.cs b/ICSharpCode.Decompiler/TypeSystem/ByReferenceType.cs index 6f587b389..1b686012e 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ByReferenceType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ByReferenceType.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -26,17 +27,17 @@ namespace ICSharpCode.Decompiler.TypeSystem public ByReferenceType(IType elementType) : base(elementType) { } - + public override TypeKind Kind { get { return TypeKind.ByReference; } } - + public override string NameSuffix { get { return "&"; } } - + public override bool? IsReferenceType { get { return null; } } @@ -47,18 +48,18 @@ namespace ICSharpCode.Decompiler.TypeSystem { return elementType.GetHashCode() ^ 91725813; } - + public override bool Equals(IType other) { ByReferenceType a = other as ByReferenceType; return a != null && elementType.Equals(a.elementType); } - + public override IType AcceptVisitor(TypeVisitor visitor) { return visitor.VisitByReferenceType(this); } - + public override IType VisitChildren(TypeVisitor visitor) { IType e = elementType.AcceptVisitor(visitor); @@ -68,38 +69,38 @@ namespace ICSharpCode.Decompiler.TypeSystem return new ByReferenceType(e); } } - + [Serializable] public sealed class ByReferenceTypeReference : ITypeReference, ISupportsInterning { readonly ITypeReference elementType; - + public ByReferenceTypeReference(ITypeReference elementType) { if (elementType == null) throw new ArgumentNullException(nameof(elementType)); this.elementType = elementType; } - + public ITypeReference ElementType { get { return elementType; } } - + public IType Resolve(ITypeResolveContext context) { return new ByReferenceType(elementType.Resolve(context)); } - + public override string ToString() { return elementType.ToString() + "&"; } - + int ISupportsInterning.GetHashCodeForInterning() { return elementType.GetHashCode() ^ 91725814; } - + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { ByReferenceTypeReference brt = other as ByReferenceTypeReference; diff --git a/ICSharpCode.Decompiler/TypeSystem/ComHelper.cs b/ICSharpCode.Decompiler/TypeSystem/ComHelper.cs index b0064f746..3ef59ecac 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ComHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ComHelper.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Linq; + using ICSharpCode.Decompiler.Semantics; namespace ICSharpCode.Decompiler.TypeSystem @@ -35,18 +36,19 @@ namespace ICSharpCode.Decompiler.TypeSystem && typeDefinition.Kind == TypeKind.Interface && typeDefinition.HasAttribute(KnownAttribute.ComImport, inherit: false); } - + /// /// Gets the CoClass of the specified COM interface. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Co", - Justification = "Consistent with CoClassAttribute")] + Justification = "Consistent with CoClassAttribute")] public static IType GetCoClass(ITypeDefinition typeDefinition) { if (typeDefinition == null) return SpecialType.UnknownType; var coClassAttribute = typeDefinition.GetAttribute(KnownAttribute.CoClass, inherit: false); - if (coClassAttribute != null && coClassAttribute.FixedArguments.Length == 1) { + if (coClassAttribute != null && coClassAttribute.FixedArguments.Length == 1) + { if (coClassAttribute.FixedArguments[0].Value is IType ty) return ty; } diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index 9c126bbcf..58915a02e 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -18,15 +18,17 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; -using SRM = System.Reflection.Metadata; + +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; using static ICSharpCode.Decompiler.Metadata.MetadataExtensions; -using System.Diagnostics; -using System.Collections.Immutable; -using ICSharpCode.Decompiler.Metadata; + +using SRM = System.Reflection.Metadata; namespace ICSharpCode.Decompiler.TypeSystem { @@ -176,40 +178,51 @@ namespace ICSharpCode.Decompiler.TypeSystem var referencedAssemblies = new List(); var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference)>(); var mainMetadata = mainModule.Metadata; - foreach (var h in mainMetadata.GetModuleReferences()) { + foreach (var h in mainMetadata.GetModuleReferences()) + { var moduleRef = mainMetadata.GetModuleReference(h); var moduleName = mainMetadata.GetString(moduleRef.Name); - foreach (var fileHandle in mainMetadata.AssemblyFiles) { + foreach (var fileHandle in mainMetadata.AssemblyFiles) + { var file = mainMetadata.GetAssemblyFile(fileHandle); - if (mainMetadata.StringComparer.Equals(file.Name, moduleName) && file.ContainsMetadata) { + if (mainMetadata.StringComparer.Equals(file.Name, moduleName) && file.ContainsMetadata) + { assemblyReferenceQueue.Enqueue((false, mainModule, moduleName)); break; } } } - foreach (var refs in mainModule.AssemblyReferences) { + foreach (var refs in mainModule.AssemblyReferences) + { assemblyReferenceQueue.Enqueue((true, mainModule, refs)); } var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) => reference.IsAssembly ? "A:" + ((AssemblyReference)reference.Reference).FullName : - "M:" + reference.Reference); + "M:" + reference.Reference); var processedAssemblyReferences = new HashSet<(bool IsAssembly, PEFile Parent, object Reference)>(comparer); - while (assemblyReferenceQueue.Count > 0) { + while (assemblyReferenceQueue.Count > 0) + { var asmRef = assemblyReferenceQueue.Dequeue(); if (!processedAssemblyReferences.Add(asmRef)) continue; PEFile asm; - if (asmRef.IsAssembly) { + if (asmRef.IsAssembly) + { asm = assemblyResolver.Resolve((AssemblyReference)asmRef.Reference); - } else { + } + else + { asm = assemblyResolver.ResolveModule(asmRef.MainModule, (string)asmRef.Reference); } - if (asm != null) { + if (asm != null) + { referencedAssemblies.Add(asm); var metadata = asm.Metadata; - foreach (var h in metadata.ExportedTypes) { + foreach (var h in metadata.ExportedTypes) + { var exportedType = metadata.GetExportedType(h); - switch (exportedType.Implementation.Kind) { + switch (exportedType.Implementation.Kind) + { case SRM.HandleKind.AssemblyReference: assemblyReferenceQueue.Enqueue((true, asm, new AssemblyReference(asm, (SRM.AssemblyReferenceHandle)exportedType.Implementation))); break; @@ -227,9 +240,12 @@ namespace ICSharpCode.Decompiler.TypeSystem // Other known types are necessary in order for transforms to work (e.g. Task for async transform). // Figure out which known types are missing from our type system so far: var missingKnownTypes = KnownTypeReference.AllKnownTypes.Where(IsMissing).ToList(); - if (missingKnownTypes.Count > 0) { + if (missingKnownTypes.Count > 0) + { Init(mainModule.WithOptions(typeSystemOptions), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.CreateWithTypes(missingKnownTypes) })); - } else { + } + else + { Init(mainModuleWithOptions, referencedAssembliesWithOptions); } this.MainModule = (MetadataModule)base.MainModule; @@ -239,14 +255,15 @@ namespace ICSharpCode.Decompiler.TypeSystem var name = knownType.TypeName; if (!mainModule.GetTypeDefinition(name).IsNil) return false; - foreach (var file in referencedAssemblies) { + foreach (var file in referencedAssemblies) + { if (!file.GetTypeDefinition(name).IsNil) return false; } return true; } } - + public new MetadataModule MainModule { get; } } } diff --git a/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs b/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs index 9eaf22a51..9df4bf8a4 100644 --- a/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs +++ b/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs @@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { public readonly string Name; public readonly int AdditionalTypeParameterCount; - + public NestedTypeName(string name, int additionalTypeParameterCount) { if (name == null) @@ -50,16 +50,16 @@ namespace ICSharpCode.Decompiler.TypeSystem this.AdditionalTypeParameterCount = additionalTypeParameterCount; } } - + readonly TopLevelTypeName topLevelType; readonly NestedTypeName[] nestedTypes; - + FullTypeName(TopLevelTypeName topLevelTypeName, NestedTypeName[] nestedTypes) { this.topLevelType = topLevelTypeName; this.nestedTypes = nestedTypes; } - + /// /// Constructs a FullTypeName representing the given top-level type. /// @@ -73,7 +73,7 @@ namespace ICSharpCode.Decompiler.TypeSystem this.topLevelType = topLevelTypeName; this.nestedTypes = null; } - + /// /// Constructs a FullTypeName by parsing the given reflection name. /// Note that FullTypeName can only represent type definition names. If the reflection name @@ -87,30 +87,34 @@ namespace ICSharpCode.Decompiler.TypeSystem public FullTypeName(string reflectionName) { int pos = reflectionName.IndexOf('+'); - if (pos < 0) { + if (pos < 0) + { // top-level type this.topLevelType = new TopLevelTypeName(reflectionName); this.nestedTypes = null; - } else { + } + else + { // nested type string[] parts = reflectionName.Split('+'); this.topLevelType = new TopLevelTypeName(parts[0]); this.nestedTypes = new NestedTypeName[parts.Length - 1]; - for (int i = 0; i < nestedTypes.Length; i++) { + for (int i = 0; i < nestedTypes.Length; i++) + { int tpc; string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(parts[i + 1], out tpc); nestedTypes[i] = new NestedTypeName(name, tpc); } } } - + /// /// Gets the top-level type name. /// public TopLevelTypeName TopLevelTypeName { get { return topLevelType; } } - + /// /// Gets whether this is a nested type. /// @@ -119,7 +123,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return nestedTypes != null; } } - + /// /// Gets the nesting level. /// @@ -128,7 +132,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return nestedTypes != null ? nestedTypes.Length : 0; } } - + /// /// Gets the name of the type. /// For nested types, this is the name of the innermost type. @@ -141,16 +145,18 @@ namespace ICSharpCode.Decompiler.TypeSystem return topLevelType.Name; } } - + public string ReflectionName { get { if (nestedTypes == null) return topLevelType.ReflectionName; StringBuilder b = new StringBuilder(topLevelType.ReflectionName); - foreach (NestedTypeName nt in nestedTypes) { + foreach (NestedTypeName nt in nestedTypes) + { b.Append('+'); b.Append(nt.Name); - if (nt.AdditionalTypeParameterCount > 0) { + if (nt.AdditionalTypeParameterCount > 0) + { b.Append('`'); b.Append(nt.AdditionalTypeParameterCount); } @@ -158,22 +164,24 @@ namespace ICSharpCode.Decompiler.TypeSystem return b.ToString(); } } - + /// /// Gets the total type parameter count. /// public int TypeParameterCount { get { int tpc = topLevelType.TypeParameterCount; - if (nestedTypes != null) { - foreach (var nt in nestedTypes) { + if (nestedTypes != null) + { + foreach (var nt in nestedTypes) + { tpc += nt.AdditionalTypeParameterCount; } } return tpc; } } - + /// /// Gets the name of the nested type at the given level. /// @@ -183,7 +191,7 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new InvalidOperationException(); return nestedTypes[nestingLevel].Name; } - + /// /// Gets the number of additional type parameters of the nested type at the given level. /// @@ -193,7 +201,7 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new InvalidOperationException(); return nestedTypes[nestingLevel].AdditionalTypeParameterCount; } - + /// /// Gets the declaring type name. /// @@ -209,7 +217,7 @@ namespace ICSharpCode.Decompiler.TypeSystem Array.Copy(nestedTypes, 0, outerNestedTypeNames, 0, outerNestedTypeNames.Length); return new FullTypeName(topLevelType, outerNestedTypeNames); } - + /// /// Creates a nested type name. /// @@ -226,58 +234,58 @@ namespace ICSharpCode.Decompiler.TypeSystem newNestedTypeNames[newNestedTypeNames.Length - 1] = newNestedType; return new FullTypeName(topLevelType, newNestedTypeNames); } - + public static implicit operator FullTypeName(TopLevelTypeName topLevelTypeName) { return new FullTypeName(topLevelTypeName); } - + public override string ToString() { return this.ReflectionName; } - + #region Equals and GetHashCode implementation public override bool Equals(object obj) { return obj is FullTypeName && Equals((FullTypeName)obj); } - + public bool Equals(FullTypeName other) { return FullTypeNameComparer.Ordinal.Equals(this, other); } - + public override int GetHashCode() { return FullTypeNameComparer.Ordinal.GetHashCode(this); } - + public static bool operator ==(FullTypeName left, FullTypeName right) { return left.Equals(right); } - + public static bool operator !=(FullTypeName left, FullTypeName right) { return !left.Equals(right); } #endregion } - + [Serializable] public sealed class FullTypeNameComparer : IEqualityComparer { public static readonly FullTypeNameComparer Ordinal = new FullTypeNameComparer(StringComparer.Ordinal); public static readonly FullTypeNameComparer OrdinalIgnoreCase = new FullTypeNameComparer(StringComparer.OrdinalIgnoreCase); - + public readonly StringComparer NameComparer; - + public FullTypeNameComparer(StringComparer nameComparer) { this.NameComparer = nameComparer; } - + public bool Equals(FullTypeName x, FullTypeName y) { if (x.NestingLevel != y.NestingLevel) @@ -285,10 +293,11 @@ namespace ICSharpCode.Decompiler.TypeSystem TopLevelTypeName topX = x.TopLevelTypeName; TopLevelTypeName topY = y.TopLevelTypeName; if (topX.TypeParameterCount == topY.TypeParameterCount - && NameComparer.Equals(topX.Name, topY.Name) - && NameComparer.Equals(topX.Namespace, topY.Namespace)) + && NameComparer.Equals(topX.Name, topY.Name) + && NameComparer.Equals(topX.Namespace, topY.Namespace)) { - for (int i = 0; i < x.NestingLevel; i++) { + for (int i = 0; i < x.NestingLevel; i++) + { if (x.GetNestedTypeAdditionalTypeParameterCount(i) != y.GetNestedTypeAdditionalTypeParameterCount(i)) return false; if (!NameComparer.Equals(x.GetNestedTypeName(i), y.GetNestedTypeName(i))) @@ -298,13 +307,15 @@ namespace ICSharpCode.Decompiler.TypeSystem } return false; } - + public int GetHashCode(FullTypeName obj) { TopLevelTypeName top = obj.TopLevelTypeName; int hash = NameComparer.GetHashCode(top.Name) ^ NameComparer.GetHashCode(top.Namespace) ^ top.TypeParameterCount; - unchecked { - for (int i = 0; i < obj.NestingLevel; i++) { + unchecked + { + for (int i = 0; i < obj.NestingLevel; i++) + { hash *= 31; hash += NameComparer.GetHashCode(obj.Name) ^ obj.TypeParameterCount; } diff --git a/ICSharpCode.Decompiler/TypeSystem/GenericContext.cs b/ICSharpCode.Decompiler/TypeSystem/GenericContext.cs index 13e3a54fa..ddb41c94e 100644 --- a/ICSharpCode.Decompiler/TypeSystem/GenericContext.cs +++ b/ICSharpCode.Decompiler/TypeSystem/GenericContext.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -47,10 +48,13 @@ namespace ICSharpCode.Decompiler.TypeSystem internal GenericContext(IEntity context) { - if (context is ITypeDefinition td) { + if (context is ITypeDefinition td) + { this.ClassTypeParameters = td.TypeParameters; this.MethodTypeParameters = null; - } else { + } + else + { this.ClassTypeParameters = context.DeclaringTypeDefinition?.TypeParameters; this.MethodTypeParameters = (context as IMethod)?.TypeParameters; } diff --git a/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs b/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs index 3c5d056f7..d2191da74 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IAssembly.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.TypeSystem @@ -41,7 +42,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// IModule Resolve(ITypeResolveContext context); } - + /// /// Represents a metadata module. /// @@ -56,12 +57,12 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets whether this assembly is the main assembly of the compilation. /// bool IsMainModule { get; } - + /// /// Gets the assembly name (short name). /// string AssemblyName { get; } - + /// /// Gets the full assembly name (including public key token etc.) /// @@ -76,12 +77,12 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the list of all module attributes in the project. /// IEnumerable GetModuleAttributes(); - + /// /// Gets whether the internals of this assembly are visible in the specified assembly. /// bool InternalsVisibleTo(IModule module); - + /// /// Gets the root namespace for this module. /// @@ -91,13 +92,13 @@ namespace ICSharpCode.Decompiler.TypeSystem /// to get the combined view of all referenced assemblies. /// INamespace RootNamespace { get; } - + /// /// Gets the type definition for a top-level type. /// /// This method uses ordinal name comparison, not the compilation's name comparer. ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName); - + /// /// Gets all non-nested types in the assembly. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/IAttribute.cs b/ICSharpCode.Decompiler/TypeSystem/IAttribute.cs index e05f97769..53b61b0c8 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IAttribute.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IAttribute.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Semantics; namespace ICSharpCode.Decompiler.TypeSystem @@ -33,7 +34,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the type of the attribute. /// IType AttributeType { get; } - + /// /// Gets the constructor being used. /// This property may return null if no matching constructor was found. diff --git a/ICSharpCode.Decompiler/TypeSystem/ICodeContext.cs b/ICSharpCode.Decompiler/TypeSystem/ICodeContext.cs index a3daa5a07..6d9525c08 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ICodeContext.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ICodeContext.cs @@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Does not include method parameters. /// IEnumerable LocalVariables { get; } - + /// /// Gets whether the context is within a lambda expression or anonymous method. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/ICompilation.cs b/ICSharpCode.Decompiler/TypeSystem/ICompilation.cs index 1fd554d5d..d41f350f4 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ICompilation.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ICompilation.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem @@ -30,7 +31,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// referenced by the main module. /// IModule MainModule { get; } - + /// /// Gets the list of all modules in the compilation. /// @@ -44,7 +45,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// This list does not include the main module. /// IReadOnlyList ReferencedModules { get; } - + /// /// Gets the root namespace of this compilation. /// This is a merged version of the root namespaces of all assemblies. @@ -53,7 +54,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// This always is the namespace without a name - it's unrelated to the 'root namespace' project setting. /// INamespace RootNamespace { get; } - + /// /// Gets the root namespace for a given extern alias. /// @@ -63,18 +64,18 @@ namespace ICSharpCode.Decompiler.TypeSystem /// If no alias with the specified name exists, this method returns null. /// INamespace GetNamespaceForExternAlias(string alias); - + IType FindType(KnownTypeCode typeCode); - + /// /// Gets the name comparer for the language being compiled. /// This is the string comparer used for the INamespace.GetTypeDefinition method. /// StringComparer NameComparer { get; } - + CacheManager CacheManager { get; } } - + public interface ICompilationProvider { /// diff --git a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs index 51c1f7241..f45bdd2c1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs @@ -18,6 +18,7 @@ using System.Collections.Immutable; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.TypeSystem diff --git a/ICSharpCode.Decompiler/TypeSystem/IEntity.cs b/ICSharpCode.Decompiler/TypeSystem/IEntity.cs index e80b9b9ad..4bd680a75 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IEntity.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IEntity.cs @@ -40,21 +40,21 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the short name of the entity. /// new string Name { get; } - + /// /// Gets the declaring class. /// For members, this is the class that contains the member. /// For nested classes, this is the outer class. For top-level entities, this property returns null. /// ITypeDefinition DeclaringTypeDefinition { get; } - + /// /// Gets/Sets the declaring type (incl. type arguments, if any). /// This property will return null for top-level entities. /// If this is not a specialized member, the value returned is equal to . /// IType DeclaringType { get; } - + /// /// The module in which this entity is defined. /// @@ -76,13 +76,13 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Returns true if either the 'static' or the 'const' modifier is set. /// bool IsStatic { get; } - + /// /// Returns whether this entity is abstract. /// /// Static classes also count as abstract classes. bool IsAbstract { get; } - + /// /// Returns whether this entity is sealed. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/IEvent.cs b/ICSharpCode.Decompiler/TypeSystem/IEvent.cs index ee17f2b75..ee9aa2b80 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IEvent.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IEvent.cs @@ -23,7 +23,7 @@ namespace ICSharpCode.Decompiler.TypeSystem bool CanAdd { get; } bool CanRemove { get; } bool CanInvoke { get; } - + IMethod AddAccessor { get; } IMethod RemoveAccessor { get; } IMethod InvokeAccessor { get; } diff --git a/ICSharpCode.Decompiler/TypeSystem/IField.cs b/ICSharpCode.Decompiler/TypeSystem/IField.cs index 9551b611a..18f5a00b7 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IField.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IField.cs @@ -27,12 +27,12 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the name of the field. /// new string Name { get; } // solve ambiguity between IMember.Name and IVariable.Name - + /// /// Gets whether this field is readonly. /// bool IsReadOnly { get; } - + /// /// Gets whether this field is volatile. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/IFreezable.cs b/ICSharpCode.Decompiler/TypeSystem/IFreezable.cs index 50bd42c68..b6dae14f0 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IFreezable.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IFreezable.cs @@ -24,7 +24,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets if this instance is frozen. Frozen instances are immutable and thus thread-safe. /// bool IsFrozen { get; } - + /// /// Freezes this instance. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/IInterningProvider.cs b/ICSharpCode.Decompiler/TypeSystem/IInterningProvider.cs index 68b740ebb..0c670f214 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IInterningProvider.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IInterningProvider.cs @@ -41,14 +41,14 @@ namespace ICSharpCode.Decompiler.TypeSystem public abstract class InterningProvider { public static readonly InterningProvider Dummy = new DummyInterningProvider(); - + /// /// Interns the specified object. /// /// If the object is freezable, it will be frozen. /// public abstract ISupportsInterning Intern(ISupportsInterning obj); - + /// /// Interns the specified object. /// @@ -59,39 +59,39 @@ namespace ICSharpCode.Decompiler.TypeSystem ISupportsInterning input = obj; return (T)Intern(input); } - + /// /// Interns the specified string. /// public abstract string Intern(string text); - + /// /// Inters a boxed value type. /// public abstract object InternValue(object obj); - + /// /// Interns the given list. Uses reference equality to compare the list elements. /// public abstract IList InternList(IList list) where T : class; - + sealed class DummyInterningProvider : InterningProvider { public override ISupportsInterning Intern(ISupportsInterning obj) { return obj; } - + public override string Intern(string text) { return text; } - + public override object InternValue(object obj) { return obj; } - + public override IList InternList(IList list) { return list; diff --git a/ICSharpCode.Decompiler/TypeSystem/IMember.cs b/ICSharpCode.Decompiler/TypeSystem/IMember.cs index 2ba6ecb94..47718c4d1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IMember.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IMember.cs @@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the declaring type reference for the member. /// ITypeReference DeclaringTypeReference { get; } - + /// /// Resolves the member. /// @@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// IMember Resolve(ITypeResolveContext context); } - + /// /// Method/field/property/event. /// @@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Specialized members are the result of overload resolution with type substitution. /// IMember MemberDefinition { get; } - + /// /// Gets the return type of this member. /// This property never returns null. @@ -80,28 +80,28 @@ namespace ICSharpCode.Decompiler.TypeSystem /// so use (C).GetInterfaceImplementations() instead to handle this case. /// IEnumerable ExplicitlyImplementedInterfaceMembers { get; } - + /// /// Gets whether this member is explicitly implementing an interface. /// bool IsExplicitInterfaceImplementation { get; } - + /// /// Gets if the member is virtual. Is true only if the "virtual" modifier was used, but non-virtual /// members can be overridden, too; if they are abstract or overriding a method. /// bool IsVirtual { get; } - + /// /// Gets whether this member is overriding another member. /// bool IsOverride { get; } - + /// /// Gets if the member can be overridden. Returns true when the member is "abstract", "virtual" or "override" but not "sealed". /// bool IsOverridable { get; } - + /// /// Gets the substitution belonging to this specialized member. /// Returns TypeParameterSubstitution.Identity for not specialized members. diff --git a/ICSharpCode.Decompiler/TypeSystem/IMethod.cs b/ICSharpCode.Decompiler/TypeSystem/IMethod.cs index b12b4f064..d82dc5491 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IMethod.cs @@ -69,19 +69,19 @@ namespace ICSharpCode.Decompiler.TypeSystem bool IsConstructor { get; } bool IsDestructor { get; } bool IsOperator { get; } - + /// /// Gets whether the method has a body. /// This property returns false for abstract or extern methods, /// or for partial methods without implementation. /// bool HasBody { get; } - + /// /// Gets whether the method is a property/event accessor. /// bool IsAccessor { get; } - + /// /// If this method is an accessor, returns the corresponding property/event. /// Otherwise, returns null. @@ -99,7 +99,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// A local function doesn't contain compiler-generated method parameters at the end. /// IMethod ReducedFrom { get; } - + /// /// Specializes this method with the given substitution. /// If this method is already specialized, the new substitution is composed with the existing substition. diff --git a/ICSharpCode.Decompiler/TypeSystem/INamedElement.cs b/ICSharpCode.Decompiler/TypeSystem/INamedElement.cs index 42c86b5b0..80d4528ff 100644 --- a/ICSharpCode.Decompiler/TypeSystem/INamedElement.cs +++ b/ICSharpCode.Decompiler/TypeSystem/INamedElement.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// "System.Environment.SpecialFolder" for Environment.SpecialFolder /// string FullName { get; } - + /// /// Gets the short name of the class the return type is pointing to. /// @@ -39,7 +39,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// "SpecialFolder" for Environment.SpecialFolder /// string Name { get; } - + /// /// Gets the full reflection name of the element. /// @@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// "System.Environment+SpecialFolder" for Environment.SpecialFolder /// string ReflectionName { get; } - + /// /// Gets the full name of the namespace containing this entity. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/INamespace.cs b/ICSharpCode.Decompiler/TypeSystem/INamespace.cs index 92907299f..353fd633b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/INamespace.cs +++ b/ICSharpCode.Decompiler/TypeSystem/INamespace.cs @@ -28,44 +28,44 @@ namespace ICSharpCode.Decompiler.TypeSystem // No pointer back to unresolved namespace: // multiple unresolved namespaces (from different assemblies) get // merged into one INamespace. - + /// /// Gets the extern alias for this namespace. /// Returns an empty string for normal namespaces. /// string ExternAlias { get; } - + /// /// Gets the full name of this namespace. (e.g. "System.Collections") /// string FullName { get; } - + /// /// Gets the short name of this namespace (e.g. "Collections"). /// new string Name { get; } - + /// /// Gets the parent namespace. /// Returns null if this is the root namespace. /// INamespace ParentNamespace { get; } - + /// /// Gets the child namespaces in this namespace. /// IEnumerable ChildNamespaces { get; } - + /// /// Gets the types in this namespace. /// IEnumerable Types { get; } - + /// /// Gets the modules that contribute types to this namespace (or to child namespaces). /// IEnumerable ContributingModules { get; } - + /// /// Gets a direct child namespace by its short name. /// Returns null when the namespace cannot be found. @@ -74,7 +74,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// This method uses the compilation's current string comparer. /// INamespace GetChildNamespace(string name); - + /// /// Gets the type with the specified short name and type parameter count. /// Returns null if the type cannot be found. diff --git a/ICSharpCode.Decompiler/TypeSystem/IParameter.cs b/ICSharpCode.Decompiler/TypeSystem/IParameter.cs index 7801a0e09..ff7fdea3b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IParameter.cs @@ -16,8 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System.Runtime.CompilerServices; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace ICSharpCode.Decompiler.TypeSystem { @@ -43,12 +43,12 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the reference kind of this parameter. /// ReferenceKind ReferenceKind { get; } - + /// /// Gets whether this parameter is a C# 'ref' parameter. /// bool IsRef { get; } - + /// /// Gets whether this parameter is a C# 'out' parameter. /// @@ -69,7 +69,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// The default value is given by the function. /// bool IsOptional { get; } - + /// /// Gets whether this parameter has a constant value when presented in method signature. /// @@ -85,7 +85,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// On the call sites, though, we can still use the value inferred from the attribute. /// bool HasConstantValueInSignature { get; } - + /// /// Gets the owner of this parameter. /// May return null; for example when parameters belong to lambdas or anonymous methods. diff --git a/ICSharpCode.Decompiler/TypeSystem/IProperty.cs b/ICSharpCode.Decompiler/TypeSystem/IProperty.cs index 388c770e0..56673e52b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IProperty.cs @@ -25,10 +25,10 @@ namespace ICSharpCode.Decompiler.TypeSystem { bool CanGet { get; } bool CanSet { get; } - + IMethod Getter { get; } IMethod Setter { get; } - + bool IsIndexer { get; } /// diff --git a/ICSharpCode.Decompiler/TypeSystem/ISupportsInterning.cs b/ICSharpCode.Decompiler/TypeSystem/ISupportsInterning.cs index 4ab83d78d..dfab4ea57 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ISupportsInterning.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ISupportsInterning.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets a hash code for interning. /// int GetHashCodeForInterning(); - + /// /// Equality test for interning. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/ISymbol.cs b/ICSharpCode.Decompiler/TypeSystem/ISymbol.cs index b269c785a..6bfcd5b71 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ISymbol.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ISymbol.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// ReturnType, } - + /// /// Interface for type system symbols. /// @@ -89,7 +89,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// (which derived interfaces of ISymbol are implemented) /// SymbolKind SymbolKind { get; } - + /// /// Gets the short name of the symbol. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/IType.cs b/ICSharpCode.Decompiler/TypeSystem/IType.cs index 5a399e8d7..c9725d04e 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IType.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the type kind. /// TypeKind Kind { get; } - + /// /// Gets whether the type is a reference type or value type. /// @@ -63,7 +63,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// null, if the type is not known (e.g. unconstrained generic type parameter or type not found) /// bool? IsReferenceType { get; } - + /// /// Gets whether this type is "ref-like": a ByReferenceType or "ref struct". /// @@ -84,13 +84,13 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Can return null for types which do not have a type definition (for example arrays, pointers, type parameters). /// ITypeDefinition GetDefinition(); - + /// /// Gets the parent type, if this is a nested type. /// Returns null for top-level types. /// IType DeclaringType { get; } - + /// /// Gets the number of type parameters. /// @@ -114,7 +114,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// The return value of the ITypeVisitor.Visit call IType AcceptVisitor(TypeVisitor visitor); - + /// /// Calls ITypeVisitor.Visit for all children of this type, and reconstructs this type with the children based /// on the return values of the visit calls. @@ -123,20 +123,20 @@ namespace ICSharpCode.Decompiler.TypeSystem /// If the visitor returned the original types for all children (or if there are no children), returns this. /// IType VisitChildren(TypeVisitor visitor); - + /// /// Gets the direct base types. /// /// Returns the direct base types including interfaces IEnumerable DirectBaseTypes { get; } - + /// /// Gets a type visitor that performs the substitution of class type parameters with the type arguments /// of this parameterized type. /// Returns TypeParameterSubstitution.Identity if the type is not parametrized. /// TypeParameterSubstitution GetSubstitution(); - + /// /// Gets inner classes (including inherited inner classes). /// @@ -169,7 +169,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// IEnumerable GetNestedTypes(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 {} } @@ -178,7 +178,7 @@ namespace ICSharpCode.Decompiler.TypeSystem // 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 inner classes (including inherited inner classes) /// that have typeArguments.Count additional type parameters. @@ -194,7 +194,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// from an and 'leaks' type parameters in member signatures. /// IEnumerable GetNestedTypes(IReadOnlyList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); - + /// /// Gets all instance constructors for this type. /// @@ -210,7 +210,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// IEnumerable GetConstructors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers); - + /// /// Gets all methods that can be called on this type. /// @@ -237,7 +237,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); - + /// /// Gets all generic methods that can be called on this type with the specified type arguments. /// @@ -258,7 +258,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// IEnumerable GetMethods(IReadOnlyList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); - + /// /// Gets all properties that can be called on this type. /// @@ -270,7 +270,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// and the appropriate will be returned. /// IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); - + /// /// Gets all fields that can be accessed on this type. /// @@ -282,7 +282,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// and the appropriate will be returned. /// IEnumerable GetFields(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); - + /// /// Gets all events that can be accessed on this type. /// @@ -294,7 +294,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// and the appropriate will be returned. /// IEnumerable GetEvents(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); - + /// /// Gets all members that can be called on this type. /// @@ -313,7 +313,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); - + /// /// Gets all accessors belonging to properties or events on this type. /// @@ -325,7 +325,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); } - + [Flags] public enum GetMemberOptions { diff --git a/ICSharpCode.Decompiler/TypeSystem/ITypeDefinition.cs b/ICSharpCode.Decompiler/TypeSystem/ITypeDefinition.cs index 19b727adc..e0e796cc9 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ITypeDefinition.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ITypeDefinition.cs @@ -28,17 +28,17 @@ namespace ICSharpCode.Decompiler.TypeSystem { IReadOnlyList NestedTypes { get; } IReadOnlyList Members { get; } - + IEnumerable Fields { get; } IEnumerable Methods { get; } IEnumerable Properties { get; } IEnumerable Events { get; } - + /// /// Gets the known type code for this type definition. /// KnownTypeCode KnownTypeCode { get; } - + /// /// For enums: returns the underlying primitive type. /// For all other types: returns . @@ -50,18 +50,18 @@ namespace ICSharpCode.Decompiler.TypeSystem /// For all other types: returns false. /// bool IsReadOnly { get; } - + /// /// Gets the full name of this type. /// FullTypeName FullTypeName { get; } - + /// /// Gets/Sets the declaring type (incl. type arguments, if any). /// This property will return null for top-level types. /// new IType DeclaringType { get; } // solves ambiguity between IType.DeclaringType and IEntity.DeclaringType - + /// /// Gets whether this type contains extension methods. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs index 8ff935184..4079d274a 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem @@ -43,12 +44,12 @@ namespace ICSharpCode.Decompiler.TypeSystem /// ITypeParameter instance is used both on Outer`1 and Outer`1+Inner. /// IEntity Owner { get; } - + /// /// Gets the index of the type parameter in the type parameter list of the owning method/class. /// int Index { get; } - + /// /// Gets the name of the type parameter. /// @@ -58,32 +59,32 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the attributes declared on this type parameter. /// IEnumerable GetAttributes(); - + /// /// Gets the variance of this type parameter. /// VarianceModifier Variance { get; } - + /// /// Gets the effective base class of this type parameter. /// IType EffectiveBaseClass { get; } - + /// /// Gets the effective interface set of this type parameter. /// IReadOnlyCollection EffectiveInterfaceSet { get; } - + /// /// Gets if the type parameter has the 'new()' constraint. /// bool HasDefaultConstructorConstraint { get; } - + /// /// Gets if the type parameter has the 'class' constraint. /// bool HasReferenceTypeConstraint { get; } - + /// /// Gets if the type parameter has the 'struct' or 'unmanaged' constraint. /// @@ -117,7 +118,7 @@ namespace ICSharpCode.Decompiler.TypeSystem this.Attributes = attributes ?? EmptyList.Instance; } } - + /// /// Represents the variance of a type parameter. /// diff --git a/ICSharpCode.Decompiler/TypeSystem/ITypeReference.cs b/ICSharpCode.Decompiler/TypeSystem/ITypeReference.cs index 8a6dfe501..92ef08450 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ITypeReference.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ITypeReference.cs @@ -26,10 +26,10 @@ namespace ICSharpCode.Decompiler.TypeSystem { // Keep this interface simple: I decided against having GetMethods/GetEvents etc. here, // so that the Resolve step is never hidden from the consumer. - + // I decided against implementing IFreezable here: IUnresolvedTypeDefinition can be used as ITypeReference, // but when freezing the reference, one wouldn't expect the definition to freeze. - + /// /// Resolves this type reference. /// @@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// IType Resolve(ITypeResolveContext context); } - + public interface ITypeResolveContext : ICompilationProvider { /// @@ -54,17 +54,17 @@ namespace ICSharpCode.Decompiler.TypeSystem /// This property may return null if this context does not specify any module. /// IModule CurrentModule { get; } - + /// /// Gets the current type definition. /// - ITypeDefinition CurrentTypeDefinition { get ;} - + ITypeDefinition CurrentTypeDefinition { get; } + /// /// Gets the current member. /// IMember CurrentMember { get; } - + ITypeResolveContext WithCurrentTypeDefinition(ITypeDefinition typeDefinition); ITypeResolveContext WithCurrentMember(IMember member); } diff --git a/ICSharpCode.Decompiler/TypeSystem/IVariable.cs b/ICSharpCode.Decompiler/TypeSystem/IVariable.cs index 327c571f7..13e1c270e 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IVariable.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IVariable.cs @@ -27,12 +27,12 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the name of the variable. /// new string Name { get; } - + /// /// Gets the type of the variable. /// IType Type { get; } - + /// /// Gets whether this variable is a constant (C#-like const). /// diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractFreezable.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractFreezable.cs index ee2efaa20..aca56d7e3 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractFreezable.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractFreezable.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -31,49 +32,54 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation if (freezable.IsFrozen) throw new InvalidOperationException("Cannot mutate frozen " + freezable.GetType().Name); } - + public static IList FreezeListAndElements(IList list) { - if (list != null) { + if (list != null) + { foreach (T item in list) Freeze(item); } return FreezeList(list); } - + public static IList FreezeList(IList list) { if (list == null || list.Count == 0) return EmptyList.Instance; - if (list.IsReadOnly) { + if (list.IsReadOnly) + { // If the list is already read-only, return it directly. // This is important, otherwise we might undo the effects of interning. return list; - } else { + } + else + { return new ReadOnlyCollection(list.ToArray()); } } - + public static void Freeze(object item) { IFreezable f = item as IFreezable; if (f != null) f.Freeze(); } - + public static T FreezeAndReturn(T item) where T : IFreezable { item.Freeze(); return item; } - + /// /// If the item is not frozen, this method creates and returns a frozen clone. /// If the item is already frozen, it is returned without creating a clone. /// public static T GetFrozenClone(T item) where T : IFreezable, ICloneable { - if (!item.IsFrozen) { + if (!item.IsFrozen) + { item = (T)item.Clone(); item.Freeze(); } @@ -85,25 +91,26 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public abstract class AbstractFreezable : IFreezable { bool isFrozen; - + /// /// Gets if this instance is frozen. Frozen instances are immutable and thus thread-safe. /// public bool IsFrozen { get { return isFrozen; } } - + /// /// Freezes this instance. /// public void Freeze() { - if (!isFrozen) { + if (!isFrozen) + { FreezeInternal(); isFrozen = true; } } - + protected virtual void FreezeInternal() { } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractType.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractType.cs index fd484d9ae..44e63b963 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractType.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -34,25 +35,28 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation get { string ns = this.Namespace; string name = this.Name; - if (string.IsNullOrEmpty(ns)) { + if (string.IsNullOrEmpty(ns)) + { return name; - } else { + } + else + { return ns + "." + name; } } } - + public abstract string Name { get; } - + public virtual string Namespace { get { return string.Empty; } } - + public virtual string ReflectionName { get { return this.FullName; } } - - public abstract bool? IsReferenceType { get; } + + public abstract bool? IsReferenceType { get; } public virtual bool IsByRefLike => false; @@ -65,7 +69,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } public abstract TypeKind Kind { get; } - + public virtual int TypeParameterCount { get { return 0; } } @@ -81,56 +85,56 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public virtual IType DeclaringType { get { return null; } } - + public virtual ITypeDefinition GetDefinition() { return null; } - + public virtual IEnumerable DirectBaseTypes { get { return EmptyList.Instance; } } - + public virtual IEnumerable GetNestedTypes(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - + public virtual IEnumerable GetNestedTypes(IReadOnlyList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - + public virtual IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - + public virtual IEnumerable GetMethods(IReadOnlyList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - + public virtual IEnumerable GetConstructors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) { return EmptyList.Instance; } - + public virtual IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - + public virtual IEnumerable GetFields(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - + public virtual IEnumerable GetEvents(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - + public virtual IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { IEnumerable members = GetMethods(filter, options); @@ -139,17 +143,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation .Concat(GetFields(filter, options)) .Concat(GetEvents(filter, options)); } - + public virtual IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - + public TypeParameterSubstitution GetSubstitution() { return TypeParameterSubstitution.Identity; } - + public TypeParameterSubstitution GetSubstitution(IReadOnlyList methodTypeArguments) { return TypeParameterSubstitution.Identity; @@ -159,27 +163,27 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { return Equals(obj as IType); } - + public override int GetHashCode() { return base.GetHashCode(); } - + public virtual bool Equals(IType other) { return this == other; // use reference equality by default } - + public override string ToString() { return this.ReflectionName; } - + public virtual IType AcceptVisitor(TypeVisitor visitor) { return visitor.VisitOtherType(this); } - + public virtual IType VisitChildren(TypeVisitor visitor) { return this; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs index c302529bc..c034d1d2a 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -32,7 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation readonly int index; readonly string name; readonly VarianceModifier variance; - + protected AbstractTypeParameter(IEntity owner, int index, string name, VarianceModifier variance) { if (owner == null) @@ -44,7 +45,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.name = name ?? ((this.OwnerType == SymbolKind.Method ? "!!" : "!") + index.ToString(CultureInfo.InvariantCulture)); this.variance = variance; } - + protected AbstractTypeParameter(ICompilation compilation, SymbolKind ownerType, int index, string name, VarianceModifier variance) { if (compilation == null) @@ -55,40 +56,42 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.name = name ?? ((this.OwnerType == SymbolKind.Method ? "!!" : "!") + index.ToString(CultureInfo.InvariantCulture)); this.variance = variance; } - + SymbolKind ISymbol.SymbolKind { get { return SymbolKind.TypeParameter; } } - + public SymbolKind OwnerType { get { return ownerType; } } - + public IEntity Owner { get { return owner; } } - + public int Index { get { return index; } } public abstract IEnumerable GetAttributes(); - + public VarianceModifier Variance { get { return variance; } } - + public ICompilation Compilation { get { return compilation; } } - + volatile IType effectiveBaseClass; - + public IType EffectiveBaseClass { get { - if (effectiveBaseClass == null) { + if (effectiveBaseClass == null) + { // protect against cyclic type parameters - using (var busyLock = BusyManager.Enter(this)) { + using (var busyLock = BusyManager.Enter(this)) + { if (!busyLock.Success) return SpecialType.UnknownType; // don't cache this error effectiveBaseClass = CalculateEffectiveBaseClass(); @@ -97,17 +100,21 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return effectiveBaseClass; } } - + IType CalculateEffectiveBaseClass() { if (HasValueTypeConstraint) return this.Compilation.FindType(KnownTypeCode.ValueType); - + List classTypeConstraints = new List(); - foreach (IType constraint in this.DirectBaseTypes) { - if (constraint.Kind == TypeKind.Class) { + foreach (IType constraint in this.DirectBaseTypes) + { + if (constraint.Kind == TypeKind.Class) + { classTypeConstraints.Add(constraint); - } else if (constraint.Kind == TypeKind.TypeParameter) { + } + else if (constraint.Kind == TypeKind.TypeParameter) + { IType baseClass = ((ITypeParameter)constraint).EffectiveBaseClass; if (baseClass.Kind == TypeKind.Class) classTypeConstraints.Add(baseClass); @@ -117,23 +124,28 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return this.Compilation.FindType(KnownTypeCode.Object); // Find the derived-most type in the resulting set: IType result = classTypeConstraints[0]; - for (int i = 1; i < classTypeConstraints.Count; i++) { + for (int i = 1; i < classTypeConstraints.Count; i++) + { if (classTypeConstraints[i].GetDefinition().IsDerivedFrom(result.GetDefinition())) result = classTypeConstraints[i]; } return result; } - + IReadOnlyCollection effectiveInterfaceSet; - + public IReadOnlyCollection EffectiveInterfaceSet { get { var result = LazyInit.VolatileRead(ref effectiveInterfaceSet); - if (result != null) { + if (result != null) + { return result; - } else { + } + else + { // protect against cyclic type parameters - using (var busyLock = BusyManager.Enter(this)) { + using (var busyLock = BusyManager.Enter(this)) + { if (!busyLock.Success) return EmptyList.Instance; // don't cache this error return LazyInit.GetOrSet(ref effectiveInterfaceSet, CalculateEffectiveInterfaceSet()); @@ -145,16 +157,20 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IReadOnlyCollection CalculateEffectiveInterfaceSet() { HashSet result = new HashSet(); - foreach (IType constraint in this.DirectBaseTypes) { - if (constraint.Kind == TypeKind.Interface) { + foreach (IType constraint in this.DirectBaseTypes) + { + if (constraint.Kind == TypeKind.Interface) + { result.Add(constraint); - } else if (constraint.Kind == TypeKind.TypeParameter) { + } + else if (constraint.Kind == TypeKind.TypeParameter) + { result.UnionWith(((ITypeParameter)constraint).EffectiveInterfaceSet); } } return result.ToArray(); } - + public abstract bool HasDefaultConstructorConstraint { get; } public abstract bool HasReferenceTypeConstraint { get; } public abstract bool HasValueTypeConstraint { get; } @@ -164,21 +180,24 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public TypeKind Kind { get { return TypeKind.TypeParameter; } } - + public bool? IsReferenceType { get { if (this.HasValueTypeConstraint) return false; if (this.HasReferenceTypeConstraint) return true; - + // A type parameter is known to be a reference type if it has the reference type constraint // or its effective base class is not object or System.ValueType. IType effectiveBaseClass = this.EffectiveBaseClass; - if (effectiveBaseClass.Kind == TypeKind.Class || effectiveBaseClass.Kind == TypeKind.Delegate) { + if (effectiveBaseClass.Kind == TypeKind.Class || effectiveBaseClass.Kind == TypeKind.Delegate) + { ITypeDefinition effectiveBaseClassDef = effectiveBaseClass.GetDefinition(); - if (effectiveBaseClassDef != null) { - switch (effectiveBaseClassDef.KnownTypeCode) { + if (effectiveBaseClassDef != null) + { + switch (effectiveBaseClassDef.KnownTypeCode) + { case KnownTypeCode.Object: case KnownTypeCode.ValueType: case KnownTypeCode.Enum: @@ -186,7 +205,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } } return true; - } else if (effectiveBaseClass.Kind == TypeKind.Struct || effectiveBaseClass.Kind == TypeKind.Enum) { + } + else if (effectiveBaseClass.Kind == TypeKind.Struct || effectiveBaseClass.Kind == TypeKind.Enum) + { return false; } return null; @@ -207,7 +228,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IType IType.DeclaringType { get { return null; } } - + int IType.TypeParameterCount { get { return 0; } } @@ -225,65 +246,70 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } public abstract IReadOnlyList TypeConstraints { get; } - + public string Name { get { return name; } } - + string INamedElement.Namespace { get { return string.Empty; } } - + string INamedElement.FullName { get { return name; } } - + public string ReflectionName { get { return (this.OwnerType == SymbolKind.Method ? "``" : "`") + index.ToString(CultureInfo.InvariantCulture); } } - + ITypeDefinition IType.GetDefinition() { return null; } - + public IType AcceptVisitor(TypeVisitor visitor) { return visitor.VisitTypeParameter(this); } - + public IType VisitChildren(TypeVisitor visitor) { return this; } - + IEnumerable IType.GetNestedTypes(Predicate filter, GetMemberOptions options) { return EmptyList.Instance; } - + IEnumerable IType.GetNestedTypes(IReadOnlyList typeArguments, Predicate filter, GetMemberOptions options) { return EmptyList.Instance; } - + public IEnumerable GetConstructors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - if (this.HasDefaultConstructorConstraint || this.HasValueTypeConstraint) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { + if (this.HasDefaultConstructorConstraint || this.HasValueTypeConstraint) + { var dummyCtor = FakeMethod.CreateDummyConstructor(compilation, this); - if (filter == null || filter(dummyCtor)) { - return new [] { dummyCtor }; + if (filter == null || filter(dummyCtor)) + { + return new[] { dummyCtor }; } } return EmptyList.Instance; - } else { + } + else + { return GetMembersHelper.GetConstructors(this, filter, options); } } - + public IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) @@ -291,7 +317,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation else return GetMembersHelper.GetMethods(this, FilterNonStatic(filter), options); } - + public IEnumerable GetMethods(IReadOnlyList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) @@ -299,7 +325,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation else return GetMembersHelper.GetMethods(this, typeArguments, FilterNonStatic(filter), options); } - + public IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) @@ -307,7 +333,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation else return GetMembersHelper.GetProperties(this, FilterNonStatic(filter), options); } - + public IEnumerable GetFields(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) @@ -315,7 +341,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation else return GetMembersHelper.GetFields(this, FilterNonStatic(filter), options); } - + public IEnumerable GetEvents(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) @@ -323,7 +349,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation else return GetMembersHelper.GetEvents(this, FilterNonStatic(filter), options); } - + public IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) @@ -331,7 +357,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation else return GetMembersHelper.GetMembers(this, FilterNonStatic(filter), options); } - + public IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) @@ -344,7 +370,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { return TypeParameterSubstitution.Identity; } - + static Predicate FilterNonStatic(Predicate filter) where T : class, IMember { if (filter == null) @@ -352,22 +378,22 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation else return member => !member.IsStatic && filter(member); } - + public sealed override bool Equals(object obj) { return Equals(obj as IType); } - + public override int GetHashCode() { return base.GetHashCode(); } - + public virtual bool Equals(IType other) { return this == other; // use reference equality for type parameters } - + public override string ToString() { return this.ReflectionName; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs index 75290771f..6de21c146 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs @@ -20,14 +20,16 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Linq; using System.Reflection.Metadata; -using SRM = System.Reflection.Metadata; -using System.Text; -using ICSharpCode.Decompiler.Util; -using ICSharpCode.Decompiler.Semantics; using System.Runtime.InteropServices; -using System.Linq; +using System.Text; + using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.Semantics; +using ICSharpCode.Decompiler.Util; + +using SRM = System.Reflection.Metadata; namespace ICSharpCode.Decompiler.TypeSystem.Implementation { @@ -88,11 +90,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation Add(new DefaultAttribute(module.GetAttributeType(type), fixedArguments, ImmutableArray.Create>())); } - + #region MarshalAsAttribute (ConvertMarshalInfo) internal void AddMarshalInfo(BlobHandle marshalInfo) { - if (marshalInfo.IsNil) return; + if (marshalInfo.IsNil) + return; var metadata = module.metadata; Add(ConvertMarshalInfo(metadata.GetBlobReader(marshalInfo))); } @@ -106,44 +109,54 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation int type = marshalInfo.ReadByte(); b.AddFixedArg(unmanagedTypeType, type); - + int size; - switch (type) { + switch (type) + { case 0x1e: // FixedArray if (!marshalInfo.TryReadCompressedInteger(out size)) size = 0; b.AddNamedArg("SizeConst", KnownTypeCode.Int32, size); - if (marshalInfo.RemainingBytes > 0) { + if (marshalInfo.RemainingBytes > 0) + { type = marshalInfo.ReadByte(); if (type != 0x66) // None b.AddNamedArg("ArraySubType", unmanagedTypeType, type); } break; case 0x1d: // SafeArray - if (marshalInfo.RemainingBytes > 0) { + if (marshalInfo.RemainingBytes > 0) + { VarEnum varType = (VarEnum)marshalInfo.ReadByte(); - if (varType != VarEnum.VT_EMPTY) { + if (varType != VarEnum.VT_EMPTY) + { var varEnumType = new TopLevelTypeName(InteropServices, nameof(VarEnum)); b.AddNamedArg("SafeArraySubType", varEnumType, (int)varType); } } break; case 0x2a: // NATIVE_TYPE_ARRAY - if (marshalInfo.RemainingBytes > 0) { + if (marshalInfo.RemainingBytes > 0) + { type = marshalInfo.ReadByte(); - } else { + } + else + { type = 0x66; // Cecil uses NativeType.None as default. } - if (type != 0x50) { // Max + if (type != 0x50) + { // Max b.AddNamedArg("ArraySubType", unmanagedTypeType, type); } int sizeParameterIndex = marshalInfo.TryReadCompressedInteger(out int value) ? value : -1; size = marshalInfo.TryReadCompressedInteger(out value) ? value : -1; int sizeParameterMultiplier = marshalInfo.TryReadCompressedInteger(out value) ? value : -1; - if (size >= 0) { + if (size >= 0) + { b.AddNamedArg("SizeConst", KnownTypeCode.Int32, size); } - if (sizeParameterMultiplier != 0 && sizeParameterIndex >= 0) { + if (sizeParameterMultiplier != 0 && sizeParameterIndex >= 0) + { b.AddNamedArg("SizeParamIndex", KnownTypeCode.Int16, (short)sizeParameterIndex); } break; @@ -152,10 +165,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation string unmanagedType = marshalInfo.ReadSerializedString(); string managedType = marshalInfo.ReadSerializedString(); string cookie = marshalInfo.ReadSerializedString(); - if (managedType != null) { + if (managedType != null) + { b.AddNamedArg("MarshalType", KnownTypeCode.String, managedType); } - if (!string.IsNullOrEmpty(cookie)) { + if (!string.IsNullOrEmpty(cookie)) + { b.AddNamedArg("MarshalCookie", KnownTypeCode.String, cookie); } break; @@ -172,12 +187,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public void Add(CustomAttributeHandleCollection attributes, SymbolKind target) { var metadata = module.metadata; - foreach (var handle in attributes) { + foreach (var handle in attributes) + { var attribute = metadata.GetCustomAttribute(handle); // Attribute types shouldn't be generic (and certainly not open), so we don't need a generic context. var ctor = module.ResolveMethod(attribute.Constructor, new GenericContext()); var type = ctor.DeclaringType; - if (IgnoreAttribute(type, target)) { + if (IgnoreAttribute(type, target)) + { continue; } Add(new CustomAttribute(module, ctor, handle)); @@ -188,10 +205,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (attributeType.DeclaringType != null || attributeType.TypeParameterCount != 0) return false; - switch (attributeType.Namespace) { + switch (attributeType.Namespace) + { case "System.Runtime.CompilerServices": var options = module.TypeSystemOptions; - switch (attributeType.Name) { + switch (attributeType.Name) + { case "DynamicAttribute": return (options & TypeSystemOptions.Dynamic) != 0; case "NativeIntegerAttribute": @@ -203,7 +222,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation case "DecimalConstantAttribute": return (options & TypeSystemOptions.DecimalConstants) != 0 && (target == SymbolKind.Field || target == SymbolKind.Parameter); case "IsReadOnlyAttribute": - switch (target) { + switch (target) + { case SymbolKind.TypeDefinition: case SymbolKind.Parameter: return (options & TypeSystemOptions.ReadOnlyStructsAndParameters) != 0; @@ -240,14 +260,20 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public void AddSecurityAttributes(DeclarativeSecurityAttributeHandleCollection securityDeclarations) { var metadata = module.metadata; - foreach (var secDecl in securityDeclarations) { + foreach (var secDecl in securityDeclarations) + { if (secDecl.IsNil) continue; - try { + try + { AddSecurityAttributes(metadata.GetDeclarativeSecurityAttribute(secDecl)); - } catch (EnumUnderlyingTypeResolveException) { + } + catch (EnumUnderlyingTypeResolveException) + { // ignore resolve errors - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { // ignore invalid security declarations } } @@ -259,13 +285,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var securityAction = new CustomAttributeTypedArgument(securityActionType, (int)secDecl.Action); var metadata = module.metadata; var reader = metadata.GetBlobReader(secDecl.PermissionSet); - if (reader.ReadByte() == '.') { + if (reader.ReadByte() == '.') + { // binary attribute int attributeCount = reader.ReadCompressedInteger(); - for (int i = 0; i < attributeCount; i++) { + for (int i = 0; i < attributeCount; i++) + { Add(ReadBinarySecurityAttribute(ref reader, securityAction)); } - } else { + } + else + { // for backward compatibility with .NET 1.0: XML-encoded attribute reader.Reset(); Add(ReadXmlSecurityAttribute(ref reader, securityAction)); @@ -358,7 +388,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { AddNamedArg(name, compilation.FindType(type), value); } - + public void AddNamedArg(string name, IType type, object value) { CustomAttributeNamedArgumentKind kind; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/BaseTypeCollector.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/BaseTypeCollector.cs index 322dfa16a..d1dd98b4b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/BaseTypeCollector.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/BaseTypeCollector.cs @@ -26,17 +26,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation sealed class BaseTypeCollector : List { 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 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: @@ -49,13 +49,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // 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.DirectBaseTypes) { - if (SkipImplementedInterfaces && def != null && def.Kind != TypeKind.Interface && def.Kind != TypeKind.TypeParameter) { - if (baseType.Kind == TypeKind.Interface) { + if (!this.Contains(type)) + { + foreach (IType baseType in type.DirectBaseTypes) + { + if (SkipImplementedInterfaces && def != null && def.Kind != TypeKind.Interface && def.Kind != TypeKind.TypeParameter) + { + if (baseType.Kind == TypeKind.Interface) + { // skip the interface continue; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs index feb191d21..9ef688330 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs @@ -22,6 +22,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -75,22 +76,29 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation void DecodeValue() { - lock (this) { - try { - if (!valueDecoded) { + lock (this) + { + try + { + if (!valueDecoded) + { var metadata = module.metadata; var attr = metadata.GetCustomAttribute(handle); value = attr.DecodeValue(module.TypeProvider); valueDecoded = true; } - } catch (EnumUnderlyingTypeResolveException) { + } + catch (EnumUnderlyingTypeResolveException) + { value = new CustomAttributeValue( ImmutableArray>.Empty, ImmutableArray>.Empty ); hasDecodeErrors = true; valueDecoded = true; // in case of errors, never try again. - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { value = new CustomAttributeValue( ImmutableArray>.Empty, ImmutableArray>.Empty @@ -100,10 +108,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } } } - + internal static IMember MemberForNamedArgument(IType attributeType, CustomAttributeNamedArgument namedArgument) { - switch (namedArgument.Kind) { + switch (namedArgument.Kind) + { case CustomAttributeNamedArgumentKind.Field: return attributeType.GetFields(f => f.Name == namedArgument.Name).LastOrDefault(); case CustomAttributeNamedArgumentKind.Property: diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DecimalConstantHelper.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DecimalConstantHelper.cs index b65fdb5ef..effeb11a1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DecimalConstantHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DecimalConstantHelper.cs @@ -35,7 +35,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public static object GetDecimalConstantValue(MetadataModule module, CustomAttributeHandleCollection attributeHandles) { var metadata = module.metadata; - foreach (var attributeHandle in attributeHandles) { + foreach (var attributeHandle in attributeHandles) + { var attribute = metadata.GetCustomAttribute(attributeHandle); if (attribute.IsKnownAttribute(metadata, KnownAttribute.DecimalConstant)) return TryDecodeDecimalConstantAttribute(module, attribute); @@ -52,17 +53,20 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required. if (!(attrValue.FixedArguments[0].Value is byte scale && attrValue.FixedArguments[1].Value is byte sign)) return null; - unchecked { + unchecked + { if (attrValue.FixedArguments[2].Value is uint hi && attrValue.FixedArguments[3].Value is uint mid - && attrValue.FixedArguments[4].Value is uint lo) { + && attrValue.FixedArguments[4].Value is uint lo) + { return new decimal((int)lo, (int)mid, (int)hi, sign != 0, scale); } } { if (attrValue.FixedArguments[2].Value is int hi && attrValue.FixedArguments[3].Value is int mid - && attrValue.FixedArguments[4].Value is int lo) { + && attrValue.FixedArguments[4].Value is int lo) + { return new decimal(lo, mid, hi, sign != 0, scale); } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAssemblyReference.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAssemblyReference.cs index 2103fbf3e..6c1b4519c 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAssemblyReference.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAssemblyReference.cs @@ -27,9 +27,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public sealed class DefaultAssemblyReference : IModuleReference, ISupportsInterning { public static readonly IModuleReference CurrentAssembly = new CurrentModuleReference(); - + readonly string shortName; - + public DefaultAssemblyReference(string assemblyName) { int pos = assemblyName != null ? assemblyName.IndexOf(',') : -1; @@ -38,37 +38,39 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation else shortName = assemblyName; } - + public IModule Resolve(ITypeResolveContext context) { IModule current = context.CurrentModule; if (current != null && string.Equals(shortName, current.AssemblyName, StringComparison.OrdinalIgnoreCase)) return current; - foreach (IModule asm in context.Compilation.Modules) { + foreach (IModule asm in context.Compilation.Modules) + { if (string.Equals(shortName, asm.AssemblyName, StringComparison.OrdinalIgnoreCase)) return asm; } return null; } - + public override string ToString() { return shortName; } - + int ISupportsInterning.GetHashCodeForInterning() { - unchecked { + unchecked + { return shortName.GetHashCode(); } } - + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { DefaultAssemblyReference o = other as DefaultAssemblyReference; return o != null && shortName == o.shortName; } - + [Serializable] sealed class CurrentModuleReference : IModuleReference { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs index 8e03b96d1..f8a95d1d3 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Util; @@ -58,11 +59,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.attributeType = constructor.DeclaringType ?? SpecialType.UnknownType; this.FixedArguments = fixedArguments; this.NamedArguments = namedArguments; - if (fixedArguments.Length != constructor.Parameters.Count) { + if (fixedArguments.Length != constructor.Parameters.Count) + { throw new ArgumentException("Positional argument count must match the constructor's parameter count"); } } - + public IType AttributeType { get { return attributeType; } } @@ -72,9 +74,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IMethod Constructor { get { IMethod ctor = this.constructor; - if (ctor == null) { - foreach (IMethod candidate in this.AttributeType.GetConstructors(m => m.Parameters.Count == FixedArguments.Length)) { - if (candidate.Parameters.Select(p => p.Type).SequenceEqual(this.FixedArguments.Select(a => a.Type))) { + if (ctor == null) + { + foreach (IMethod candidate in this.AttributeType.GetConstructors(m => m.Parameters.Count == FixedArguments.Length)) + { + if (candidate.Parameters.Select(p => p.Type).SequenceEqual(this.FixedArguments.Select(a => a.Type))) + { ctor = candidate; break; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs index 961d2a81f..b03fcb3f8 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Text; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -35,7 +36,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation readonly bool isParams, isOptional; readonly object defaultValue; readonly IParameterizedMember owner; - + public DefaultParameter(IType type, string name) { if (type == null) @@ -46,9 +47,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.name = name; this.attributes = EmptyList.Instance; } - + public DefaultParameter(IType type, string name, IParameterizedMember owner = null, IReadOnlyList attributes = null, - ReferenceKind referenceKind = ReferenceKind.None, bool isParams = false, bool isOptional = false, object defaultValue = null) + ReferenceKind referenceKind = ReferenceKind.None, bool isParams = false, bool isOptional = false, object defaultValue = null) { if (type == null) throw new ArgumentNullException(nameof(type)); @@ -63,15 +64,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.isOptional = isOptional; this.defaultValue = defaultValue; } - + SymbolKind ISymbol.SymbolKind { get { return SymbolKind.Parameter; } } - + public IParameterizedMember Owner { get { return owner; } } - + public IEnumerable GetAttributes() => attributes; public ReferenceKind ReferenceKind => referenceKind; @@ -86,29 +87,29 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public string Name { get { return name; } } - + public IType Type { get { return type; } } - + bool IVariable.IsConst { get { return false; } } - + public bool HasConstantValueInSignature { get { return IsOptional; } } - + public object GetConstantValue(bool throwOnInvalidMetadata) { return defaultValue; } - + public override string ToString() { return ToString(this); } - + public static string ToString(IParameter parameter) { StringBuilder b = new StringBuilder(); @@ -123,7 +124,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation b.Append(parameter.Name); b.Append(':'); b.Append(parameter.Type.ReflectionName); - if (parameter.IsOptional && parameter.HasConstantValueInSignature) { + if (parameter.IsOptional && parameter.HasConstantValueInSignature) + { b.Append(" = "); object val = parameter.GetConstantValue(throwOnInvalidMetadata: false); if (val != null) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs index 4333be38d..3e4398ec3 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -78,15 +79,18 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { var result = new List(); bool hasNonInterfaceConstraint = false; - if (constraints != null) { - foreach (IType c in constraints) { + if (constraints != null) + { + foreach (IType c in constraints) + { result.Add(new TypeConstraint(c)); if (c.Kind != TypeKind.Interface) hasNonInterfaceConstraint = true; } } // Do not add the 'System.Object' constraint if there is another constraint with a base class. - if (this.HasValueTypeConstraint || !hasNonInterfaceConstraint) { + if (this.HasValueTypeConstraint || !hasNonInterfaceConstraint) + { result.Add(new TypeConstraint(this.Compilation.FindType(this.HasValueTypeConstraint ? KnownTypeCode.ValueType : KnownTypeCode.Object))); } return result; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultVariable.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultVariable.cs index f08b37a4b..c81b8d85d 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultVariable.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultVariable.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation readonly IType type; readonly object constantValue; readonly bool isConst; - + public DefaultVariable(IType type, string name) { if (type == null) @@ -39,32 +39,32 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.type = type; this.name = name; } - + public DefaultVariable(IType type, string name, - bool isConst = false, object constantValue = null) + bool isConst = false, object constantValue = null) : this(type, name) { this.isConst = isConst; this.constantValue = constantValue; } - + public string Name { get { return name; } } - + public IType Type { get { return type; } } - + public bool IsConst { get { return isConst; } } - + public object GetConstantValue(bool throwOnInvalidMetadata) { return constantValue; } - + public SymbolKind SymbolKind { get { return SymbolKind.Variable; } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs index b92b6697f..16f96c6e5 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Threading; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -28,34 +29,39 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation static ITypeParameter[] methodTypeParameters = { new DummyTypeParameter(SymbolKind.Method, 0) }; static ITypeParameter[] classTypeParameters = { new DummyTypeParameter(SymbolKind.TypeDefinition, 0) }; static IReadOnlyList[] classTypeParameterLists = { EmptyList.Instance }; - + public static ITypeParameter GetMethodTypeParameter(int index) { return GetTypeParameter(ref methodTypeParameters, SymbolKind.Method, index); } - + public static ITypeParameter GetClassTypeParameter(int index) { return GetTypeParameter(ref classTypeParameters, SymbolKind.TypeDefinition, index); } - + static ITypeParameter GetTypeParameter(ref ITypeParameter[] typeParameters, SymbolKind symbolKind, int index) { ITypeParameter[] tps = typeParameters; - while (index >= tps.Length) { + while (index >= tps.Length) + { // We don't have a normal type parameter for this index, so we need to extend our array. // Because the array can be used concurrently from multiple threads, we have to use // Interlocked.CompareExchange. ITypeParameter[] newTps = new ITypeParameter[index + 1]; tps.CopyTo(newTps, 0); - for (int i = tps.Length; i < newTps.Length; i++) { + for (int i = tps.Length; i < newTps.Length; i++) + { newTps[i] = new DummyTypeParameter(symbolKind, i); } ITypeParameter[] oldTps = Interlocked.CompareExchange(ref typeParameters, newTps, tps); - if (oldTps == tps) { + if (oldTps == tps) + { // exchange successful tps = newTps; - } else { + } + else + { // exchange not successful tps = oldTps; } @@ -69,96 +75,102 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation internal static IReadOnlyList GetClassTypeParameterList(int length) { IReadOnlyList[] tps = classTypeParameterLists; - while (length >= tps.Length) { + while (length >= tps.Length) + { // We don't have a normal type parameter for this index, so we need to extend our array. // Because the array can be used concurrently from multiple threads, we have to use // Interlocked.CompareExchange. IReadOnlyList[] newTps = new IReadOnlyList[length + 1]; tps.CopyTo(newTps, 0); - for (int i = tps.Length; i < newTps.Length; i++) { + for (int i = tps.Length; i < newTps.Length; i++) + { var newList = new ITypeParameter[i]; - for (int j = 0; j < newList.Length; j++) { + for (int j = 0; j < newList.Length; j++) + { newList[j] = GetClassTypeParameter(j); } newTps[i] = newList; } var oldTps = Interlocked.CompareExchange(ref classTypeParameterLists, newTps, tps); - if (oldTps == tps) { + if (oldTps == tps) + { // exchange successful tps = newTps; - } else { + } + else + { // exchange not successful tps = oldTps; } } return tps[length]; } - + readonly SymbolKind ownerType; readonly int index; - + private DummyTypeParameter(SymbolKind ownerType, int index) { this.ownerType = ownerType; this.index = index; } - + SymbolKind ISymbol.SymbolKind { get { return SymbolKind.TypeParameter; } } - + public override string Name { get { return (ownerType == SymbolKind.Method ? "!!" : "!") + index; } } - + public override string ReflectionName { get { return (ownerType == SymbolKind.Method ? "``" : "`") + index; } } - + public override string ToString() { return ReflectionName + " (dummy)"; } - + public override bool? IsReferenceType { get { return null; } } - + public override TypeKind Kind { get { return TypeKind.TypeParameter; } } - + public override IType AcceptVisitor(TypeVisitor visitor) { return visitor.VisitTypeParameter(this); } - + public int Index { get { return index; } } - - IEnumerable ITypeParameter.GetAttributes() =>EmptyList.Instance; - + + IEnumerable ITypeParameter.GetAttributes() => EmptyList.Instance; + SymbolKind ITypeParameter.OwnerType { get { return ownerType; } } - + VarianceModifier ITypeParameter.Variance { get { return VarianceModifier.Invariant; } } - + IEntity ITypeParameter.Owner { get { return null; } } - + IType ITypeParameter.EffectiveBaseClass { get { return SpecialType.UnknownType; } } - + IReadOnlyCollection ITypeParameter.EffectiveInterfaceSet { get { return EmptyList.Instance; } } @@ -173,9 +185,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override IType ChangeNullability(Nullability nullability) { - if (nullability == Nullability.Oblivious) { + if (nullability == Nullability.Oblivious) + { return this; - } else { + } + else + { return new NullabilityAnnotatedTypeParameter(this, nullability); } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs index 837539720..e1ca453c2 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Reflection; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -130,7 +131,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } public override SymbolKind SymbolKind => symbolKind; - + IEnumerable IMethod.GetReturnTypeAttributes() => EmptyList.Instance; bool IMethod.ReturnTypeIsRefReadOnly => false; bool IMethod.ThisIsRefReadOnly => false; @@ -154,7 +155,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IMethod IMethod.ReducedFrom => null; public IReadOnlyList Parameters { get; set; } = EmptyList.Instance; - + public override IMember Specialize(TypeParameterSubstitution substitution) { return SpecializedMethod.Create(this, substitution); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/GetClassTypeReference.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/GetClassTypeReference.cs index b8b3f368a..0c161ca5c 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/GetClassTypeReference.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/GetClassTypeReference.cs @@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.module = module; this.isReferenceType = isReferenceType; } - + /// /// Creates a new GetClassTypeReference that searches a top-level type in all assemblies. /// @@ -78,15 +78,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation /// of the compilation. /// public IModuleReference Module { get { return module; } } - + /// /// Gets the full name of the type this reference is searching for. /// public FullTypeName FullTypeName { get { return fullTypeName; } } - + internal static IType ResolveInAllAssemblies(ICompilation compilation, in FullTypeName fullTypeName) { - foreach (var asm in compilation.Modules) { + foreach (var asm in compilation.Modules) + { IType type = asm.GetTypeDefinition(fullTypeName); if (type != null) return type; @@ -98,43 +99,52 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (context == null) throw new ArgumentNullException(nameof(context)); - + IType type = null; - if (module == null) { + if (module == null) + { // No assembly specified: look in all assemblies, but prefer the current assembly - if (context.CurrentModule != null) { + if (context.CurrentModule != null) + { type = context.CurrentModule.GetTypeDefinition(fullTypeName); } - if (type == null) { + if (type == null) + { type = ResolveInAllAssemblies(context.Compilation, in fullTypeName); } - } else { + } + else + { // Assembly specified: only look in the specified assembly. // But if that's not loaded in the compilation, allow fall back to other assemblies. // (the non-loaded assembly might be a facade containing type forwarders - // for example, when referencing a portable library from a non-portable project) IModule asm = module.Resolve(context); - if (asm != null) { + if (asm != null) + { type = asm.GetTypeDefinition(fullTypeName); - } else { + } + else + { type = ResolveInAllAssemblies(context.Compilation, in fullTypeName); } } return type ?? new UnknownType(fullTypeName, isReferenceType); } - + public override string ToString() { return fullTypeName.ToString() + (module != null ? ", " + module.ToString() : null); } - + int ISupportsInterning.GetHashCodeForInterning() { - unchecked { + unchecked + { return 33 * module.GetHashCode() + fullTypeName.GetHashCode(); } } - + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { GetClassTypeReference o = other as GetClassTypeReference; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/GetMembersHelper.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/GetMembersHelper.cs index d0c2505cd..a160a4499 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/GetMembersHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/GetMembersHelper.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -39,42 +40,52 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { return GetNestedTypes(type, null, filter, options); } - + public static IEnumerable GetNestedTypes(IType type, IReadOnlyList nestedTypeArguments, Predicate filter, GetMemberOptions options) { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetNestedTypesImpl(type, nestedTypeArguments, filter, options); - } else { + } + else + { return type.GetNonInterfaceBaseTypes().SelectMany(t => GetNestedTypesImpl(t, nestedTypeArguments, filter, options)); } } - + static IEnumerable GetNestedTypesImpl(IType outerType, IReadOnlyList nestedTypeArguments, 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) { + foreach (ITypeDefinition nestedType in outerTypeDef.NestedTypes) + { int totalTypeParameterCount = nestedType.TypeParameterCount; - if (nestedTypeArguments != null) { + if (nestedTypeArguments != null) + { if (totalTypeParameterCount - outerTypeParameterCount != nestedTypeArguments.Count) continue; } if (!(filter == null || filter(nestedType))) continue; - - if (totalTypeParameterCount == 0 || (options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { + + if (totalTypeParameterCount == 0 || (options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + { yield return nestedType; - } else { + } + else + { // We need to parameterize the nested type IType[] newTypeArguments = new IType[totalTypeParameterCount]; - for (int i = 0; i < outerTypeParameterCount; i++) { + for (int i = 0; i < outerTypeParameterCount; i++) + { newTypeArguments[i] = pt != null ? pt.GetTypeArgument(i) : outerTypeDef.TypeParameters[i]; } - for (int i = outerTypeParameterCount; i < totalTypeParameterCount; i++) { + for (int i = outerTypeParameterCount; i < totalTypeParameterCount; i++) + { if (nestedTypeArguments != null) newTypeArguments[i] = nestedTypeArguments[i - outerTypeParameterCount]; else @@ -85,48 +96,55 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } } #endregion - + #region GetMethods public static IEnumerable GetMethods(IType type, Predicate filter, GetMemberOptions options) { return GetMethods(type, null, filter, options); } - + public static IEnumerable GetMethods(IType type, IReadOnlyList typeArguments, Predicate filter, GetMemberOptions options) { - if (typeArguments != null && typeArguments.Count > 0) { + if (typeArguments != null && typeArguments.Count > 0) + { filter = FilterTypeParameterCount(typeArguments.Count).And(filter); } - - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetMethodsImpl(type, typeArguments, filter, options); - } else { + } + else + { return type.GetNonInterfaceBaseTypes().SelectMany(t => GetMethodsImpl(t, typeArguments, 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, IReadOnlyList methodTypeArguments, Predicate filter, GetMemberOptions options) { IEnumerable declaredMethods = baseType.GetMethods(filter, options | declaredMembers); - + ParameterizedType pt = baseType as ParameterizedType; if ((options & GetMemberOptions.ReturnMemberDefinitions) == 0 - && (pt != null || (methodTypeArguments != null && methodTypeArguments.Count > 0))) + && (pt != null || (methodTypeArguments != null && methodTypeArguments.Count > 0))) { TypeParameterSubstitution substitution = null; - foreach (IMethod m in declaredMethods) { - if (methodTypeArguments != null && methodTypeArguments.Count > 0) { + foreach (IMethod m in declaredMethods) + { + if (methodTypeArguments != null && methodTypeArguments.Count > 0) + { if (m.TypeParameters.Count != methodTypeArguments.Count) continue; } - if (substitution == null) { + if (substitution == null) + { if (pt != null) substitution = pt.GetSubstitution(methodTypeArguments); else @@ -134,152 +152,189 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } yield return new SpecializedMethod(m, substitution); } - } else { - foreach (IMethod m in declaredMethods) { + } + else + { + foreach (IMethod m in declaredMethods) + { yield return m; } } } #endregion - + #region GetAccessors public static IEnumerable GetAccessors(IType type, Predicate filter, GetMemberOptions options) { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetAccessorsImpl(type, filter, options); - } else { + } + else + { return type.GetNonInterfaceBaseTypes().SelectMany(t => GetAccessorsImpl(t, filter, options)); } } - + static IEnumerable GetAccessorsImpl(IType baseType, Predicate filter, GetMemberOptions options) { return GetConstructorsOrAccessorsImpl(baseType, baseType.GetAccessors(filter, options | declaredMembers), options); } #endregion - + #region GetConstructors public static IEnumerable GetConstructors(IType type, Predicate filter, GetMemberOptions options) { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetConstructorsImpl(type, filter, options); - } else { + } + else + { return type.GetNonInterfaceBaseTypes().SelectMany(t => GetConstructorsImpl(t, filter, options)); } } - + static IEnumerable GetConstructorsImpl(IType baseType, Predicate filter, GetMemberOptions options) { return GetConstructorsOrAccessorsImpl(baseType, baseType.GetConstructors(filter, options | declaredMembers), options); } - + static IEnumerable GetConstructorsOrAccessorsImpl(IType baseType, IEnumerable declaredMembers, GetMemberOptions options) { - if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + { return declaredMembers; } - + ParameterizedType pt = baseType as ParameterizedType; - if (pt != null) { + if (pt != null) + { var substitution = pt.GetSubstitution(); return declaredMembers.Select(m => new SpecializedMethod(m, substitution) { DeclaringType = pt }); - } else { + } + else + { return declaredMembers; } } #endregion - + #region GetProperties public static IEnumerable GetProperties(IType type, Predicate filter, GetMemberOptions options) { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetPropertiesImpl(type, filter, options); - } else { + } + else + { return type.GetNonInterfaceBaseTypes().SelectMany(t => GetPropertiesImpl(t, filter, options)); } } - + static IEnumerable GetPropertiesImpl(IType baseType, Predicate filter, GetMemberOptions options) { IEnumerable declaredProperties = baseType.GetProperties(filter, options | declaredMembers); - if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + { return declaredProperties; } - + ParameterizedType pt = baseType as ParameterizedType; - if (pt != null) { + if (pt != null) + { var substitution = pt.GetSubstitution(); return declaredProperties.Select(m => new SpecializedProperty(m, substitution) { DeclaringType = pt }); - } else { + } + else + { return declaredProperties; } } #endregion - + #region GetFields public static IEnumerable GetFields(IType type, Predicate filter, GetMemberOptions options) { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetFieldsImpl(type, filter, options); - } else { + } + else + { return type.GetNonInterfaceBaseTypes().SelectMany(t => GetFieldsImpl(t, filter, options)); } } - + static IEnumerable GetFieldsImpl(IType baseType, Predicate filter, GetMemberOptions options) { IEnumerable declaredFields = baseType.GetFields(filter, options | declaredMembers); - if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + { return declaredFields; } - + ParameterizedType pt = baseType as ParameterizedType; - if (pt != null) { + if (pt != null) + { var substitution = pt.GetSubstitution(); return declaredFields.Select(m => new SpecializedField(m, substitution) { DeclaringType = pt }); - } else { + } + else + { return declaredFields; } } #endregion - + #region GetEvents public static IEnumerable GetEvents(IType type, Predicate filter, GetMemberOptions options) { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetEventsImpl(type, filter, options); - } else { + } + else + { return type.GetNonInterfaceBaseTypes().SelectMany(t => GetEventsImpl(t, filter, options)); } } - + static IEnumerable GetEventsImpl(IType baseType, Predicate filter, GetMemberOptions options) { IEnumerable declaredEvents = baseType.GetEvents(filter, options | declaredMembers); - if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + { return declaredEvents; } - + ParameterizedType pt = baseType as ParameterizedType; - if (pt != null) { + if (pt != null) + { var substitution = pt.GetSubstitution(); return declaredEvents.Select(m => new SpecializedEvent(m, substitution) { DeclaringType = pt }); - } else { + } + else + { return declaredEvents; } } #endregion - + #region GetMembers public static IEnumerable GetMembers(IType type, Predicate filter, GetMemberOptions options) { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetMembersImpl(type, filter, options); - } else { + } + else + { return type.GetNonInterfaceBaseTypes().SelectMany(t => GetMembersImpl(t, filter, options)); } } - + static IEnumerable GetMembersImpl(IType baseType, Predicate filter, GetMemberOptions options) { foreach (var m in GetMethodsImpl(baseType, null, filter, options)) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs index f55cdb36f..e73f0ec3d 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.Decompiler.TypeSystem InternalsVisibleTo, TypeForwardedTo, ReferenceAssembly, - + // Type attributes: Serializable, Flags, @@ -182,7 +182,8 @@ namespace ICSharpCode.Decompiler.TypeSystem { if (!attributeType.GetNonInterfaceBaseTypes().Any(t => t.IsKnownType(KnownTypeCode.Attribute))) return KnownAttribute.None; - for (int i = 1; i < typeNames.Length; i++) { + for (int i = 1; i < typeNames.Length; i++) + { if (typeNames[i] == attributeType.FullTypeName) return (KnownAttribute)i; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownTypeCache.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownTypeCache.cs index 242bbb6a9..0970a3b53 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownTypeCache.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/KnownTypeCache.cs @@ -27,28 +27,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { readonly ICompilation compilation; readonly IType[] knownTypes = new IType[KnownTypeReference.KnownTypeCodeCount]; - + public KnownTypeCache(ICompilation compilation) { this.compilation = compilation; } - + public IType FindType(KnownTypeCode typeCode) { IType type = LazyInit.VolatileRead(ref knownTypes[(int)typeCode]); - if (type != null) { + if (type != null) + { return type; } return LazyInit.GetOrSet(ref knownTypes[(int)typeCode], SearchType(typeCode)); } - + IType SearchType(KnownTypeCode typeCode) { KnownTypeReference typeRef = KnownTypeReference.Get(typeCode); if (typeRef == null) return SpecialType.UnknownType; var typeName = new TopLevelTypeName(typeRef.Namespace, typeRef.Name, typeRef.TypeParameterCount); - foreach (IModule asm in compilation.Modules) { + foreach (IModule asm in compilation.Modules) + { var typeDef = asm.GetTypeDefinition(typeName); if (typeDef != null) return typeDef; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs index 1e14fa85b..240ccaed8 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -61,7 +62,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation && NumberOfCompilerGeneratedTypeParameters == other.NumberOfCompilerGeneratedTypeParameters && IsStaticLocalFunction == other.IsStaticLocalFunction; } - + public override int GetHashCode() { return baseMethod.GetHashCode(); @@ -94,7 +95,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation baseMethod.Specialize(substitution), Name, IsStaticLocalFunction, NumberOfCompilerGeneratedParameters, NumberOfCompilerGeneratedTypeParameters); } - + IMember IMember.Specialize(TypeParameterSubstitution substitution) { return Specialize(substitution); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MergedNamespace.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MergedNamespace.cs index 34aec4a4c..31a332ad7 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MergedNamespace.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MergedNamespace.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -34,7 +35,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation readonly INamespace parentNamespace; readonly INamespace[] namespaces; Dictionary childNamespaces; - + /// /// Creates a new merged root namespace. /// @@ -51,7 +52,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.namespaces = namespaces; this.externAlias = externAlias; } - + /// /// Creates a new merged child namespace. /// @@ -68,45 +69,45 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.compilation = parentNamespace.Compilation; this.externAlias = parentNamespace.ExternAlias; } - + public string ExternAlias { get { return externAlias; } } - + public string FullName { get { return namespaces[0].FullName; } } - + public string Name { get { return namespaces[0].Name; } } - + public INamespace ParentNamespace { get { return parentNamespace; } } - + public IEnumerable Types { get { return namespaces.SelectMany(ns => ns.Types); } } - + public SymbolKind SymbolKind { get { return SymbolKind.Namespace; } } - + public ICompilation Compilation { get { return compilation; } } - + public IEnumerable ContributingModules { get { return namespaces.SelectMany(ns => ns.ContributingModules); } } - + public IEnumerable ChildNamespaces { get { return GetChildNamespaces().Values; } } - + public INamespace GetChildNamespace(string name) { INamespace ns; @@ -115,28 +116,35 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation else return null; } - + Dictionary GetChildNamespaces() { var result = LazyInit.VolatileRead(ref this.childNamespaces); - if (result != null) { + if (result != null) + { return result; - } else { + } + else + { result = new Dictionary(compilation.NameComparer); - foreach (var g in namespaces.SelectMany(ns => ns.ChildNamespaces).GroupBy(ns => ns.Name, compilation.NameComparer)) { + foreach (var g in namespaces.SelectMany(ns => ns.ChildNamespaces).GroupBy(ns => ns.Name, compilation.NameComparer)) + { result.Add(g.Key, new MergedNamespace(this, g.ToArray())); } return LazyInit.GetOrSet(ref this.childNamespaces, result); } } - + public ITypeDefinition GetTypeDefinition(string name, int typeParameterCount) { ITypeDefinition anyTypeDef = null; - foreach (var ns in namespaces) { + foreach (var ns in namespaces) + { ITypeDefinition typeDef = ns.GetTypeDefinition(name, typeParameterCount); - if (typeDef != null) { - if (typeDef.Accessibility == Accessibility.Public) { + if (typeDef != null) + { + if (typeDef.Accessibility == Accessibility.Public) + { // Prefer accessible types over non-accessible types. return typeDef; // || (typeDef.IsInternal && typeDef.ParentAssembly.InternalsVisibleTo(...)) @@ -149,11 +157,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } return anyTypeDef; } - + public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "[MergedNamespace {0}{1} (from {2} assemblies)]", - externAlias != null ? externAlias + "::" : null, this.FullName, this.namespaces.Length); + externAlias != null ? externAlias + "::" : null, this.FullName, this.namespaces.Length); } } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs index cd59290b7..1ad755cd2 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs @@ -25,6 +25,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Util; @@ -60,7 +61,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public EntityHandle MetadataToken => handle; public string Name => name; - + SymbolKind ISymbol.SymbolKind => SymbolKind.Event; public bool CanAdd => !accessors.Adder.IsNil; @@ -134,7 +135,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override bool Equals(object obj) { - if (obj is MetadataEvent ev) { + if (obj is MetadataEvent ev) + { return handle == ev.handle && module.PEFile == ev.module.PEFile; } return false; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs index 0e24e62c2..16c44187d 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs @@ -23,6 +23,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Threading; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -42,7 +43,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation object constantValue; IType type; bool isVolatile; // initialized together with this.type - // this can't be bool? as bool? is not thread-safe from torn reads + // this can't be bool? as bool? is not thread-safe from torn reads byte decimalConstantState; internal MetadataField(MetadataModule module, FieldDefinitionHandle handle) @@ -78,7 +79,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public Accessibility Accessibility { get { - switch (attributes & FieldAttributes.FieldAccessMask) { + switch (attributes & FieldAttributes.FieldAccessMask) + { case FieldAttributes.Public: return Accessibility.Public; case FieldAttributes.FamANDAssem: @@ -97,7 +99,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool IsReadOnly => (attributes & FieldAttributes.InitOnly) != 0; public bool IsStatic => (attributes & FieldAttributes.Static) != 0; - + SymbolKind ISymbol.SymbolKind => SymbolKind.Field; IMember IMember.MemberDefinition => this; TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity; @@ -114,9 +116,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public ITypeDefinition DeclaringTypeDefinition { get { var declType = LazyInit.VolatileRead(ref this.declaringType); - if (declType != null) { + if (declType != null) + { return declType; - } else { + } + else + { var def = module.metadata.GetFieldDefinition(handle); return LazyInit.GetOrSet(ref this.declaringType, module.GetDefinition(def.GetDeclaringType())); @@ -127,7 +132,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IType DeclaringType => DeclaringTypeDefinition; public IModule ParentModule => module; public ICompilation Compilation => module.Compilation; - + public IEnumerable GetAttributes() { var b = new AttributeListBuilder(module); @@ -136,12 +141,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // FieldOffsetAttribute int offset = fieldDef.GetOffset(); - if (offset != -1) { + if (offset != -1) + { b.Add(KnownAttribute.FieldOffset, KnownTypeCode.Int32, offset); } // NonSerializedAttribute - if ((fieldDef.Attributes & FieldAttributes.NotSerialized) != 0) { + if ((fieldDef.Attributes & FieldAttributes.NotSerialized) != 0) + { b.Add(KnownAttribute.NonSerialized); } @@ -157,7 +164,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool IsVolatile { get { - if (LazyInit.VolatileRead(ref this.type) == null) { + if (LazyInit.VolatileRead(ref this.type) == null) + { DecodeTypeAndVolatileFlag(); } return this.isVolatile; @@ -167,7 +175,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IType Type { get { var ty = LazyInit.VolatileRead(ref this.type); - if (ty != null) { + if (ty != null) + { return ty; } return DecodeTypeAndVolatileFlag(); @@ -179,16 +188,20 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var metadata = module.metadata; var fieldDef = metadata.GetFieldDefinition(handle); IType ty; - try { + try + { ty = fieldDef.DecodeSignature(module.TypeProvider, new GenericContext(DeclaringType?.TypeParameters)); - if (ty is ModifiedType mod && mod.Modifier.Name == "IsVolatile" && mod.Modifier.Namespace == "System.Runtime.CompilerServices") { + if (ty is ModifiedType mod && mod.Modifier.Name == "IsVolatile" && mod.Modifier.Namespace == "System.Runtime.CompilerServices") + { Volatile.Write(ref this.isVolatile, true); ty = mod.ElementType; } ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, Compilation, fieldDef.GetCustomAttributes(), metadata, module.OptionsForEntity(this), DeclaringTypeDefinition?.NullableContext ?? Nullability.Oblivious); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { ty = SpecialType.UnknownType; } return LazyInit.GetOrSet(ref this.type, ty); @@ -199,7 +212,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation bool IsDecimalConstant { get { - if (decimalConstantState == ThreeState.Unknown) { + if (decimalConstantState == ThreeState.Unknown) + { var fieldDef = module.metadata.GetFieldDefinition(handle); decimalConstantState = ThreeState.From(DecimalConstantHelper.IsDecimalConstant(module, fieldDef.GetCustomAttributes())); } @@ -212,32 +226,42 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation object val = LazyInit.VolatileRead(ref this.constantValue); if (val != null) return val; - try { + try + { var metadata = module.metadata; var fieldDef = metadata.GetFieldDefinition(handle); - if (IsDecimalConstant && DecimalConstantHelper.AllowsDecimalConstants(module)) { + if (IsDecimalConstant && DecimalConstantHelper.AllowsDecimalConstants(module)) + { val = DecimalConstantHelper.GetDecimalConstantValue(module, fieldDef.GetCustomAttributes()); - } else { + } + else + { var constantHandle = fieldDef.GetDefaultValue(); if (constantHandle.IsNil) return null; var constant = metadata.GetConstant(constantHandle); var blobReader = metadata.GetBlobReader(constant.Value); - try { + try + { val = blobReader.ReadConstant(constant.TypeCode); - } catch (ArgumentOutOfRangeException) { + } + catch (ArgumentOutOfRangeException) + { throw new BadImageFormatException($"Constant with invalid typecode: {constant.TypeCode}"); } } return LazyInit.GetOrSet(ref this.constantValue, val); - } catch (BadImageFormatException) when (!throwOnInvalidMetadata) { + } + catch (BadImageFormatException) when (!throwOnInvalidMetadata) + { return null; } } public override bool Equals(object obj) { - if (obj is MetadataField f) { + if (obj is MetadataField f) + { return handle == f.handle && module.PEFile == f.module.PEFile; } return false; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs index a015d7d3d..442a851d1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs @@ -25,6 +25,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -65,19 +66,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.symbolKind = SymbolKind.Method; var (accessorOwner, semanticsAttribute) = module.PEFile.MethodSemanticsLookup.GetSemantics(handle); const MethodAttributes finalizerAttributes = (MethodAttributes.Virtual | MethodAttributes.Family | MethodAttributes.HideBySig); - if (semanticsAttribute != 0) { + if (semanticsAttribute != 0) + { this.symbolKind = SymbolKind.Accessor; this.accessorOwner = accessorOwner; this.AccessorKind = semanticsAttribute; - } else if ((attributes & (MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)) != 0) { + } + else if ((attributes & (MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)) != 0) + { string name = this.Name; if (name == ".cctor" || name == ".ctor") this.symbolKind = SymbolKind.Constructor; else if (name.StartsWith("op_", StringComparison.Ordinal)) this.symbolKind = SymbolKind.Operator; - } else if ((attributes & finalizerAttributes) == finalizerAttributes) { + } + else if ((attributes & finalizerAttributes) == finalizerAttributes) + { string name = this.Name; - if (name == "Finalize" && Parameters.Count == 0) { + if (name == "Finalize" && Parameters.Count == 0) + { this.symbolKind = SymbolKind.Destructor; } } @@ -174,11 +181,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IType returnType; IParameter[] parameters; ModifiedType mod; - try { + try + { var nullableContext = methodDef.GetCustomAttributes().GetNullableContext(module.metadata) ?? DeclaringTypeDefinition.NullableContext; var signature = methodDef.DecodeSignature(module.TypeProvider, genericContext); (returnType, parameters, mod) = DecodeSignature(module, this, signature, methodDef.GetParameters(), nullableContext, module.OptionsForEntity(this)); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { returnType = SpecialType.UnknownType; parameters = Empty.Array; mod = null; @@ -199,24 +209,31 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IParameter[] parameters = new IParameter[signature.RequiredParameterCount + (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs ? 1 : 0)]; IType parameterType; - if (parameterHandles != null) { - foreach (var parameterHandle in parameterHandles) { + if (parameterHandles != null) + { + foreach (var parameterHandle in parameterHandles) + { var par = metadata.GetParameter(parameterHandle); - if (par.SequenceNumber == 0) { + if (par.SequenceNumber == 0) + { // "parameter" holds return type attributes. // Note: for properties, the attributes normally stored on a method's return type // are instead stored as normal attributes on the property. // So MetadataProperty provides a non-null value for returnTypeAttributes, // which then should be preferred over the attributes on the accessor's parameters. - if (returnTypeAttributes == null) { + if (returnTypeAttributes == null) + { returnTypeAttributes = par.GetCustomAttributes(); } - } else if (par.SequenceNumber > 0 && i < signature.RequiredParameterCount) { + } + else if (par.SequenceNumber > 0 && i < signature.RequiredParameterCount) + { // "Successive rows of the Param table that are owned by the same method shall be // ordered by increasing Sequence value - although gaps in the sequence are allowed" Debug.Assert(i < par.SequenceNumber); // Fill gaps in the sequence with non-metadata parameters: - while (i < par.SequenceNumber - 1) { + while (i < par.SequenceNumber - 1) + { parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType( signature.ParameterTypes[i], module.Compilation, null, metadata, typeSystemOptions, nullableContext); parameters[i] = new DefaultParameter(parameterType, name: string.Empty, owner, @@ -231,14 +248,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } } } - while (i < signature.RequiredParameterCount) { + while (i < signature.RequiredParameterCount) + { parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType( signature.ParameterTypes[i], module.Compilation, null, metadata, typeSystemOptions, nullableContext); parameters[i] = new DefaultParameter(parameterType, name: string.Empty, owner, referenceKind: parameterType.Kind == TypeKind.ByReference ? ReferenceKind.Ref : ReferenceKind.None); i++; } - if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { + if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) + { parameters[i] = new DefaultParameter(SpecialType.ArgList, name: string.Empty, owner); i++; } @@ -272,9 +291,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public ITypeDefinition DeclaringTypeDefinition { get { var declType = LazyInit.VolatileRead(ref this.declaringType); - if (declType != null) { + if (declType != null) + { return declType; - } else { + } + else + { var def = module.metadata.GetMethodDefinition(handle); return LazyInit.GetOrSet(ref this.declaringType, module.GetDefinition(def.GetDeclaringType())); @@ -305,7 +327,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation #region DllImportAttribute var info = def.GetImport(); - if ((attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl && !info.Module.IsNil) { + if ((attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl && !info.Module.IsNil) + { var dllImport = new AttributeBuilder(module, KnownAttribute.DllImport); dllImport.AddFixedArg(KnownTypeCode.String, metadata.GetString(metadata.GetModuleReference(info.Module).Name)); @@ -317,7 +340,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation dllImport.AddNamedArg("BestFitMapping", KnownTypeCode.Boolean, true); CallingConvention callingConvention; - switch (info.Attributes & MethodImportAttributes.CallingConventionMask) { + switch (info.Attributes & MethodImportAttributes.CallingConventionMask) + { case 0: Debug.WriteLine($"P/Invoke calling convention not set on: {this}"); callingConvention = 0; @@ -340,13 +364,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation default: throw new NotSupportedException("unknown calling convention"); } - if (callingConvention != CallingConvention.Winapi) { + if (callingConvention != CallingConvention.Winapi) + { var callingConventionType = FindInteropType(nameof(CallingConvention)); dllImport.AddNamedArg("CallingConvention", callingConventionType, (int)callingConvention); } CharSet charSet = CharSet.None; - switch (info.Attributes & MethodImportAttributes.CharSetMask) { + switch (info.Attributes & MethodImportAttributes.CharSetMask) + { case MethodImportAttributes.CharSetAnsi: charSet = CharSet.Ansi; break; @@ -357,22 +383,28 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation charSet = CharSet.Unicode; break; } - if (charSet != CharSet.None) { + if (charSet != CharSet.None) + { var charSetType = FindInteropType(nameof(CharSet)); dllImport.AddNamedArg("CharSet", charSetType, (int)charSet); } - if (!info.Name.IsNil && info.Name != def.Name) { + if (!info.Name.IsNil && info.Name != def.Name) + { dllImport.AddNamedArg("EntryPoint", KnownTypeCode.String, metadata.GetString(info.Name)); } - if ((info.Attributes & MethodImportAttributes.ExactSpelling) == MethodImportAttributes.ExactSpelling) { + if ((info.Attributes & MethodImportAttributes.ExactSpelling) == MethodImportAttributes.ExactSpelling) + { dllImport.AddNamedArg("ExactSpelling", KnownTypeCode.Boolean, true); } - if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig) { + if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig) + { implAttributes &= ~MethodImplAttributes.PreserveSig; - } else { + } + else + { dllImport.AddNamedArg("PreserveSig", KnownTypeCode.Boolean, false); } @@ -389,14 +421,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation #endregion #region PreserveSigAttribute - if (implAttributes == MethodImplAttributes.PreserveSig) { + if (implAttributes == MethodImplAttributes.PreserveSig) + { b.Add(KnownAttribute.PreserveSig); implAttributes = 0; } #endregion #region MethodImplAttribute - if (implAttributes != 0) { + if (implAttributes != 0) + { b.Add(KnownAttribute.MethodImpl, new TopLevelTypeName("System.Runtime.CompilerServices", nameof(MethodImplOptions)), (int)implAttributes @@ -418,9 +452,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var metadata = module.metadata; var methodDefinition = metadata.GetMethodDefinition(handle); var parameters = methodDefinition.GetParameters(); - if (parameters.Count > 0) { + if (parameters.Count > 0) + { var retParam = metadata.GetParameter(parameters.First()); - if (retParam.SequenceNumber == 0) { + if (retParam.SequenceNumber == 0) + { b.AddMarshalInfo(retParam.GetMarshallingDescriptor()); b.Add(retParam.GetCustomAttributes(), SymbolKind.ReturnType); } @@ -430,16 +466,19 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool ReturnTypeIsRefReadOnly { get { - if (returnTypeIsRefReadonly != ThreeState.Unknown) { + if (returnTypeIsRefReadonly != ThreeState.Unknown) + { return returnTypeIsRefReadonly == ThreeState.True; } var metadata = module.metadata; var methodDefinition = metadata.GetMethodDefinition(handle); var parameters = methodDefinition.GetParameters(); bool hasReadOnlyAttr = false; - if (parameters.Count > 0) { + if (parameters.Count > 0) + { var retParam = metadata.GetParameter(parameters.First()); - if (retParam.SequenceNumber == 0) { + if (retParam.SequenceNumber == 0) + { hasReadOnlyAttr = retParam.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.IsReadOnly); } } @@ -450,13 +489,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool ThisIsRefReadOnly { get { - if (thisIsRefReadonly != ThreeState.Unknown) { + if (thisIsRefReadonly != ThreeState.Unknown) + { return thisIsRefReadonly == ThreeState.True; } var metadata = module.metadata; var methodDefinition = metadata.GetMethodDefinition(handle); bool hasReadOnlyAttr = DeclaringTypeDefinition?.IsReadOnly ?? false; - if ((module.TypeSystemOptions & TypeSystemOptions.ReadOnlyMethods) != 0) { + if ((module.TypeSystemOptions & TypeSystemOptions.ReadOnlyMethods) != 0) + { hasReadOnlyAttr |= methodDefinition.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.IsReadOnly); } this.thisIsRefReadonly = ThreeState.From(hasReadOnlyAttr); @@ -470,7 +511,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation internal static Accessibility GetAccessibility(MethodAttributes attr) { - switch (attr & MethodAttributes.MemberAccessMask) { + switch (attr & MethodAttributes.MemberAccessMask) + { case MethodAttributes.Public: return Accessibility.Public; case MethodAttributes.Assembly: @@ -503,7 +545,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override bool Equals(object obj) { - if (obj is MetadataMethod m) { + if (obj is MetadataMethod m) + { return handle == m.handle && module.PEFile == m.module.PEFile; } return false; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataNamespace.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataNamespace.cs index 5d5d5052e..6a35f8568 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataNamespace.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataNamespace.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -51,12 +52,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IEnumerable ChildNamespaces { get { var children = LazyInit.VolatileRead(ref childNamespaces); - if (children != null) { + if (children != null) + { return children; } var nsDefs = ns.NamespaceDefinitions; children = new INamespace[nsDefs.Length]; - for (int i = 0; i < children.Length; i++) { + for (int i = 0; i < children.Length; i++) + { var nsHandle = nsDefs[i]; string fullName = module.metadata.GetString(nsHandle); children[i] = new MetadataNamespace(module, this, fullName, @@ -68,7 +71,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IEnumerable INamespace.Types { get { - foreach (var typeHandle in ns.TypeDefinitions) { + foreach (var typeHandle in ns.TypeDefinitions) + { var def = module.GetDefinition(typeHandle); if (def != null) yield return def; @@ -84,7 +88,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation INamespace INamespace.GetChildNamespace(string name) { - foreach (var ns in ChildNamespaces) { + foreach (var ns in ChildNamespaces) + { if (ns.Name == name) return ns; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs index 562d14ec7..5820d9c21 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs @@ -22,6 +22,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -66,7 +67,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation if (IsOptional && !HasConstantValueInSignature) b.Add(KnownAttribute.Optional); - if (!IsOut && !IsIn) { + if (!IsOut && !IsIn) + { if ((attributes & ParameterAttributes.In) == ParameterAttributes.In) b.Add(KnownAttribute.In); if ((attributes & ParameterAttributes.Out) == ParameterAttributes.Out) @@ -94,7 +96,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return ReferenceKind.None; if ((attributes & inOut) == ParameterAttributes.Out) return ReferenceKind.Out; - if ((module.TypeSystemOptions & TypeSystemOptions.ReadOnlyStructsAndParameters) != 0) { + if ((module.TypeSystemOptions & TypeSystemOptions.ReadOnlyStructsAndParameters) != 0) + { var metadata = module.metadata; var parameterDef = metadata.GetParameter(handle); if (parameterDef.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.IsReadOnly)) @@ -128,7 +131,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public object GetConstantValue(bool throwOnInvalidMetadata) { - try { + try + { var metadata = module.metadata; var parameterDef = metadata.GetParameter(handle); if (IsDecimalConstant) @@ -140,23 +144,31 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var constant = metadata.GetConstant(constantHandle); var blobReader = metadata.GetBlobReader(constant.Value); - try { + try + { return blobReader.ReadConstant(constant.TypeCode); - } catch (ArgumentOutOfRangeException) { + } + catch (ArgumentOutOfRangeException) + { throw new BadImageFormatException($"Constant with invalid typecode: {constant.TypeCode}"); } - } catch (BadImageFormatException) when (!throwOnInvalidMetadata) { + } + catch (BadImageFormatException) when (!throwOnInvalidMetadata) + { return null; } } public bool HasConstantValueInSignature { get { - if (constantValueInSignatureState == ThreeState.Unknown) { - if (IsDecimalConstant) { + if (constantValueInSignatureState == ThreeState.Unknown) + { + if (IsDecimalConstant) + { constantValueInSignatureState = ThreeState.From(DecimalConstantHelper.AllowsDecimalConstants(module)); } - else { + else + { constantValueInSignatureState = ThreeState.From(!module.metadata.GetParameter(handle).GetDefaultValue().IsNil); } } @@ -166,7 +178,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation bool IsDecimalConstant { get { - if (decimalConstantState == ThreeState.Unknown) { + if (decimalConstantState == ThreeState.Unknown) + { var parameterDef = module.metadata.GetParameter(handle); decimalConstantState = ThreeState.From(DecimalConstantHelper.IsDecimalConstant(module, parameterDef.GetCustomAttributes())); } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs index 2f33e3d17..b0dd16219 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs @@ -22,6 +22,7 @@ using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -56,13 +57,18 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation setter = module.GetDefinition(accessors.Setter); name = metadata.GetString(prop.Name); // Maybe we should defer the calculation of symbolKind? - if (DetermineIsIndexer(name)) { + if (DetermineIsIndexer(name)) + { symbolKind = SymbolKind.Indexer; - } else if (name.IndexOf('.') >= 0) { + } + else if (name.IndexOf('.') >= 0) + { // explicit interface implementation var interfaceProp = this.ExplicitlyImplementedInterfaceMembers.FirstOrDefault() as IProperty; symbolKind = interfaceProp?.SymbolKind ?? SymbolKind.Property; - } else { + } + else + { symbolKind = SymbolKind.Property; } } @@ -126,23 +132,29 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var genericContext = new GenericContext(DeclaringType.TypeParameters); IType returnType; IParameter[] parameters; - try { + try + { var signature = propertyDef.DecodeSignature(module.TypeProvider, genericContext); var accessors = propertyDef.GetAccessors(); var declTypeDef = this.DeclaringTypeDefinition; ParameterHandleCollection? parameterHandles; Nullability nullableContext; - if (!accessors.Getter.IsNil) { + if (!accessors.Getter.IsNil) + { var getter = module.metadata.GetMethodDefinition(accessors.Getter); parameterHandles = getter.GetParameters(); nullableContext = getter.GetCustomAttributes().GetNullableContext(module.metadata) ?? declTypeDef?.NullableContext ?? Nullability.Oblivious; - } else if (!accessors.Setter.IsNil) { + } + else if (!accessors.Setter.IsNil) + { var setter = module.metadata.GetMethodDefinition(accessors.Setter); parameterHandles = setter.GetParameters(); nullableContext = setter.GetCustomAttributes().GetNullableContext(module.metadata) ?? declTypeDef?.NullableContext ?? Nullability.Oblivious; - } else { + } + else + { parameterHandles = null; nullableContext = declTypeDef?.NullableContext ?? Nullability.Oblivious; } @@ -157,7 +169,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation module, this, signature, parameterHandles, nullableContext, typeOptions, returnTypeAttributes: propertyDef.GetCustomAttributes()); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { returnType = SpecialType.UnknownType; parameters = Empty.Array; } @@ -187,7 +201,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var b = new AttributeListBuilder(module); var metadata = module.metadata; var propertyDef = metadata.GetPropertyDefinition(propertyHandle); - if (IsIndexer && Name != "Item" && !IsExplicitInterfaceImplementation) { + if (IsIndexer && Name != "Item" && !IsExplicitInterfaceImplementation) + { b.Add(KnownAttribute.IndexerName, KnownTypeCode.String, Name); } b.Add(propertyDef.GetCustomAttributes(), symbolKind); @@ -208,8 +223,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation Accessibility ComputeAccessibility() { - if (IsOverride && (getter == null || setter == null)) { - foreach (var baseMember in InheritanceHelper.GetBaseMembers(this, includeImplementedInterfaces: false)) { + if (IsOverride && (getter == null || setter == null)) + { + foreach (var baseMember in InheritanceHelper.GetBaseMembers(this, includeImplementedInterfaces: false)) + { if (!baseMember.IsOverride) return baseMember.Accessibility; } @@ -236,7 +253,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override bool Equals(object obj) { - if (obj is MetadataProperty p) { + if (obj is MetadataProperty p) + { return propertyHandle == p.propertyHandle && module.PEFile == p.module.PEFile; } return false; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs index 6ca831740..4abfd390b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs @@ -26,6 +26,7 @@ using System.Reflection.Metadata.Ecma335; using System.Runtime.InteropServices; using System.Text; using System.Threading; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Util; @@ -73,47 +74,64 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.attributes = td.Attributes; this.fullTypeName = td.GetFullTypeName(metadata); // Find DeclaringType + KnownTypeCode: - if (fullTypeName.IsNested) { + if (fullTypeName.IsNested) + { this.DeclaringTypeDefinition = module.GetDefinition(td.GetDeclaringType()); - + // Create type parameters: this.TypeParameters = MetadataTypeParameter.Create(module, this.DeclaringTypeDefinition, this, td.GetGenericParameters()); this.NullableContext = td.GetCustomAttributes().GetNullableContext(metadata) ?? this.DeclaringTypeDefinition.NullableContext; - } else { + } + else + { // Create type parameters: this.TypeParameters = MetadataTypeParameter.Create(module, this, td.GetGenericParameters()); this.NullableContext = td.GetCustomAttributes().GetNullableContext(metadata) ?? module.NullableContext; var topLevelTypeName = fullTypeName.TopLevelTypeName; - for (int i = 0; i < KnownTypeReference.KnownTypeCodeCount; i++) { + for (int i = 0; i < KnownTypeReference.KnownTypeCodeCount; i++) + { var ktr = KnownTypeReference.Get((KnownTypeCode)i); - if (ktr != null && ktr.TypeName == topLevelTypeName) { + if (ktr != null && ktr.TypeName == topLevelTypeName) + { this.KnownTypeCode = (KnownTypeCode)i; break; } } } // Find type kind: - if ((attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface) { + if ((attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface) + { this.Kind = TypeKind.Interface; - } else if (td.IsEnum(metadata, out var underlyingType)) { + } + else if (td.IsEnum(metadata, out var underlyingType)) + { this.Kind = TypeKind.Enum; this.EnumUnderlyingType = module.Compilation.FindType(underlyingType.ToKnownTypeCode()); - } else if (td.IsValueType(metadata)) { - if (KnownTypeCode == KnownTypeCode.Void) { + } + else if (td.IsValueType(metadata)) + { + if (KnownTypeCode == KnownTypeCode.Void) + { this.Kind = TypeKind.Void; - } else { + } + else + { this.Kind = TypeKind.Struct; this.IsByRefLike = (module.TypeSystemOptions & TypeSystemOptions.RefStructs) == TypeSystemOptions.RefStructs && td.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.IsByRefLike); this.IsReadOnly = (module.TypeSystemOptions & TypeSystemOptions.ReadOnlyStructsAndParameters) == TypeSystemOptions.ReadOnlyStructsAndParameters && td.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.IsReadOnly); } - } else if (td.IsDelegate(metadata)) { + } + else if (td.IsDelegate(metadata)) + { this.Kind = TypeKind.Delegate; - } else { + } + else + { this.Kind = TypeKind.Class; this.HasExtensionMethods = this.IsStatic && (module.TypeSystemOptions & TypeSystemOptions.ExtensionMethods) == TypeSystemOptions.ExtensionMethods @@ -136,7 +154,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var metadata = module.metadata; var nestedTypeCollection = metadata.GetTypeDefinition(handle).GetNestedTypes(); var nestedTypeList = new List(nestedTypeCollection.Length); - foreach (TypeDefinitionHandle h in nestedTypeCollection) { + foreach (TypeDefinitionHandle h in nestedTypeCollection) + { nestedTypeList.Add(module.GetDefinition(h)); } if ((module.TypeSystemOptions & TypeSystemOptions.Uncached) != 0) @@ -166,10 +185,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var metadata = module.metadata; var fieldCollection = metadata.GetTypeDefinition(handle).GetFields(); var fieldList = new List(fieldCollection.Count); - foreach (FieldDefinitionHandle h in fieldCollection) { + foreach (FieldDefinitionHandle h in fieldCollection) + { var field = metadata.GetFieldDefinition(h); var attr = field.Attributes; - if (module.IsVisible(attr)) { + if (module.IsVisible(attr)) + { fieldList.Add(module.GetDefinition(h)); } } @@ -187,12 +208,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var metadata = module.metadata; var propertyCollection = metadata.GetTypeDefinition(handle).GetProperties(); var propertyList = new List(propertyCollection.Count); - foreach (PropertyDefinitionHandle h in propertyCollection) { + foreach (PropertyDefinitionHandle h in propertyCollection) + { var property = metadata.GetPropertyDefinition(h); var accessors = property.GetAccessors(); bool getterVisible = !accessors.Getter.IsNil && module.IsVisible(metadata.GetMethodDefinition(accessors.Getter).Attributes); bool setterVisible = !accessors.Setter.IsNil && module.IsVisible(metadata.GetMethodDefinition(accessors.Setter).Attributes); - if (getterVisible || setterVisible) { + if (getterVisible || setterVisible) + { propertyList.Add(module.GetDefinition(h)); } } @@ -210,13 +233,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var metadata = module.metadata; var eventCollection = metadata.GetTypeDefinition(handle).GetEvents(); var eventList = new List(eventCollection.Count); - foreach (EventDefinitionHandle h in eventCollection) { + foreach (EventDefinitionHandle h in eventCollection) + { var ev = metadata.GetEventDefinition(h); var accessors = ev.GetAccessors(); if (accessors.Adder.IsNil) continue; var addMethod = metadata.GetMethodDefinition(accessors.Adder); - if (module.IsVisible(addMethod.Attributes)) { + if (module.IsVisible(addMethod.Attributes)) + { eventList.Add(module.GetDefinition(h)); } } @@ -235,13 +260,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var methodsCollection = metadata.GetTypeDefinition(handle).GetMethods(); var methodsList = new List(methodsCollection.Count); var methodSemantics = module.PEFile.MethodSemanticsLookup; - foreach (MethodDefinitionHandle h in methodsCollection) { + foreach (MethodDefinitionHandle h in methodsCollection) + { var md = metadata.GetMethodDefinition(h); - if (methodSemantics.GetSemantics(h).Item2 == 0 && module.IsVisible(md.Attributes)) { + if (methodSemantics.GetSemantics(h).Item2 == 0 && module.IsVisible(md.Attributes)) + { methodsList.Add(module.GetDefinition(h)); } } - if (this.Kind == TypeKind.Struct || this.Kind == TypeKind.Enum) { + if (this.Kind == TypeKind.Struct || this.Kind == TypeKind.Enum) + { methodsList.Add(FakeMethod.CreateDummyConstructor(Compilation, this, IsAbstract ? Accessibility.Protected : Accessibility.Public)); } if ((module.TypeSystemOptions & TypeSystemOptions.Uncached) != 0) @@ -255,7 +283,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool? IsReferenceType { get { - switch (Kind) { + switch (Kind) + { case TypeKind.Struct: case TypeKind.Enum: case TypeKind.Void: @@ -291,22 +320,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var interfaceImplCollection = td.GetInterfaceImplementations(); baseTypes = new List(1 + interfaceImplCollection.Count); IType baseType = null; - try { + try + { EntityHandle baseTypeHandle = td.BaseType; - if (!baseTypeHandle.IsNil) { + if (!baseTypeHandle.IsNil) + { baseType = module.ResolveType(baseTypeHandle, context); } - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { baseType = SpecialType.UnknownType; } - if (baseType != null) { + if (baseType != null) + { baseTypes.Add(baseType); - } else if (Kind == TypeKind.Interface) { + } + else if (Kind == TypeKind.Interface) + { // td.BaseType.IsNil is always true for interfaces, // but the type system expects every interface to derive from System.Object as well. baseTypes.Add(Compilation.FindType(KnownTypeCode.Object)); } - foreach (var h in interfaceImplCollection) { + foreach (var h in interfaceImplCollection) + { var iface = metadata.GetInterfaceImplementation(h); baseTypes.Add(module.ResolveType(iface.Interface, context, iface.GetCustomAttributes(), Nullability.Oblivious)); } @@ -338,7 +375,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation #region StructLayoutAttribute LayoutKind layoutKind = LayoutKind.Auto; - switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) { + switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) + { case TypeAttributes.SequentialLayout: layoutKind = LayoutKind.Sequential; break; @@ -347,7 +385,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation break; } CharSet charSet = CharSet.None; - switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) { + switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) + { case TypeAttributes.AnsiClass: charSet = CharSet.Ansi; break; @@ -360,19 +399,23 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } var layout = typeDefinition.GetLayout(); LayoutKind defaultLayoutKind = Kind == TypeKind.Struct ? LayoutKind.Sequential : LayoutKind.Auto; - if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || layout.PackingSize > 0 || layout.Size > 0) { + if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || layout.PackingSize > 0 || layout.Size > 0) + { var structLayout = new AttributeBuilder(module, KnownAttribute.StructLayout); structLayout.AddFixedArg( new TopLevelTypeName("System.Runtime.InteropServices", "LayoutKind"), (int)layoutKind); - if (charSet != CharSet.Ansi) { + if (charSet != CharSet.Ansi) + { var charSetType = Compilation.FindType(new TopLevelTypeName("System.Runtime.InteropServices", "CharSet")); structLayout.AddNamedArg("CharSet", charSetType, (int)charSet); } - if (layout.PackingSize > 0) { + if (layout.PackingSize > 0) + { structLayout.AddNamedArg("Pack", KnownTypeCode.Int32, (int)layout.PackingSize); } - if (layout.Size > 0) { + if (layout.Size > 0) + { structLayout.AddNamedArg("Size", KnownTypeCode.Int32, (int)layout.Size); } b.Add(structLayout.Build()); @@ -392,12 +435,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return defaultMemberName; var metadata = module.metadata; var typeDefinition = metadata.GetTypeDefinition(handle); - foreach (var h in typeDefinition.GetCustomAttributes()) { + foreach (var h in typeDefinition.GetCustomAttributes()) + { var a = metadata.GetCustomAttribute(h); if (!a.IsKnownAttribute(metadata, KnownAttribute.DefaultMember)) continue; var value = a.DecodeValue(module.TypeProvider); - if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is string name) { + if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is string name) + { defaultMemberName = name; break; } @@ -409,7 +454,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public Accessibility Accessibility { get { - switch (attributes & TypeAttributes.VisibilityMask) { + switch (attributes & TypeAttributes.VisibilityMask) + { case TypeAttributes.NotPublic: case TypeAttributes.NestedAssembly: return Accessibility.Internal; @@ -467,7 +513,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override bool Equals(object obj) { - if (obj is MetadataTypeDefinition td) { + if (obj is MetadataTypeDefinition td) + { return handle == td.handle && module.PEFile == td.module.PEFile; } return false; @@ -487,13 +534,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IEnumerable GetNestedTypes(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { const GetMemberOptions opt = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions; - if ((options & opt) == opt) { + if ((options & opt) == opt) + { return GetFiltered(this.NestedTypes, filter); - } else { + } + else + { return GetMembersHelper.GetNestedTypes(this, filter, options); } } - + public IEnumerable GetNestedTypes(IReadOnlyList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return GetMembersHelper.GetNestedTypes(this, typeArguments, filter, options); @@ -511,7 +561,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IEnumerable ApplyFilter(IEnumerable input, Predicate filter) where T : class { - foreach (var member in input) { + foreach (var member in input) + { if (filter(member)) yield return member; } @@ -521,9 +572,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (Kind == TypeKind.Void) return EmptyList.Instance; - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetFiltered(this.Methods, ExtensionMethods.And(m => !m.IsConstructor, filter)); - } else { + } + else + { return GetMembersHelper.GetMethods(this, filter, options); } } @@ -539,19 +593,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (Kind == TypeKind.Void) return EmptyList.Instance; - if (ComHelper.IsComImport(this)) { + if (ComHelper.IsComImport(this)) + { IType coClass = ComHelper.GetCoClass(this); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { + using (var busyLock = BusyManager.Enter(this)) + { + if (busyLock.Success) + { return coClass.GetConstructors(filter, options) .Select(m => new SpecializedMethod(m, m.Substitution) { DeclaringType = this }); } } return EmptyList.Instance; } - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetFiltered(this.Methods, ExtensionMethods.And(m => m.IsConstructor && !m.IsStatic, filter)); - } else { + } + else + { return GetMembersHelper.GetConstructors(this, filter, options); } } @@ -560,9 +620,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (Kind == TypeKind.Void) return EmptyList.Instance; - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetFiltered(this.Properties, filter); - } else { + } + else + { return GetMembersHelper.GetProperties(this, filter, options); } } @@ -571,9 +634,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (Kind == TypeKind.Void) return EmptyList.Instance; - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetFiltered(this.Fields, filter); - } else { + } + else + { return GetMembersHelper.GetFields(this, filter, options); } } @@ -582,9 +648,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (Kind == TypeKind.Void) return EmptyList.Instance; - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetFiltered(this.Events, filter); - } else { + } + else + { return GetMembersHelper.GetEvents(this, filter, options); } } @@ -593,27 +662,34 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { if (Kind == TypeKind.Void) return EmptyList.Instance; - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetFiltered(this.Members, filter); - } else { + } + else + { return GetMembersHelper.GetMembers(this, filter, options); } } - + public IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if (Kind == TypeKind.Void) return EmptyList.Instance; - if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + { return GetFilteredAccessors(filter); - } else { + } + else + { return GetMembersHelper.GetAccessors(this, filter, options); } } IEnumerable GetFilteredAccessors(Predicate filter) { - foreach (var prop in this.Properties) { + foreach (var prop in this.Properties) + { var getter = prop.Getter; if (getter != null && (filter == null || filter(getter))) yield return getter; @@ -621,7 +697,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation if (setter != null && (filter == null || filter(setter))) yield return setter; } - foreach (var ev in this.Events) { + foreach (var ev in this.Events) + { var adder = ev.AddAccessor; if (adder != null && (filter == null || filter(adder))) yield return adder; @@ -640,7 +717,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { var metadata = module.metadata; var td = metadata.GetTypeDefinition(handle); - foreach (var implHandle in td.GetMethodImplementations()) { + foreach (var implHandle in td.GetMethodImplementations()) + { var impl = metadata.GetMethodImplementation(implHandle); if (impl.MethodBody == method) yield return module.ResolveMethod(impl.MethodDeclaration, new GenericContext(this.TypeParameters)); @@ -651,7 +729,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { var metadata = module.metadata; var td = metadata.GetTypeDefinition(handle); - foreach (var implHandle in td.GetMethodImplementations()) { + foreach (var implHandle in td.GetMethodImplementations()) + { var impl = metadata.GetMethodImplementation(implHandle); if (impl.MethodBody == method) return true; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs index aef3b2db4..58bc4ca1b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs @@ -23,6 +23,7 @@ using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -47,7 +48,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var outerTps = copyFromOuter.TypeParameters; var tps = new ITypeParameter[handles.Count]; int i = 0; - foreach (var handle in handles) { + foreach (var handle in handles) + { if (i < outerTps.Count) tps[i] = outerTps[i]; else @@ -63,7 +65,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return Empty.Array; var tps = new ITypeParameter[handles.Count]; int i = 0; - foreach (var handle in handles) { + foreach (var handle in handles) + { tps[i] = Create(module, owner, i, handle); i++; } @@ -89,7 +92,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation private static VarianceModifier GetVariance(GenericParameterAttributes attr) { - switch (attr & GenericParameterAttributes.VarianceMask) { + switch (attr & GenericParameterAttributes.VarianceMask) + { case GenericParameterAttributes.Contravariant: return VarianceModifier.Contravariant; case GenericParameterAttributes.Covariant: @@ -118,7 +122,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override bool HasUnmanagedConstraint { get { - if (unmanagedConstraint == ThreeState.Unknown) { + if (unmanagedConstraint == ThreeState.Unknown) + { unmanagedConstraint = ThreeState.From(LoadUnmanagedConstraint()); } return unmanagedConstraint == ThreeState.True; @@ -136,7 +141,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override Nullability NullabilityConstraint { get { - if (nullabilityConstraint == nullabilityNotYetLoaded) { + if (nullabilityConstraint == nullabilityNotYetLoaded) + { nullabilityConstraint = (byte)LoadNullabilityConstraint(); } return (Nullability)nullabilityConstraint; @@ -151,22 +157,31 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var metadata = module.metadata; var gp = metadata.GetGenericParameter(handle); - foreach (var handle in gp.GetCustomAttributes()) { + foreach (var handle in gp.GetCustomAttributes()) + { var customAttribute = metadata.GetCustomAttribute(handle); - if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.Nullable)) { + if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.Nullable)) + { var attrVal = customAttribute.DecodeValue(module.TypeProvider); - if (attrVal.FixedArguments.Length == 1) { - if (attrVal.FixedArguments[0].Value is byte b && b <= 2) { + if (attrVal.FixedArguments.Length == 1) + { + if (attrVal.FixedArguments[0].Value is byte b && b <= 2) + { return (Nullability)b; } } } } - if (Owner is MetadataMethod method) { + if (Owner is MetadataMethod method) + { return method.NullableContext; - } else if (Owner is ITypeDefinition td) { + } + else if (Owner is ITypeDefinition td) + { return td.NullableContext; - } else { + } + else + { return Nullability.Oblivious; } } @@ -174,7 +189,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override IReadOnlyList TypeConstraints { get { var constraints = LazyInit.VolatileRead(ref this.constraints); - if (constraints == null) { + if (constraints == null) + { constraints = LazyInit.GetOrSet(ref this.constraints, DecodeConstraints()); } return constraints; @@ -186,33 +202,45 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var metadata = module.metadata; var gp = metadata.GetGenericParameter(handle); Nullability nullableContext; - if (Owner is ITypeDefinition typeDef) { + if (Owner is ITypeDefinition typeDef) + { nullableContext = typeDef.NullableContext; - } else if (Owner is MetadataMethod method) { + } + else if (Owner is MetadataMethod method) + { nullableContext = method.NullableContext; - } else { + } + else + { nullableContext = Nullability.Oblivious; } var constraintHandleCollection = gp.GetConstraints(); var result = new List(constraintHandleCollection.Count + 1); bool hasNonInterfaceConstraint = false; - foreach (var constraintHandle in constraintHandleCollection) { + foreach (var constraintHandle in constraintHandleCollection) + { var constraint = metadata.GetGenericParameterConstraint(constraintHandle); var attrs = constraint.GetCustomAttributes(); var ty = module.ResolveType(constraint.Type, new GenericContext(Owner), attrs, nullableContext); - if (attrs.Count == 0) { + if (attrs.Count == 0) + { result.Add(new TypeConstraint(ty)); - } else { + } + else + { AttributeListBuilder b = new AttributeListBuilder(module); b.Add(attrs, SymbolKind.Constraint); result.Add(new TypeConstraint(ty, b.Build())); } hasNonInterfaceConstraint |= (ty.Kind != TypeKind.Interface); } - if (this.HasValueTypeConstraint) { + if (this.HasValueTypeConstraint) + { result.Add(new TypeConstraint(Compilation.FindType(KnownTypeCode.ValueType))); - } else if (!hasNonInterfaceConstraint) { + } + else if (!hasNonInterfaceConstraint) + { result.Add(new TypeConstraint(Compilation.FindType(KnownTypeCode.Object))); } return result; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs index 5874e8c29..376f5c5f5 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -67,7 +68,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName) { - foreach (var typeDef in typeDefinitions) { + foreach (var typeDef in typeDefinitions) + { if (typeDef.FullTypeName == topLevelTypeName) return typeDef; } @@ -172,7 +174,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation bool? IType.IsReferenceType { get { - switch (typeKind) { + switch (typeKind) + { case TypeKind.Class: case TypeKind.Interface: return true; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/NestedTypeReference.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/NestedTypeReference.cs index 03096f53d..2380c7730 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/NestedTypeReference.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/NestedTypeReference.cs @@ -52,32 +52,34 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.additionalTypeParameterCount = additionalTypeParameterCount; this.isReferenceType = isReferenceType; } - + 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; - if (declaringType != null) { + if (declaringType != null) + { int tpc = declaringType.TypeParameterCount; - foreach (IType type in declaringType.NestedTypes) { + foreach (IType type in declaringType.NestedTypes) + { if (type.Name == name && type.TypeParameterCount == tpc + additionalTypeParameterCount) return type; } } return new UnknownType(null, name, additionalTypeParameterCount); } - + public override string ToString() { if (additionalTypeParameterCount == 0) @@ -85,16 +87,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation else return declaringTypeRef + "+" + name + "`" + additionalTypeParameterCount; } - + int ISupportsInterning.GetHashCodeForInterning() { return declaringTypeRef.GetHashCode() ^ name.GetHashCode() ^ additionalTypeParameterCount; } - + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { NestedTypeReference o = other as NestedTypeReference; - return o != null && declaringTypeRef == o.declaringTypeRef && name == o.name + return o != null && declaringTypeRef == o.declaringTypeRef && name == o.name && additionalTypeParameterCount == o.additionalTypeParameterCount && isReferenceType == o.isReferenceType; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs index 3b93a66a7..7a41c50c0 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs @@ -52,26 +52,34 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override IType VisitChildren(TypeVisitor visitor) { IType newBase = baseType.AcceptVisitor(visitor); - if (newBase != baseType) { - if (newBase.Nullability == Nullability.Nullable) { + if (newBase != baseType) + { + if (newBase.Nullability == Nullability.Nullable) + { // `T!` with substitution T=`U?` becomes `U?` // This happens during type substitution for generic methods. return newBase; } - if (newBase.Kind == TypeKind.TypeParameter || newBase.IsReferenceType == true) { + if (newBase.Kind == TypeKind.TypeParameter || newBase.IsReferenceType == true) + { return newBase.ChangeNullability(nullability); - } else { + } + else + { // `T!` with substitution T=`int` becomes `int`, not `int!` return newBase; } - } else { + } + else + { return this; } } public override string ToString() { - switch (nullability) { + switch (nullability) + { case Nullability.Nullable: return $"{baseType.ToString()}?"; case Nullability.NotNullable: diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/PinnedType.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/PinnedType.cs index 0e9e1d732..14bcdd899 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/PinnedType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/PinnedType.cs @@ -17,13 +17,15 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; -using SRM = System.Reflection.Metadata; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; -using System.Collections.Generic; -using System.Diagnostics; + +using SRM = System.Reflection.Metadata; namespace ICSharpCode.Decompiler.TypeSystem.Implementation { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SimpleCompilation.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SimpleCompilation.cs index 7ca5cd549..ade71cf71 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SimpleCompilation.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SimpleCompilation.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -34,7 +35,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IReadOnlyList referencedAssemblies; bool initialized; INamespace rootNamespace; - + public SimpleCompilation(IModuleReference mainAssembly, params IModuleReference[] assemblyReferences) { Init(mainAssembly, assemblyReferences); @@ -60,11 +61,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation List assemblies = new List(); assemblies.Add(this.mainModule); List referencedAssemblies = new List(); - foreach (var asmRef in assemblyReferences) { + foreach (var asmRef in assemblyReferences) + { IModule asm; - try { + try + { asm = asmRef.Resolve(context); - } catch (InvalidOperationException) { + } + catch (InvalidOperationException) + { throw new InvalidOperationException("Tried to initialize compilation with an invalid assembly reference. (Forgot to load the assembly reference ? - see CecilLoader)"); } if (asm != null && !assemblies.Contains(asm)) @@ -85,7 +90,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return mainModule; } } - + public IReadOnlyList Modules { get { if (!initialized) @@ -93,7 +98,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return assemblies; } } - + public IReadOnlyList ReferencedModules { get { if (!initialized) @@ -101,36 +106,40 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return referencedAssemblies; } } - + public INamespace RootNamespace { get { INamespace ns = LazyInit.VolatileRead(ref this.rootNamespace); - if (ns != null) { + if (ns != null) + { return ns; - } else { + } + else + { if (!initialized) throw new InvalidOperationException("Compilation isn't initialized yet"); return LazyInit.GetOrSet(ref this.rootNamespace, CreateRootNamespace()); } } } - + protected virtual INamespace CreateRootNamespace() { // SimpleCompilation does not support extern aliases; but derived classes might. // CreateRootNamespace() is virtual so that derived classes can change the global namespace. INamespace[] namespaces = new INamespace[referencedAssemblies.Count + 1]; namespaces[0] = mainModule.RootNamespace; - for (int i = 0; i < referencedAssemblies.Count; i++) { + for (int i = 0; i < referencedAssemblies.Count; i++) + { namespaces[i + 1] = referencedAssemblies[i].RootNamespace; } return new MergedNamespace(this, namespaces); } - + public CacheManager CacheManager { get { return cacheManager; } } - + public virtual INamespace GetNamespaceForExternAlias(string alias) { if (string.IsNullOrEmpty(alias)) @@ -138,16 +147,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // SimpleCompilation does not support extern aliases; but derived classes might. return null; } - + public IType FindType(KnownTypeCode typeCode) { return knownTypeCache.FindType(typeCode); } - + public StringComparer NameComparer { get { return StringComparer.Ordinal; } } - + public override string ToString() { return "[" + GetType().Name + " " + mainModule.AssemblyName + "]"; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedEvent.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedEvent.cs index d40a42b2b..756445879 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedEvent.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedEvent.cs @@ -28,7 +28,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public static IEvent Create(IEvent ev, TypeParameterSubstitution substitution) { if (TypeParameterSubstitution.Identity.Equals(substitution) - || ev.DeclaringType.TypeParameterCount == 0) { + || ev.DeclaringType.TypeParameterCount == 0) + { return ev; } if (substitution.MethodTypeArguments != null && substitution.MethodTypeArguments.Count > 0) @@ -37,36 +38,36 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } readonly IEvent eventDefinition; - + public SpecializedEvent(IEvent eventDefinition, TypeParameterSubstitution substitution) : base(eventDefinition) { this.eventDefinition = eventDefinition; AddSubstitution(substitution); } - + public bool CanAdd { get { return eventDefinition.CanAdd; } } - + public bool CanRemove { get { return eventDefinition.CanRemove; } } - + public bool CanInvoke { get { return eventDefinition.CanInvoke; } } - + IMethod addAccessor, removeAccessor, invokeAccessor; - + public IMethod AddAccessor { get { return WrapAccessor(ref this.addAccessor, eventDefinition.AddAccessor); } } - + public IMethod RemoveAccessor { get { return WrapAccessor(ref this.removeAccessor, eventDefinition.RemoveAccessor); } } - + public IMethod InvokeAccessor { get { return WrapAccessor(ref this.invokeAccessor, eventDefinition.InvokeAccessor); } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedField.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedField.cs index 7e8e66312..ac0dc9c40 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedField.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedField.cs @@ -27,7 +27,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { internal static IField Create(IField fieldDefinition, TypeParameterSubstitution substitution) { - if (TypeParameterSubstitution.Identity.Equals(substitution) || fieldDefinition.DeclaringType.TypeParameterCount == 0) { + if (TypeParameterSubstitution.Identity.Equals(substitution) || fieldDefinition.DeclaringType.TypeParameterCount == 0) + { return fieldDefinition; } if (substitution.MethodTypeArguments != null && substitution.MethodTypeArguments.Count > 0) @@ -36,7 +37,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } readonly IField fieldDefinition; - + public SpecializedField(IField fieldDefinition, TypeParameterSubstitution substitution) : base(fieldDefinition) { @@ -47,20 +48,21 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool IsReadOnly { get { return fieldDefinition.IsReadOnly; } } - + public bool IsVolatile { get { return fieldDefinition.IsVolatile; } } - + IType IVariable.Type { get { return this.ReturnType; } } - + public bool IsConst { get { return fieldDefinition.IsConst; } } - public object GetConstantValue(bool throwOnInvalidMetadata) { + public object GetConstantValue(bool throwOnInvalidMetadata) + { return fieldDefinition.GetConstantValue(throwOnInvalidMetadata); } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs index 9b88d0aef..50a2405d8 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs @@ -22,6 +22,7 @@ using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -33,21 +34,21 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { protected readonly IMember baseMember; TypeParameterSubstitution substitution; - + IType declaringType; IType returnType; - + protected SpecializedMember(IMember memberDefinition) { if (memberDefinition == null) throw new ArgumentNullException(nameof(memberDefinition)); if (memberDefinition is SpecializedMember) throw new ArgumentException("Member definition cannot be specialized. Please use IMember.Specialize() instead of directly constructing SpecializedMember instances."); - + this.baseMember = memberDefinition; this.substitution = TypeParameterSubstitution.Identity; } - + /// /// Performs a substitution. This method may only be called by constructors in derived classes. /// @@ -57,28 +58,31 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation Debug.Assert(returnType == null); this.substitution = TypeParameterSubstitution.Compose(newSubstitution, this.substitution); } - + internal IMethod WrapAccessor(ref IMethod cachingField, IMethod accessorDefinition) { if (accessorDefinition == null) return null; var result = LazyInit.VolatileRead(ref cachingField); - if (result != null) { + if (result != null) + { return result; - } else { + } + else + { var sm = accessorDefinition.Specialize(substitution); //sm.AccessorOwner = this; return LazyInit.GetOrSet(ref cachingField, sm); } } - + /// /// Gets the substitution belonging to this specialized member. /// public TypeParameterSubstitution Substitution { get { return substitution; } } - + public IType DeclaringType { get { var result = LazyInit.VolatileRead(ref this.declaringType); @@ -86,13 +90,19 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return result; IType definitionDeclaringType = baseMember.DeclaringType; ITypeDefinition definitionDeclaringTypeDef = definitionDeclaringType as ITypeDefinition; - if (definitionDeclaringTypeDef != null && definitionDeclaringType.TypeParameterCount > 0) { - if (substitution.ClassTypeArguments != null && substitution.ClassTypeArguments.Count == definitionDeclaringType.TypeParameterCount) { + if (definitionDeclaringTypeDef != null && definitionDeclaringType.TypeParameterCount > 0) + { + if (substitution.ClassTypeArguments != null && substitution.ClassTypeArguments.Count == definitionDeclaringType.TypeParameterCount) + { result = new ParameterizedType(definitionDeclaringTypeDef, substitution.ClassTypeArguments); - } else { + } + else + { result = new ParameterizedType(definitionDeclaringTypeDef, definitionDeclaringTypeDef.TypeParameters).AcceptVisitor(substitution); } - } else if (definitionDeclaringType != null) { + } + else if (definitionDeclaringType != null) + { result = definitionDeclaringType.AcceptVisitor(substitution); } return LazyInit.GetOrSet(ref this.declaringType, result); @@ -106,11 +116,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.declaringType = value; } } - + public IMember MemberDefinition { get { return baseMember.MemberDefinition; } } - + public IType ReturnType { get { var result = LazyInit.VolatileRead(ref this.returnType); @@ -122,7 +132,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation protected set { // This setter is used for LiftedUserDefinedOperator, a special case of specialized member // (not a normal type parameter substitution). - + // As this setter is used only during construction before the member is published // to other threads, we don't need a volatile write. this.returnType = value; @@ -134,25 +144,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool IsVirtual { get { return baseMember.IsVirtual; } } - + public bool IsOverride { get { return baseMember.IsOverride; } } - + public bool IsOverridable { get { return baseMember.IsOverridable; } } - + public SymbolKind SymbolKind { get { return baseMember.SymbolKind; } } - + public ITypeDefinition DeclaringTypeDefinition { get { return baseMember.DeclaringTypeDefinition; } } IEnumerable IEntity.GetAttributes() => baseMember.GetAttributes(); - + public IEnumerable ExplicitlyImplementedInterfaceMembers { get { // Note: if the interface is generic, then the interface members should already be specialized, @@ -160,47 +170,47 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return baseMember.ExplicitlyImplementedInterfaceMembers.Select(m => m.Specialize(substitution)); } } - + public bool IsExplicitInterfaceImplementation { get { return baseMember.IsExplicitInterfaceImplementation; } } - + public Accessibility Accessibility { get { return baseMember.Accessibility; } } - + public bool IsStatic { get { return baseMember.IsStatic; } } - + public bool IsAbstract { get { return baseMember.IsAbstract; } } - + public bool IsSealed { get { return baseMember.IsSealed; } } - + public string FullName { get { return baseMember.FullName; } } - + public string Name { get { return baseMember.Name; } } - + public string Namespace { get { return baseMember.Namespace; } } - + public string ReflectionName { get { return baseMember.ReflectionName; } } - + public ICompilation Compilation { get { return baseMember.Compilation; } } - + public IModule ParentModule { get { return baseMember.ParentModule; } } @@ -226,14 +236,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return false; return this.baseMember.Equals(other.baseMember) && this.substitution.Equals(other.substitution); } - + public override int GetHashCode() { - unchecked { + unchecked + { return 1000000007 * baseMember.GetHashCode() + 1000000009 * substitution.GetHashCode(); } } - + public override string ToString() { StringBuilder b = new StringBuilder("["); @@ -248,16 +259,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return b.ToString(); } } - + public abstract class SpecializedParameterizedMember : SpecializedMember, IParameterizedMember { IReadOnlyList parameters; - + protected SpecializedParameterizedMember(IParameterizedMember memberDefinition) : base(memberDefinition) { } - + public IReadOnlyList Parameters { get { var result = LazyInit.VolatileRead(ref this.parameters); @@ -269,21 +280,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation protected set { // This setter is used for LiftedUserDefinedOperator, a special case of specialized member // (not a normal type parameter substitution). - + // As this setter is used only during construction before the member is published // to other threads, we don't need a volatile write. this.parameters = value; } } - + protected IParameter[] CreateParameters(Func substitution) { var paramDefs = ((IParameterizedMember)this.baseMember).Parameters; - if (paramDefs.Count == 0) { + if (paramDefs.Count == 0) + { return Empty.Array; - } else { + } + else + { var parameters = new IParameter[paramDefs.Count]; - for (int i = 0; i < parameters.Length; i++) { + for (int i = 0; i < parameters.Length; i++) + { var p = paramDefs[i]; IType newType = substitution(p.Type); parameters[i] = new SpecializedParameter(p, newType, this); @@ -291,7 +306,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return parameters; } } - + public override string ToString() { StringBuilder b = new StringBuilder("["); @@ -301,8 +316,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation b.Append('.'); b.Append(this.Name); b.Append('('); - for (int i = 0; i < this.Parameters.Count; i++) { - if (i > 0) b.Append(", "); + for (int i = 0; i < this.Parameters.Count; i++) + { + if (i > 0) + b.Append(", "); b.Append(this.Parameters[i].ToString()); } b.Append("):"); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs index 7ec70de21..e72d6eeb7 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -36,7 +37,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return methodDefinition; if (methodDefinition.DeclaringType is ArrayType) return new SpecializedMethod(methodDefinition, substitution); - if (methodDefinition.TypeParameters.Count == 0) { + if (methodDefinition.TypeParameters.Count == 0) + { if (methodDefinition.DeclaringType.TypeParameterCount == 0) return methodDefinition; if (substitution.MethodTypeArguments != null && substitution.MethodTypeArguments.Count > 0) @@ -49,7 +51,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation readonly ITypeParameter[] specializedTypeParameters; readonly bool isParameterized; readonly TypeParameterSubstitution substitutionWithoutSpecializedTypeParameters; - + public SpecializedMethod(IMethod methodDefinition, TypeParameterSubstitution substitution) : base(methodDefinition) { @@ -57,14 +59,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation throw new ArgumentNullException(nameof(substitution)); this.methodDefinition = methodDefinition; this.isParameterized = substitution.MethodTypeArguments != null; - if (methodDefinition.TypeParameters.Count > 0) { + if (methodDefinition.TypeParameters.Count > 0) + { // The method is generic, so we need to specialize the type parameters // (for specializing the constraints, and also to set the correct Owner) specializedTypeParameters = new ITypeParameter[methodDefinition.TypeParameters.Count]; - for (int i = 0; i < specializedTypeParameters.Length; i++) { + for (int i = 0; i < specializedTypeParameters.Length; i++) + { specializedTypeParameters[i] = new SpecializedTypeParameter(methodDefinition.TypeParameters[i], this); } - if (!isParameterized) { + if (!isParameterized) + { // Add substitution that replaces the base method's type parameters with our specialized version // but do this only if the type parameters on the baseMember have not already been substituted substitutionWithoutSpecializedTypeParameters = this.Substitution; @@ -73,23 +78,28 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } // Add the main substitution after the method type parameter specialization. AddSubstitution(substitution); - if (substitutionWithoutSpecializedTypeParameters != null) { + if (substitutionWithoutSpecializedTypeParameters != null) + { // If we already have a substitution without specialized type parameters, update that: substitutionWithoutSpecializedTypeParameters = TypeParameterSubstitution.Compose(substitution, substitutionWithoutSpecializedTypeParameters); - } else { + } + else + { // Otherwise just use the whole substitution, as that doesn't contain specialized type parameters // in this case. substitutionWithoutSpecializedTypeParameters = this.Substitution; } - if (specializedTypeParameters != null) { + if (specializedTypeParameters != null) + { // Set the substitution on the type parameters to the final composed substitution - foreach (var tp in specializedTypeParameters.OfType()) { + foreach (var tp in specializedTypeParameters.OfType()) + { if (tp.Owner == this) tp.substitution = base.Substitution; } } } - + public IReadOnlyList TypeArguments { get { return this.Substitution.MethodTypeArguments ?? EmptyList.Instance; } } @@ -117,19 +127,19 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool IsConstructor { get { return methodDefinition.IsConstructor; } } - + public bool IsDestructor { get { return methodDefinition.IsDestructor; } } - + public bool IsOperator { get { return methodDefinition.IsOperator; } } - + public bool HasBody { get { return methodDefinition.HasBody; } } - + public bool IsAccessor { get { return methodDefinition.IsAccessor; } } @@ -141,13 +151,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } IMember accessorOwner; - + public IMember AccessorOwner { get { var result = LazyInit.VolatileRead(ref accessorOwner); - if (result != null) { + if (result != null) + { return result; - } else { + } + else + { var ownerDefinition = methodDefinition.AccessorOwner; if (ownerDefinition == null) return null; @@ -176,10 +189,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return false; return this.baseMember.Equals(other.baseMember) && this.substitutionWithoutSpecializedTypeParameters.Equals(other.substitutionWithoutSpecializedTypeParameters); } - + public override int GetHashCode() { - unchecked { + unchecked + { return 1000000013 * baseMember.GetHashCode() + 1000000009 * substitutionWithoutSpecializedTypeParameters.GetHashCode(); } } @@ -188,12 +202,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { return methodDefinition.Specialize(TypeParameterSubstitution.Compose(newSubstitution, substitutionWithoutSpecializedTypeParameters)); } - + IMethod IMethod.Specialize(TypeParameterSubstitution newSubstitution) { return methodDefinition.Specialize(TypeParameterSubstitution.Compose(newSubstitution, substitutionWithoutSpecializedTypeParameters)); } - + public override string ToString() { StringBuilder b = new StringBuilder("["); @@ -202,20 +216,27 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation b.Append(this.DeclaringType.ReflectionName); b.Append('.'); b.Append(this.Name); - if (this.TypeArguments.Count > 0) { + if (this.TypeArguments.Count > 0) + { b.Append('['); - for (int i = 0; i < this.TypeArguments.Count; i++) { - if (i > 0) b.Append(", "); + for (int i = 0; i < this.TypeArguments.Count; i++) + { + if (i > 0) + b.Append(", "); b.Append(this.TypeArguments[i].ToString()); } b.Append(']'); - } else if (this.TypeParameters.Count > 0) { + } + else if (this.TypeParameters.Count > 0) + { b.Append("``"); b.Append(this.TypeParameters.Count); } b.Append('('); - for (int i = 0; i < this.Parameters.Count; i++) { - if (i > 0) b.Append(", "); + for (int i = 0; i < this.Parameters.Count; i++) + { + if (i > 0) + b.Append(", "); b.Append(this.Parameters[i].ToString()); } b.Append("):"); @@ -223,14 +244,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation b.Append(']'); return b.ToString(); } - + sealed class SpecializedTypeParameter : AbstractTypeParameter { readonly ITypeParameter baseTp; - + // The substition is set at the end of SpecializedMethod constructor internal TypeVisitor substitution; - + public SpecializedTypeParameter(ITypeParameter baseTp, IMethod specializedOwner) : base(specializedOwner, baseTp.Index, baseTp.Name, baseTp.Variance) { @@ -245,14 +266,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { return baseTp.GetHashCode() ^ this.Owner.GetHashCode(); } - + public override bool Equals(IType other) { // Compare the owner, not the substitution, because the substitution may contain this specialized type parameter recursively SpecializedTypeParameter o = other as SpecializedTypeParameter; return o != null && baseTp.Equals(o.baseTp) && this.Owner.Equals(o.Owner); } - + public override bool HasValueTypeConstraint => baseTp.HasValueTypeConstraint; public override bool HasReferenceTypeConstraint => baseTp.HasReferenceTypeConstraint; public override bool HasDefaultConstructorConstraint => baseTp.HasDefaultConstructorConstraint; @@ -265,7 +286,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override IReadOnlyList TypeConstraints { get { var typeConstraints = LazyInit.VolatileRead(ref this.typeConstraints); - if (typeConstraints == null) { + if (typeConstraints == null) + { typeConstraints = baseTp.TypeConstraints.SelectReadOnlyArray(c => new TypeConstraint(c.Type.AcceptVisitor(substitution), c.Attributes)); typeConstraints = LazyInit.GetOrSet(ref this.typeConstraints, typeConstraints); } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedProperty.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedProperty.cs index 3cd66fe33..4fa3e49a5 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedProperty.cs @@ -27,7 +27,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { internal static IProperty Create(IProperty propertyDefinition, TypeParameterSubstitution substitution) { - if (TypeParameterSubstitution.Identity.Equals(substitution) || propertyDefinition.DeclaringType.TypeParameterCount == 0) { + if (TypeParameterSubstitution.Identity.Equals(substitution) || propertyDefinition.DeclaringType.TypeParameterCount == 0) + { return propertyDefinition; } if (substitution.MethodTypeArguments != null && substitution.MethodTypeArguments.Count > 0) @@ -36,32 +37,32 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } readonly IProperty propertyDefinition; - + public SpecializedProperty(IProperty propertyDefinition, TypeParameterSubstitution substitution) : base(propertyDefinition) { this.propertyDefinition = propertyDefinition; AddSubstitution(substitution); } - + public bool CanGet { get { return propertyDefinition.CanGet; } } - + public bool CanSet { get { return propertyDefinition.CanSet; } } - + IMethod getter, setter; - + public IMethod Getter { get { return WrapAccessor(ref this.getter, propertyDefinition.Getter); } } - + public IMethod Setter { get { return WrapAccessor(ref this.setter, propertyDefinition.Setter); } } - + public bool IsIndexer { get { return propertyDefinition.IsIndexer; } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs index 0acaf9d28..58e8ca0a0 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs @@ -17,11 +17,12 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using ICSharpCode.Decompiler.Util; -using System.Reflection; -using System.Reflection.Metadata; using System.Diagnostics; using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; + +using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation { @@ -50,9 +51,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.slicing = slicing; var parameters = new List(); parameters.Add(new DefaultParameter(indexOrRangeType, "")); - if (slicing) { + if (slicing) + { Debug.Assert(underlyingMethod.Parameters.Count == 2); - } else { + } + else + { parameters.AddRange(underlyingMethod.Parameters.Skip(1)); } this.parameters = parameters; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeParameterReference.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeParameterReference.cs index f328d3615..c8d943477 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeParameterReference.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeParameterReference.cs @@ -18,6 +18,7 @@ using System; using System.Globalization; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -27,25 +28,29 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { static readonly TypeParameterReference[] classTypeParameterReferences = new TypeParameterReference[8]; static readonly TypeParameterReference[] methodTypeParameterReferences = new TypeParameterReference[8]; - + /// /// Creates a type parameter reference. /// For common type parameter references, this method may return a shared instance. /// public static TypeParameterReference Create(SymbolKind ownerType, int index) { - if (index >= 0 && index < 8 && (ownerType == SymbolKind.TypeDefinition || ownerType == SymbolKind.Method)) { + if (index >= 0 && index < 8 && (ownerType == SymbolKind.TypeDefinition || ownerType == SymbolKind.Method)) + { TypeParameterReference[] arr = (ownerType == SymbolKind.TypeDefinition) ? classTypeParameterReferences : methodTypeParameterReferences; TypeParameterReference result = LazyInit.VolatileRead(ref arr[index]); - if (result == null) { + if (result == null) + { result = LazyInit.GetOrSet(ref arr[index], new TypeParameterReference(ownerType, index)); } return result; - } else { + } + else + { return new TypeParameterReference(ownerType, index); } } - + readonly SymbolKind ownerType; readonly int index; @@ -60,26 +65,33 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.ownerType = ownerType; this.index = index; } - + public IType Resolve(ITypeResolveContext context) { - if (ownerType == SymbolKind.Method) { + if (ownerType == SymbolKind.Method) + { IMethod method = context.CurrentMember as IMethod; - if (method != null && index < method.TypeParameters.Count) { + if (method != null && index < method.TypeParameters.Count) + { return method.TypeParameters[index]; } return DummyTypeParameter.GetMethodTypeParameter(index); - } else if (ownerType == SymbolKind.TypeDefinition) { + } + else if (ownerType == SymbolKind.TypeDefinition) + { ITypeDefinition typeDef = context.CurrentTypeDefinition; - if (typeDef != null && index < typeDef.TypeParameters.Count) { + if (typeDef != null && index < typeDef.TypeParameters.Count) + { return typeDef.TypeParameters[index]; } return DummyTypeParameter.GetClassTypeParameter(index); - } else { + } + else + { return SpecialType.UnknownType; } } - + public override string ToString() { if (ownerType == SymbolKind.Method) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeWithElementType.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeWithElementType.cs index 768b086e6..1b3d9f019 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeWithElementType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/TypeWithElementType.cs @@ -23,26 +23,26 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public abstract class TypeWithElementType : AbstractType { protected IType elementType; - + protected TypeWithElementType(IType elementType) { if (elementType == null) throw new ArgumentNullException(nameof(elementType)); this.elementType = elementType; } - + public override string Name { get { return elementType.Name + NameSuffix; } } - + public override string Namespace { get { return elementType.Namespace; } } - + public override string FullName { get { return elementType.FullName + NameSuffix; } } - + public override string ReflectionName { get { return elementType.ReflectionName + NameSuffix; } } @@ -53,11 +53,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } public abstract string NameSuffix { get; } - + public IType ElementType { get { return elementType; } } - + // Force concrete implementations to override VisitChildren - the base implementation // in AbstractType assumes there are no children, but we know there is (at least) 1. public abstract override IType VisitChildren(TypeVisitor visitor); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs index 84d483df2..51abb1a48 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/UnknownType.cs @@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.fullTypeName = new TopLevelTypeName(namespaceName ?? string.Empty, name, typeParameterCount); this.isReferenceType = isReferenceType; } - + /// /// Creates a new unknown type. /// @@ -54,35 +54,38 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public UnknownType(FullTypeName fullTypeName, bool? isReferenceType = null) { this.isReferenceType = isReferenceType; - if (fullTypeName.Name == null) { + if (fullTypeName.Name == null) + { Debug.Assert(fullTypeName == default(FullTypeName)); this.namespaceKnown = false; this.fullTypeName = new TopLevelTypeName(string.Empty, "?", 0); - } else { + } + else + { this.namespaceKnown = true; this.fullTypeName = fullTypeName; } } - + public override TypeKind Kind { get { return TypeKind.Unknown; } } - + IType ITypeReference.Resolve(ITypeResolveContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); return this; } - + public override string Name { get { return fullTypeName.Name; } } - + public override string Namespace { get { return fullTypeName.TopLevelTypeName.Namespace; } } - + public override string ReflectionName { get { return namespaceKnown ? fullTypeName.ReflectionName : "?"; } } @@ -109,7 +112,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { return (namespaceKnown ? 812571 : 12651) ^ fullTypeName.GetHashCode(); } - + public override bool Equals(IType other) { UnknownType o = other as UnknownType; @@ -117,7 +120,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return false; return this.namespaceKnown == o.namespaceKnown && this.fullTypeName == o.fullTypeName && this.isReferenceType == o.isReferenceType; } - + public override string ToString() { return "[UnknownType " + fullTypeName.ReflectionName + "]"; diff --git a/ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs b/ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs index 2d78d65b7..365d2f900 100644 --- a/ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs @@ -50,8 +50,10 @@ namespace ICSharpCode.Decompiler.TypeSystem if (member == null) throw new ArgumentNullException(nameof(member)); - if (includeImplementedInterfaces) { - if (member.IsExplicitInterfaceImplementation && member.ExplicitlyImplementedInterfaceMembers.Count() == 1) { + if (includeImplementedInterfaces) + { + if (member.IsExplicitInterfaceImplementation && member.ExplicitlyImplementedInterfaceMembers.Count() == 1) + { // C#-style explicit interface implementation member = member.ExplicitlyImplementedInterfaceMembers.First(); yield return member; @@ -62,30 +64,40 @@ namespace ICSharpCode.Decompiler.TypeSystem var substitution = member.Substitution; member = member.MemberDefinition; - if (member.DeclaringTypeDefinition == null) { + if (member.DeclaringTypeDefinition == null) + { // For global methods, return empty list. (prevent SharpDevelop UDC crash 4524) yield break; } IEnumerable allBaseTypes; - if (includeImplementedInterfaces) { + if (includeImplementedInterfaces) + { allBaseTypes = member.DeclaringTypeDefinition.GetAllBaseTypes(); - } else { + } + else + { allBaseTypes = member.DeclaringTypeDefinition.GetNonInterfaceBaseTypes(); } - foreach (IType baseType in allBaseTypes.Reverse()) { + foreach (IType baseType in allBaseTypes.Reverse()) + { if (baseType == member.DeclaringTypeDefinition) continue; IEnumerable baseMembers; - if (member.SymbolKind == SymbolKind.Accessor) { + if (member.SymbolKind == SymbolKind.Accessor) + { baseMembers = baseType.GetAccessors(m => m.Name == member.Name && m.Accessibility > Accessibility.Private, GetMemberOptions.IgnoreInheritedMembers); - } else { + } + else + { baseMembers = baseType.GetMembers(m => m.Name == member.Name && m.Accessibility > Accessibility.Private, GetMemberOptions.IgnoreInheritedMembers); } - foreach (IMember baseMember in baseMembers) { + foreach (IMember baseMember in baseMembers) + { System.Diagnostics.Debug.Assert(baseMember.Accessibility != Accessibility.Private); - if (SignatureComparer.Ordinal.Equals(member, baseMember)) { + if (SignatureComparer.Ordinal.Equals(member, baseMember)) + { yield return baseMember.Specialize(substitution); } } @@ -110,10 +122,14 @@ namespace ICSharpCode.Decompiler.TypeSystem baseMember = baseMember.MemberDefinition; bool includeInterfaces = baseMember.DeclaringTypeDefinition.Kind == TypeKind.Interface; IMethod method = baseMember as IMethod; - if (method != null) { - foreach (IMethod derivedMethod in derivedType.Methods) { - if (derivedMethod.Name == method.Name && derivedMethod.Parameters.Count == method.Parameters.Count) { - if (derivedMethod.TypeParameters.Count == method.TypeParameters.Count) { + if (method != null) + { + foreach (IMethod derivedMethod in derivedType.Methods) + { + if (derivedMethod.Name == method.Name && derivedMethod.Parameters.Count == method.Parameters.Count) + { + if (derivedMethod.TypeParameters.Count == method.TypeParameters.Count) + { // The method could override the base method: if (GetBaseMembers(derivedMethod, includeInterfaces).Any(m => m.MemberDefinition == baseMember)) return derivedMethod; @@ -122,23 +138,30 @@ namespace ICSharpCode.Decompiler.TypeSystem } } IProperty property = baseMember as IProperty; - if (property != null) { - foreach (IProperty derivedProperty in derivedType.Properties) { - if (derivedProperty.Name == property.Name && derivedProperty.Parameters.Count == property.Parameters.Count) { + if (property != null) + { + foreach (IProperty derivedProperty in derivedType.Properties) + { + if (derivedProperty.Name == property.Name && derivedProperty.Parameters.Count == property.Parameters.Count) + { // The property could override the base property: if (GetBaseMembers(derivedProperty, includeInterfaces).Any(m => m.MemberDefinition == baseMember)) return derivedProperty; } } } - if (baseMember is IEvent) { - foreach (IEvent derivedEvent in derivedType.Events) { + if (baseMember is IEvent) + { + foreach (IEvent derivedEvent in derivedType.Events) + { if (derivedEvent.Name == baseMember.Name) return derivedEvent; } } - if (baseMember is IField) { - foreach (IField derivedField in derivedType.Fields) { + if (baseMember is IField) + { + foreach (IField derivedField in derivedType.Fields) + { if (derivedField.Name == baseMember.Name) return derivedField; } @@ -150,11 +173,13 @@ namespace ICSharpCode.Decompiler.TypeSystem #region Attributes internal static IEnumerable GetAttributes(ITypeDefinition typeDef) { - foreach (var baseType in typeDef.GetNonInterfaceBaseTypes().Reverse()) { + foreach (var baseType in typeDef.GetNonInterfaceBaseTypes().Reverse()) + { ITypeDefinition baseTypeDef = baseType.GetDefinition(); if (baseTypeDef == null) continue; - foreach (var attr in baseTypeDef.GetAttributes()) { + foreach (var attr in baseTypeDef.GetAttributes()) + { yield return attr; } } @@ -163,13 +188,16 @@ namespace ICSharpCode.Decompiler.TypeSystem internal static IEnumerable GetAttributes(IMember member) { HashSet visitedMembers = new HashSet(); - do { + do + { member = member.MemberDefinition; // it's sufficient to look at the definitions - if (!visitedMembers.Add(member)) { + if (!visitedMembers.Add(member)) + { // abort if we seem to be in an infinite loop (cyclic inheritance) break; } - foreach (var attr in member.GetAttributes()) { + foreach (var attr in member.GetAttributes()) + { yield return attr; } } while (member.IsOverride && (member = InheritanceHelper.GetBaseMember(member)) != null); diff --git a/ICSharpCode.Decompiler/TypeSystem/IntersectionType.cs b/ICSharpCode.Decompiler/TypeSystem/IntersectionType.cs index e02e54e1b..3db10f748 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IntersectionType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IntersectionType.cs @@ -22,6 +22,7 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -32,21 +33,22 @@ namespace ICSharpCode.Decompiler.TypeSystem public class IntersectionType : AbstractType { readonly ReadOnlyCollection types; - + public ReadOnlyCollection Types { get { return types; } } - + private IntersectionType(IType[] types) { Debug.Assert(types.Length >= 2); this.types = Array.AsReadOnly(types); } - + public static IType Create(IEnumerable types) { IType[] arr = types.Distinct().ToArray(); - foreach (IType type in arr) { + foreach (IType type in arr) + { if (type == null) throw new ArgumentNullException(); } @@ -57,15 +59,16 @@ namespace ICSharpCode.Decompiler.TypeSystem else return new IntersectionType(arr); } - + public override TypeKind Kind { get { return TypeKind.Intersection; } } - + public override string Name { get { StringBuilder b = new StringBuilder(); - foreach (var t in types) { + foreach (var t in types) + { if (b.Length > 0) b.Append(" & "); b.Append(t.Name); @@ -73,11 +76,12 @@ namespace ICSharpCode.Decompiler.TypeSystem return b.ToString(); } } - + public override string ReflectionName { get { StringBuilder b = new StringBuilder(); - foreach (var t in types) { + foreach (var t in types) + { if (b.Length > 0) b.Append(" & "); b.Append(t.ReflectionName); @@ -85,10 +89,11 @@ namespace ICSharpCode.Decompiler.TypeSystem return b.ToString(); } } - + public override bool? IsReferenceType { get { - foreach (var t in types) { + foreach (var t in types) + { bool? isReferenceType = t.IsReferenceType; if (isReferenceType.HasValue) return isReferenceType.Value; @@ -96,24 +101,28 @@ namespace ICSharpCode.Decompiler.TypeSystem return null; } } - + public override int GetHashCode() { int hashCode = 0; - unchecked { - foreach (var t in types) { + unchecked + { + foreach (var t in types) + { hashCode *= 7137517; hashCode += t.GetHashCode(); } } return hashCode; } - + public override bool Equals(IType other) { IntersectionType o = other as IntersectionType; - if (o != null && types.Count == o.types.Count) { - for (int i = 0; i < types.Count; i++) { + if (o != null && types.Count == o.types.Count) + { + for (int i = 0; i < types.Count; i++) + { if (!types[i].Equals(o.types[i])) return false; } @@ -121,46 +130,46 @@ namespace ICSharpCode.Decompiler.TypeSystem } return false; } - + public override IEnumerable DirectBaseTypes { get { return types; } } - + public override IEnumerable GetMethods(Predicate filter, GetMemberOptions options) { return GetMembersHelper.GetMethods(this, FilterNonStatic(filter), options); } - + public override IEnumerable GetMethods(IReadOnlyList typeArguments, Predicate filter, GetMemberOptions options) { return GetMembersHelper.GetMethods(this, typeArguments, filter, options); } - + public override IEnumerable GetProperties(Predicate filter, GetMemberOptions options) { return GetMembersHelper.GetProperties(this, FilterNonStatic(filter), options); } - + public override IEnumerable GetFields(Predicate filter, GetMemberOptions options) { return GetMembersHelper.GetFields(this, FilterNonStatic(filter), options); } - + public override IEnumerable GetEvents(Predicate filter, GetMemberOptions options) { return GetMembersHelper.GetEvents(this, FilterNonStatic(filter), options); } - + public override IEnumerable GetMembers(Predicate filter, GetMemberOptions options) { return GetMembersHelper.GetMembers(this, FilterNonStatic(filter), options); } - + public override IEnumerable GetAccessors(Predicate filter, GetMemberOptions options) { return GetMembersHelper.GetAccessors(this, FilterNonStatic(filter), options); } - + static Predicate FilterNonStatic(Predicate filter) where T : class, IMember { if (filter == null) diff --git a/ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs b/ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs index d3a121ffc..03b2b1267 100644 --- a/ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs +++ b/ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { // Note: DefaultResolvedTypeDefinition uses (KnownTypeCode)-1 as special value for "not yet calculated". // The order of type codes at the beginning must correspond to those in System.TypeCode. - + /// /// Not one of the known types. /// @@ -67,9 +67,9 @@ namespace ICSharpCode.Decompiler.TypeSystem DateTime, /// string (System.String) String = 18, - + // String was the last element from System.TypeCode, now our additional known types start - + /// void (System.Void) Void, /// System.Type @@ -226,7 +226,7 @@ namespace ICSharpCode.Decompiler.TypeSystem new KnownTypeReference(KnownTypeCode.Index, TypeKind.Struct, "System", "Index", 0), new KnownTypeReference(KnownTypeCode.Range, TypeKind.Struct, "System", "Range", 0), }; - + /// /// Gets the known type reference for the specified type code. /// Returns null for KnownTypeCode.None. @@ -235,10 +235,11 @@ namespace ICSharpCode.Decompiler.TypeSystem { return knownTypeReferences[(int)typeCode]; } - + public static IEnumerable AllKnownTypes { get { - for (int i = 0; i < KnownTypeCodeCount; i++) { + for (int i = 0; i < KnownTypeCodeCount; i++) + { var ktr = Get((KnownTypeCode)i); if (ktr == null) continue; @@ -265,19 +266,19 @@ namespace ICSharpCode.Decompiler.TypeSystem this.typeKind = typeKind; this.baseType = baseType; } - + public KnownTypeCode KnownTypeCode { get { return knownTypeCode; } } - + public string Namespace { get { return namespaceName; } } - + public string Name { get { return name; } } - + public int TypeParameterCount { get { return typeParameterCount; } } @@ -288,19 +289,20 @@ namespace ICSharpCode.Decompiler.TypeSystem { return context.Compilation.FindType(knownTypeCode); } - + public override string ToString() { return GetCSharpNameByTypeCode(knownTypeCode) ?? (this.Namespace + "." + this.Name); } - + /// /// Gets the C# primitive type name from the known type code. /// Returns null if there is no primitive name for the specified type. /// public static string GetCSharpNameByTypeCode(KnownTypeCode knownTypeCode) { - switch (knownTypeCode) { + switch (knownTypeCode) + { case KnownTypeCode.Object: return "object"; case KnownTypeCode.Boolean: diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs index 10f6a17fd..313d12a14 100644 --- a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs +++ b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs @@ -24,6 +24,7 @@ using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; @@ -59,11 +60,14 @@ namespace ICSharpCode.Decompiler.TypeSystem this.TypeProvider = new TypeProvider(this); // assembly metadata - if (metadata.IsAssembly) { + if (metadata.IsAssembly) + { var asmdef = metadata.GetAssemblyDefinition(); this.AssemblyName = metadata.GetString(asmdef.Name); this.FullAssemblyName = metadata.GetFullAssemblyName(); - } else { + } + else + { var moddef = metadata.GetModuleDefinition(); this.AssemblyName = metadata.GetString(moddef.Name); this.FullAssemblyName = this.AssemblyName; @@ -73,7 +77,8 @@ namespace ICSharpCode.Decompiler.TypeSystem this.minAccessibilityForNRT = FindMinimumAccessibilityForNRT(metadata, customAttrs); this.rootNamespace = new MetadataNamespace(this, null, string.Empty, metadata.GetNamespaceDefinitionRoot()); - if (!options.HasFlag(TypeSystemOptions.Uncached)) { + if (!options.HasFlag(TypeSystemOptions.Uncached)) + { // create arrays for resolved entities, indexed by row index this.typeDefs = new MetadataTypeDefinition[metadata.TypeDefinitions.Count + 1]; this.fieldDefs = new MetadataField[metadata.FieldDefinitions.Count + 1]; @@ -104,13 +109,15 @@ namespace ICSharpCode.Decompiler.TypeSystem public INamespace RootNamespace => rootNamespace; public IEnumerable TopLevelTypeDefinitions => TypeDefinitions.Where(td => td.DeclaringTypeDefinition == null); - + public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName) { var typeDefHandle = PEFile.GetTypeDefinition(topLevelTypeName); - if (typeDefHandle.IsNil) { + if (typeDefHandle.IsNil) + { var forwarderHandle = PEFile.GetTypeForwarder(topLevelTypeName); - if (!forwarderHandle.IsNil) { + if (!forwarderHandle.IsNil) + { var forwarder = metadata.GetExportedType(forwarderHandle); return ResolveForwardedType(forwarder).GetDefinition(); } @@ -124,7 +131,8 @@ namespace ICSharpCode.Decompiler.TypeSystem { if (this == module) return true; - foreach (string shortName in GetInternalsVisibleTo()) { + foreach (string shortName in GetInternalsVisibleTo()) + { if (string.Equals(module.AssemblyName, shortName, StringComparison.OrdinalIgnoreCase)) return true; } @@ -136,24 +144,32 @@ namespace ICSharpCode.Decompiler.TypeSystem string[] GetInternalsVisibleTo() { var result = LazyInit.VolatileRead(ref this.internalsVisibleTo); - if (result != null) { + if (result != null) + { return result; } - if (metadata.IsAssembly) { + if (metadata.IsAssembly) + { var list = new List(); - foreach (var attrHandle in metadata.GetAssemblyDefinition().GetCustomAttributes()) { + foreach (var attrHandle in metadata.GetAssemblyDefinition().GetCustomAttributes()) + { var attr = metadata.GetCustomAttribute(attrHandle); - if (attr.IsKnownAttribute(metadata, KnownAttribute.InternalsVisibleTo)) { + if (attr.IsKnownAttribute(metadata, KnownAttribute.InternalsVisibleTo)) + { var attrValue = attr.DecodeValue(this.TypeProvider); - if (attrValue.FixedArguments.Length == 1) { - if (attrValue.FixedArguments[0].Value is string s) { + if (attrValue.FixedArguments.Length == 1) + { + if (attrValue.FixedArguments[0].Value is string s) + { list.Add(GetShortName(s)); } } } } result = list.ToArray(); - } else { + } + else + { result = Empty.Array; } return LazyInit.GetOrSet(ref this.internalsVisibleTo, result); @@ -177,7 +193,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public IEnumerable TypeDefinitions { get { - foreach (var tdHandle in metadata.TypeDefinitions) { + foreach (var tdHandle in metadata.TypeDefinitions) + { yield return GetDefinition(tdHandle); } } @@ -304,8 +321,10 @@ namespace ICSharpCode.Decompiler.TypeSystem return null; var modRef = metadata.GetModuleReference(handle); string name = metadata.GetString(modRef.Name); - foreach (var mod in Compilation.Modules) { - if (mod.Name == name) { + foreach (var mod in Compilation.Modules) + { + if (mod.Name == name) + { return mod; } } @@ -317,7 +336,8 @@ namespace ICSharpCode.Decompiler.TypeSystem if (handle.IsNil) return null; var tr = metadata.GetTypeReference(handle); - switch (tr.ResolutionScope.Kind) { + switch (tr.ResolutionScope.Kind) + { case HandleKind.TypeReference: return GetDeclaringModule((TypeReferenceHandle)tr.ResolutionScope); case HandleKind.AssemblyReference: @@ -341,7 +361,8 @@ namespace ICSharpCode.Decompiler.TypeSystem if (typeRefDefSpec.IsNil) return SpecialType.UnknownType; IType ty; - switch (typeRefDefSpec.Kind) { + switch (typeRefDefSpec.Kind) + { case HandleKind.TypeDefinition: ty = TypeProvider.GetTypeFromDefinition(metadata, (TypeDefinitionHandle)typeRefDefSpec, 0); break; @@ -383,7 +404,8 @@ namespace ICSharpCode.Decompiler.TypeSystem { if (methodReference.IsNil) throw new ArgumentNullException(nameof(methodReference)); - switch (methodReference.Kind) { + switch (methodReference.Kind) + { case HandleKind.MethodDefinition: return ResolveMethodDefinition((MethodDefinitionHandle)methodReference, expandVarArgs: true); case HandleKind.MemberReference: @@ -398,7 +420,8 @@ namespace ICSharpCode.Decompiler.TypeSystem IMethod ResolveMethodDefinition(MethodDefinitionHandle methodDefHandle, bool expandVarArgs) { var method = GetDefinition(methodDefHandle); - if (expandVarArgs && method.Parameters.LastOrDefault()?.Type.Kind == TypeKind.ArgList) { + if (expandVarArgs && method.Parameters.LastOrDefault()?.Type.Kind == TypeKind.ArgList) + { method = new VarArgInstanceMethod(method, EmptyList.Instance); } return method; @@ -410,11 +433,14 @@ namespace ICSharpCode.Decompiler.TypeSystem var methodTypeArgs = methodSpec.DecodeSignature(TypeProvider, context) .SelectReadOnlyArray(IntroduceTupleTypes); IMethod method; - if (methodSpec.Method.Kind == HandleKind.MethodDefinition) { + if (methodSpec.Method.Kind == HandleKind.MethodDefinition) + { // generic instance of a methoddef (=generic method in non-generic class in current assembly) method = ResolveMethodDefinition((MethodDefinitionHandle)methodSpec.Method, expandVarArgs); method = method.Specialize(new TypeParameterSubstitution(null, methodTypeArgs)); - } else { + } + else + { method = ResolveMethodReference((MemberReferenceHandle)methodSpec.Method, context, methodTypeArgs, expandVarArgs); } return method; @@ -434,13 +460,17 @@ namespace ICSharpCode.Decompiler.TypeSystem MethodSignature signature; IReadOnlyList classTypeArguments = null; IMethod method; - if (memberRef.Parent.Kind == HandleKind.MethodDefinition) { + if (memberRef.Parent.Kind == HandleKind.MethodDefinition) + { method = ResolveMethodDefinition((MethodDefinitionHandle)memberRef.Parent, expandVarArgs: false); signature = memberRef.DecodeMethodSignature(TypeProvider, context); - } else { + } + else + { var declaringType = ResolveDeclaringType(memberRef.Parent, context); var declaringTypeDefinition = declaringType.GetDefinition(); - if (declaringType.TypeArguments.Count > 0) { + if (declaringType.TypeArguments.Count > 0) + { classTypeArguments = declaringType.TypeArguments; } // Note: declaringType might be parameterized, but the signature is for the original method definition. @@ -448,48 +478,64 @@ namespace ICSharpCode.Decompiler.TypeSystem string name = metadata.GetString(memberRef.Name); signature = memberRef.DecodeMethodSignature(TypeProvider, new GenericContext(declaringTypeDefinition?.TypeParameters)); - if (declaringTypeDefinition != null) { + if (declaringTypeDefinition != null) + { // Find the set of overloads to search: IEnumerable methods; - if (name == ".ctor") { + if (name == ".ctor") + { methods = declaringTypeDefinition.GetConstructors(); - } else if (name == ".cctor") { + } + else if (name == ".cctor") + { methods = declaringTypeDefinition.Methods.Where(m => m.IsConstructor && m.IsStatic); - } else { + } + else + { methods = declaringTypeDefinition.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers) .Concat(declaringTypeDefinition.GetAccessors(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers)); } // Determine the expected parameters from the signature: ImmutableArray parameterTypes; - if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { + if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) + { parameterTypes = signature.ParameterTypes .Take(signature.RequiredParameterCount) .Concat(new[] { SpecialType.ArgList }) .ToImmutableArray(); - } else { + } + else + { parameterTypes = signature.ParameterTypes; } // Search for the matching method: method = null; - foreach (var m in methods) { + foreach (var m in methods) + { if (m.TypeParameters.Count != signature.GenericParameterCount) continue; - if (CompareSignatures(m.Parameters, parameterTypes) && CompareTypes(m.ReturnType, signature.ReturnType)) { + if (CompareSignatures(m.Parameters, parameterTypes) && CompareTypes(m.ReturnType, signature.ReturnType)) + { method = m; break; } } - } else { + } + else + { method = null; } - if (method == null) { + if (method == null) + { method = CreateFakeMethod(declaringType, name, signature); } } - if (classTypeArguments != null || methodTypeArguments != null) { + if (classTypeArguments != null || methodTypeArguments != null) + { method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments)); } - if (expandVarArgs && signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { + if (expandVarArgs && signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) + { method = new VarArgInstanceMethod(method, signature.ParameterTypes.Skip(signature.RequiredParameterCount)); } return method; @@ -511,7 +557,8 @@ namespace ICSharpCode.Decompiler.TypeSystem { if (parameterTypes.Length != parameters.Count) return false; - for (int i = 0; i < parameterTypes.Length; i++) { + for (int i = 0; i < parameterTypes.Length; i++) + { if (!CompareTypes(parameterTypes[i], parameters[i].Type)) return false; } @@ -533,20 +580,26 @@ namespace ICSharpCode.Decompiler.TypeSystem m.IsStatic = !signature.Header.IsInstance; TypeParameterSubstitution substitution = null; - if (signature.GenericParameterCount > 0) { + if (signature.GenericParameterCount > 0) + { var typeParameters = new List(); - for (int i = 0; i < signature.GenericParameterCount; i++) { + for (int i = 0; i < signature.GenericParameterCount; i++) + { typeParameters.Add(new DefaultTypeParameter(m, i)); } m.TypeParameters = typeParameters; substitution = new TypeParameterSubstitution(declaringType.TypeArguments, typeParameters); - } else if (declaringType.TypeArguments.Count > 0) { + } + else if (declaringType.TypeArguments.Count > 0) + { substitution = declaringType.GetSubstitution(); } var parameters = new List(); - for (int i = 0; i < signature.RequiredParameterCount; i++) { + for (int i = 0; i < signature.RequiredParameterCount; i++) + { var type = signature.ParameterTypes[i]; - if (substitution != null) { + if (substitution != null) + { // replace the dummy method type parameters with the owned instances we just created type = type.AcceptVisitor(substitution); } @@ -572,7 +625,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public IEntity ResolveEntity(EntityHandle entityHandle, GenericContext context = default) { - switch (entityHandle.Kind) { + switch (entityHandle.Kind) + { case HandleKind.TypeReference: case HandleKind.TypeDefinition: case HandleKind.TypeSpecification: @@ -580,7 +634,8 @@ namespace ICSharpCode.Decompiler.TypeSystem return ResolveType(entityHandle, context).GetDefinition(); case HandleKind.MemberReference: var memberReferenceHandle = (MemberReferenceHandle)entityHandle; - switch (metadata.GetMemberReference(memberReferenceHandle).GetKind()) { + switch (metadata.GetMemberReference(memberReferenceHandle).GetKind()) + { case MemberReferenceKind.Method: // for consistency with the MethodDefinition case, never expand varargs return ResolveMethodReference(memberReferenceHandle, context, expandVarArgs: false); @@ -616,9 +671,11 @@ namespace ICSharpCode.Decompiler.TypeSystem // 'f' in the predicate is also the definition, even if declaringType is a ParameterizedType var field = declaringType.GetFields(f => f.Name == name && CompareTypes(f.ReturnType, signature), GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); - if (field == null) { + if (field == null) + { // If it's a field in a generic type, we need to substitute the type arguments: - if (declaringType.TypeArguments.Count > 0) { + if (declaringType.TypeArguments.Count > 0) + { signature = signature.AcceptVisitor(declaringType.GetSubstitution()); } field = new FakeField(Compilation) { @@ -666,13 +723,15 @@ namespace ICSharpCode.Decompiler.TypeSystem public IEnumerable GetAssemblyAttributes() { var b = new AttributeListBuilder(this); - if (metadata.IsAssembly) { + if (metadata.IsAssembly) + { var assembly = metadata.GetAssemblyDefinition(); b.Add(metadata.GetCustomAttributes(Handle.AssemblyDefinition), SymbolKind.Module); b.AddSecurityAttributes(assembly.GetDeclarativeSecurityAttributes()); // AssemblyVersionAttribute - if (assembly.Version != null) { + if (assembly.Version != null) + { b.Add(KnownAttribute.AssemblyVersion, KnownTypeCode.String, assembly.Version.ToString()); } @@ -688,7 +747,8 @@ namespace ICSharpCode.Decompiler.TypeSystem { var b = new AttributeListBuilder(this); b.Add(metadata.GetCustomAttributes(Handle.ModuleDefinition), SymbolKind.Module); - if (!metadata.IsAssembly) { + if (!metadata.IsAssembly) + { AddTypeForwarderAttributes(ref b); } return b.Build(); @@ -696,9 +756,11 @@ namespace ICSharpCode.Decompiler.TypeSystem void AddTypeForwarderAttributes(ref AttributeListBuilder b) { - foreach (ExportedTypeHandle t in metadata.ExportedTypes) { + foreach (ExportedTypeHandle t in metadata.ExportedTypes) + { var type = metadata.GetExportedType(t); - if (type.IsForwarder) { + if (type.IsForwarder) + { b.Add(KnownAttribute.TypeForwardedTo, KnownTypeCode.Type, ResolveForwardedType(type)); } } @@ -710,10 +772,13 @@ namespace ICSharpCode.Decompiler.TypeSystem var typeName = forwarder.GetFullTypeName(metadata); if (module == null) return new UnknownType(typeName); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { + using (var busyLock = BusyManager.Enter(this)) + { + if (busyLock.Success) + { var td = module.GetTypeDefinition(typeName); - if (td != null) { + if (td != null) + { return td; } } @@ -722,7 +787,8 @@ namespace ICSharpCode.Decompiler.TypeSystem IModule ResolveModule(ExportedType type) { - switch (type.Implementation.Kind) { + switch (type.Implementation.Kind) + { case HandleKind.AssemblyFile: // TODO : Resolve assembly file (module)... return this; @@ -732,8 +798,10 @@ namespace ICSharpCode.Decompiler.TypeSystem case HandleKind.AssemblyReference: var asmRef = metadata.GetAssemblyReference((AssemblyReferenceHandle)type.Implementation); string shortName = metadata.GetString(asmRef.Name); - foreach (var asm in Compilation.Modules) { - if (string.Equals(asm.AssemblyName, shortName, StringComparison.OrdinalIgnoreCase)) { + foreach (var asm in Compilation.Modules) + { + if (string.Equals(asm.AssemblyName, shortName, StringComparison.OrdinalIgnoreCase)) + { return asm; } } @@ -774,7 +842,7 @@ namespace ICSharpCode.Decompiler.TypeSystem if (attr != null) return attr; attr = new DefaultAttribute(GetAttributeType(type), - ImmutableArray.Create>(), + ImmutableArray.Create>(), ImmutableArray.Create>()); return LazyInit.GetOrSet(ref knownAttributes[(int)type], attr); } @@ -808,18 +876,26 @@ namespace ICSharpCode.Decompiler.TypeSystem static Accessibility FindMinimumAccessibilityForNRT(MetadataReader metadata, CustomAttributeHandleCollection customAttributes) { // Determine the minimum effective accessibility an entity must have, so that the metadata stores the nullability for its type. - foreach (var handle in customAttributes) { + foreach (var handle in customAttributes) + { var customAttribute = metadata.GetCustomAttribute(handle); - if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.NullablePublicOnly)) { + if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.NullablePublicOnly)) + { CustomAttributeValue value; - try { + try + { value = customAttribute.DecodeValue(Metadata.MetadataExtensions.MinimalAttributeTypeProvider); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { continue; - } catch (EnumUnderlyingTypeResolveException) { + } + catch (EnumUnderlyingTypeResolveException) + { continue; } - if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is bool includesInternals) { + if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is bool includesInternals) + { return includesInternals ? Accessibility.ProtectedAndInternal : Accessibility.Protected; } } @@ -839,8 +915,10 @@ namespace ICSharpCode.Decompiler.TypeSystem internal TypeSystemOptions OptionsForEntity(IEntity entity) { var opt = this.options; - if ((opt & TypeSystemOptions.NullabilityAnnotations) != 0) { - if (!ShouldDecodeNullableAttributes(entity)) { + if ((opt & TypeSystemOptions.NullabilityAnnotations) != 0) + { + if (!ShouldDecodeNullableAttributes(entity)) + { opt &= ~TypeSystemOptions.NullabilityAnnotations; } } diff --git a/ICSharpCode.Decompiler/TypeSystem/ModifiedType.cs b/ICSharpCode.Decompiler/TypeSystem/ModifiedType.cs index 17536a98b..31c677e33 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ModifiedType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ModifiedType.cs @@ -107,12 +107,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation { return elementType.GetProperties(filter, options); } - + public override IType VisitChildren(TypeVisitor visitor) { var newElementType = elementType.AcceptVisitor(visitor); var newModifier = modifier.AcceptVisitor(visitor); - if (newModifier != modifier || newElementType != elementType) { + if (newModifier != modifier || newElementType != elementType) + { return new ModifiedType(newModifier, newElementType, kind == TypeKind.ModReq); } return this; @@ -133,7 +134,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override int GetHashCode() { - unchecked { + unchecked + { return (int)kind ^ (elementType.GetHashCode() * 1344795899) ^ (modifier.GetHashCode() * 901375117); } } diff --git a/ICSharpCode.Decompiler/TypeSystem/NormalizeTypeVisitor.cs b/ICSharpCode.Decompiler/TypeSystem/NormalizeTypeVisitor.cs index 5ad28ed06..505a06359 100644 --- a/ICSharpCode.Decompiler/TypeSystem/NormalizeTypeVisitor.cs +++ b/ICSharpCode.Decompiler/TypeSystem/NormalizeTypeVisitor.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -51,20 +52,28 @@ namespace ICSharpCode.Decompiler.TypeSystem public override IType VisitTypeParameter(ITypeParameter type) { - if (type.OwnerType == SymbolKind.Method && ReplaceMethodTypeParametersWithDummy) { + if (type.OwnerType == SymbolKind.Method && ReplaceMethodTypeParametersWithDummy) + { return DummyTypeParameter.GetMethodTypeParameter(type.Index); - } else if (type.OwnerType == SymbolKind.TypeDefinition && ReplaceClassTypeParametersWithDummy) { + } + else if (type.OwnerType == SymbolKind.TypeDefinition && ReplaceClassTypeParametersWithDummy) + { return DummyTypeParameter.GetClassTypeParameter(type.Index); - } else if (RemoveNullability && type is NullabilityAnnotatedTypeParameter natp) { + } + else if (RemoveNullability && type is NullabilityAnnotatedTypeParameter natp) + { return natp.TypeWithoutAnnotation.AcceptVisitor(this); - } else { + } + else + { return base.VisitTypeParameter(type); } } public override IType VisitTypeDefinition(ITypeDefinition type) { - switch (type.KnownTypeCode) { + switch (type.KnownTypeCode) + { case KnownTypeCode.Object when DynamicAndObject: // Instead of normalizing dynamic->object, // we do this the opposite direction, so that we don't need a compilation to find the object type. @@ -82,9 +91,12 @@ namespace ICSharpCode.Decompiler.TypeSystem public override IType VisitTupleType(TupleType type) { - if (TupleToUnderlyingType) { + if (TupleToUnderlyingType) + { return type.UnderlyingType.AcceptVisitor(this); - } else { + } + else + { return base.VisitTupleType(type); } } @@ -107,18 +119,24 @@ namespace ICSharpCode.Decompiler.TypeSystem public override IType VisitModOpt(ModifiedType type) { - if (RemoveModOpt) { + if (RemoveModOpt) + { return type.ElementType.AcceptVisitor(this); - } else { + } + else + { return base.VisitModOpt(type); } } public override IType VisitModReq(ModifiedType type) { - if (RemoveModReq) { + if (RemoveModReq) + { return type.ElementType.AcceptVisitor(this); - } else { + } + else + { return base.VisitModReq(type); } } diff --git a/ICSharpCode.Decompiler/TypeSystem/NullableType.cs b/ICSharpCode.Decompiler/TypeSystem/NullableType.cs index 42f72cf65..0fa461890 100644 --- a/ICSharpCode.Decompiler/TypeSystem/NullableType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/NullableType.cs @@ -35,12 +35,12 @@ namespace ICSharpCode.Decompiler.TypeSystem ParameterizedType pt = type.SkipModifiers() as ParameterizedType; return pt != null && pt.TypeParameterCount == 1 && pt.GenericType.IsKnownType(KnownTypeCode.NullableOfT); } - + public static bool IsNonNullableValueType(IType type) { return type.IsReferenceType == false && !IsNullable(type); } - + /// /// Returns the element type, if is a nullable type. /// Otherwise, returns the type itself. @@ -55,7 +55,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return type; } - + /// /// Creates a nullable type. /// @@ -65,15 +65,15 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new ArgumentNullException(nameof(compilation)); if (elementType == null) throw new ArgumentNullException(nameof(elementType)); - + IType nullableType = compilation.FindType(KnownTypeCode.NullableOfT); ITypeDefinition nullableTypeDef = nullableType.GetDefinition(); if (nullableTypeDef != null) - return new ParameterizedType(nullableTypeDef, new [] { elementType }); + return new ParameterizedType(nullableTypeDef, new[] { elementType }); else return nullableType; } - + /// /// Creates a nullable type reference. /// @@ -81,7 +81,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { if (elementType == null) throw new ArgumentNullException(nameof(elementType)); - return new ParameterizedTypeReference(KnownTypeReference.Get(KnownTypeCode.NullableOfT), new [] { elementType }); + return new ParameterizedTypeReference(KnownTypeReference.Get(KnownTypeCode.NullableOfT), new[] { elementType }); } } } diff --git a/ICSharpCode.Decompiler/TypeSystem/ParameterListComparer.cs b/ICSharpCode.Decompiler/TypeSystem/ParameterListComparer.cs index 6fafe982b..af823370c 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ParameterListComparer.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ParameterListComparer.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -50,14 +51,15 @@ namespace ICSharpCode.Decompiler.TypeSystem includeModifiers = includeModifiers }; } - + public bool Equals(IReadOnlyList x, IReadOnlyList y) { if (x == y) return true; if (x == null || y == null || x.Count != y.Count) return false; - for (int i = 0; i < x.Count; i++) { + for (int i = 0; i < x.Count; i++) + { var a = x[i]; var b = y[i]; if (a == null && b == null) @@ -65,30 +67,33 @@ namespace ICSharpCode.Decompiler.TypeSystem if (a == null || b == null) return false; - if (includeModifiers) { + if (includeModifiers) + { if (a.ReferenceKind != b.ReferenceKind) return false; if (a.IsParams != b.IsParams) return false; } - + // We want to consider the parameter lists "Method(T a)" and "Method(S b)" as equal. // However, the parameter types are not considered equal, as T is a different type parameter than S. // In order to compare the method signatures, we will normalize all method type parameters. IType aType = a.Type.AcceptVisitor(normalizationVisitor); IType bType = b.Type.AcceptVisitor(normalizationVisitor); - + if (!aType.Equals(bType)) return false; } return true; } - + public int GetHashCode(IReadOnlyList obj) { int hashCode = obj.Count; - unchecked { - foreach (IParameter p in obj) { + unchecked + { + foreach (IParameter p in obj) + { hashCode *= 27; IType type = p.Type.AcceptVisitor(normalizationVisitor); hashCode += type.GetHashCode(); @@ -97,7 +102,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return hashCode; } } - + /// /// Compares member signatures. /// @@ -107,19 +112,19 @@ namespace ICSharpCode.Decompiler.TypeSystem public sealed class SignatureComparer : IEqualityComparer { StringComparer nameComparer; - + public SignatureComparer(StringComparer nameComparer) { if (nameComparer == null) throw new ArgumentNullException(nameof(nameComparer)); this.nameComparer = nameComparer; } - + /// /// Gets a signature comparer that uses an ordinal comparison for the member name. /// public static readonly SignatureComparer Ordinal = new SignatureComparer(StringComparer.Ordinal); - + public bool Equals(IMember x, IMember y) { if (x == y) @@ -128,23 +133,28 @@ namespace ICSharpCode.Decompiler.TypeSystem return false; IParameterizedMember px = x as IParameterizedMember; IParameterizedMember py = y as IParameterizedMember; - if (px != null && py != null) { + if (px != null && py != null) + { IMethod mx = x as IMethod; IMethod my = y as IMethod; if (mx != null && my != null && mx.TypeParameters.Count != my.TypeParameters.Count) return false; return ParameterListComparer.Instance.Equals(px.Parameters, py.Parameters); - } else { + } + else + { return true; } } - + public int GetHashCode(IMember obj) { - unchecked { + unchecked + { int hash = (int)obj.SymbolKind * 33 + nameComparer.GetHashCode(obj.Name); IParameterizedMember pm = obj as IParameterizedMember; - if (pm != null) { + if (pm != null) + { hash *= 27; hash += ParameterListComparer.Instance.GetHashCode(pm.Parameters); IMethod m = pm as IMethod; diff --git a/ICSharpCode.Decompiler/TypeSystem/ParameterizedType.cs b/ICSharpCode.Decompiler/TypeSystem/ParameterizedType.cs index 3f1d500e3..64f2f2a63 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ParameterizedType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ParameterizedType.cs @@ -22,6 +22,7 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -40,7 +41,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { readonly IType genericType; readonly IType[] typeArguments; - + public ParameterizedType(IType genericType, IEnumerable typeArguments) { if (genericType == null) @@ -54,7 +55,8 @@ namespace ICSharpCode.Decompiler.TypeSystem if (genericType.TypeParameterCount != this.typeArguments.Length) throw new ArgumentException("Number of type arguments must match the type definition's number of type parameters"); ICompilationProvider gp = genericType as ICompilationProvider; - for (int i = 0; i < this.typeArguments.Length; i++) { + for (int i = 0; i < this.typeArguments.Length; i++) + { if (this.typeArguments[i] == null) throw new ArgumentNullException("typeArguments[" + i + "]"); ICompilationProvider p = this.typeArguments[i] as ICompilationProvider; @@ -62,7 +64,7 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new InvalidOperationException("Cannot parameterize a type with type arguments from a different compilation."); } } - + /// /// Fast internal version of the constructor. (no safety checks) /// Keeps the array that was passed and assumes it won't be modified. @@ -73,15 +75,15 @@ namespace ICSharpCode.Decompiler.TypeSystem this.genericType = genericType; this.typeArguments = typeArguments; } - + public TypeKind Kind { get { return genericType.Kind; } } - + public IType GenericType { get { return genericType; } } - + public bool? IsReferenceType => genericType.IsReferenceType; public bool IsByRefLike => genericType.IsByRefLike; public Nullability Nullability => genericType.Nullability; @@ -99,7 +101,7 @@ namespace ICSharpCode.Decompiler.TypeSystem get { IType declaringType = genericType.DeclaringType; if (declaringType != null && declaringType.TypeParameterCount > 0 - && declaringType.TypeParameterCount <= genericType.TypeParameterCount) + && declaringType.TypeParameterCount <= genericType.TypeParameterCount) { IType[] newTypeArgs = new IType[declaringType.TypeParameterCount]; Array.Copy(this.typeArguments, 0, newTypeArgs, 0, newTypeArgs.Length); @@ -112,24 +114,25 @@ namespace ICSharpCode.Decompiler.TypeSystem public int TypeParameterCount { get { return typeArguments.Length; } } - + public string FullName { get { return genericType.FullName; } } - + public string Name { get { return genericType.Name; } } - + public string Namespace { get { return genericType.Namespace; } } - + public string ReflectionName { get { StringBuilder b = new StringBuilder(genericType.ReflectionName); b.Append('['); - for (int i = 0; i < typeArguments.Length; i++) { + for (int i = 0; i < typeArguments.Length; i++) + { if (i > 0) b.Append(','); b.Append('['); @@ -145,7 +148,8 @@ namespace ICSharpCode.Decompiler.TypeSystem { StringBuilder b = new StringBuilder(genericType.ToString()); b.Append('['); - for (int i = 0; i < typeArguments.Length; i++) { + for (int i = 0; i < typeArguments.Length; i++) + { if (i > 0) b.Append(','); b.Append('['); @@ -176,7 +180,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { return genericType.GetDefinition(); } - + /// /// Gets a type visitor that performs the substitution of class type parameters with the type arguments /// of this parameterized type. @@ -185,7 +189,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { 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, @@ -195,14 +199,14 @@ namespace ICSharpCode.Decompiler.TypeSystem { return new TypeParameterSubstitution(typeArguments, methodTypeArguments); } - + public IEnumerable DirectBaseTypes { get { var substitution = GetSubstitution(); return genericType.DirectBaseTypes.Select(t => t.AcceptVisitor(substitution)); } } - + public IEnumerable GetNestedTypes(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) @@ -210,7 +214,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return GetMembersHelper.GetNestedTypes(this, filter, options); } - + public IEnumerable GetNestedTypes(IReadOnlyList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) @@ -218,7 +222,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return GetMembersHelper.GetNestedTypes(this, typeArguments, filter, options); } - + public IEnumerable GetConstructors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) @@ -226,7 +230,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return GetMembersHelper.GetConstructors(this, filter, options); } - + public IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) @@ -234,7 +238,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return GetMembersHelper.GetMethods(this, filter, options); } - + public IEnumerable GetMethods(IReadOnlyList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) @@ -242,7 +246,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return GetMembersHelper.GetMethods(this, typeArguments, filter, options); } - + public IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) @@ -250,7 +254,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return GetMembersHelper.GetProperties(this, filter, options); } - + public IEnumerable GetFields(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) @@ -258,7 +262,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return GetMembersHelper.GetFields(this, filter, options); } - + public IEnumerable GetEvents(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) @@ -266,7 +270,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return GetMembersHelper.GetEvents(this, filter, options); } - + public IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) @@ -274,7 +278,7 @@ namespace ICSharpCode.Decompiler.TypeSystem else return GetMembersHelper.GetMembers(this, filter, options); } - + public IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) @@ -282,12 +286,12 @@ namespace ICSharpCode.Decompiler.TypeSystem else return GetMembersHelper.GetAccessors(this, filter, options); } - + public override bool Equals(object obj) { return Equals(obj as IType); } - + public bool Equals(IType other) { if (this == other) @@ -295,43 +299,49 @@ namespace ICSharpCode.Decompiler.TypeSystem ParameterizedType c = other as ParameterizedType; if (c == null || !genericType.Equals(c.genericType) || typeArguments.Length != c.typeArguments.Length) return false; - for (int i = 0; i < typeArguments.Length; i++) { + for (int i = 0; i < typeArguments.Length; i++) + { if (!typeArguments[i].Equals(c.typeArguments[i])) return false; } return true; } - + public override int GetHashCode() { int hashCode = genericType.GetHashCode(); - unchecked { - foreach (var ta in typeArguments) { + unchecked + { + foreach (var ta in typeArguments) + { hashCode *= 1000000007; hashCode += 1000000009 * ta.GetHashCode(); } } return hashCode; } - + public IType AcceptVisitor(TypeVisitor visitor) { return visitor.VisitParameterizedType(this); } - + public IType VisitChildren(TypeVisitor visitor) { IType g = genericType.AcceptVisitor(visitor); // Keep ta == null as long as no elements changed, allocate the array only if necessary. IType[] ta = (g != genericType) ? new IType[typeArguments.Length] : null; - for (int i = 0; i < typeArguments.Length; i++) { + for (int i = 0; i < typeArguments.Length; i++) + { IType r = typeArguments[i].AcceptVisitor(visitor); if (r == null) throw new NullReferenceException("TypeVisitor.Visit-method returned null"); - if (ta == null && r != typeArguments[i]) { + if (ta == null && r != typeArguments[i]) + { // we found a difference, so we need to allocate the array ta = new IType[typeArguments.Length]; - for (int j = 0; j < i; j++) { + for (int j = 0; j < i; j++) + { ta[j] = typeArguments[j]; } } @@ -344,7 +354,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return new ParameterizedType(g, ta ?? typeArguments); } } - + /// /// ParameterizedTypeReference is a reference to generic class that specifies the type parameters. /// Example: List<string> @@ -354,7 +364,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { readonly ITypeReference genericType; readonly ITypeReference[] typeArguments; - + public ParameterizedTypeReference(ITypeReference genericType, IEnumerable typeArguments) { if (genericType == null) @@ -363,22 +373,23 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new ArgumentNullException(nameof(typeArguments)); this.genericType = genericType; this.typeArguments = typeArguments.ToArray(); - for (int i = 0; i < this.typeArguments.Length; i++) { + for (int i = 0; i < this.typeArguments.Length; i++) + { if (this.typeArguments[i] == null) throw new ArgumentNullException("typeArguments[" + i + "]"); } } - + public ITypeReference GenericType { get { return genericType; } } - + public IReadOnlyList TypeArguments { get { return typeArguments; } } - + public IType Resolve(ITypeResolveContext context) { IType baseType = genericType.Resolve(context); @@ -386,7 +397,8 @@ namespace ICSharpCode.Decompiler.TypeSystem if (tpc == 0) return baseType; IType[] resolvedTypes = new IType[tpc]; - for (int i = 0; i < resolvedTypes.Length; i++) { + for (int i = 0; i < resolvedTypes.Length; i++) + { if (i < typeArguments.Length) resolvedTypes[i] = typeArguments[i].Resolve(context); else @@ -394,12 +406,13 @@ namespace ICSharpCode.Decompiler.TypeSystem } return new ParameterizedType(baseType, resolvedTypes); } - + public override string ToString() { StringBuilder b = new StringBuilder(genericType.ToString()); b.Append('['); - for (int i = 0; i < typeArguments.Length; i++) { + for (int i = 0; i < typeArguments.Length; i++) + { if (i > 0) b.Append(','); b.Append('['); @@ -409,24 +422,28 @@ namespace ICSharpCode.Decompiler.TypeSystem b.Append(']'); return b.ToString(); } - + int ISupportsInterning.GetHashCodeForInterning() { int hashCode = genericType.GetHashCode(); - unchecked { - foreach (ITypeReference t in typeArguments) { + unchecked + { + foreach (ITypeReference t in typeArguments) + { hashCode *= 27; hashCode += t.GetHashCode(); } } return hashCode; } - + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { ParameterizedTypeReference o = other as ParameterizedTypeReference; - if (o != null && genericType == o.genericType && typeArguments.Length == o.typeArguments.Length) { - for (int i = 0; i < typeArguments.Length; i++) { + 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; } diff --git a/ICSharpCode.Decompiler/TypeSystem/PointerType.cs b/ICSharpCode.Decompiler/TypeSystem/PointerType.cs index 654269fb0..3de6cd4b7 100644 --- a/ICSharpCode.Decompiler/TypeSystem/PointerType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/PointerType.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -26,37 +27,37 @@ namespace ICSharpCode.Decompiler.TypeSystem public PointerType(IType elementType) : base(elementType) { } - + public override TypeKind Kind { get { return TypeKind.Pointer; } } - + public override string NameSuffix { get { return "*"; } } - + public override bool? IsReferenceType { get { return null; } } - + public override int GetHashCode() { return elementType.GetHashCode() ^ 91725811; } - + public override bool Equals(IType other) { PointerType a = other as PointerType; return a != null && elementType.Equals(a.elementType); } - + public override IType AcceptVisitor(TypeVisitor visitor) { return visitor.VisitPointerType(this); } - + public override IType VisitChildren(TypeVisitor visitor) { IType e = elementType.AcceptVisitor(visitor); @@ -66,38 +67,38 @@ namespace ICSharpCode.Decompiler.TypeSystem return new PointerType(e); } } - + [Serializable] public sealed class PointerTypeReference : ITypeReference, ISupportsInterning { readonly ITypeReference elementType; - + public PointerTypeReference(ITypeReference elementType) { if (elementType == null) throw new ArgumentNullException(nameof(elementType)); this.elementType = elementType; } - + public ITypeReference ElementType { get { return elementType; } } - + public IType Resolve(ITypeResolveContext context) { return new PointerType(elementType.Resolve(context)); } - + public override string ToString() { return elementType.ToString() + "*"; } - + int ISupportsInterning.GetHashCodeForInterning() { return elementType.GetHashCode() ^ 91725812; } - + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { PointerTypeReference o = other as PointerTypeReference; diff --git a/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs b/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs index dda869426..4898ee5e1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -30,12 +31,12 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// A reflection class used to represent null. /// - public sealed class Null {} - + public sealed class Null { } + /// /// A reflection class used to represent dynamic. /// - public sealed class Dynamic {} + public sealed class Dynamic { } /// /// A reflection class used to represent nint. @@ -50,8 +51,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// A reflection class used to represent an unbound type argument. /// - public sealed class UnboundTypeArgument {} - + public sealed class UnboundTypeArgument { } + #region ICompilation.FindType /// /// Retrieves the specified type in this compilation. @@ -66,7 +67,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return type.ToTypeReference().Resolve(new SimpleTypeResolveContext(compilation)); } #endregion - + #region Type.ToTypeReference() /// /// Creates a reference to the specified type. @@ -83,12 +84,14 @@ namespace ICSharpCode.Decompiler.TypeSystem { if (type == null) return SpecialType.UnknownType; - if (type.IsGenericType && !type.IsGenericTypeDefinition) { + if (type.IsGenericType && !type.IsGenericTypeDefinition) + { ITypeReference def = ToTypeReference(type.GetGenericTypeDefinition()); Type[] arguments = type.GetGenericArguments(); ITypeReference[] args = new ITypeReference[arguments.Length]; bool allUnbound = true; - for (int i = 0; i < arguments.Length; i++) { + for (int i = 0; i < arguments.Length; i++) + { args[i] = ToTypeReference(arguments[i]); allUnbound &= args[i].Equals(SpecialType.UnboundTypeArgument); } @@ -96,19 +99,32 @@ namespace ICSharpCode.Decompiler.TypeSystem return def; else return new ParameterizedTypeReference(def, args); - } else if (type.IsArray) { + } + else if (type.IsArray) + { return new ArrayTypeReference(ToTypeReference(type.GetElementType()), type.GetArrayRank()); - } else if (type.IsPointer) { + } + else if (type.IsPointer) + { return new PointerTypeReference(ToTypeReference(type.GetElementType())); - } else if (type.IsByRef) { + } + else if (type.IsByRef) + { return new ByReferenceTypeReference(ToTypeReference(type.GetElementType())); - } else if (type.IsGenericParameter) { - if (type.DeclaringMethod != null) { + } + else if (type.IsGenericParameter) + { + if (type.DeclaringMethod != null) + { return TypeParameterReference.Create(SymbolKind.Method, type.GenericParameterPosition); - } else { + } + else + { return TypeParameterReference.Create(SymbolKind.TypeDefinition, type.GenericParameterPosition); } - } else if (type.DeclaringType != null) { + } + else if (type.DeclaringType != null) + { if (type == typeof(Dynamic)) return SpecialType.Dynamic; else if (type == typeof(NInt)) @@ -123,7 +139,9 @@ namespace ICSharpCode.Decompiler.TypeSystem int typeParameterCount; string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); return new NestedTypeReference(baseTypeRef, name, typeParameterCount); - } else { + } + else + { IModuleReference assemblyReference = new DefaultAssemblyReference(type.Assembly.FullName); int typeParameterCount; string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); @@ -131,7 +149,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } } #endregion - + #region SplitTypeParameterCountFromReflectionName /// /// Removes the ` with type parameter count from the reflection name. @@ -140,13 +158,16 @@ namespace ICSharpCode.Decompiler.TypeSystem public static string SplitTypeParameterCountFromReflectionName(string reflectionName) { int pos = reflectionName.LastIndexOf('`'); - if (pos < 0) { + if (pos < 0) + { return reflectionName; - } else { + } + else + { return reflectionName.Substring(0, pos); } } - + /// /// Removes the ` with type parameter count from the reflection name. /// @@ -154,10 +175,13 @@ namespace ICSharpCode.Decompiler.TypeSystem public static string SplitTypeParameterCountFromReflectionName(string reflectionName, out int typeParameterCount) { int pos = reflectionName.LastIndexOf('`'); - if (pos < 0) { + if (pos < 0) + { typeParameterCount = 0; return reflectionName; - } else { + } + else + { string typeCount = reflectionName.Substring(pos + 1); if (int.TryParse(typeCount, out typeParameterCount)) return reflectionName.Substring(0, pos); @@ -166,7 +190,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } } #endregion - + #region TypeCode support /// /// Retrieves a built-in type using the specified type code. @@ -175,7 +199,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { return compilation.FindType((KnownTypeCode)typeCode); } - + /// /// Creates a reference to the specified type. /// @@ -185,14 +209,15 @@ namespace ICSharpCode.Decompiler.TypeSystem { return KnownTypeReference.Get((KnownTypeCode)typeCode); } - + /// /// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes match. /// public static TypeCode GetTypeCode(this IType type) { ITypeDefinition def = type as ITypeDefinition; - if (def != null) { + if (def != null) + { KnownTypeCode typeCode = def.KnownTypeCode; if (typeCode <= KnownTypeCode.String && typeCode != KnownTypeCode.Void) return (TypeCode)typeCode; @@ -202,7 +227,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return TypeCode.Empty; } #endregion - + #region ParseReflectionName /// /// Parses a reflection name into a type reference. @@ -231,10 +256,11 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new ReflectionNameParseException(pos, "Expected end of type name"); return r; } - + static bool IsReflectionNameSpecialCharacter(char c) { - switch (c) { + switch (c) + { case '+': case '`': case '[': @@ -247,40 +273,48 @@ namespace ICSharpCode.Decompiler.TypeSystem return false; } } - + /// /// Parses the reflection name starting at pos. /// If local is true, only parses local type names, not assembly qualified type names. /// - static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, bool local=false) + static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, bool local = false) { if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); ITypeReference reference; - if (reflectionTypeName[pos] == '`') { + if (reflectionTypeName[pos] == '`') + { // type parameter reference pos++; if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); - if (reflectionTypeName[pos] == '`') { + if (reflectionTypeName[pos] == '`') + { // method type parameter reference pos++; int index = ReadTypeParameterCount(reflectionTypeName, ref pos); reference = TypeParameterReference.Create(SymbolKind.Method, index); - } else { + } + else + { // class type parameter reference int index = ReadTypeParameterCount(reflectionTypeName, ref pos); reference = TypeParameterReference.Create(SymbolKind.TypeDefinition, index); } - } else { + } + else + { // not a type parameter reference: read the actual type name string typeName = ReadTypeName(reflectionTypeName, ref pos, out int tpc); string assemblyName = local ? null : SkipAheadAndReadAssemblyName(reflectionTypeName, pos); reference = CreateGetClassTypeReference(assemblyName, typeName, tpc); } // read type suffixes - while (pos < reflectionTypeName.Length) { - switch (reflectionTypeName[pos++]) { + while (pos < reflectionTypeName.Length) + { + switch (reflectionTypeName[pos++]) + { case '+': int tpc; string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); @@ -296,17 +330,23 @@ namespace ICSharpCode.Decompiler.TypeSystem // this might be an array or a generic type if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); - if (reflectionTypeName[pos] != ']' && reflectionTypeName[pos] != ',') { + if (reflectionTypeName[pos] != ']' && reflectionTypeName[pos] != ',') + { // it's a generic type List typeArguments = new List(); bool first = true; - while (first || pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { - if (first) { + while (first || pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') + { + if (first) + { first = false; - } else { + } + else + { pos++; // skip ',' } - if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') { + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') + { // non-local type names are enclosed in another set of [] pos++; @@ -316,29 +356,40 @@ namespace ICSharpCode.Decompiler.TypeSystem pos++; else throw new ReflectionNameParseException(pos, "Expected end of type argument"); - } else { + } + else + { // local type names occur directly in the outer [] typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, local: true)); } } - - if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { + + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') + { pos++; reference = new ParameterizedTypeReference(reference, typeArguments); - } else { + } + else + { throw new ReflectionNameParseException(pos, "Expected end of generic type"); } - } else { + } + else + { // it's an array int dimensions = 1; - while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { + while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') + { dimensions++; pos++; } - if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') + { pos++; // end of array reference = new ArrayTypeReference(reference, dimensions); - } else { + } + else + { throw new ReflectionNameParseException(pos, "Invalid array modifier"); } } @@ -358,13 +409,16 @@ namespace ICSharpCode.Decompiler.TypeSystem } return reference; } - + static ITypeReference CreateGetClassTypeReference(string assemblyName, string typeName, int tpc) { IModuleReference assemblyReference; - if (assemblyName != null) { + if (assemblyName != null) + { assemblyReference = new DefaultAssemblyReference(assemblyName); - } else { + } + else + { assemblyReference = null; } int pos = typeName.LastIndexOf('.'); @@ -373,12 +427,14 @@ namespace ICSharpCode.Decompiler.TypeSystem else return new GetClassTypeReference(assemblyReference, typeName.Substring(0, pos), typeName.Substring(pos + 1), tpc); } - + static string SkipAheadAndReadAssemblyName(string reflectionTypeName, int pos) { int nestingLevel = 0; - while (pos < reflectionTypeName.Length) { - switch (reflectionTypeName[pos++]) { + while (pos < reflectionTypeName.Length) + { + switch (reflectionTypeName[pos++]) + { case '[': nestingLevel++; break; @@ -388,7 +444,8 @@ namespace ICSharpCode.Decompiler.TypeSystem nestingLevel--; break; case ',': - if (nestingLevel == 0) { + if (nestingLevel == 0) + { // first skip the whitespace while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ' ') pos++; @@ -403,7 +460,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } return null; } - + static string ReadTypeName(string reflectionTypeName, ref int pos, out int tpc) { int startPos = pos; @@ -413,19 +470,23 @@ namespace ICSharpCode.Decompiler.TypeSystem if (pos == startPos) throw new ReflectionNameParseException(pos, "Expected type name"); string typeName = reflectionTypeName.Substring(startPos, pos - startPos); - if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '`') { + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '`') + { pos++; tpc = ReadTypeParameterCount(reflectionTypeName, ref pos); - } else { + } + else + { tpc = 0; } return typeName; } - + internal static int ReadTypeParameterCount(string reflectionTypeName, ref int pos) { int startPos = pos; - while (pos < reflectionTypeName.Length) { + while (pos < reflectionTypeName.Length) + { char c = reflectionTypeName[pos]; if (c < '0' || c > '9') break; diff --git a/ICSharpCode.Decompiler/TypeSystem/ReflectionNameParseException.cs b/ICSharpCode.Decompiler/TypeSystem/ReflectionNameParseException.cs index 6dd3e77f2..2618d4415 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ReflectionNameParseException.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ReflectionNameParseException.cs @@ -28,32 +28,32 @@ namespace ICSharpCode.Decompiler.TypeSystem public class ReflectionNameParseException : Exception { int position; - + public int Position { get { return position; } } - + public ReflectionNameParseException(int position) { this.position = position; } - + public ReflectionNameParseException(int position, string message) : base(message) { this.position = position; } - + public ReflectionNameParseException(int position, string message, Exception innerException) : base(message, innerException) { this.position = position; } - + // This constructor is needed for serialization. protected ReflectionNameParseException(SerializationInfo info, StreamingContext context) : base(info, context) { position = info.GetInt32("position"); } - + public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); diff --git a/ICSharpCode.Decompiler/TypeSystem/SimpleTypeResolveContext.cs b/ICSharpCode.Decompiler/TypeSystem/SimpleTypeResolveContext.cs index 10a042da6..782de8da1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/SimpleTypeResolveContext.cs +++ b/ICSharpCode.Decompiler/TypeSystem/SimpleTypeResolveContext.cs @@ -29,14 +29,14 @@ namespace ICSharpCode.Decompiler.TypeSystem readonly IModule currentModule; readonly ITypeDefinition currentTypeDefinition; readonly IMember currentMember; - + public SimpleTypeResolveContext(ICompilation compilation) { if (compilation == null) throw new ArgumentNullException(nameof(compilation)); this.compilation = compilation; } - + public SimpleTypeResolveContext(IModule module) { if (module == null) @@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.TypeSystem this.compilation = module.Compilation; this.currentModule = module; } - + public SimpleTypeResolveContext(IEntity entity) { if (entity == null) @@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.TypeSystem this.currentTypeDefinition = (entity as ITypeDefinition) ?? entity.DeclaringTypeDefinition; this.currentMember = entity as IMember; } - + private SimpleTypeResolveContext(ICompilation compilation, IModule currentModule, ITypeDefinition currentTypeDefinition, IMember currentMember) { this.compilation = compilation; @@ -62,28 +62,28 @@ namespace ICSharpCode.Decompiler.TypeSystem this.currentTypeDefinition = currentTypeDefinition; this.currentMember = currentMember; } - + public ICompilation Compilation { get { return compilation; } } - + public IModule CurrentModule { get { return currentModule; } } - + public ITypeDefinition CurrentTypeDefinition { get { return currentTypeDefinition; } } - + public IMember CurrentMember { get { return currentMember; } } - + public ITypeResolveContext WithCurrentTypeDefinition(ITypeDefinition typeDefinition) { return new SimpleTypeResolveContext(compilation, currentModule, typeDefinition, currentMember); } - + public ITypeResolveContext WithCurrentMember(IMember member) { return new SimpleTypeResolveContext(compilation, currentModule, currentTypeDefinition, member); diff --git a/ICSharpCode.Decompiler/TypeSystem/SpecialType.cs b/ICSharpCode.Decompiler/TypeSystem/SpecialType.cs index 1cd54683b..12601f9a4 100644 --- a/ICSharpCode.Decompiler/TypeSystem/SpecialType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/SpecialType.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -31,7 +32,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the type representing resolve errors. /// public readonly static SpecialType UnknownType = new SpecialType(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. /// @@ -61,44 +62,44 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Type representing the result of the C# '__arglist()' expression. /// public readonly static SpecialType ArgList = new SpecialType(TypeKind.ArgList, "__arglist", isReferenceType: null); - + /// /// A type used for unbound type arguments in partially parameterized types. /// /// public readonly static SpecialType UnboundTypeArgument = new SpecialType(TypeKind.UnboundTypeArgument, "", isReferenceType: null); - + readonly TypeKind kind; readonly string name; readonly bool? isReferenceType; - + private SpecialType(TypeKind kind, string name, bool? isReferenceType) { this.kind = kind; this.name = name; this.isReferenceType = isReferenceType; } - + public override string Name { get { return name; } } - + public override TypeKind Kind { get { return kind; } } - + public override bool? IsReferenceType { get { return isReferenceType; } } - + IType ITypeReference.Resolve(ITypeResolveContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); return this; } - - #pragma warning disable 809 + +#pragma warning disable 809 [Obsolete("Please compare special types using the kind property instead.")] public override bool Equals(IType other) { @@ -106,7 +107,7 @@ namespace ICSharpCode.Decompiler.TypeSystem // However, an unknown type with additional information is not considered to be equal to the SpecialType with TypeKind.Unknown. return other is SpecialType && other.Kind == kind; } - + public override int GetHashCode() { return 81625621 ^ (int)kind; diff --git a/ICSharpCode.Decompiler/TypeSystem/TaskType.cs b/ICSharpCode.Decompiler/TypeSystem/TaskType.cs index f59e82496..5289b75b0 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TaskType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TaskType.cs @@ -39,14 +39,15 @@ namespace ICSharpCode.Decompiler.TypeSystem else return type.TypeArguments[0]; } - + /// /// Gets whether the specified type is Task or Task<T>. /// public static bool IsTask(IType type) { ITypeDefinition def = type.GetDefinition(); - if (def != null) { + if (def != null) + { if (def.KnownTypeCode == KnownTypeCode.Task) return true; if (def.KnownTypeCode == KnownTypeCode.TaskOfT) @@ -62,7 +63,8 @@ namespace ICSharpCode.Decompiler.TypeSystem { builderType = null; ITypeDefinition def = type.GetDefinition(); - if (def != null) { + if (def != null) + { if (def.TypeParameterCount > 1) return false; var attribute = def.GetAttribute(KnownAttribute.AsyncMethodBuilder); @@ -85,11 +87,13 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Returns the full type-name of the builder type, if successful. public static bool IsNonGenericTaskType(IType task, out FullTypeName builderTypeName) { - if (task.IsKnownType(KnownTypeCode.Task)) { + if (task.IsKnownType(KnownTypeCode.Task)) + { builderTypeName = new TopLevelTypeName(ns, "AsyncTaskMethodBuilder"); return true; } - if (IsCustomTask(task, out var builderType)) { + if (IsCustomTask(task, out var builderType)) + { builderTypeName = new FullTypeName(builderType.ReflectionName); return builderTypeName.TypeParameterCount == 0; } @@ -103,11 +107,13 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Returns the full type-name of the builder type, if successful. public static bool IsGenericTaskType(IType task, out FullTypeName builderTypeName) { - if (task.IsKnownType(KnownTypeCode.TaskOfT)) { + if (task.IsKnownType(KnownTypeCode.TaskOfT)) + { builderTypeName = new TopLevelTypeName(ns, "AsyncTaskMethodBuilder", 1); return true; } - if (IsCustomTask(task, out var builderType)) { + if (IsCustomTask(task, out var builderType)) + { builderTypeName = new FullTypeName(builderType.ReflectionName); return builderTypeName.TypeParameterCount == 1; } @@ -124,13 +130,13 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new ArgumentNullException(nameof(compilation)); if (elementType == null) throw new ArgumentNullException(nameof(elementType)); - + if (elementType.Kind == TypeKind.Void) return compilation.FindType(KnownTypeCode.Task); IType taskType = compilation.FindType(KnownTypeCode.TaskOfT); ITypeDefinition taskTypeDef = taskType.GetDefinition(); if (taskTypeDef != null) - return new ParameterizedType(taskTypeDef, new [] { elementType }); + return new ParameterizedType(taskTypeDef, new[] { elementType }); else return taskType; } diff --git a/ICSharpCode.Decompiler/TypeSystem/TopLevelTypeName.cs b/ICSharpCode.Decompiler/TypeSystem/TopLevelTypeName.cs index 4e70f5ec6..d6039e150 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TopLevelTypeName.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TopLevelTypeName.cs @@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.TypeSystem readonly string namespaceName; readonly string name; readonly int typeParameterCount; - + public TopLevelTypeName(string namespaceName, string name, int typeParameterCount = 0) { if (namespaceName == null) @@ -43,99 +43,104 @@ namespace ICSharpCode.Decompiler.TypeSystem this.name = name; this.typeParameterCount = typeParameterCount; } - + public TopLevelTypeName(string reflectionName) { int pos = reflectionName.LastIndexOf('.'); - if (pos < 0) { + if (pos < 0) + { namespaceName = string.Empty; name = reflectionName; - } else { + } + else + { namespaceName = reflectionName.Substring(0, pos); name = reflectionName.Substring(pos + 1); } name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount); } - + public string Namespace { get { return namespaceName; } } - + public string Name { get { return name; } } - + public int TypeParameterCount { get { return typeParameterCount; } } - + public string ReflectionName { get { StringBuilder b = new StringBuilder(); - if (!string.IsNullOrEmpty(namespaceName)) { + if (!string.IsNullOrEmpty(namespaceName)) + { b.Append(namespaceName); b.Append('.'); } b.Append(name); - if (typeParameterCount > 0) { + if (typeParameterCount > 0) + { b.Append('`'); b.Append(typeParameterCount); } return b.ToString(); } } - + public override string ToString() { return this.ReflectionName; } - + public override bool Equals(object obj) { return (obj is TopLevelTypeName) && Equals((TopLevelTypeName)obj); } - + public bool Equals(TopLevelTypeName other) { return this.namespaceName == other.namespaceName && this.name == other.name && this.typeParameterCount == other.typeParameterCount; } - + public override int GetHashCode() { return (name != null ? name.GetHashCode() : 0) ^ (namespaceName != null ? namespaceName.GetHashCode() : 0) ^ typeParameterCount; } - + public static bool operator ==(TopLevelTypeName lhs, TopLevelTypeName rhs) { return lhs.Equals(rhs); } - + public static bool operator !=(TopLevelTypeName lhs, TopLevelTypeName rhs) { return !lhs.Equals(rhs); } } - + [Serializable] public sealed class TopLevelTypeNameComparer : IEqualityComparer { public static readonly TopLevelTypeNameComparer Ordinal = new TopLevelTypeNameComparer(StringComparer.Ordinal); public static readonly TopLevelTypeNameComparer OrdinalIgnoreCase = new TopLevelTypeNameComparer(StringComparer.OrdinalIgnoreCase); - + public readonly StringComparer NameComparer; - + public TopLevelTypeNameComparer(StringComparer nameComparer) { this.NameComparer = nameComparer; } - + public bool Equals(TopLevelTypeName x, TopLevelTypeName y) { return x.TypeParameterCount == y.TypeParameterCount && NameComparer.Equals(x.Name, y.Name) && NameComparer.Equals(x.Namespace, y.Namespace); } - + public int GetHashCode(TopLevelTypeName obj) { return NameComparer.GetHashCode(obj.Name) ^ NameComparer.GetHashCode(obj.Namespace) ^ obj.TypeParameterCount; diff --git a/ICSharpCode.Decompiler/TypeSystem/TupleType.cs b/ICSharpCode.Decompiler/TypeSystem/TupleType.cs index 906fa413a..26c61cbbf 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TupleType.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TupleType.cs @@ -22,6 +22,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Text; + using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; @@ -53,7 +54,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the names of the tuple elements. /// public ImmutableArray ElementNames { get; } - + public TupleType(ICompilation compilation, ImmutableArray elementTypes, ImmutableArray elementNames = default(ImmutableArray), IModule valueTupleAssembly = null) @@ -61,9 +62,12 @@ namespace ICSharpCode.Decompiler.TypeSystem this.Compilation = compilation; this.UnderlyingType = CreateUnderlyingType(compilation, elementTypes, valueTupleAssembly); this.ElementTypes = elementTypes; - if (elementNames.IsDefault) { + if (elementNames.IsDefault) + { this.ElementNames = Enumerable.Repeat(null, elementTypes.Length).ToImmutableArray(); - } else { + } + else + { Debug.Assert(elementNames.Length == elementTypes.Length); this.ElementNames = elementNames; } @@ -77,7 +81,8 @@ namespace ICSharpCode.Decompiler.TypeSystem var type = new ParameterizedType( FindValueTupleType(compilation, valueTupleAssembly, remainder), elementTypes.Slice(pos)); - while (pos > 0) { + while (pos > 0) + { pos -= (RestPosition - 1); type = new ParameterizedType( FindValueTupleType(compilation, valueTupleAssembly, RestPosition), @@ -90,7 +95,8 @@ namespace ICSharpCode.Decompiler.TypeSystem private static IType FindValueTupleType(ICompilation compilation, IModule valueTupleAssembly, int tpc) { var typeName = new TopLevelTypeName("System", "ValueTuple", tpc); - if (valueTupleAssembly != null) { + if (valueTupleAssembly != null) + { var typeDef = valueTupleAssembly.GetTypeDefinition(typeName); if (typeDef != null) return typeDef; @@ -104,19 +110,25 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static bool IsTupleCompatible(IType type, out int tupleCardinality) { - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.Tuple: tupleCardinality = ((TupleType)type).ElementTypes.Length; return true; case TypeKind.Class: case TypeKind.Struct: - if (type.Namespace == "System" && type.Name == "ValueTuple") { + if (type.Namespace == "System" && type.Name == "ValueTuple") + { int tpc = type.TypeParameterCount; - if (tpc > 0 && tpc < RestPosition) { + if (tpc > 0 && tpc < RestPosition) + { tupleCardinality = tpc; return true; - } else if (tpc == RestPosition && type is ParameterizedType pt) { - if (IsTupleCompatible(pt.TypeArguments[RestIndex], out tupleCardinality)) { + } + else if (tpc == RestPosition && type is ParameterizedType pt) + { + if (IsTupleCompatible(pt.TypeArguments[RestIndex], out tupleCardinality)) + { tupleCardinality += RestPosition - 1; return true; } @@ -135,13 +147,16 @@ namespace ICSharpCode.Decompiler.TypeSystem public static TupleType FromUnderlyingType(ICompilation compilation, IType type) { var elementTypes = GetTupleElementTypes(type); - if (elementTypes.Length > 0) { + if (elementTypes.Length > 0) + { return new TupleType( compilation, elementTypes, valueTupleAssembly: type.GetDefinition()?.ParentModule ); - } else { + } + else + { return null; } } @@ -152,15 +167,19 @@ namespace ICSharpCode.Decompiler.TypeSystem public static ImmutableArray GetTupleElementTypes(IType tupleType) { List output = null; - if (Collect(tupleType)) { + if (Collect(tupleType)) + { return output.ToImmutableArray(); - } else { + } + else + { return default(ImmutableArray); } bool Collect(IType type) { - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.Tuple: if (output == null) output = new List(); @@ -168,14 +187,18 @@ namespace ICSharpCode.Decompiler.TypeSystem return true; case TypeKind.Class: case TypeKind.Struct: - if (type.Namespace == "System" && type.Name == "ValueTuple") { + if (type.Namespace == "System" && type.Name == "ValueTuple") + { if (output == null) output = new List(); int tpc = type.TypeParameterCount; - if (tpc > 0 && tpc < RestPosition) { + if (tpc > 0 && tpc < RestPosition) + { output.AddRange(type.TypeArguments); return true; - } else if (tpc == RestPosition) { + } + else if (tpc == RestPosition) + { output.AddRange(type.TypeArguments.Take(RestPosition - 1)); return Collect(type.TypeArguments[RestIndex]); } @@ -210,9 +233,11 @@ namespace ICSharpCode.Decompiler.TypeSystem public override int GetHashCode() { - unchecked { + unchecked + { int hash = UnderlyingType.GetHashCode(); - foreach (string name in ElementNames) { + foreach (string name in ElementNames) + { hash *= 31; hash += name != null ? name.GetHashCode() : 0; } @@ -224,11 +249,13 @@ namespace ICSharpCode.Decompiler.TypeSystem { StringBuilder b = new StringBuilder(); b.Append('('); - for (int i = 0; i < ElementTypes.Length; i++) { + for (int i = 0; i < ElementTypes.Length; i++) + { if (i > 0) b.Append(", "); b.Append(ElementTypes[i]); - if (ElementNames[i] != null) { + if (ElementNames[i] != null) + { b.Append(' '); b.Append(ElementNames[i]); } @@ -245,20 +272,26 @@ namespace ICSharpCode.Decompiler.TypeSystem public override IType VisitChildren(TypeVisitor visitor) { IType[] newElementTypes = null; - for (int i = 0; i < ElementTypes.Length; i++) { + for (int i = 0; i < ElementTypes.Length; i++) + { IType type = ElementTypes[i]; var newType = type.AcceptVisitor(visitor); - if (newType != type) { - if (newElementTypes == null) { + if (newType != type) + { + if (newElementTypes == null) + { newElementTypes = ElementTypes.ToArray(); } newElementTypes[i] = newType; } } - if (newElementTypes != null) { + if (newElementTypes != null) + { return new TupleType(this.Compilation, newElementTypes.ToImmutableArray(), this.ElementNames, this.GetDefinition()?.ParentModule); - } else { + } + else + { return this; } } @@ -287,7 +320,8 @@ namespace ICSharpCode.Decompiler.TypeSystem public override IEnumerable GetFields(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { // The fields from the underlying type (Item1..Item7 and Rest) - foreach (var field in UnderlyingType.GetFields(filter, options)) { + foreach (var field in UnderlyingType.GetFields(filter, options)) + { yield return field; } /*for (int i = 0; i < ElementTypes.Length; i++) { diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeKind.cs b/ICSharpCode.Decompiler/TypeSystem/TypeKind.cs index 8bc26d43c..4d813cfed 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeKind.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeKind.cs @@ -26,7 +26,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { /// 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. @@ -39,7 +39,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// A that is an enum. /// System.Enum itself is TypeKind.Class Enum, - + /// The System.Void type. /// Void, @@ -60,11 +60,11 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// IType.GetNestedTypes(Predicate{ITypeDefinition}, GetMemberOptions) UnboundTypeArgument, - + /// The type is a type parameter. /// TypeParameter, - + /// An array type /// Array, @@ -74,7 +74,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// A managed reference type /// ByReference, - + /// Intersection of several types /// Intersection, diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeParameterSubstitution.cs b/ICSharpCode.Decompiler/TypeSystem/TypeParameterSubstitution.cs index 0e92e7326..0202f72fa 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeParameterSubstitution.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeParameterSubstitution.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Text; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -31,10 +32,10 @@ namespace ICSharpCode.Decompiler.TypeSystem /// The identity function. /// public static readonly TypeParameterSubstitution Identity = new TypeParameterSubstitution(null, null); - + readonly IReadOnlyList classTypeArguments; readonly IReadOnlyList methodTypeArguments; - + /// /// Creates a new type parameter substitution. /// @@ -51,7 +52,7 @@ namespace ICSharpCode.Decompiler.TypeSystem this.classTypeArguments = classTypeArguments; this.methodTypeArguments = methodTypeArguments; } - + /// /// Gets the list of class type arguments. /// Returns null if this substitution keeps class type parameters unmodified. @@ -59,7 +60,7 @@ namespace ICSharpCode.Decompiler.TypeSystem public IReadOnlyList ClassTypeArguments { get { return classTypeArguments; } } - + /// /// Gets the list of method type arguments. /// Returns null if this substitution keeps method type parameters unmodified. @@ -67,7 +68,7 @@ namespace ICSharpCode.Decompiler.TypeSystem public IReadOnlyList MethodTypeArguments { get { return methodTypeArguments; } } - + #region Compose /// /// Computes a single TypeParameterSubstitution so that for all types t: @@ -87,11 +88,12 @@ namespace ICSharpCode.Decompiler.TypeSystem var methodTypeArguments = f.methodTypeArguments != null ? GetComposedTypeArguments(f.methodTypeArguments, g) : g.methodTypeArguments; return new TypeParameterSubstitution(classTypeArguments, methodTypeArguments); } - + static IReadOnlyList GetComposedTypeArguments(IReadOnlyList input, TypeParameterSubstitution substitution) { IType[] result = new IType[input.Count]; - for (int i = 0; i < result.Length; i++) { + for (int i = 0; i < result.Length; i++) + { result[i] = input[i].AcceptVisitor(substitution); } return result; @@ -115,14 +117,15 @@ namespace ICSharpCode.Decompiler.TypeSystem return TypeListEquals(classTypeArguments, other.classTypeArguments) && TypeListEquals(methodTypeArguments, other.methodTypeArguments); } - + public override int GetHashCode() { - unchecked { + unchecked + { return 1124131 * TypeListHashCode(classTypeArguments) + 1821779 * TypeListHashCode(methodTypeArguments); } } - + static bool TypeListEquals(IReadOnlyList a, IReadOnlyList b) { if (a == b) @@ -131,7 +134,8 @@ namespace ICSharpCode.Decompiler.TypeSystem return false; if (a.Count != b.Count) return false; - for (int i = 0; i < a.Count; i++) { + for (int i = 0; i < a.Count; i++) + { if (!a[i].Equals(b[i])) return false; } @@ -146,7 +150,8 @@ namespace ICSharpCode.Decompiler.TypeSystem return false; if (a.Count != b.Count) return false; - for (int i = 0; i < a.Count; i++) { + for (int i = 0; i < a.Count; i++) + { var an = a[i].AcceptVisitor(normalization); var bn = b[i].AcceptVisitor(normalization); if (!an.Equals(bn)) @@ -159,9 +164,11 @@ namespace ICSharpCode.Decompiler.TypeSystem { if (obj == null) return 0; - unchecked { + unchecked + { int hashCode = 1; - foreach (var element in obj) { + foreach (var element in obj) + { hashCode *= 27; hashCode += element.GetHashCode(); } @@ -169,35 +176,46 @@ namespace ICSharpCode.Decompiler.TypeSystem } } #endregion - + public override IType VisitTypeParameter(ITypeParameter type) { int index = type.Index; - if (classTypeArguments != null && type.OwnerType == SymbolKind.TypeDefinition) { + if (classTypeArguments != null && type.OwnerType == SymbolKind.TypeDefinition) + { if (index >= 0 && index < classTypeArguments.Count) return classTypeArguments[index]; else return SpecialType.UnknownType; - } else if (methodTypeArguments != null && type.OwnerType == SymbolKind.Method) { + } + else if (methodTypeArguments != null && type.OwnerType == SymbolKind.Method) + { if (index >= 0 && index < methodTypeArguments.Count) return methodTypeArguments[index]; else return SpecialType.UnknownType; - } else { + } + else + { return base.VisitTypeParameter(type); } } public override IType VisitNullabilityAnnotatedType(NullabilityAnnotatedType type) { - if (type is NullabilityAnnotatedTypeParameter tp) { - if (tp.Nullability == Nullability.Nullable) { + if (type is NullabilityAnnotatedTypeParameter tp) + { + if (tp.Nullability == Nullability.Nullable) + { return VisitTypeParameter(tp).ChangeNullability(Nullability.Nullable); - } else { + } + else + { // T! substituted with T=oblivious string should result in oblivious string return VisitTypeParameter(tp); } - } else { + } + else + { return base.VisitNullabilityAnnotatedType(type); } } @@ -207,29 +225,47 @@ namespace ICSharpCode.Decompiler.TypeSystem 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(", "); + 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].ReflectionName); } - if (classTypeArguments.Count == 0) { - if (first) first = false; else b.Append(", "); + if (classTypeArguments.Count == 0) + { + if (first) + first = false; + else + b.Append(", "); b.Append("[]"); } } - if (methodTypeArguments != null) { - for (int i = 0; i < methodTypeArguments.Count; i++) { - if (first) first = false; else b.Append(", "); + 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].ReflectionName); } - if (methodTypeArguments.Count == 0) { - if (first) first = false; else b.Append(", "); + if (methodTypeArguments.Count == 0) + { + if (first) + first = false; + else + b.Append(", "); b.Append("[]"); } } diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs index 5c2924d8c..95cdb6d0a 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs @@ -19,8 +19,10 @@ using System; using System.Collections.Immutable; using System.Reflection.Metadata.Ecma335; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem.Implementation; + using SRM = System.Reflection.Metadata; namespace ICSharpCode.Decompiler.TypeSystem @@ -110,7 +112,8 @@ namespace ICSharpCode.Decompiler.TypeSystem bool? IsReferenceType(SRM.MetadataReader reader, SRM.EntityHandle handle, byte rawTypeKind) { - switch (reader.ResolveSignatureTypeKind(handle, rawTypeKind)) { + switch (reader.ResolveSignatureTypeKind(handle, rawTypeKind)) + { case SRM.SignatureTypeKind.ValueType: return false; case SRM.SignatureTypeKind.Class: @@ -134,9 +137,12 @@ namespace ICSharpCode.Decompiler.TypeSystem IModule resolvedModule = module.GetDeclaringModule(handle); var fullTypeName = handle.GetFullTypeName(reader); IType type; - if (resolvedModule != null) { + if (resolvedModule != null) + { type = resolvedModule.GetTypeDefinition(fullTypeName); - } else { + } + else + { type = GetClassTypeReference.ResolveInAllAssemblies(compilation, in fullTypeName); } return type ?? new UnknownType(fullTypeName, IsReferenceType(reader, handle, rawTypeKind)); @@ -144,17 +150,21 @@ namespace ICSharpCode.Decompiler.TypeSystem public IType GetTypeFromSerializedName(string name) { - if (name == null) { + if (name == null) + { return null; } - try { + try + { return ReflectionHelper.ParseReflectionName(name) .Resolve(module != null ? new SimpleTypeResolveContext(module) : new SimpleTypeResolveContext(compilation)); - } catch (ReflectionNameParseException ex) { + } + catch (ReflectionNameParseException ex) + { throw new BadImageFormatException($"Invalid type name: \"{name}\": {ex.Message}"); } } - + public IType GetTypeFromSpecification(SRM.MetadataReader reader, GenericContext genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind) { return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext); diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs index 26da4cdd9..af5bfb903 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Semantics; @@ -95,7 +96,8 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new ArgumentNullException(nameof(type)); if (baseType == null) return false; - if (type.Compilation != baseType.Compilation) { + if (type.Compilation != baseType.Compilation) + { throw new InvalidOperationException("Both arguments to IsDerivedFrom() must be from the same compilation."); } return type.GetAllBaseTypeDefinitions().Contains(baseType); @@ -121,11 +123,13 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static IEnumerable GetDeclaringTypeDefinitions(this ITypeDefinition definition) { - if (definition == null) { + if (definition == null) + { throw new ArgumentNullException(nameof(definition)); } - while (definition != null) { + while (definition != null) + { yield return definition; definition = definition.DeclaringTypeDefinition; } @@ -145,7 +149,8 @@ namespace ICSharpCode.Decompiler.TypeSystem // If both classes and methods, or different classes (nested types) // are involved, find the most specific one int newNestingLevel = GetNestingLevel(type.Owner); - if (newNestingLevel > typeParameterOwnerNestingLevel) { + if (newNestingLevel > typeParameterOwnerNestingLevel) + { typeParameterOwner = type.Owner; typeParameterOwnerNestingLevel = newNestingLevel; } @@ -155,7 +160,8 @@ namespace ICSharpCode.Decompiler.TypeSystem static int GetNestingLevel(IEntity entity) { int level = 0; - while (entity != null) { + while (entity != null) + { level++; entity = entity.DeclaringTypeDefinition; } @@ -276,7 +282,8 @@ namespace ICSharpCode.Decompiler.TypeSystem public static IType SkipModifiers(this IType ty) { - while (ty is ModifiedType mt) { + while (ty is ModifiedType mt) + { ty = mt.ElementType; } return ty; @@ -338,7 +345,8 @@ namespace ICSharpCode.Decompiler.TypeSystem { if (compilation == null) throw new ArgumentNullException(nameof(compilation)); - foreach (IModule asm in compilation.Modules) { + foreach (IModule asm in compilation.Modules) + { ITypeDefinition def = asm.GetTypeDefinition(fullTypeName); if (def != null) return def; @@ -359,7 +367,8 @@ namespace ICSharpCode.Decompiler.TypeSystem if (typeDef == null) return null; int typeParameterCount = topLevelTypeName.TypeParameterCount; - for (int i = 0; i < fullTypeName.NestingLevel; i++) { + for (int i = 0; i < fullTypeName.NestingLevel; i++) + { string name = fullTypeName.GetNestedTypeName(i); typeParameterCount += fullTypeName.GetNestedTypeAdditionalTypeParameterCount(i); typeDef = FindNestedType(typeDef, name, typeParameterCount); @@ -371,7 +380,8 @@ namespace ICSharpCode.Decompiler.TypeSystem static ITypeDefinition FindNestedType(ITypeDefinition typeDef, string name, int typeParameterCount) { - foreach (var nestedType in typeDef.NestedTypes) { + foreach (var nestedType in typeDef.NestedTypes) + { if (nestedType.Name == name && nestedType.TypeParameterCount == typeParameterCount) return nestedType; } @@ -431,15 +441,23 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static IEnumerable GetAttributes(this IEntity entity, bool inherit) { - if (inherit) { - if (entity is ITypeDefinition td) { + if (inherit) + { + if (entity is ITypeDefinition td) + { return InheritanceHelper.GetAttributes(td); - } else if (entity is IMember m) { + } + else if (entity is IMember m) + { return InheritanceHelper.GetAttributes(m); - } else { + } + else + { throw new NotSupportedException("Unknown entity type"); } - } else { + } + else + { return entity.GetAttributes(); } } @@ -486,13 +504,20 @@ namespace ICSharpCode.Decompiler.TypeSystem #region ResolveResult public static ISymbol GetSymbol(this ResolveResult rr) { - if (rr is LocalResolveResult) { + if (rr is LocalResolveResult) + { return ((LocalResolveResult)rr).Variable; - } else if (rr is MemberResolveResult) { + } + else if (rr is MemberResolveResult) + { return ((MemberResolveResult)rr).Member; - } else if (rr is TypeResolveResult) { + } + else if (rr is TypeResolveResult) + { return ((TypeResolveResult)rr).Type.GetDefinition(); - } else if (rr is ConversionResolveResult) { + } + else if (rr is ConversionResolveResult) + { return ((ConversionResolveResult)rr).Input.GetSymbol(); } @@ -503,13 +528,17 @@ namespace ICSharpCode.Decompiler.TypeSystem public static IType GetElementTypeFromIEnumerable(this IType collectionType, ICompilation compilation, bool allowIEnumerator, out bool? isGeneric) { bool foundNonGenericIEnumerable = false; - foreach (IType baseType in collectionType.GetAllBaseTypes()) { + foreach (IType baseType in collectionType.GetAllBaseTypes()) + { ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null) { + if (baseTypeDef != null) + { KnownTypeCode typeCode = baseTypeDef.KnownTypeCode; - if (typeCode == KnownTypeCode.IEnumerableOfT || (allowIEnumerator && typeCode == KnownTypeCode.IEnumeratorOfT)) { + if (typeCode == KnownTypeCode.IEnumerableOfT || (allowIEnumerator && typeCode == KnownTypeCode.IEnumeratorOfT)) + { ParameterizedType pt = baseType as ParameterizedType; - if (pt != null) { + if (pt != null) + { isGeneric = true; return pt.GetTypeArgument(0); } @@ -519,7 +548,8 @@ namespace ICSharpCode.Decompiler.TypeSystem } } // System.Collections.IEnumerable found in type hierarchy -> Object is element type. - if (foundNonGenericIEnumerable) { + if (foundNonGenericIEnumerable) + { isGeneric = false; return compilation.FindType(KnownTypeCode.Object); } @@ -545,10 +575,12 @@ namespace ICSharpCode.Decompiler.TypeSystem public static bool IsDirectImportOf(this ITypeDefinition type, IModule module) { var moduleReference = type.ParentModule; - foreach (var asmRef in module.PEFile.AssemblyReferences) { + foreach (var asmRef in module.PEFile.AssemblyReferences) + { if (asmRef.FullName == moduleReference.FullAssemblyName) return true; - if (asmRef.Name == "netstandard" && asmRef.GetPublicKeyToken() != null) { + if (asmRef.Name == "netstandard" && asmRef.GetPublicKeyToken() != null) + { var referencedModule = module.Compilation.FindModuleByReference(asmRef); if (referencedModule != null && !referencedModule.PEFile.GetTypeForwarder(type.FullTypeName).IsNil) return true; @@ -559,13 +591,17 @@ namespace ICSharpCode.Decompiler.TypeSystem public static IModule FindModuleByReference(this ICompilation compilation, IAssemblyReference assemblyName) { - foreach (var module in compilation.Modules) { - if (string.Equals(module.FullAssemblyName, assemblyName.FullName, StringComparison.OrdinalIgnoreCase)) { + foreach (var module in compilation.Modules) + { + if (string.Equals(module.FullAssemblyName, assemblyName.FullName, StringComparison.OrdinalIgnoreCase)) + { return module; } } - foreach (var module in compilation.Modules) { - if (string.Equals(module.Name, assemblyName.Name, StringComparison.OrdinalIgnoreCase)) { + foreach (var module in compilation.Modules) + { + if (string.Equals(module.Name, assemblyName.Name, StringComparison.OrdinalIgnoreCase)) + { return module; } } diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs b/ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs index e92748db9..3d2856c34 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs @@ -32,7 +32,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static int GetSize(this IType type) { - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.Pointer: case TypeKind.ByReference: case TypeKind.Class: @@ -50,7 +51,8 @@ namespace ICSharpCode.Decompiler.TypeSystem var typeDef = type.GetDefinition(); if (typeDef == null) return 0; - switch (typeDef.KnownTypeCode) { + switch (typeDef.KnownTypeCode) + { case KnownTypeCode.Boolean: case KnownTypeCode.SByte: case KnownTypeCode.Byte: @@ -85,7 +87,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static int GetSize(this StackType type) { - switch (type) { + switch (type) + { case StackType.I4: return 4; case StackType.I8: @@ -122,7 +125,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static bool IsCSharpSmallIntegerType(this IType type) { - switch (type.GetDefinition()?.KnownTypeCode) { + switch (type.GetDefinition()?.KnownTypeCode) + { case KnownTypeCode.Byte: case KnownTypeCode.SByte: case KnownTypeCode.Int16: @@ -140,7 +144,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static bool IsCSharpNativeIntegerType(this IType type) { - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.NInt: case TypeKind.NUInt: return true; @@ -156,7 +161,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static bool IsCSharpPrimitiveIntegerType(this IType type) { - switch (type.GetDefinition()?.KnownTypeCode) { + switch (type.GetDefinition()?.KnownTypeCode) + { case KnownTypeCode.Byte: case KnownTypeCode.SByte: case KnownTypeCode.Int16: @@ -177,7 +183,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static bool IsIntegerType(this StackType type) { - switch (type) { + switch (type) + { case StackType.I4: case StackType.I: case StackType.I8: @@ -193,7 +200,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static bool IsFloatType(this StackType type) { - switch (type) { + switch (type) + { case StackType.F4: case StackType.F8: return true; @@ -252,9 +260,11 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static StackType GetStackType(this IType type) { - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.Unknown: - if (type.IsReferenceType == true) { + if (type.IsReferenceType == true) + { return StackType.O; } return StackType.Unknown; @@ -275,7 +285,8 @@ namespace ICSharpCode.Decompiler.TypeSystem ITypeDefinition typeDef = type.GetEnumUnderlyingType().GetDefinition(); if (typeDef == null) return StackType.O; - switch (typeDef.KnownTypeCode) { + switch (typeDef.KnownTypeCode) + { case KnownTypeCode.Boolean: case KnownTypeCode.Char: case KnownTypeCode.SByte: @@ -325,7 +336,8 @@ namespace ICSharpCode.Decompiler.TypeSystem public static Sign GetSign(this IType type) { type = type.SkipModifiers(); - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.Pointer: case TypeKind.NUInt: return Sign.Unsigned; @@ -335,7 +347,8 @@ namespace ICSharpCode.Decompiler.TypeSystem var typeDef = type.GetEnumUnderlyingType().GetDefinition(); if (typeDef == null) return Sign.None; - switch (typeDef.KnownTypeCode) { + switch (typeDef.KnownTypeCode) + { case KnownTypeCode.SByte: case KnownTypeCode.Int16: case KnownTypeCode.Int32: @@ -363,7 +376,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static PrimitiveType ToPrimitiveType(this KnownTypeCode knownTypeCode) { - switch (knownTypeCode) { + switch (knownTypeCode) + { case KnownTypeCode.SByte: return PrimitiveType.I1; case KnownTypeCode.Int16: @@ -400,11 +414,16 @@ namespace ICSharpCode.Decompiler.TypeSystem public static PrimitiveType ToPrimitiveType(this IType type) { type = type.SkipModifiers(); - switch (type.Kind) { - case TypeKind.Unknown: return PrimitiveType.Unknown; - case TypeKind.ByReference: return PrimitiveType.Ref; - case TypeKind.NInt: return PrimitiveType.I; - case TypeKind.NUInt: return PrimitiveType.U; + switch (type.Kind) + { + case TypeKind.Unknown: + return PrimitiveType.Unknown; + case TypeKind.ByReference: + return PrimitiveType.Ref; + case TypeKind.NInt: + return PrimitiveType.I; + case TypeKind.NUInt: + return PrimitiveType.U; } var def = type.GetEnumUnderlyingType().GetDefinition(); return def != null ? def.KnownTypeCode.ToPrimitiveType() : PrimitiveType.None; @@ -415,7 +434,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static KnownTypeCode ToKnownTypeCode(this PrimitiveType primitiveType) { - switch (primitiveType) { + switch (primitiveType) + { case PrimitiveType.I1: return KnownTypeCode.SByte; case PrimitiveType.I2: @@ -448,7 +468,8 @@ namespace ICSharpCode.Decompiler.TypeSystem public static KnownTypeCode ToKnownTypeCode(this StackType stackType, Sign sign = Sign.None) { - switch (stackType) { + switch (stackType) + { case StackType.I4: return sign == Sign.Unsigned ? KnownTypeCode.UInt32 : KnownTypeCode.Int32; case StackType.I8: @@ -470,7 +491,8 @@ namespace ICSharpCode.Decompiler.TypeSystem public static PrimitiveType ToPrimitiveType(this StackType stackType, Sign sign = Sign.None) { - switch (stackType) { + switch (stackType) + { case StackType.I4: return sign == Sign.Unsigned ? PrimitiveType.U4 : PrimitiveType.I4; case StackType.I8: diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeVisitor.cs b/ICSharpCode.Decompiler/TypeSystem/TypeVisitor.cs index 4960d0265..e934f0ac0 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeVisitor.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeVisitor.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -30,27 +31,27 @@ namespace ICSharpCode.Decompiler.TypeSystem { return type.VisitChildren(this); } - + public virtual IType VisitTypeParameter(ITypeParameter type) { return type.VisitChildren(this); } - + public virtual IType VisitParameterizedType(ParameterizedType type) { return type.VisitChildren(this); } - + public virtual IType VisitArrayType(ArrayType type) { return type.VisitChildren(this); } - + public virtual IType VisitPointerType(PointerType type) { return type.VisitChildren(this); } - + public virtual IType VisitByReferenceType(ByReferenceType type) { return type.VisitChildren(this); diff --git a/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs b/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs index 6b53caa88..eee269c66 100644 --- a/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs @@ -22,6 +22,7 @@ using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem @@ -40,7 +41,8 @@ namespace ICSharpCode.Decompiler.TypeSystem var paramList = new List(baseMethod.Parameters); Debug.Assert(paramList.Last().Type.Kind == TypeKind.ArgList); paramList.RemoveAt(paramList.Count - 1); - foreach (IType varArg in varArgTypes) { + foreach (IType varArg in varArgTypes) + { paramList.Add(new DefaultParameter(varArg, name: string.Empty, owner: this)); } this.parameters = paramList.ToArray(); @@ -51,17 +53,17 @@ namespace ICSharpCode.Decompiler.TypeSystem public int RegularParameterCount { get { return baseMethod.Parameters.Count - 1; } } - + public IReadOnlyList Parameters { get { return parameters; } } - + public override bool Equals(object obj) { VarArgInstanceMethod other = obj as VarArgInstanceMethod; return other != null && baseMethod.Equals(other.baseMethod); } - + public override int GetHashCode() { return baseMethod.GetHashCode(); @@ -77,24 +79,28 @@ namespace ICSharpCode.Decompiler.TypeSystem { StringBuilder b = new StringBuilder("["); b.Append(this.SymbolKind); - if (this.DeclaringType != null) { + if (this.DeclaringType != null) + { b.Append(this.DeclaringType.ReflectionName); b.Append('.'); } b.Append(this.Name); - if (this.TypeParameters.Count > 0) { + if (this.TypeParameters.Count > 0) + { b.Append("``"); b.Append(this.TypeParameters.Count); } b.Append('('); - for (int i = 0; i < this.Parameters.Count; i++) { + for (int i = 0; i < this.Parameters.Count; i++) + { if (i > 0) b.Append(", "); if (i == this.RegularParameterCount) b.Append("..., "); b.Append(this.Parameters[i].Type.ReflectionName); } - if (this.Parameters.Count == this.RegularParameterCount) { + if (this.Parameters.Count == this.RegularParameterCount) + { b.Append(", ..."); } b.Append("):"); @@ -102,7 +108,7 @@ namespace ICSharpCode.Decompiler.TypeSystem b.Append(']'); return b.ToString(); } - + #region IMethod implementation public IMethod Specialize(TypeParameterSubstitution substitution) { @@ -146,11 +152,11 @@ namespace ICSharpCode.Decompiler.TypeSystem public bool IsOperator { get { return baseMethod.IsOperator; } } - + public bool HasBody { get { return baseMethod.HasBody; } } - + public bool IsAccessor => baseMethod.IsAccessor; public IMember AccessorOwner => baseMethod.AccessorOwner; public MethodSemanticsAttributes AccessorKind => baseMethod.AccessorKind; @@ -203,7 +209,7 @@ namespace ICSharpCode.Decompiler.TypeSystem #endregion #region ISymbol implementation - + public SymbolKind SymbolKind { get { return baseMethod.SymbolKind; } } @@ -215,7 +221,7 @@ namespace ICSharpCode.Decompiler.TypeSystem #endregion #region IEntity implementation - + public ITypeDefinition DeclaringTypeDefinition { get { return baseMethod.DeclaringTypeDefinition; } } @@ -247,7 +253,7 @@ namespace ICSharpCode.Decompiler.TypeSystem public Accessibility Accessibility { get { return baseMethod.Accessibility; } } - + #endregion #region INamedElement implementation diff --git a/ICSharpCode.Decompiler/Util/BitSet.cs b/ICSharpCode.Decompiler/Util/BitSet.cs index a9e9deddf..9ca0a2b0c 100644 --- a/ICSharpCode.Decompiler/Util/BitSet.cs +++ b/ICSharpCode.Decompiler/Util/BitSet.cs @@ -30,15 +30,15 @@ namespace ICSharpCode.Decompiler.Util const int BitsPerWord = 64; const int Log2BitsPerWord = 6; const ulong Mask = 0xffffffffffffffffUL; - + readonly ulong[] words; - + static int WordIndex(int bitIndex) { Debug.Assert(bitIndex >= 0); return bitIndex >> Log2BitsPerWord; } - + /// /// Creates a new bitset, where initially all bits are zero. /// @@ -51,7 +51,7 @@ namespace ICSharpCode.Decompiler.Util { this.words = bits; } - + public BitSet Clone() { return new BitSet((ulong[])words.Clone()); @@ -74,7 +74,8 @@ namespace ICSharpCode.Decompiler.Util /// public bool Any() { - for (int i = 0; i < words.Length; i++) { + for (int i = 0; i < words.Length; i++) + { if (words[i] != 0) return true; } @@ -87,19 +88,24 @@ namespace ICSharpCode.Decompiler.Util public bool All(int startIndex, int endIndex) { Debug.Assert(startIndex <= endIndex); - if (startIndex >= endIndex) { + if (startIndex >= endIndex) + { return true; } int startWordIndex = WordIndex(startIndex); int endWordIndex = WordIndex(endIndex - 1); ulong startMask = Mask << startIndex; ulong endMask = Mask >> -endIndex; // same as (Mask >> (64 - (endIndex % 64))) - if (startWordIndex == endWordIndex) { + if (startWordIndex == endWordIndex) + { return (words[startWordIndex] & (startMask & endMask)) == (startMask & endMask); - } else { + } + else + { if ((words[startWordIndex] & startMask) != startMask) return false; - for (int i = startWordIndex + 1; i < endWordIndex; i++) { + for (int i = startWordIndex + 1; i < endWordIndex; i++) + { if (words[i] != ulong.MaxValue) return false; } @@ -113,25 +119,27 @@ namespace ICSharpCode.Decompiler.Util public bool SetEquals(BitSet other) { Debug.Assert(words.Length == other.words.Length); - for (int i = 0; i < words.Length; i++) { + for (int i = 0; i < words.Length; i++) + { if (words[i] != other.words[i]) return false; } return true; } - + /// /// Gets whether this set is a subset of other, or equal. /// public bool IsSubsetOf(BitSet other) { - for (int i = 0; i < words.Length; i++) { + for (int i = 0; i < words.Length; i++) + { if ((words[i] & ~other.words[i]) != 0) return false; } return true; } - + /// /// Gets whether this set is a superset of other, or equal. /// @@ -139,99 +147,112 @@ namespace ICSharpCode.Decompiler.Util { return other.IsSubsetOf(this); } - + public bool IsProperSubsetOf(BitSet other) { return IsSubsetOf(other) && !SetEquals(other); } - + public bool IsProperSupersetOf(BitSet other) { return IsSupersetOf(other) && !SetEquals(other); } - + /// /// Gets whether at least one bit is set in both bitsets. /// public bool Overlaps(BitSet other) { - for (int i = 0; i < words.Length; i++) { + for (int i = 0; i < words.Length; i++) + { if ((words[i] & other.words[i]) != 0) return true; } return false; } - + public void UnionWith(BitSet other) { Debug.Assert(words.Length == other.words.Length); - for (int i = 0; i < words.Length; i++) { + for (int i = 0; i < words.Length; i++) + { words[i] |= other.words[i]; } } - + public void IntersectWith(BitSet other) { - for (int i = 0; i < words.Length; i++) { + for (int i = 0; i < words.Length; i++) + { words[i] &= other.words[i]; } } - + public void Set(int index) { words[WordIndex(index)] |= (1UL << index); } - + /// /// Sets all bits i; where startIndex <= i < endIndex. /// public void Set(int startIndex, int endIndex) { Debug.Assert(startIndex <= endIndex); - if (startIndex >= endIndex) { + if (startIndex >= endIndex) + { return; } int startWordIndex = WordIndex(startIndex); int endWordIndex = WordIndex(endIndex - 1); ulong startMask = Mask << startIndex; ulong endMask = Mask >> -endIndex; // same as (Mask >> (64 - (endIndex % 64))) - if (startWordIndex == endWordIndex) { + if (startWordIndex == endWordIndex) + { words[startWordIndex] |= (startMask & endMask); - } else { + } + else + { words[startWordIndex] |= startMask; - for (int i = startWordIndex + 1; i < endWordIndex; i++) { + for (int i = startWordIndex + 1; i < endWordIndex; i++) + { words[i] = ulong.MaxValue; } words[endWordIndex] |= endMask; } } - + // Note: intentionally no SetAll(), because it would also set the // extra bits (due to the capacity being rounded up to a full word). - + public void Clear(int index) { words[WordIndex(index)] &= ~(1UL << index); } - + /// /// Clear all bits i; where startIndex <= i < endIndex. /// public void Clear(int startIndex, int endIndex) { Debug.Assert(startIndex <= endIndex); - if (startIndex >= endIndex) { + if (startIndex >= endIndex) + { return; } int startWordIndex = WordIndex(startIndex); int endWordIndex = WordIndex(endIndex - 1); ulong startMask = Mask << startIndex; ulong endMask = Mask >> -endIndex; // same as (Mask >> (64 - (endIndex % 64))) - if (startWordIndex == endWordIndex) { + if (startWordIndex == endWordIndex) + { words[startWordIndex] &= ~(startMask & endMask); - } else { + } + else + { words[startWordIndex] &= ~startMask; - for (int i = startWordIndex + 1; i < endWordIndex; i++) { + for (int i = startWordIndex + 1; i < endWordIndex; i++) + { words[i] = 0; } words[endWordIndex] &= ~endMask; @@ -240,7 +261,8 @@ namespace ICSharpCode.Decompiler.Util public void ClearAll() { - for (int i = 0; i < words.Length; i++) { + for (int i = 0; i < words.Length; i++) + { words[i] = 0; } } @@ -250,16 +272,19 @@ namespace ICSharpCode.Decompiler.Util Debug.Assert(words.Length == incoming.words.Length); Array.Copy(incoming.words, 0, words, 0, words.Length); } - + public override string ToString() { StringBuilder b = new StringBuilder(); b.Append('{'); - for (int i = 0; i < words.Length * BitsPerWord; i++) { - if (this[i]) { + for (int i = 0; i < words.Length * BitsPerWord; i++) + { + if (this[i]) + { if (b.Length > 1) b.Append(", "); - if (b.Length > 500) { + if (b.Length > 500) + { b.Append("..."); break; } diff --git a/ICSharpCode.Decompiler/Util/BusyManager.cs b/ICSharpCode.Decompiler/Util/BusyManager.cs index 1ab8e0a8d..f277fc40a 100644 --- a/ICSharpCode.Decompiler/Util/BusyManager.cs +++ b/ICSharpCode.Decompiler/Util/BusyManager.cs @@ -31,38 +31,40 @@ namespace ICSharpCode.Decompiler.Util { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", - Justification = "Should always be used with 'var'")] + Justification = "Should always be used with 'var'")] public struct BusyLock : IDisposable { public static readonly BusyLock Failed = new BusyLock(null); - + readonly List objectList; - + internal BusyLock(List objectList) { this.objectList = objectList; } - + public bool Success { get { return objectList != null; } } - + public void Dispose() { - if (objectList != null) { + if (objectList != null) + { objectList.RemoveAt(objectList.Count - 1); } } } - + [ThreadStatic] static List _activeObjects; - + public static BusyLock Enter(object obj) { List activeObjects = _activeObjects; if (activeObjects == null) activeObjects = _activeObjects = new List(); - for (int i = 0; i < activeObjects.Count; i++) { + for (int i = 0; i < activeObjects.Count; i++) + { if (activeObjects[i] == obj) return BusyLock.Failed; } diff --git a/ICSharpCode.Decompiler/Util/CSharpPrimitiveCast.cs b/ICSharpCode.Decompiler/Util/CSharpPrimitiveCast.cs index 719465c03..b57516b45 100644 --- a/ICSharpCode.Decompiler/Util/CSharpPrimitiveCast.cs +++ b/ICSharpCode.Decompiler/Util/CSharpPrimitiveCast.cs @@ -43,408 +43,724 @@ namespace ICSharpCode.Decompiler.Util else return CSharpPrimitiveCastUnchecked(targetType, input); } - + static object CSharpPrimitiveCastChecked(TypeCode targetType, object input) { - checked { + checked + { TypeCode sourceType = Type.GetTypeCode(input.GetType()); if (sourceType == targetType) return input; - switch (targetType) { + switch (targetType) + { case TypeCode.Char: - switch (sourceType) { - case TypeCode.SByte: return (char)(sbyte)input; - case TypeCode.Byte: return (char)(byte)input; - case TypeCode.Int16: return (char)(short)input; - case TypeCode.UInt16: return (char)(ushort)input; - case TypeCode.Int32: return (char)(int)input; - case TypeCode.UInt32: return (char)(uint)input; - case TypeCode.Int64: return (char)(long)input; - case TypeCode.UInt64: return (char)(ulong)input; - case TypeCode.Single: return (char)(float)input; - case TypeCode.Double: return (char)(double)input; - case TypeCode.Decimal: return (char)(decimal)input; - case TypeCode.Boolean: return (char)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.SByte: + return (char)(sbyte)input; + case TypeCode.Byte: + return (char)(byte)input; + case TypeCode.Int16: + return (char)(short)input; + case TypeCode.UInt16: + return (char)(ushort)input; + case TypeCode.Int32: + return (char)(int)input; + case TypeCode.UInt32: + return (char)(uint)input; + case TypeCode.Int64: + return (char)(long)input; + case TypeCode.UInt64: + return (char)(ulong)input; + case TypeCode.Single: + return (char)(float)input; + case TypeCode.Double: + return (char)(double)input; + case TypeCode.Decimal: + return (char)(decimal)input; + case TypeCode.Boolean: + return (char)((bool)input ? 1 : 0); } break; case TypeCode.SByte: - switch (sourceType) { - case TypeCode.Char: return (sbyte)(char)input; - case TypeCode.Byte: return (sbyte)(byte)input; - case TypeCode.Int16: return (sbyte)(short)input; - case TypeCode.UInt16: return (sbyte)(ushort)input; - case TypeCode.Int32: return (sbyte)(int)input; - case TypeCode.UInt32: return (sbyte)(uint)input; - case TypeCode.Int64: return (sbyte)(long)input; - case TypeCode.UInt64: return (sbyte)(ulong)input; - case TypeCode.Single: return (sbyte)(float)input; - case TypeCode.Double: return (sbyte)(double)input; - case TypeCode.Decimal: return (sbyte)(decimal)input; - case TypeCode.Boolean: return (sbyte)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (sbyte)(char)input; + case TypeCode.Byte: + return (sbyte)(byte)input; + case TypeCode.Int16: + return (sbyte)(short)input; + case TypeCode.UInt16: + return (sbyte)(ushort)input; + case TypeCode.Int32: + return (sbyte)(int)input; + case TypeCode.UInt32: + return (sbyte)(uint)input; + case TypeCode.Int64: + return (sbyte)(long)input; + case TypeCode.UInt64: + return (sbyte)(ulong)input; + case TypeCode.Single: + return (sbyte)(float)input; + case TypeCode.Double: + return (sbyte)(double)input; + case TypeCode.Decimal: + return (sbyte)(decimal)input; + case TypeCode.Boolean: + return (sbyte)((bool)input ? 1 : 0); } break; case TypeCode.Byte: - switch (sourceType) { - case TypeCode.Char: return (byte)(char)input; - case TypeCode.SByte: return (byte)(sbyte)input; - case TypeCode.Int16: return (byte)(short)input; - case TypeCode.UInt16: return (byte)(ushort)input; - case TypeCode.Int32: return (byte)(int)input; - case TypeCode.UInt32: return (byte)(uint)input; - case TypeCode.Int64: return (byte)(long)input; - case TypeCode.UInt64: return (byte)(ulong)input; - case TypeCode.Single: return (byte)(float)input; - case TypeCode.Double: return (byte)(double)input; - case TypeCode.Decimal: return (byte)(decimal)input; - case TypeCode.Boolean: return (byte)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (byte)(char)input; + case TypeCode.SByte: + return (byte)(sbyte)input; + case TypeCode.Int16: + return (byte)(short)input; + case TypeCode.UInt16: + return (byte)(ushort)input; + case TypeCode.Int32: + return (byte)(int)input; + case TypeCode.UInt32: + return (byte)(uint)input; + case TypeCode.Int64: + return (byte)(long)input; + case TypeCode.UInt64: + return (byte)(ulong)input; + case TypeCode.Single: + return (byte)(float)input; + case TypeCode.Double: + return (byte)(double)input; + case TypeCode.Decimal: + return (byte)(decimal)input; + case TypeCode.Boolean: + return (byte)((bool)input ? 1 : 0); } break; case TypeCode.Int16: - switch (sourceType) { - case TypeCode.Char: return (short)(char)input; - case TypeCode.SByte: return (short)(sbyte)input; - case TypeCode.Byte: return (short)(byte)input; - case TypeCode.UInt16: return (short)(ushort)input; - case TypeCode.Int32: return (short)(int)input; - case TypeCode.UInt32: return (short)(uint)input; - case TypeCode.Int64: return (short)(long)input; - case TypeCode.UInt64: return (short)(ulong)input; - case TypeCode.Single: return (short)(float)input; - case TypeCode.Double: return (short)(double)input; - case TypeCode.Decimal: return (short)(decimal)input; - case TypeCode.Boolean: return (short)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (short)(char)input; + case TypeCode.SByte: + return (short)(sbyte)input; + case TypeCode.Byte: + return (short)(byte)input; + case TypeCode.UInt16: + return (short)(ushort)input; + case TypeCode.Int32: + return (short)(int)input; + case TypeCode.UInt32: + return (short)(uint)input; + case TypeCode.Int64: + return (short)(long)input; + case TypeCode.UInt64: + return (short)(ulong)input; + case TypeCode.Single: + return (short)(float)input; + case TypeCode.Double: + return (short)(double)input; + case TypeCode.Decimal: + return (short)(decimal)input; + case TypeCode.Boolean: + return (short)((bool)input ? 1 : 0); } break; case TypeCode.UInt16: - switch (sourceType) { - case TypeCode.Char: return (ushort)(char)input; - case TypeCode.SByte: return (ushort)(sbyte)input; - case TypeCode.Byte: return (ushort)(byte)input; - case TypeCode.Int16: return (ushort)(short)input; - case TypeCode.Int32: return (ushort)(int)input; - case TypeCode.UInt32: return (ushort)(uint)input; - case TypeCode.Int64: return (ushort)(long)input; - case TypeCode.UInt64: return (ushort)(ulong)input; - case TypeCode.Single: return (ushort)(float)input; - case TypeCode.Double: return (ushort)(double)input; - case TypeCode.Decimal: return (ushort)(decimal)input; - case TypeCode.Boolean: return (ushort)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (ushort)(char)input; + case TypeCode.SByte: + return (ushort)(sbyte)input; + case TypeCode.Byte: + return (ushort)(byte)input; + case TypeCode.Int16: + return (ushort)(short)input; + case TypeCode.Int32: + return (ushort)(int)input; + case TypeCode.UInt32: + return (ushort)(uint)input; + case TypeCode.Int64: + return (ushort)(long)input; + case TypeCode.UInt64: + return (ushort)(ulong)input; + case TypeCode.Single: + return (ushort)(float)input; + case TypeCode.Double: + return (ushort)(double)input; + case TypeCode.Decimal: + return (ushort)(decimal)input; + case TypeCode.Boolean: + return (ushort)((bool)input ? 1 : 0); } break; case TypeCode.Int32: - switch (sourceType) { - case TypeCode.Char: return (int)(char)input; - case TypeCode.SByte: return (int)(sbyte)input; - case TypeCode.Byte: return (int)(byte)input; - case TypeCode.Int16: return (int)(short)input; - case TypeCode.UInt16: return (int)(ushort)input; - case TypeCode.UInt32: return (int)(uint)input; - case TypeCode.Int64: return (int)(long)input; - case TypeCode.UInt64: return (int)(ulong)input; - case TypeCode.Single: return (int)(float)input; - case TypeCode.Double: return (int)(double)input; - case TypeCode.Decimal: return (int)(decimal)input; - case TypeCode.Boolean: return (int)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (int)(char)input; + case TypeCode.SByte: + return (int)(sbyte)input; + case TypeCode.Byte: + return (int)(byte)input; + case TypeCode.Int16: + return (int)(short)input; + case TypeCode.UInt16: + return (int)(ushort)input; + case TypeCode.UInt32: + return (int)(uint)input; + case TypeCode.Int64: + return (int)(long)input; + case TypeCode.UInt64: + return (int)(ulong)input; + case TypeCode.Single: + return (int)(float)input; + case TypeCode.Double: + return (int)(double)input; + case TypeCode.Decimal: + return (int)(decimal)input; + case TypeCode.Boolean: + return (int)((bool)input ? 1 : 0); } break; case TypeCode.UInt32: - switch (sourceType) { - case TypeCode.Char: return (uint)(char)input; - case TypeCode.SByte: return (uint)(sbyte)input; - case TypeCode.Byte: return (uint)(byte)input; - case TypeCode.Int16: return (uint)(short)input; - case TypeCode.UInt16: return (uint)(ushort)input; - case TypeCode.Int32: return (uint)(int)input; - case TypeCode.Int64: return (uint)(long)input; - case TypeCode.UInt64: return (uint)(ulong)input; - case TypeCode.Single: return (uint)(float)input; - case TypeCode.Double: return (uint)(double)input; - case TypeCode.Decimal: return (uint)(decimal)input; - case TypeCode.Boolean: return (uint)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (uint)(char)input; + case TypeCode.SByte: + return (uint)(sbyte)input; + case TypeCode.Byte: + return (uint)(byte)input; + case TypeCode.Int16: + return (uint)(short)input; + case TypeCode.UInt16: + return (uint)(ushort)input; + case TypeCode.Int32: + return (uint)(int)input; + case TypeCode.Int64: + return (uint)(long)input; + case TypeCode.UInt64: + return (uint)(ulong)input; + case TypeCode.Single: + return (uint)(float)input; + case TypeCode.Double: + return (uint)(double)input; + case TypeCode.Decimal: + return (uint)(decimal)input; + case TypeCode.Boolean: + return (uint)((bool)input ? 1 : 0); } break; case TypeCode.Int64: - switch (sourceType) { - case TypeCode.Char: return (long)(char)input; - case TypeCode.SByte: return (long)(sbyte)input; - case TypeCode.Byte: return (long)(byte)input; - case TypeCode.Int16: return (long)(short)input; - case TypeCode.UInt16: return (long)(ushort)input; - case TypeCode.Int32: return (long)(int)input; - case TypeCode.UInt32: return (long)(uint)input; - case TypeCode.UInt64: return (long)(ulong)input; - case TypeCode.Single: return (long)(float)input; - case TypeCode.Double: return (long)(double)input; - case TypeCode.Decimal: return (long)(decimal)input; - case TypeCode.Boolean: return (long)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (long)(char)input; + case TypeCode.SByte: + return (long)(sbyte)input; + case TypeCode.Byte: + return (long)(byte)input; + case TypeCode.Int16: + return (long)(short)input; + case TypeCode.UInt16: + return (long)(ushort)input; + case TypeCode.Int32: + return (long)(int)input; + case TypeCode.UInt32: + return (long)(uint)input; + case TypeCode.UInt64: + return (long)(ulong)input; + case TypeCode.Single: + return (long)(float)input; + case TypeCode.Double: + return (long)(double)input; + case TypeCode.Decimal: + return (long)(decimal)input; + case TypeCode.Boolean: + return (long)((bool)input ? 1 : 0); } break; case TypeCode.UInt64: - switch (sourceType) { - case TypeCode.Char: return (ulong)(char)input; - case TypeCode.SByte: return (ulong)(sbyte)input; - case TypeCode.Byte: return (ulong)(byte)input; - case TypeCode.Int16: return (ulong)(short)input; - case TypeCode.UInt16: return (ulong)(ushort)input; - case TypeCode.Int32: return (ulong)(int)input; - case TypeCode.UInt32: return (ulong)(uint)input; - case TypeCode.Int64: return (ulong)(long)input; - case TypeCode.Single: return (ulong)(float)input; - case TypeCode.Double: return (ulong)(double)input; - case TypeCode.Decimal: return (ulong)(decimal)input; - case TypeCode.Boolean: return (ulong)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (ulong)(char)input; + case TypeCode.SByte: + return (ulong)(sbyte)input; + case TypeCode.Byte: + return (ulong)(byte)input; + case TypeCode.Int16: + return (ulong)(short)input; + case TypeCode.UInt16: + return (ulong)(ushort)input; + case TypeCode.Int32: + return (ulong)(int)input; + case TypeCode.UInt32: + return (ulong)(uint)input; + case TypeCode.Int64: + return (ulong)(long)input; + case TypeCode.Single: + return (ulong)(float)input; + case TypeCode.Double: + return (ulong)(double)input; + case TypeCode.Decimal: + return (ulong)(decimal)input; + case TypeCode.Boolean: + return (ulong)((bool)input ? 1 : 0); } break; case TypeCode.Single: - switch (sourceType) { - case TypeCode.Char: return (float)(char)input; - case TypeCode.SByte: return (float)(sbyte)input; - case TypeCode.Byte: return (float)(byte)input; - case TypeCode.Int16: return (float)(short)input; - case TypeCode.UInt16: return (float)(ushort)input; - case TypeCode.Int32: return (float)(int)input; - case TypeCode.UInt32: return (float)(uint)input; - case TypeCode.Int64: return (float)(long)input; - case TypeCode.UInt64: return (float)(ulong)input; - case TypeCode.Double: return (float)(double)input; - case TypeCode.Decimal: return (float)(decimal)input; - case TypeCode.Boolean: return (float)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (float)(char)input; + case TypeCode.SByte: + return (float)(sbyte)input; + case TypeCode.Byte: + return (float)(byte)input; + case TypeCode.Int16: + return (float)(short)input; + case TypeCode.UInt16: + return (float)(ushort)input; + case TypeCode.Int32: + return (float)(int)input; + case TypeCode.UInt32: + return (float)(uint)input; + case TypeCode.Int64: + return (float)(long)input; + case TypeCode.UInt64: + return (float)(ulong)input; + case TypeCode.Double: + return (float)(double)input; + case TypeCode.Decimal: + return (float)(decimal)input; + case TypeCode.Boolean: + return (float)((bool)input ? 1 : 0); } break; case TypeCode.Double: - switch (sourceType) { - case TypeCode.Char: return (double)(char)input; - case TypeCode.SByte: return (double)(sbyte)input; - case TypeCode.Byte: return (double)(byte)input; - case TypeCode.Int16: return (double)(short)input; - case TypeCode.UInt16: return (double)(ushort)input; - case TypeCode.Int32: return (double)(int)input; - case TypeCode.UInt32: return (double)(uint)input; - case TypeCode.Int64: return (double)(long)input; - case TypeCode.UInt64: return (double)(ulong)input; - case TypeCode.Single: return (double)(float)input; - case TypeCode.Decimal: return (double)(decimal)input; - case TypeCode.Boolean: return (double)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (double)(char)input; + case TypeCode.SByte: + return (double)(sbyte)input; + case TypeCode.Byte: + return (double)(byte)input; + case TypeCode.Int16: + return (double)(short)input; + case TypeCode.UInt16: + return (double)(ushort)input; + case TypeCode.Int32: + return (double)(int)input; + case TypeCode.UInt32: + return (double)(uint)input; + case TypeCode.Int64: + return (double)(long)input; + case TypeCode.UInt64: + return (double)(ulong)input; + case TypeCode.Single: + return (double)(float)input; + case TypeCode.Decimal: + return (double)(decimal)input; + case TypeCode.Boolean: + return (double)((bool)input ? 1 : 0); } break; case TypeCode.Decimal: - switch (sourceType) { - case TypeCode.Char: return (decimal)(char)input; - case TypeCode.SByte: return (decimal)(sbyte)input; - case TypeCode.Byte: return (decimal)(byte)input; - case TypeCode.Int16: return (decimal)(short)input; - case TypeCode.UInt16: return (decimal)(ushort)input; - case TypeCode.Int32: return (decimal)(int)input; - case TypeCode.UInt32: return (decimal)(uint)input; - case TypeCode.Int64: return (decimal)(long)input; - case TypeCode.UInt64: return (decimal)(ulong)input; - case TypeCode.Single: return (decimal)(float)input; - case TypeCode.Double: return (decimal)(double)input; - case TypeCode.Boolean: return (decimal)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (decimal)(char)input; + case TypeCode.SByte: + return (decimal)(sbyte)input; + case TypeCode.Byte: + return (decimal)(byte)input; + case TypeCode.Int16: + return (decimal)(short)input; + case TypeCode.UInt16: + return (decimal)(ushort)input; + case TypeCode.Int32: + return (decimal)(int)input; + case TypeCode.UInt32: + return (decimal)(uint)input; + case TypeCode.Int64: + return (decimal)(long)input; + case TypeCode.UInt64: + return (decimal)(ulong)input; + case TypeCode.Single: + return (decimal)(float)input; + case TypeCode.Double: + return (decimal)(double)input; + case TypeCode.Boolean: + return (decimal)((bool)input ? 1 : 0); } break; } throw new InvalidCastException("Cast from " + sourceType + " to " + targetType + "not supported."); } } - + static object CSharpPrimitiveCastUnchecked(TypeCode targetType, object input) { - unchecked { + unchecked + { TypeCode sourceType = Type.GetTypeCode(input.GetType()); if (sourceType == targetType) return input; - switch (targetType) { + switch (targetType) + { case TypeCode.Char: - switch (sourceType) { - case TypeCode.SByte: return (char)(sbyte)input; - case TypeCode.Byte: return (char)(byte)input; - case TypeCode.Int16: return (char)(short)input; - case TypeCode.UInt16: return (char)(ushort)input; - case TypeCode.Int32: return (char)(int)input; - case TypeCode.UInt32: return (char)(uint)input; - case TypeCode.Int64: return (char)(long)input; - case TypeCode.UInt64: return (char)(ulong)input; - case TypeCode.Single: return (char)(float)input; - case TypeCode.Double: return (char)(double)input; - case TypeCode.Decimal: return (char)(decimal)input; - case TypeCode.Boolean: return (char)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.SByte: + return (char)(sbyte)input; + case TypeCode.Byte: + return (char)(byte)input; + case TypeCode.Int16: + return (char)(short)input; + case TypeCode.UInt16: + return (char)(ushort)input; + case TypeCode.Int32: + return (char)(int)input; + case TypeCode.UInt32: + return (char)(uint)input; + case TypeCode.Int64: + return (char)(long)input; + case TypeCode.UInt64: + return (char)(ulong)input; + case TypeCode.Single: + return (char)(float)input; + case TypeCode.Double: + return (char)(double)input; + case TypeCode.Decimal: + return (char)(decimal)input; + case TypeCode.Boolean: + return (char)((bool)input ? 1 : 0); } break; case TypeCode.SByte: - switch (sourceType) { - case TypeCode.Char: return (sbyte)(char)input; - case TypeCode.Byte: return (sbyte)(byte)input; - case TypeCode.Int16: return (sbyte)(short)input; - case TypeCode.UInt16: return (sbyte)(ushort)input; - case TypeCode.Int32: return (sbyte)(int)input; - case TypeCode.UInt32: return (sbyte)(uint)input; - case TypeCode.Int64: return (sbyte)(long)input; - case TypeCode.UInt64: return (sbyte)(ulong)input; - case TypeCode.Single: return (sbyte)(float)input; - case TypeCode.Double: return (sbyte)(double)input; - case TypeCode.Decimal: return (sbyte)(decimal)input; - case TypeCode.Boolean: return (sbyte)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (sbyte)(char)input; + case TypeCode.Byte: + return (sbyte)(byte)input; + case TypeCode.Int16: + return (sbyte)(short)input; + case TypeCode.UInt16: + return (sbyte)(ushort)input; + case TypeCode.Int32: + return (sbyte)(int)input; + case TypeCode.UInt32: + return (sbyte)(uint)input; + case TypeCode.Int64: + return (sbyte)(long)input; + case TypeCode.UInt64: + return (sbyte)(ulong)input; + case TypeCode.Single: + return (sbyte)(float)input; + case TypeCode.Double: + return (sbyte)(double)input; + case TypeCode.Decimal: + return (sbyte)(decimal)input; + case TypeCode.Boolean: + return (sbyte)((bool)input ? 1 : 0); } break; case TypeCode.Byte: - switch (sourceType) { - case TypeCode.Char: return (byte)(char)input; - case TypeCode.SByte: return (byte)(sbyte)input; - case TypeCode.Int16: return (byte)(short)input; - case TypeCode.UInt16: return (byte)(ushort)input; - case TypeCode.Int32: return (byte)(int)input; - case TypeCode.UInt32: return (byte)(uint)input; - case TypeCode.Int64: return (byte)(long)input; - case TypeCode.UInt64: return (byte)(ulong)input; - case TypeCode.Single: return (byte)(float)input; - case TypeCode.Double: return (byte)(double)input; - case TypeCode.Decimal: return (byte)(decimal)input; - case TypeCode.Boolean: return (byte)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (byte)(char)input; + case TypeCode.SByte: + return (byte)(sbyte)input; + case TypeCode.Int16: + return (byte)(short)input; + case TypeCode.UInt16: + return (byte)(ushort)input; + case TypeCode.Int32: + return (byte)(int)input; + case TypeCode.UInt32: + return (byte)(uint)input; + case TypeCode.Int64: + return (byte)(long)input; + case TypeCode.UInt64: + return (byte)(ulong)input; + case TypeCode.Single: + return (byte)(float)input; + case TypeCode.Double: + return (byte)(double)input; + case TypeCode.Decimal: + return (byte)(decimal)input; + case TypeCode.Boolean: + return (byte)((bool)input ? 1 : 0); } break; case TypeCode.Int16: - switch (sourceType) { - case TypeCode.Char: return (short)(char)input; - case TypeCode.SByte: return (short)(sbyte)input; - case TypeCode.Byte: return (short)(byte)input; - case TypeCode.UInt16: return (short)(ushort)input; - case TypeCode.Int32: return (short)(int)input; - case TypeCode.UInt32: return (short)(uint)input; - case TypeCode.Int64: return (short)(long)input; - case TypeCode.UInt64: return (short)(ulong)input; - case TypeCode.Single: return (short)(float)input; - case TypeCode.Double: return (short)(double)input; - case TypeCode.Decimal: return (short)(decimal)input; - case TypeCode.Boolean: return (short)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (short)(char)input; + case TypeCode.SByte: + return (short)(sbyte)input; + case TypeCode.Byte: + return (short)(byte)input; + case TypeCode.UInt16: + return (short)(ushort)input; + case TypeCode.Int32: + return (short)(int)input; + case TypeCode.UInt32: + return (short)(uint)input; + case TypeCode.Int64: + return (short)(long)input; + case TypeCode.UInt64: + return (short)(ulong)input; + case TypeCode.Single: + return (short)(float)input; + case TypeCode.Double: + return (short)(double)input; + case TypeCode.Decimal: + return (short)(decimal)input; + case TypeCode.Boolean: + return (short)((bool)input ? 1 : 0); } break; case TypeCode.UInt16: - switch (sourceType) { - case TypeCode.Char: return (ushort)(char)input; - case TypeCode.SByte: return (ushort)(sbyte)input; - case TypeCode.Byte: return (ushort)(byte)input; - case TypeCode.Int16: return (ushort)(short)input; - case TypeCode.Int32: return (ushort)(int)input; - case TypeCode.UInt32: return (ushort)(uint)input; - case TypeCode.Int64: return (ushort)(long)input; - case TypeCode.UInt64: return (ushort)(ulong)input; - case TypeCode.Single: return (ushort)(float)input; - case TypeCode.Double: return (ushort)(double)input; - case TypeCode.Decimal: return (ushort)(decimal)input; - case TypeCode.Boolean: return (ushort)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (ushort)(char)input; + case TypeCode.SByte: + return (ushort)(sbyte)input; + case TypeCode.Byte: + return (ushort)(byte)input; + case TypeCode.Int16: + return (ushort)(short)input; + case TypeCode.Int32: + return (ushort)(int)input; + case TypeCode.UInt32: + return (ushort)(uint)input; + case TypeCode.Int64: + return (ushort)(long)input; + case TypeCode.UInt64: + return (ushort)(ulong)input; + case TypeCode.Single: + return (ushort)(float)input; + case TypeCode.Double: + return (ushort)(double)input; + case TypeCode.Decimal: + return (ushort)(decimal)input; + case TypeCode.Boolean: + return (ushort)((bool)input ? 1 : 0); } break; case TypeCode.Int32: - switch (sourceType) { - case TypeCode.Char: return (int)(char)input; - case TypeCode.SByte: return (int)(sbyte)input; - case TypeCode.Byte: return (int)(byte)input; - case TypeCode.Int16: return (int)(short)input; - case TypeCode.UInt16: return (int)(ushort)input; - case TypeCode.UInt32: return (int)(uint)input; - case TypeCode.Int64: return (int)(long)input; - case TypeCode.UInt64: return (int)(ulong)input; - case TypeCode.Single: return (int)(float)input; - case TypeCode.Double: return (int)(double)input; - case TypeCode.Decimal: return (int)(decimal)input; - case TypeCode.Boolean: return (int)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (int)(char)input; + case TypeCode.SByte: + return (int)(sbyte)input; + case TypeCode.Byte: + return (int)(byte)input; + case TypeCode.Int16: + return (int)(short)input; + case TypeCode.UInt16: + return (int)(ushort)input; + case TypeCode.UInt32: + return (int)(uint)input; + case TypeCode.Int64: + return (int)(long)input; + case TypeCode.UInt64: + return (int)(ulong)input; + case TypeCode.Single: + return (int)(float)input; + case TypeCode.Double: + return (int)(double)input; + case TypeCode.Decimal: + return (int)(decimal)input; + case TypeCode.Boolean: + return (int)((bool)input ? 1 : 0); } break; case TypeCode.UInt32: - switch (sourceType) { - case TypeCode.Char: return (uint)(char)input; - case TypeCode.SByte: return (uint)(sbyte)input; - case TypeCode.Byte: return (uint)(byte)input; - case TypeCode.Int16: return (uint)(short)input; - case TypeCode.UInt16: return (uint)(ushort)input; - case TypeCode.Int32: return (uint)(int)input; - case TypeCode.Int64: return (uint)(long)input; - case TypeCode.UInt64: return (uint)(ulong)input; - case TypeCode.Single: return (uint)(float)input; - case TypeCode.Double: return (uint)(double)input; - case TypeCode.Decimal: return (uint)(decimal)input; - case TypeCode.Boolean: return (uint)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (uint)(char)input; + case TypeCode.SByte: + return (uint)(sbyte)input; + case TypeCode.Byte: + return (uint)(byte)input; + case TypeCode.Int16: + return (uint)(short)input; + case TypeCode.UInt16: + return (uint)(ushort)input; + case TypeCode.Int32: + return (uint)(int)input; + case TypeCode.Int64: + return (uint)(long)input; + case TypeCode.UInt64: + return (uint)(ulong)input; + case TypeCode.Single: + return (uint)(float)input; + case TypeCode.Double: + return (uint)(double)input; + case TypeCode.Decimal: + return (uint)(decimal)input; + case TypeCode.Boolean: + return (uint)((bool)input ? 1 : 0); } break; case TypeCode.Int64: - switch (sourceType) { - case TypeCode.Char: return (long)(char)input; - case TypeCode.SByte: return (long)(sbyte)input; - case TypeCode.Byte: return (long)(byte)input; - case TypeCode.Int16: return (long)(short)input; - case TypeCode.UInt16: return (long)(ushort)input; - case TypeCode.Int32: return (long)(int)input; - case TypeCode.UInt32: return (long)(uint)input; - case TypeCode.UInt64: return (long)(ulong)input; - case TypeCode.Single: return (long)(float)input; - case TypeCode.Double: return (long)(double)input; - case TypeCode.Decimal: return (long)(decimal)input; - case TypeCode.Boolean: return (long)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (long)(char)input; + case TypeCode.SByte: + return (long)(sbyte)input; + case TypeCode.Byte: + return (long)(byte)input; + case TypeCode.Int16: + return (long)(short)input; + case TypeCode.UInt16: + return (long)(ushort)input; + case TypeCode.Int32: + return (long)(int)input; + case TypeCode.UInt32: + return (long)(uint)input; + case TypeCode.UInt64: + return (long)(ulong)input; + case TypeCode.Single: + return (long)(float)input; + case TypeCode.Double: + return (long)(double)input; + case TypeCode.Decimal: + return (long)(decimal)input; + case TypeCode.Boolean: + return (long)((bool)input ? 1 : 0); } break; case TypeCode.UInt64: - switch (sourceType) { - case TypeCode.Char: return (ulong)(char)input; - case TypeCode.SByte: return (ulong)(sbyte)input; - case TypeCode.Byte: return (ulong)(byte)input; - case TypeCode.Int16: return (ulong)(short)input; - case TypeCode.UInt16: return (ulong)(ushort)input; - case TypeCode.Int32: return (ulong)(int)input; - case TypeCode.UInt32: return (ulong)(uint)input; - case TypeCode.Int64: return (ulong)(long)input; - case TypeCode.Single: return (ulong)(float)input; - case TypeCode.Double: return (ulong)(double)input; - case TypeCode.Decimal: return (ulong)(decimal)input; - case TypeCode.Boolean: return (ulong)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (ulong)(char)input; + case TypeCode.SByte: + return (ulong)(sbyte)input; + case TypeCode.Byte: + return (ulong)(byte)input; + case TypeCode.Int16: + return (ulong)(short)input; + case TypeCode.UInt16: + return (ulong)(ushort)input; + case TypeCode.Int32: + return (ulong)(int)input; + case TypeCode.UInt32: + return (ulong)(uint)input; + case TypeCode.Int64: + return (ulong)(long)input; + case TypeCode.Single: + return (ulong)(float)input; + case TypeCode.Double: + return (ulong)(double)input; + case TypeCode.Decimal: + return (ulong)(decimal)input; + case TypeCode.Boolean: + return (ulong)((bool)input ? 1 : 0); } break; case TypeCode.Single: - switch (sourceType) { - case TypeCode.Char: return (float)(char)input; - case TypeCode.SByte: return (float)(sbyte)input; - case TypeCode.Byte: return (float)(byte)input; - case TypeCode.Int16: return (float)(short)input; - case TypeCode.UInt16: return (float)(ushort)input; - case TypeCode.Int32: return (float)(int)input; - case TypeCode.UInt32: return (float)(uint)input; - case TypeCode.Int64: return (float)(long)input; - case TypeCode.UInt64: return (float)(ulong)input; - case TypeCode.Double: return (float)(double)input; - case TypeCode.Decimal: return (float)(decimal)input; - case TypeCode.Boolean: return (float)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (float)(char)input; + case TypeCode.SByte: + return (float)(sbyte)input; + case TypeCode.Byte: + return (float)(byte)input; + case TypeCode.Int16: + return (float)(short)input; + case TypeCode.UInt16: + return (float)(ushort)input; + case TypeCode.Int32: + return (float)(int)input; + case TypeCode.UInt32: + return (float)(uint)input; + case TypeCode.Int64: + return (float)(long)input; + case TypeCode.UInt64: + return (float)(ulong)input; + case TypeCode.Double: + return (float)(double)input; + case TypeCode.Decimal: + return (float)(decimal)input; + case TypeCode.Boolean: + return (float)((bool)input ? 1 : 0); } break; case TypeCode.Double: - switch (sourceType) { - case TypeCode.Char: return (double)(char)input; - case TypeCode.SByte: return (double)(sbyte)input; - case TypeCode.Byte: return (double)(byte)input; - case TypeCode.Int16: return (double)(short)input; - case TypeCode.UInt16: return (double)(ushort)input; - case TypeCode.Int32: return (double)(int)input; - case TypeCode.UInt32: return (double)(uint)input; - case TypeCode.Int64: return (double)(long)input; - case TypeCode.UInt64: return (double)(ulong)input; - case TypeCode.Single: return (double)(float)input; - case TypeCode.Decimal: return (double)(decimal)input; - case TypeCode.Boolean: return (double)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (double)(char)input; + case TypeCode.SByte: + return (double)(sbyte)input; + case TypeCode.Byte: + return (double)(byte)input; + case TypeCode.Int16: + return (double)(short)input; + case TypeCode.UInt16: + return (double)(ushort)input; + case TypeCode.Int32: + return (double)(int)input; + case TypeCode.UInt32: + return (double)(uint)input; + case TypeCode.Int64: + return (double)(long)input; + case TypeCode.UInt64: + return (double)(ulong)input; + case TypeCode.Single: + return (double)(float)input; + case TypeCode.Decimal: + return (double)(decimal)input; + case TypeCode.Boolean: + return (double)((bool)input ? 1 : 0); } break; case TypeCode.Decimal: - switch (sourceType) { - case TypeCode.Char: return (decimal)(char)input; - case TypeCode.SByte: return (decimal)(sbyte)input; - case TypeCode.Byte: return (decimal)(byte)input; - case TypeCode.Int16: return (decimal)(short)input; - case TypeCode.UInt16: return (decimal)(ushort)input; - case TypeCode.Int32: return (decimal)(int)input; - case TypeCode.UInt32: return (decimal)(uint)input; - case TypeCode.Int64: return (decimal)(long)input; - case TypeCode.UInt64: return (decimal)(ulong)input; - case TypeCode.Single: return (decimal)(float)input; - case TypeCode.Double: return (decimal)(double)input; - case TypeCode.Boolean: return (decimal)((bool)input ? 1 : 0); + switch (sourceType) + { + case TypeCode.Char: + return (decimal)(char)input; + case TypeCode.SByte: + return (decimal)(sbyte)input; + case TypeCode.Byte: + return (decimal)(byte)input; + case TypeCode.Int16: + return (decimal)(short)input; + case TypeCode.UInt16: + return (decimal)(ushort)input; + case TypeCode.Int32: + return (decimal)(int)input; + case TypeCode.UInt32: + return (decimal)(uint)input; + case TypeCode.Int64: + return (decimal)(long)input; + case TypeCode.UInt64: + return (decimal)(ulong)input; + case TypeCode.Single: + return (decimal)(float)input; + case TypeCode.Double: + return (decimal)(double)input; + case TypeCode.Boolean: + return (decimal)((bool)input ? 1 : 0); } break; } diff --git a/ICSharpCode.Decompiler/Util/CacheManager.cs b/ICSharpCode.Decompiler/Util/CacheManager.cs index 151c7feb6..75bef2203 100644 --- a/ICSharpCode.Decompiler/Util/CacheManager.cs +++ b/ICSharpCode.Decompiler/Util/CacheManager.cs @@ -31,24 +31,24 @@ namespace ICSharpCode.Decompiler.Util readonly ConcurrentDictionary sharedDict = new ConcurrentDictionary(ReferenceComparer.Instance); // There used to be a thread-local dictionary here, but I removed it as it was causing memory // leaks in some use cases. - + public object GetShared(object key) { object value; sharedDict.TryGetValue(key, out value); return value; } - + public object GetOrAddShared(object key, Func valueFactory) { return sharedDict.GetOrAdd(key, valueFactory); } - + public object GetOrAddShared(object key, object value) { return sharedDict.GetOrAdd(key, value); } - + public void SetShared(object key, object value) { sharedDict[key] = value; diff --git a/ICSharpCode.Decompiler/Util/CallbackOnDispose.cs b/ICSharpCode.Decompiler/Util/CallbackOnDispose.cs index 5fbdbb530..ac83ff562 100644 --- a/ICSharpCode.Decompiler/Util/CallbackOnDispose.cs +++ b/ICSharpCode.Decompiler/Util/CallbackOnDispose.cs @@ -31,18 +31,19 @@ namespace ICSharpCode.Decompiler.Util public sealed class CallbackOnDispose : IDisposable { Action action; - + public CallbackOnDispose(Action action) { if (action == null) throw new ArgumentNullException(nameof(action)); this.action = action; } - + public void Dispose() { Action a = Interlocked.Exchange(ref action, null); - if (a != null) { + if (a != null) + { a(); } } diff --git a/ICSharpCode.Decompiler/Util/CollectionExtensions.cs b/ICSharpCode.Decompiler/Util/CollectionExtensions.cs index df585d159..a4a4123ac 100644 --- a/ICSharpCode.Decompiler/Util/CollectionExtensions.cs +++ b/ICSharpCode.Decompiler/Util/CollectionExtensions.cs @@ -21,11 +21,14 @@ namespace ICSharpCode.Decompiler.Util public static IEnumerable<(A, B)> ZipLongest(this IEnumerable input1, IEnumerable input2) { - using (var it1 = input1.GetEnumerator()) { - using (var it2 = input2.GetEnumerator()) { + using (var it1 = input1.GetEnumerator()) + { + using (var it2 = input2.GetEnumerator()) + { bool hasElements1 = true; bool hasElements2 = true; - while (true) { + while (true) + { if (hasElements1) hasElements1 = it1.MoveNext(); if (hasElements2) @@ -40,7 +43,8 @@ namespace ICSharpCode.Decompiler.Util public static IEnumerable Slice(this IReadOnlyList input, int offset, int length) { - for (int i = offset; i < offset + length; i++) { + for (int i = offset; i < offset + length; i++) + { yield return input[i]; } } @@ -48,7 +52,8 @@ namespace ICSharpCode.Decompiler.Util public static IEnumerable Slice(this IReadOnlyList input, int offset) { int length = input.Count; - for (int i = offset; i < length; i++) { + for (int i = offset; i < length; i++) + { yield return input[i]; } } @@ -76,18 +81,19 @@ namespace ICSharpCode.Decompiler.Util return default(T); return stack.Pop(); } - + public static T PeekOrDefault(this Stack stack) { if (stack.Count == 0) return default(T); return stack.Peek(); } - + public static int MaxOrDefault(this IEnumerable input, Func selector, int defaultValue = 0) { int max = defaultValue; - foreach (var element in input) { + foreach (var element in input) + { int value = selector(element); if (value > max) max = value; @@ -99,8 +105,10 @@ namespace ICSharpCode.Decompiler.Util { var comparer = EqualityComparer.Default; int index = 0; - foreach (T item in collection) { - if (comparer.Equals(item, value)) { + foreach (T item in collection) + { + if (comparer.Equals(item, value)) + { return index; } index++; @@ -113,7 +121,7 @@ namespace ICSharpCode.Decompiler.Util foreach (T item in input) collection.Add(item); } - + /// /// Equivalent to collection.Select(func).ToArray(), but more efficient as it makes /// use of the input collection's known size. @@ -122,7 +130,8 @@ namespace ICSharpCode.Decompiler.Util { U[] result = new U[collection.Count]; int index = 0; - foreach (var element in collection) { + foreach (var element in collection) + { result[index++] = func(element); } return result; @@ -136,7 +145,8 @@ namespace ICSharpCode.Decompiler.Util { U[] result = new U[collection.Count]; int index = 0; - foreach (var element in collection) { + foreach (var element in collection) + { result[index++] = func(element); } return result; @@ -150,7 +160,8 @@ namespace ICSharpCode.Decompiler.Util { U[] result = new U[collection.Count]; int index = 0; - foreach (var element in collection) { + foreach (var element in collection) + { result[index++] = func(element); } return result; @@ -164,7 +175,8 @@ namespace ICSharpCode.Decompiler.Util { U[] result = new U[collection.Length]; int index = 0; - foreach (var element in collection) { + foreach (var element in collection) + { result[index++] = func(element); } return result; @@ -177,7 +189,8 @@ namespace ICSharpCode.Decompiler.Util public static List SelectList(this ICollection collection, Func func) { List result = new List(collection.Count); - foreach (var element in collection) { + foreach (var element in collection) + { result.Add(func(element)); } return result; @@ -193,7 +206,8 @@ namespace ICSharpCode.Decompiler.Util public static IEnumerable<(int, T)> WithIndex(this ICollection source) { int index = 0; - foreach (var item in source) { + foreach (var item in source) + { yield return (index, item); index++; } @@ -205,23 +219,30 @@ namespace ICSharpCode.Decompiler.Util public static IEnumerable Merge(this IEnumerable input1, IEnumerable input2, Comparison comparison) { using (var enumA = input1.GetEnumerator()) - using (var enumB = input2.GetEnumerator()) { + using (var enumB = input2.GetEnumerator()) + { bool moreA = enumA.MoveNext(); bool moreB = enumB.MoveNext(); - while (moreA && moreB) { - if (comparison(enumA.Current, enumB.Current) <= 0) { + while (moreA && moreB) + { + if (comparison(enumA.Current, enumB.Current) <= 0) + { yield return enumA.Current; moreA = enumA.MoveNext(); - } else { + } + else + { yield return enumB.Current; moreB = enumB.MoveNext(); } } - while (moreA) { + while (moreA) + { yield return enumA.Current; moreA = enumA.MoveNext(); } - while (moreB) { + while (moreB) + { yield return enumB.Current; moreB = enumB.MoveNext(); } @@ -249,15 +270,18 @@ namespace ICSharpCode.Decompiler.Util throw new ArgumentNullException(nameof(keySelector)); if (keyComparer == null) keyComparer = Comparer.Default; - using (var enumerator = source.GetEnumerator()) { + using (var enumerator = source.GetEnumerator()) + { if (!enumerator.MoveNext()) throw new InvalidOperationException("Sequence contains no elements"); T minElement = enumerator.Current; K minKey = keySelector(minElement); - while (enumerator.MoveNext()) { + while (enumerator.MoveNext()) + { T element = enumerator.Current; K key = keySelector(element); - if (keyComparer.Compare(key, minKey) < 0) { + if (keyComparer.Compare(key, minKey) < 0) + { minElement = element; minKey = key; } @@ -287,15 +311,18 @@ namespace ICSharpCode.Decompiler.Util throw new ArgumentNullException(nameof(keySelector)); if (keyComparer == null) keyComparer = Comparer.Default; - using (var enumerator = source.GetEnumerator()) { + using (var enumerator = source.GetEnumerator()) + { if (!enumerator.MoveNext()) throw new InvalidOperationException("Sequence contains no elements"); T maxElement = enumerator.Current; K maxKey = keySelector(maxElement); - while (enumerator.MoveNext()) { + while (enumerator.MoveNext()) + { T element = enumerator.Current; K key = keySelector(element); - if (keyComparer.Compare(key, maxKey) > 0) { + if (keyComparer.Compare(key, maxKey) > 0) + { maxElement = element; maxKey = key; } @@ -317,7 +344,8 @@ namespace ICSharpCode.Decompiler.Util { bool any = false; T first = default; - foreach (var t in source) { + foreach (var t in source) + { if (any) return default(T); first = t; @@ -327,7 +355,7 @@ namespace ICSharpCode.Decompiler.Util return first; } -#region Aliases/shortcuts for Enumerable extension methods + #region Aliases/shortcuts for Enumerable extension methods public static bool Any(this ICollection list) => list.Count > 0; public static bool Any(this T[] array, Predicate match) => Array.Exists(array, match); public static bool Any(this List list, Predicate match) => list.Exists(match); @@ -339,6 +367,6 @@ namespace ICSharpCode.Decompiler.Util public static T FirstOrDefault(this List list, Predicate predicate) => list.Find(predicate); public static T Last(this IList list) => list[list.Count - 1]; -#endregion + #endregion } } diff --git a/ICSharpCode.Decompiler/Util/EmptyList.cs b/ICSharpCode.Decompiler/Util/EmptyList.cs index d39ff4671..2b4e6c45d 100644 --- a/ICSharpCode.Decompiler/Util/EmptyList.cs +++ b/ICSharpCode.Decompiler/Util/EmptyList.cs @@ -26,87 +26,87 @@ namespace ICSharpCode.Decompiler.Util public sealed class EmptyList : IList, IEnumerator, IReadOnlyList { public static readonly EmptyList Instance = new EmptyList(); - - private EmptyList() {} - + + private EmptyList() { } + public T this[int index] { get { throw new ArgumentOutOfRangeException(nameof(index)); } set { throw new ArgumentOutOfRangeException(nameof(index)); } } - + public int 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.Decompiler/Util/GraphVizGraph.cs b/ICSharpCode.Decompiler/Util/GraphVizGraph.cs index 588733995..bfa574005 100644 --- a/ICSharpCode.Decompiler/Util/GraphVizGraph.cs +++ b/ICSharpCode.Decompiler/Util/GraphVizGraph.cs @@ -73,9 +73,12 @@ namespace ICSharpCode.Decompiler.Util static string Escape(string text) { - if (Regex.IsMatch(text, @"^[\w\d]+$")) { + if (Regex.IsMatch(text, @"^[\w\d]+$")) + { return text; - } else { + } + else + { return "\"" + text.Replace("\\", "\\\\").Replace("\r", "").Replace("\n", "\\n").Replace("\"", "\\\"") + "\""; } } @@ -88,21 +91,24 @@ namespace ICSharpCode.Decompiler.Util internal static void WriteAttribute(TextWriter writer, string name, double? value, ref bool isFirst) { - if (value != null) { + if (value != null) + { WriteAttribute(writer, name, value.Value.ToString(CultureInfo.InvariantCulture), ref isFirst); } } internal static void WriteAttribute(TextWriter writer, string name, bool? value, ref bool isFirst) { - if (value != null) { + if (value != null) + { WriteAttribute(writer, name, value.Value ? "true" : "false", ref isFirst); } } internal static void WriteAttribute(TextWriter writer, string name, string value, ref bool isFirst) { - if (value != null) { + if (value != null) + { if (isFirst) isFirst = false; else @@ -118,10 +124,12 @@ namespace ICSharpCode.Decompiler.Util writer.WriteLine("digraph G {"); writer.WriteLine("node [fontsize = 16];"); WriteGraphAttribute(writer, "rankdir", rankdir); - foreach (GraphVizNode node in nodes) { + foreach (GraphVizNode node in nodes) + { node.Save(writer); } - foreach (GraphVizEdge edge in edges) { + foreach (GraphVizEdge edge in edges) + { edge.Save(writer); } writer.WriteLine("}"); diff --git a/ICSharpCode.Decompiler/Util/Interval.cs b/ICSharpCode.Decompiler/Util/Interval.cs index 6f92b6fd3..269045d5a 100644 --- a/ICSharpCode.Decompiler/Util/Interval.cs +++ b/ICSharpCode.Decompiler/Util/Interval.cs @@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler.Util /// If possible, prefer using InclusiveEnd for comparisons, as that does not have an overflow problem. /// public readonly int End; - + /// /// Creates a new interval. /// @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.Util this.Start = start; this.End = end; } - + /// /// Gets the inclusive end of the interval. (End - 1) /// For empty intervals, this returns Start - 1. @@ -82,13 +82,13 @@ namespace ICSharpCode.Decompiler.Util return Start > InclusiveEnd; } } - + public bool Contains(int val) { // Use 'val <= InclusiveEnd' instead of 'val < End' to allow intervals to include int.MaxValue. return Start <= val && val <= InclusiveEnd; } - + /// /// Calculates the intersection between this interval and the other interval. /// @@ -101,7 +101,7 @@ namespace ICSharpCode.Decompiler.Util else return default(Interval); } - + public override string ToString() { if (End == int.MinValue) @@ -109,13 +109,13 @@ namespace ICSharpCode.Decompiler.Util else return string.Format("[{0}..{1})", Start, End); } - + #region Equals and GetHashCode implementation public override bool Equals(object obj) { return (obj is Interval) && Equals((Interval)obj); } - + public bool Equals(Interval other) { return this.Start == other.Start && this.End == other.End; @@ -197,7 +197,7 @@ namespace ICSharpCode.Decompiler.Util throw new ArgumentException(); return new LongInterval(start, unchecked(inclusiveEnd + 1)); } - + /// /// Gets the inclusive end of the interval. (End - 1) /// For empty intervals, this returns Start - 1. @@ -218,13 +218,13 @@ namespace ICSharpCode.Decompiler.Util return Start > InclusiveEnd; } } - + public bool Contains(long val) { // Use 'val <= InclusiveEnd' instead of 'val < End' to allow intervals to include long.MaxValue. return Start <= val && val <= InclusiveEnd; } - + /// /// Calculates the intersection between this interval and the other interval. /// @@ -237,46 +237,55 @@ namespace ICSharpCode.Decompiler.Util else return default(LongInterval); } - + /// /// Returns an enumerator over all values in this interval. /// public IEnumerable Range() { - if (End == long.MinValue) { + if (End == long.MinValue) + { long i = Start; - while (true) { + while (true) + { yield return i; if (i == long.MaxValue) break; i++; } - } else { + } + else + { for (long i = Start; i < End; i++) yield return i; } } - + public override string ToString() { - if (End == long.MinValue) { + if (End == long.MinValue) + { if (Start == long.MinValue) return string.Format("[long.MinValue..long.MaxValue]", End); else return string.Format("[{0}..long.MaxValue]", Start); - } else if (Start == long.MinValue) { + } + else if (Start == long.MinValue) + { return string.Format("[long.MinValue..{0})", End); - } else { + } + else + { return string.Format("[{0}..{1})", Start, End); } } - + #region Equals and GetHashCode implementation public override bool Equals(object obj) { return (obj is LongInterval) && Equals((LongInterval)obj); } - + public bool Equals(LongInterval other) { return this.Start == other.Start && this.End == other.End; diff --git a/ICSharpCode.Decompiler/Util/KeyComparer.cs b/ICSharpCode.Decompiler/Util/KeyComparer.cs index 5a604aa06..7cd6d7047 100644 --- a/ICSharpCode.Decompiler/Util/KeyComparer.cs +++ b/ICSharpCode.Decompiler/Util/KeyComparer.cs @@ -27,17 +27,17 @@ namespace ICSharpCode.Decompiler.Util { return new KeyComparer(keySelector, Comparer.Default, EqualityComparer.Default); } - + public static KeyComparer Create(Func keySelector, IComparer comparer, IEqualityComparer equalityComparer) { return new KeyComparer(keySelector, comparer, equalityComparer); } - + public static IComparer Create(Func keySelector, IComparer comparer) { return new KeyComparer(keySelector, comparer, EqualityComparer.Default); } - + public static IEqualityComparer Create(Func keySelector, IEqualityComparer equalityComparer) { return new KeyComparer(keySelector, Comparer.Default, equalityComparer); @@ -48,13 +48,13 @@ namespace ICSharpCode.Decompiler.Util list.Sort(Create(keySelector)); } } - + public class KeyComparer : IComparer, IEqualityComparer { readonly Func keySelector; readonly IComparer keyComparer; readonly IEqualityComparer keyEqualityComparer; - + public KeyComparer(Func keySelector, IComparer keyComparer, IEqualityComparer keyEqualityComparer) { if (keySelector == null) @@ -67,17 +67,17 @@ namespace ICSharpCode.Decompiler.Util this.keyComparer = keyComparer; this.keyEqualityComparer = keyEqualityComparer; } - + public int Compare(TElement x, TElement y) { return keyComparer.Compare(keySelector(x), keySelector(y)); } - + public bool Equals(TElement x, TElement y) { return keyEqualityComparer.Equals(keySelector(x), keySelector(y)); } - + public int GetHashCode(TElement obj) { return keyEqualityComparer.GetHashCode(keySelector(obj)); diff --git a/ICSharpCode.Decompiler/Util/LazyInit.cs b/ICSharpCode.Decompiler/Util/LazyInit.cs index 2bb246093..6f95ca130 100644 --- a/ICSharpCode.Decompiler/Util/LazyInit.cs +++ b/ICSharpCode.Decompiler/Util/LazyInit.cs @@ -26,7 +26,7 @@ namespace ICSharpCode.Decompiler.Util { return Volatile.Read(ref location); } - + /// /// Atomically performs the following operation: /// - If target is null: stores newValue in target and returns newValue. diff --git a/ICSharpCode.Decompiler/Util/LongDict.cs b/ICSharpCode.Decompiler/Util/LongDict.cs index 840e48e48..8f58848a4 100644 --- a/ICSharpCode.Decompiler/Util/LongDict.cs +++ b/ICSharpCode.Decompiler/Util/LongDict.cs @@ -50,8 +50,10 @@ namespace ICSharpCode.Decompiler.Util LongSet available = LongSet.Universe; var keys = new List(); var values = new List(); - foreach (var (key, val) in entries) { - foreach (var interval in key.IntersectWith(available).Intervals) { + foreach (var (key, val) in entries) + { + foreach (var interval in key.IntersectWith(available).Intervals) + { keys.Add(interval); values.Add(val); } @@ -69,7 +71,8 @@ namespace ICSharpCode.Decompiler.Util // We use this to find the previous element (if there wasn't any exact match). if (pos < 0) pos = ~pos - 1; - if (pos >= 0 && this.keys[pos].Contains(key)) { + if (pos >= 0 && this.keys[pos].Contains(key)) + { value = this.values[pos]; return true; } @@ -85,7 +88,8 @@ namespace ICSharpCode.Decompiler.Util public IEnumerator> GetEnumerator() { - for (int i = 0; i < this.keys.Length; ++i) { + for (int i = 0; i < this.keys.Length; ++i) + { yield return new KeyValuePair(this.keys[i], this.values[i]); } } diff --git a/ICSharpCode.Decompiler/Util/LongSet.cs b/ICSharpCode.Decompiler/Util/LongSet.cs index 118701218..697c43330 100644 --- a/ICSharpCode.Decompiler/Util/LongSet.cs +++ b/ICSharpCode.Decompiler/Util/LongSet.cs @@ -38,21 +38,25 @@ namespace ICSharpCode.Decompiler.Util /// This invariant ensures every LongSet is always in a normalized representation. /// public readonly ImmutableArray Intervals; - + private LongSet(ImmutableArray intervals) { this.Intervals = intervals; #if DEBUG // Check invariant long minValue = long.MinValue; - for (int i = 0; i < intervals.Length; i++) { + for (int i = 0; i < intervals.Length; i++) + { Debug.Assert(!intervals[i].IsEmpty); Debug.Assert(minValue <= intervals[i].Start); - if (intervals[i].InclusiveEnd == long.MaxValue - 1 || intervals[i].InclusiveEnd == long.MaxValue) { + if (intervals[i].InclusiveEnd == long.MaxValue - 1 || intervals[i].InclusiveEnd == long.MaxValue) + { // An inclusive end of long.MaxValue-1 or long.MaxValue means (after the gap of 1 element), // there isn't any room for more non-empty intervals. Debug.Assert(i == intervals.Length - 1); - } else { + } + else + { minValue = checked(intervals[i].End + 1); // enforce least 1 gap between intervals } } @@ -66,7 +70,7 @@ namespace ICSharpCode.Decompiler.Util : this(ImmutableArray.Create(LongInterval.Inclusive(value, value))) { } - + /// /// Create a new LongSet that contains the values from the interval. /// @@ -93,8 +97,7 @@ namespace ICSharpCode.Decompiler.Util /// public static readonly LongSet Universe = new LongSet(LongInterval.Inclusive(long.MinValue, long.MaxValue)); - public bool IsEmpty - { + public bool IsEmpty { get { return Intervals.IsEmpty; } } @@ -105,9 +108,11 @@ namespace ICSharpCode.Decompiler.Util /// public ulong Count() { - unchecked { + unchecked + { ulong count = 0; - foreach (var interval in Intervals) { + foreach (var interval in Intervals) + { count += (ulong)(interval.End - interval.Start); } if (count == 0 && !Intervals.IsEmpty) @@ -116,7 +121,7 @@ namespace ICSharpCode.Decompiler.Util return count; } } - + IEnumerable DoIntersectWith(LongSet other) { @@ -124,16 +129,21 @@ namespace ICSharpCode.Decompiler.Util var enumB = other.Intervals.GetEnumerator(); bool moreA = enumA.MoveNext(); bool moreB = enumB.MoveNext(); - while (moreA && moreB) { + while (moreA && moreB) + { LongInterval a = enumA.Current; LongInterval b = enumB.Current; LongInterval intersection = a.Intersect(b); - if (!intersection.IsEmpty) { + if (!intersection.IsEmpty) + { yield return intersection; } - if (a.InclusiveEnd < b.InclusiveEnd) { + if (a.InclusiveEnd < b.InclusiveEnd) + { moreA = enumA.MoveNext(); - } else { + } + else + { moreB = enumB.MoveNext(); } } @@ -158,36 +168,48 @@ namespace ICSharpCode.Decompiler.Util long start = long.MinValue; long end = long.MinValue; bool empty = true; - foreach (var element in input) { + foreach (var element in input) + { Debug.Assert(start <= element.Start); Debug.Assert(!element.IsEmpty); - if (!empty && element.Start <= end) { + if (!empty && element.Start <= end) + { // element overlaps or touches [start, end), so combine the intervals: - if (element.End == long.MinValue) { + if (element.End == long.MinValue) + { // special case: element goes all the way up to long.MaxValue inclusive end = long.MinValue; - } else { + } + else + { end = Math.Max(end, element.End); } - } else { + } + else + { // flush existing interval: - if (!empty) { + if (!empty) + { yield return new LongInterval(start, end); - } else { + } + else + { empty = false; } start = element.Start; end = element.End; } - if (end == long.MinValue) { + if (end == long.MinValue) + { // special case: element goes all the way up to long.MaxValue inclusive // all further intervals in the input must be contained in [start, end), // so ignore them (and avoid trouble due to the overflow in `end`). break; } } - if (!empty) { + if (!empty) + { yield return new LongInterval(start, end); } } @@ -197,22 +219,27 @@ namespace ICSharpCode.Decompiler.Util var mergedIntervals = this.Intervals.Merge(other.Intervals, (a, b) => a.Start.CompareTo(b.Start)); return new LongSet(MergeOverlapping(mergedIntervals).ToImmutableArray()); } - + /// /// Creates a new LongSet where val is added to each element of this LongSet. /// public LongSet AddOffset(long val) { - if (val == 0) { + if (val == 0) + { return this; } var newIntervals = new List(Intervals.Length + 1); - foreach (var element in Intervals) { + foreach (var element in Intervals) + { long newStart = unchecked(element.Start + val); long newInclusiveEnd = unchecked(element.InclusiveEnd + val); - if (newStart <= newInclusiveEnd) { + if (newStart <= newInclusiveEnd) + { newIntervals.Add(LongInterval.Inclusive(newStart, newInclusiveEnd)); - } else { + } + else + { // interval got split by integer overflow newIntervals.Add(LongInterval.Inclusive(newStart, long.MaxValue)); newIntervals.Add(LongInterval.Inclusive(long.MinValue, newInclusiveEnd)); @@ -221,7 +248,7 @@ namespace ICSharpCode.Decompiler.Util newIntervals.Sort((a, b) => a.Start.CompareTo(b.Start)); return new LongSet(MergeOverlapping(newIntervals).ToImmutableArray()); } - + /// /// Creates a new set that contains all values that are in this, but not in other. /// @@ -236,19 +263,23 @@ namespace ICSharpCode.Decompiler.Util public LongSet Invert() { // The loop below assumes a non-empty LongSet, so handle the empty case specially. - if (IsEmpty) { + if (IsEmpty) + { return Universe; } List newIntervals = new List(Intervals.Length + 1); long prevEnd = long.MinValue; // previous exclusive end - foreach (var interval in Intervals) { - if (interval.Start > prevEnd) { + foreach (var interval in Intervals) + { + if (interval.Start > prevEnd) + { newIntervals.Add(new LongInterval(prevEnd, interval.Start)); } prevEnd = interval.End; } // create a final interval up to long.MaxValue inclusive - if (prevEnd != long.MinValue) { + if (prevEnd != long.MinValue) + { newIntervals.Add(new LongInterval(prevEnd, long.MinValue)); } return new LongSet(newIntervals.ToImmutableArray()); @@ -290,14 +321,17 @@ namespace ICSharpCode.Decompiler.Util internal int upper_bound(long val) { int min = 0, max = Intervals.Length - 1; - while (max >= min) { + while (max >= min) + { int m = min + (max - min) / 2; LongInterval i = Intervals[m]; - if (val < i.Start) { + if (val < i.Start) + { max = m - 1; continue; } - if (val > i.End) { + if (val > i.End) + { min = m + 1; continue; } @@ -306,8 +340,7 @@ namespace ICSharpCode.Decompiler.Util return min; } - public IEnumerable Values - { + public IEnumerable Values { get { return Intervals.SelectMany(i => i.Range()); } } @@ -315,7 +348,7 @@ namespace ICSharpCode.Decompiler.Util { return string.Join(",", Intervals); } - + #region Equals and GetHashCode implementation public override bool Equals(object obj) { @@ -337,7 +370,8 @@ namespace ICSharpCode.Decompiler.Util { if (Intervals.Length != other.Intervals.Length) return false; - for (int i = 0; i < Intervals.Length; i++) { + for (int i = 0; i < Intervals.Length; i++) + { if (Intervals[i] != other.Intervals[i]) return false; } diff --git a/ICSharpCode.Decompiler/Util/MultiDictionary.cs b/ICSharpCode.Decompiler/Util/MultiDictionary.cs index dbe253f86..ec93a866c 100644 --- a/ICSharpCode.Decompiler/Util/MultiDictionary.cs +++ b/ICSharpCode.Decompiler/Util/MultiDictionary.cs @@ -27,21 +27,22 @@ namespace ICSharpCode.Decompiler.Util public class MultiDictionary : ILookup { readonly Dictionary> dict; - + public MultiDictionary() { dict = new Dictionary>(); } - + public MultiDictionary(IEqualityComparer comparer) { dict = new Dictionary>(comparer); } - + public void Add(TKey key, TValue value) { List valueList; - if (!dict.TryGetValue(key, out valueList)) { + if (!dict.TryGetValue(key, out valueList)) + { valueList = new List(); dict.Add(key, valueList); } @@ -51,8 +52,10 @@ namespace ICSharpCode.Decompiler.Util public bool Remove(TKey key, TValue value) { List valueList; - if (dict.TryGetValue(key, out valueList)) { - if (valueList.Remove(value)) { + if (dict.TryGetValue(key, out valueList)) + { + if (valueList.Remove(value)) + { if (valueList.Count == 0) dict.Remove(key); return true; @@ -60,7 +63,7 @@ namespace ICSharpCode.Decompiler.Util } return false; } - + /// /// Removes all entries with the specified key. /// @@ -69,12 +72,12 @@ namespace ICSharpCode.Decompiler.Util { return dict.Remove(key); } - + public void Clear() { dict.Clear(); } - + public IReadOnlyList this[TKey key] { get { if (dict.TryGetValue(key, out var list)) @@ -83,62 +86,62 @@ namespace ICSharpCode.Decompiler.Util return EmptyList.Instance; } } - + /// /// Returns the number of different keys. /// public int Count { get { return dict.Count; } } - + public ICollection Keys { get { return dict.Keys; } } - + public IEnumerable Values { get { return dict.Values.SelectMany(list => list); } } - + IEnumerable ILookup.this[TKey key] { get { return this[key]; } } - + bool ILookup.Contains(TKey key) { return dict.ContainsKey(key); } - + public IEnumerator> GetEnumerator() { foreach (var pair in dict) yield return new Grouping(pair.Key, pair.Value); } - + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } - + sealed class Grouping : IGrouping { readonly TKey key; readonly List values; - + public Grouping(TKey key, List values) { this.key = key; this.values = values; } - + public TKey Key { get { return key; } } - + public IEnumerator GetEnumerator() { return values.GetEnumerator(); } - + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return values.GetEnumerator(); diff --git a/ICSharpCode.Decompiler/Util/Platform.cs b/ICSharpCode.Decompiler/Util/Platform.cs index d1567cc16..b91a91060 100644 --- a/ICSharpCode.Decompiler/Util/Platform.cs +++ b/ICSharpCode.Decompiler/Util/Platform.cs @@ -27,7 +27,8 @@ namespace ICSharpCode.Decompiler.Util { public static StringComparer FileNameComparer { get { - switch (Environment.OSVersion.Platform) { + switch (Environment.OSVersion.Platform) + { case PlatformID.Unix: case PlatformID.MacOSX: return StringComparer.Ordinal; diff --git a/ICSharpCode.Decompiler/Util/ProjectedList.cs b/ICSharpCode.Decompiler/Util/ProjectedList.cs index 3a136cf36..fa632005e 100644 --- a/ICSharpCode.Decompiler/Util/ProjectedList.cs +++ b/ICSharpCode.Decompiler/Util/ProjectedList.cs @@ -26,7 +26,7 @@ namespace ICSharpCode.Decompiler.Util readonly IList input; readonly Func projection; readonly TOutput[] items; - + public ProjectedList(IList input, Func projection) { if (input == null) @@ -37,41 +37,43 @@ namespace ICSharpCode.Decompiler.Util this.projection = projection; this.items = new TOutput[input.Count]; } - + public TOutput this[int index] { get { TOutput output = LazyInit.VolatileRead(ref items[index]); - if (output != null) { + if (output != null) + { return output; } return LazyInit.GetOrSet(ref items[index], projection(input[index])); } } - + public int Count { get { return items.Length; } } - + public IEnumerator GetEnumerator() { - for (int i = 0; i < this.Count; i++) { + for (int i = 0; i < this.Count; i++) + { yield return this[i]; } } - + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } - + public sealed class ProjectedList : IReadOnlyList where TOutput : class { readonly IList input; readonly TContext context; readonly Func projection; readonly TOutput[] items; - + public ProjectedList(TContext context, IList input, Func projection) { if (input == null) @@ -83,28 +85,30 @@ namespace ICSharpCode.Decompiler.Util this.projection = projection; this.items = new TOutput[input.Count]; } - + public TOutput this[int index] { get { TOutput output = LazyInit.VolatileRead(ref items[index]); - if (output != null) { + if (output != null) + { return output; } return LazyInit.GetOrSet(ref items[index], projection(context, input[index])); } } - + public int Count { get { return items.Length; } } - + public IEnumerator GetEnumerator() { - for (int i = 0; i < this.Count; i++) { + for (int i = 0; i < this.Count; i++) + { yield return this[i]; } } - + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); diff --git a/ICSharpCode.Decompiler/Util/ReferenceComparer.cs b/ICSharpCode.Decompiler/Util/ReferenceComparer.cs index aa3ed8a07..cb4485bce 100644 --- a/ICSharpCode.Decompiler/Util/ReferenceComparer.cs +++ b/ICSharpCode.Decompiler/Util/ReferenceComparer.cs @@ -24,12 +24,12 @@ namespace ICSharpCode.Decompiler.Util public sealed class ReferenceComparer : IEqualityComparer { public readonly static ReferenceComparer Instance = new ReferenceComparer(); - + public new bool Equals(object x, object y) { return x == y; } - + public int GetHashCode(object obj) { return RuntimeHelpers.GetHashCode(obj); diff --git a/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs b/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs index a98d4bed9..58a1d3339 100644 --- a/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs +++ b/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs @@ -30,12 +30,12 @@ // Gary Barnett gary.barnett.mono@gmail.com // includes code by Mike Krüger and Lluis Sanchez +using System; using System.ComponentModel; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Xml; -using System; namespace ICSharpCode.Decompiler.Util { @@ -145,7 +145,8 @@ namespace ICSharpCode.Decompiler.Util pos = 0; inc = 80 + Environment.NewLine.Length + 1; ins = Environment.NewLine + "\t"; - while (pos < sb.Length) { + while (pos < sb.Length) + { sb.Insert(pos, ins); pos += inc; } @@ -158,7 +159,8 @@ namespace ICSharpCode.Decompiler.Util writer.WriteStartElement("data"); writer.WriteAttributeString("name", name); - if (type != null) { + if (type != null) + { writer.WriteAttributeString("type", type.AssemblyQualifiedName); // byte[] should never get a mimetype, otherwise MS.NET won't be able // to parse the data. @@ -166,7 +168,9 @@ namespace ICSharpCode.Decompiler.Util writer.WriteAttributeString("mimetype", ByteArraySerializedObjectMimeType); writer.WriteStartElement("value"); WriteNiceBase64(value, offset, length); - } else { + } + else + { writer.WriteAttributeString("mimetype", BinSerializedObjectMimeType); writer.WriteStartElement("value"); writer.WriteBase64(value, offset, length); @@ -174,7 +178,8 @@ namespace ICSharpCode.Decompiler.Util writer.WriteEndElement(); - if (!(comment == null || comment.Equals(String.Empty))) { + if (!(comment == null || comment.Equals(String.Empty))) + { writer.WriteStartElement("comment"); writer.WriteString(comment); writer.WriteEndElement(); @@ -205,7 +210,8 @@ namespace ICSharpCode.Decompiler.Util writer.WriteStartElement("value"); writer.WriteString(value); writer.WriteEndElement(); - if (!(comment == null || comment.Equals(String.Empty))) { + if (!(comment == null || comment.Equals(String.Empty))) + { writer.WriteStartElement("comment"); writer.WriteString(comment); writer.WriteEndElement(); @@ -238,7 +244,8 @@ namespace ICSharpCode.Decompiler.Util private void AddResource(string name, object value, string comment) { - if (value is string) { + if (value is string) + { AddResource(name, (string)value, comment); return; } @@ -252,17 +259,20 @@ namespace ICSharpCode.Decompiler.Util if (writer == null) InitWriter(); - if (value is byte[]) { + if (value is byte[]) + { WriteBytes(name, value.GetType(), (byte[])value, comment); return; } - if (value is ResourceSerializedObject rso) { + if (value is ResourceSerializedObject rso) + { var bytes = rso.GetBytes(); WriteBytes(name, null, bytes, 0, bytes.Length, comment); return; } - if (value == null) { + if (value == null) + { // nulls written as ResXNullRef WriteString(name, "", ResXNullRefTypeName, comment); return; @@ -273,13 +283,15 @@ namespace ICSharpCode.Decompiler.Util TypeConverter converter = TypeDescriptor.GetConverter(value); - if (converter != null && converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string))) { + if (converter != null && converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string))) + { string str = (string)converter.ConvertToInvariantString(value); WriteString(name, str, value.GetType().AssemblyQualifiedName, comment); return; } - if (converter != null && converter.CanConvertTo(typeof(byte[])) && converter.CanConvertFrom(typeof(byte[]))) { + if (converter != null && converter.CanConvertTo(typeof(byte[])) && converter.CanConvertFrom(typeof(byte[]))) + { byte[] b = (byte[])converter.ConvertTo(value, typeof(byte[])); WriteBytes(name, value.GetType(), b, comment); return; @@ -287,9 +299,12 @@ namespace ICSharpCode.Decompiler.Util MemoryStream ms = new MemoryStream(); BinaryFormatter fmt = new BinaryFormatter(); - try { + try + { fmt.Serialize(ms, value); - } catch (Exception e) { + } + catch (Exception e) + { throw new InvalidOperationException("Cannot add a " + value.GetType() + "because it cannot be serialized: " + e.Message); @@ -320,7 +335,7 @@ namespace ICSharpCode.Decompiler.Util WriteString(name, value, null, comment); } - + public void AddMetadata(string name, string value) { if (name == null) @@ -372,12 +387,14 @@ namespace ICSharpCode.Decompiler.Util public void AddMetadata(string name, object value) { - if (value is string) { + if (value is string) + { AddMetadata(name, (string)value); return; } - if (value is byte[]) { + if (value is byte[]) + { AddMetadata(name, (byte[])value); return; } @@ -400,7 +417,8 @@ namespace ICSharpCode.Decompiler.Util Type type = value.GetType(); TypeConverter converter = TypeDescriptor.GetConverter(value); - if (converter != null && converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string))) { + if (converter != null && converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string))) + { string str = (string)converter.ConvertToInvariantString(value); writer.WriteStartElement("metadata"); writer.WriteAttributeString("name", name); @@ -414,17 +432,21 @@ namespace ICSharpCode.Decompiler.Util return; } - if (converter != null && converter.CanConvertTo(typeof(byte[])) && converter.CanConvertFrom(typeof(byte[]))) { + if (converter != null && converter.CanConvertTo(typeof(byte[])) && converter.CanConvertFrom(typeof(byte[]))) + { byte[] b = (byte[])converter.ConvertTo(value, typeof(byte[])); writer.WriteStartElement("metadata"); writer.WriteAttributeString("name", name); - if (type != null) { + if (type != null) + { writer.WriteAttributeString("type", type.AssemblyQualifiedName); writer.WriteAttributeString("mimetype", ByteArraySerializedObjectMimeType); writer.WriteStartElement("value"); WriteNiceBase64(b, 0, b.Length); - } else { + } + else + { writer.WriteAttributeString("mimetype", BinSerializedObjectMimeType); writer.WriteStartElement("value"); writer.WriteBase64(b, 0, b.Length); @@ -437,9 +459,12 @@ namespace ICSharpCode.Decompiler.Util MemoryStream ms = new MemoryStream(); BinaryFormatter fmt = new BinaryFormatter(); - try { + try + { fmt.Serialize(ms, value); - } catch (Exception e) { + } + catch (Exception e) + { throw new InvalidOperationException("Cannot add a " + value.GetType() + "because it cannot be serialized: " + e.Message); @@ -448,12 +473,15 @@ namespace ICSharpCode.Decompiler.Util writer.WriteStartElement("metadata"); writer.WriteAttributeString("name", name); - if (type != null) { + if (type != null) + { writer.WriteAttributeString("type", type.AssemblyQualifiedName); writer.WriteAttributeString("mimetype", ByteArraySerializedObjectMimeType); writer.WriteStartElement("value"); WriteNiceBase64(ms.GetBuffer(), 0, ms.GetBuffer().Length); - } else { + } + else + { writer.WriteAttributeString("mimetype", BinSerializedObjectMimeType); writer.WriteStartElement("value"); writer.WriteBase64(ms.GetBuffer(), 0, ms.GetBuffer().Length); @@ -466,8 +494,10 @@ namespace ICSharpCode.Decompiler.Util public void Close() { - if (writer != null) { - if (!written) { + if (writer != null) + { + if (!written) + { Generate(); } diff --git a/ICSharpCode.Decompiler/Util/ResourcesFile.cs b/ICSharpCode.Decompiler/Util/ResourcesFile.cs index 85e18bf4d..a55637006 100644 --- a/ICSharpCode.Decompiler/Util/ResourcesFile.cs +++ b/ICSharpCode.Decompiler/Util/ResourcesFile.cs @@ -116,12 +116,16 @@ namespace ICSharpCode.Decompiler.Util // use this to skip to the end of the header int resMgrHeaderVersion = reader.ReadInt32(); int numBytesToSkip = reader.ReadInt32(); - if (numBytesToSkip < 0 || resMgrHeaderVersion < 0) { + if (numBytesToSkip < 0 || resMgrHeaderVersion < 0) + { throw new BadImageFormatException(ResourcesHeaderCorrupted); } - if (resMgrHeaderVersion > 1) { + if (resMgrHeaderVersion > 1) + { reader.BaseStream.Seek(numBytesToSkip, SeekOrigin.Current); - } else { + } + else + { // We don't care about numBytesToSkip; read the rest of the header // readerType: @@ -137,18 +141,21 @@ namespace ICSharpCode.Decompiler.Util throw new BadImageFormatException($"Unsupported resource set version: {version}"); numResources = reader.ReadInt32(); - if (numResources < 0) { + if (numResources < 0) + { throw new BadImageFormatException(ResourcesHeaderCorrupted); } // Read type positions into type positions array. // But delay initialize the type table. int numTypes = reader.ReadInt32(); - if (numTypes < 0) { + if (numTypes < 0) + { throw new BadImageFormatException(ResourcesHeaderCorrupted); } typeTable = new string[numTypes]; - for (int i = 0; i < numTypes; i++) { + for (int i = 0; i < numTypes; i++) + { typeTable[i] = reader.ReadString(); } @@ -160,24 +167,31 @@ namespace ICSharpCode.Decompiler.Util // should be aligned No need to verify the byte values. long pos = reader.BaseStream.Position - fileStartPosition; int alignBytes = unchecked((int)pos) & 7; - if (alignBytes != 0) { - for (int i = 0; i < 8 - alignBytes; i++) { + if (alignBytes != 0) + { + for (int i = 0; i < 8 - alignBytes; i++) + { reader.ReadByte(); } } // Skip over the array of name hashes - try { + try + { reader.Seek(checked(4 * numResources), SeekOrigin.Current); - } catch (OverflowException) { + } + catch (OverflowException) + { throw new BadImageFormatException(ResourcesHeaderCorrupted); } // Read in the array of relative positions for all the names. namePositions = new int[numResources]; - for (int i = 0; i < numResources; i++) { + for (int i = 0; i < numResources; i++) + { int namePosition = reader.ReadInt32(); - if (namePosition < 0) { + if (namePosition < 0) + { throw new BadImageFormatException(ResourcesHeaderCorrupted); } namePositions[i] = namePosition; @@ -185,7 +199,8 @@ namespace ICSharpCode.Decompiler.Util // Read location of data section. int dataSectionOffset = reader.ReadInt32(); - if (dataSectionOffset < 0) { + if (dataSectionOffset < 0) + { throw new BadImageFormatException(ResourcesHeaderCorrupted); } @@ -194,7 +209,8 @@ namespace ICSharpCode.Decompiler.Util dataSectionPosition = fileStartPosition + dataSectionOffset; // _nameSectionOffset should be <= _dataSectionOffset; if not, it's corrupt - if (dataSectionPosition < nameSectionPosition) { + if (dataSectionPosition < nameSectionPosition) + { throw new BadImageFormatException(ResourcesHeaderCorrupted); } } @@ -221,11 +237,13 @@ namespace ICSharpCode.Decompiler.Util { long pos = nameSectionPosition + namePositions[index]; byte[] bytes; - lock (reader) { + lock (reader) + { reader.Seek(pos, SeekOrigin.Begin); // Can't use reader.ReadString, since it's using UTF-8! int byteLen = reader.Read7BitEncodedInt(); - if (byteLen < 0) { + if (byteLen < 0) + { throw new BadImageFormatException("Resource name has negative length"); } bytes = new byte[byteLen]; @@ -233,14 +251,16 @@ namespace ICSharpCode.Decompiler.Util // Use a blocking read in case the stream doesn't give us back // everything immediately. int count = byteLen; - while (count > 0) { + while (count > 0) + { int n = reader.Read(bytes, byteLen - count, count); if (n == 0) throw new BadImageFormatException("End of stream within a resource name"); count -= n; } dataOffset = reader.ReadInt32(); - if (dataOffset < 0) { + if (dataOffset < 0) + { throw new BadImageFormatException("Negative data offset"); } } @@ -251,8 +271,10 @@ namespace ICSharpCode.Decompiler.Util { if (version != 2) return false; - lock (reader) { - for (int i = 0; i < numResources; i++) { + lock (reader) + { + for (int i = 0; i < numResources; i++) + { int dataOffset = GetResourceDataOffset(i); reader.Seek(dataSectionPosition + dataOffset, SeekOrigin.Begin); var typeCode = (ResourceTypeCode)reader.Read7BitEncodedInt(); @@ -265,15 +287,22 @@ namespace ICSharpCode.Decompiler.Util object LoadObject(int dataOffset) { - try { - lock (reader) { - if (version == 1) { + try + { + lock (reader) + { + if (version == 1) + { return LoadObjectV1(dataOffset); - } else { + } + else + { return LoadObjectV2(dataOffset); } } - } catch (EndOfStreamException e) { + } + catch (EndOfStreamException e) + { throw new BadImageFormatException("Invalid resource file", e); } } @@ -298,11 +327,13 @@ namespace ICSharpCode.Decompiler.Util return null; string typeName = FindType(typeIndex); int comma = typeName.IndexOf(','); - if (comma > 0) { + if (comma > 0) + { // strip assembly name typeName = typeName.Substring(0, comma); } - switch (typeName) { + switch (typeName) + { case "System.String": return reader.ReadString(); case "System.Byte": @@ -346,7 +377,8 @@ namespace ICSharpCode.Decompiler.Util Debug.Assert(System.Threading.Monitor.IsEntered(reader)); reader.Seek(dataSectionPosition + dataOffset, SeekOrigin.Begin); var typeCode = (ResourceTypeCode)reader.Read7BitEncodedInt(); - switch (typeCode) { + switch (typeCode) + { case ResourceTypeCode.Null: return null; @@ -402,25 +434,30 @@ namespace ICSharpCode.Decompiler.Util return new TimeSpan(ticks); // Special types - case ResourceTypeCode.ByteArray: { - int len = reader.ReadInt32(); - if (len < 0) { - throw new BadImageFormatException("Resource with negative length"); - } - return reader.ReadBytes(len); + case ResourceTypeCode.ByteArray: + { + int len = reader.ReadInt32(); + if (len < 0) + { + throw new BadImageFormatException("Resource with negative length"); } + return reader.ReadBytes(len); + } - case ResourceTypeCode.Stream: { - int len = reader.ReadInt32(); - if (len < 0) { - throw new BadImageFormatException("Resource with negative length"); - } - byte[] bytes = reader.ReadBytes(len); - return new MemoryStream(bytes, writable: false); + case ResourceTypeCode.Stream: + { + int len = reader.ReadInt32(); + if (len < 0) + { + throw new BadImageFormatException("Resource with negative length"); } + byte[] bytes = reader.ReadBytes(len); + return new MemoryStream(bytes, writable: false); + } default: - if (typeCode < ResourceTypeCode.StartOfUserTypes) { + if (typeCode < ResourceTypeCode.StartOfUserTypes) + { throw new BadImageFormatException("Invalid typeCode"); } return new ResourceSerializedObject(FindType(typeCode - ResourceTypeCode.StartOfUserTypes), this, reader.BaseStream.Position); @@ -435,7 +472,8 @@ namespace ICSharpCode.Decompiler.Util public IEnumerator> GetEnumerator() { - for (int i = 0; i < numResources; i++) { + for (int i = 0; i < numResources; i++) + { string name = GetResourceName(i, out int dataOffset); object val = LoadObject(dataOffset); yield return new KeyValuePair(name, val); @@ -452,14 +490,16 @@ namespace ICSharpCode.Decompiler.Util long[] positions = LazyInit.VolatileRead(ref startPositions); if (positions != null) return positions; - lock (reader) { + lock (reader) + { // double-checked locking positions = LazyInit.VolatileRead(ref startPositions); if (positions != null) return positions; positions = new long[numResources * 2]; int outPos = 0; - for (int i = 0; i < numResources; i++) { + for (int i = 0; i < numResources; i++) + { positions[outPos++] = nameSectionPosition + namePositions[i]; positions[outPos++] = dataSectionPosition + GetResourceDataOffset(i); } @@ -472,7 +512,8 @@ namespace ICSharpCode.Decompiler.Util { long[] positions = GetStartPositions(); int i = Array.BinarySearch(positions, pos); - if (i < 0) { + if (i < 0) + { // 'pos' the the start position of the serialized object data // This is the position after the type code, so it should not appear in the 'positions' array. // Set i to the index of the next position after 'pos'. @@ -480,11 +521,15 @@ namespace ICSharpCode.Decompiler.Util // Note: if 'pos' does exist in the array, that means the stream has length 0, // so we keep the i that we found. } - lock (reader) { + lock (reader) + { long endPos; - if (i == positions.Length) { + if (i == positions.Length) + { endPos = reader.BaseStream.Length; - } else { + } + else + { endPos = positions[i]; } int len = (int)(endPos - pos); @@ -499,7 +544,7 @@ namespace ICSharpCode.Decompiler.Util public string TypeName { get; } readonly ResourcesFile file; readonly long position; - + internal ResourceSerializedObject(string typeName, ResourcesFile file, long position) { this.TypeName = typeName; diff --git a/ICSharpCode.Decompiler/Util/TreeTraversal.cs b/ICSharpCode.Decompiler/Util/TreeTraversal.cs index b33c8b3fa..a12b35c46 100644 --- a/ICSharpCode.Decompiler/Util/TreeTraversal.cs +++ b/ICSharpCode.Decompiler/Util/TreeTraversal.cs @@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.Util { return PreOrder(new T[] { root }, recursion); } - + /// /// Converts a tree data structure into a flat list by traversing it in pre-order. /// @@ -46,26 +46,33 @@ namespace ICSharpCode.Decompiler.Util public static IEnumerable PreOrder(IEnumerable input, Func> recursion) { Stack> stack = new Stack>(); - try { + try + { stack.Push(input.GetEnumerator()); - while (stack.Count > 0) { - while (stack.Peek().MoveNext()) { + while (stack.Count > 0) + { + while (stack.Peek().MoveNext()) + { T element = stack.Peek().Current; yield return element; IEnumerable children = recursion(element); - if (children != null) { + if (children != null) + { stack.Push(children.GetEnumerator()); } } stack.Pop().Dispose(); } - } finally { - while (stack.Count > 0) { + } + finally + { + while (stack.Count > 0) + { stack.Pop().Dispose(); } } } - + /// /// Converts a tree data structure into a flat list by traversing it in post-order. /// @@ -76,7 +83,7 @@ namespace ICSharpCode.Decompiler.Util { return PostOrder(new T[] { root }, recursion); } - + /// /// Converts a tree data structure into a flat list by traversing it in post-order. /// @@ -86,15 +93,21 @@ namespace ICSharpCode.Decompiler.Util public static IEnumerable PostOrder(IEnumerable input, Func> recursion) { Stack> stack = new Stack>(); - try { + try + { stack.Push(input.GetEnumerator()); - while (stack.Count > 0) { - while (stack.Peek().MoveNext()) { + while (stack.Count > 0) + { + while (stack.Peek().MoveNext()) + { T element = stack.Peek().Current; IEnumerable children = recursion(element); - if (children != null) { + if (children != null) + { stack.Push(children.GetEnumerator()); - } else { + } + else + { yield return element; } } @@ -102,8 +115,11 @@ namespace ICSharpCode.Decompiler.Util if (stack.Count > 0) yield return stack.Peek().Current; } - } finally { - while (stack.Count > 0) { + } + finally + { + while (stack.Count > 0) + { stack.Pop().Dispose(); } } diff --git a/ICSharpCode.Decompiler/Util/UnicodeNewline.cs b/ICSharpCode.Decompiler/Util/UnicodeNewline.cs index b66e0ebea..dca342ce0 100644 --- a/ICSharpCode.Decompiler/Util/UnicodeNewline.cs +++ b/ICSharpCode.Decompiler/Util/UnicodeNewline.cs @@ -27,7 +27,8 @@ using System; namespace ICSharpCode.Decompiler.Util { - public enum UnicodeNewline { + public enum UnicodeNewline + { Unknown, /// @@ -94,22 +95,22 @@ namespace ICSharpCode.Decompiler.Util /// /// Vertical Tab, U+000B /// - public const char VT = (char)0x0B; + public const char VT = (char)0x0B; /// /// Form Feed, U+000C /// - public const char FF = (char)0x0C; + public const char FF = (char)0x0C; /// /// Line Separator, U+2028 /// - public const char LS = (char)0x2028; + public const char LS = (char)0x2028; /// /// Paragraph Separator, U+2029 /// - public const char PS = (char)0x2029; + public const char PS = (char)0x2029; /// /// Determines if a char is a new line delimiter. @@ -117,10 +118,11 @@ namespace ICSharpCode.Decompiler.Util /// 0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter. /// The current character. /// A callback getting the next character (may be null). - public static int GetDelimiterLength (char curChar, Func nextChar = null) + public static int GetDelimiterLength(char curChar, Func nextChar = null) { - if (curChar == CR) { - if (nextChar != null && nextChar () == LF) + if (curChar == CR) + { + if (nextChar != null && nextChar() == LF) return 2; return 1; } @@ -136,9 +138,10 @@ namespace ICSharpCode.Decompiler.Util /// 0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter. /// The current character. /// The next character (if != LF then length will always be 0 or 1). - public static int GetDelimiterLength (char curChar, char nextChar) + public static int GetDelimiterLength(char curChar, char nextChar) { - if (curChar == CR) { + if (curChar == CR) + { if (nextChar == LF) return 2; return 1; @@ -158,13 +161,17 @@ namespace ICSharpCode.Decompiler.Util /// The length of the delimiter /// The type of the delimiter /// A callback getting the next character (may be null). - public static bool TryGetDelimiterLengthAndType (char curChar, out int length, out UnicodeNewline type, Func nextChar = null) + public static bool TryGetDelimiterLengthAndType(char curChar, out int length, out UnicodeNewline type, Func nextChar = null) { - if (curChar == CR) { - if (nextChar != null && nextChar () == LF) { + if (curChar == CR) + { + if (nextChar != null && nextChar() == LF) + { length = 2; type = UnicodeNewline.CRLF; - } else { + } + else + { length = 1; type = UnicodeNewline.CR; @@ -172,31 +179,32 @@ namespace ICSharpCode.Decompiler.Util return true; } - switch (curChar) { - case LF: - type = UnicodeNewline.LF; - length = 1; - return true; - case NEL: - type = UnicodeNewline.NEL; - length = 1; - return true; - case VT: - type = UnicodeNewline.VT; - length = 1; - return true; - case FF: - type = UnicodeNewline.FF; - length = 1; - return true; - case LS: - type = UnicodeNewline.LS; - length = 1; - return true; - case PS: - type = UnicodeNewline.PS; - length = 1; - return true; + switch (curChar) + { + case LF: + type = UnicodeNewline.LF; + length = 1; + return true; + case NEL: + type = UnicodeNewline.NEL; + length = 1; + return true; + case VT: + type = UnicodeNewline.VT; + length = 1; + return true; + case FF: + type = UnicodeNewline.FF; + length = 1; + return true; + case LS: + type = UnicodeNewline.LS; + length = 1; + return true; + case PS: + type = UnicodeNewline.PS; + length = 1; + return true; } length = -1; type = UnicodeNewline.Unknown; @@ -211,13 +219,17 @@ namespace ICSharpCode.Decompiler.Util /// The length of the delimiter /// The type of the delimiter /// The next character (if != LF then length will always be 0 or 1). - public static bool TryGetDelimiterLengthAndType (char curChar, out int length, out UnicodeNewline type, char nextChar) + public static bool TryGetDelimiterLengthAndType(char curChar, out int length, out UnicodeNewline type, char nextChar) { - if (curChar == CR) { - if (nextChar == LF) { + if (curChar == CR) + { + if (nextChar == LF) + { length = 2; type = UnicodeNewline.CRLF; - } else { + } + else + { length = 1; type = UnicodeNewline.CR; @@ -225,31 +237,32 @@ namespace ICSharpCode.Decompiler.Util return true; } - switch (curChar) { - case LF: - type = UnicodeNewline.LF; - length = 1; - return true; - case NEL: - type = UnicodeNewline.NEL; - length = 1; - return true; - case VT: - type = UnicodeNewline.VT; - length = 1; - return true; - case FF: - type = UnicodeNewline.FF; - length = 1; - return true; - case LS: - type = UnicodeNewline.LS; - length = 1; - return true; - case PS: - type = UnicodeNewline.PS; - length = 1; - return true; + switch (curChar) + { + case LF: + type = UnicodeNewline.LF; + length = 1; + return true; + case NEL: + type = UnicodeNewline.NEL; + length = 1; + return true; + case VT: + type = UnicodeNewline.VT; + length = 1; + return true; + case FF: + type = UnicodeNewline.FF; + length = 1; + return true; + case LS: + type = UnicodeNewline.LS; + length = 1; + return true; + case PS: + type = UnicodeNewline.PS; + length = 1; + return true; } length = -1; type = UnicodeNewline.Unknown; @@ -262,25 +275,26 @@ namespace ICSharpCode.Decompiler.Util /// 0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter. /// The current character. /// A callback getting the next character (may be null). - public static UnicodeNewline GetDelimiterType (char curChar, Func nextChar = null) + public static UnicodeNewline GetDelimiterType(char curChar, Func nextChar = null) { - switch (curChar) { + switch (curChar) + { case CR: - if (nextChar != null && nextChar () == LF) - return UnicodeNewline.CRLF; - return UnicodeNewline.CR; + if (nextChar != null && nextChar() == LF) + return UnicodeNewline.CRLF; + return UnicodeNewline.CR; case LF: - return UnicodeNewline.LF; + return UnicodeNewline.LF; case NEL: - return UnicodeNewline.NEL; + return UnicodeNewline.NEL; case VT: - return UnicodeNewline.VT; + return UnicodeNewline.VT; case FF: - return UnicodeNewline.FF; + return UnicodeNewline.FF; case LS: - return UnicodeNewline.LS; + return UnicodeNewline.LS; case PS: - return UnicodeNewline.PS; + return UnicodeNewline.PS; } return UnicodeNewline.Unknown; } @@ -291,25 +305,26 @@ namespace ICSharpCode.Decompiler.Util /// 0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter. /// The current character. /// The next character (if != LF then length will always be 0 or 1). - public static UnicodeNewline GetDelimiterType (char curChar, char nextChar) + public static UnicodeNewline GetDelimiterType(char curChar, char nextChar) { - switch (curChar) { - case CR: - if (nextChar == LF) - return UnicodeNewline.CRLF; - return UnicodeNewline.CR; - case LF: - return UnicodeNewline.LF; - case NEL: - return UnicodeNewline.NEL; - case VT: - return UnicodeNewline.VT; - case FF: - return UnicodeNewline.FF; - case LS: - return UnicodeNewline.LS; - case PS: - return UnicodeNewline.PS; + switch (curChar) + { + case CR: + if (nextChar == LF) + return UnicodeNewline.CRLF; + return UnicodeNewline.CR; + case LF: + return UnicodeNewline.LF; + case NEL: + return UnicodeNewline.NEL; + case VT: + return UnicodeNewline.VT; + case FF: + return UnicodeNewline.FF; + case LS: + return UnicodeNewline.LS; + case PS: + return UnicodeNewline.PS; } return UnicodeNewline.Unknown; } @@ -335,29 +350,30 @@ namespace ICSharpCode.Decompiler.Util /// /// Gets the new line as a string. /// - public static string GetString (UnicodeNewline newLine) + public static string GetString(UnicodeNewline newLine) { - switch (newLine) { - case UnicodeNewline.Unknown: - return ""; - case UnicodeNewline.LF: - return "\n"; - case UnicodeNewline.CRLF: - return "\r\n"; - case UnicodeNewline.CR: - return "\r"; - case UnicodeNewline.NEL: - return "\u0085"; - case UnicodeNewline.VT: - return "\u000B"; - case UnicodeNewline.FF: - return "\u000C"; - case UnicodeNewline.LS: - return "\u2028"; - case UnicodeNewline.PS: - return "\u2029"; - default: - throw new ArgumentOutOfRangeException (); + switch (newLine) + { + case UnicodeNewline.Unknown: + return ""; + case UnicodeNewline.LF: + return "\n"; + case UnicodeNewline.CRLF: + return "\r\n"; + case UnicodeNewline.CR: + return "\r"; + case UnicodeNewline.NEL: + return "\u0085"; + case UnicodeNewline.VT: + return "\u000B"; + case UnicodeNewline.FF: + return "\u000C"; + case UnicodeNewline.LS: + return "\u2028"; + case UnicodeNewline.PS: + return "\u2029"; + default: + throw new ArgumentOutOfRangeException(); } } } diff --git a/ICSharpCode.Decompiler/Util/UnionFind.cs b/ICSharpCode.Decompiler/Util/UnionFind.cs index 936bd78bc..4bc0acbdf 100644 --- a/ICSharpCode.Decompiler/Util/UnionFind.cs +++ b/ICSharpCode.Decompiler/Util/UnionFind.cs @@ -42,7 +42,8 @@ namespace ICSharpCode.Decompiler.Util Node GetNode(T element) { Node node; - if (!mapping.TryGetValue(element, out node)) { + if (!mapping.TryGetValue(element, out node)) + { node = new Node { value = element, rank = 0 @@ -75,7 +76,8 @@ namespace ICSharpCode.Decompiler.Util rootA.parent = rootB; else if (rootA.rank > rootB.rank) rootB.parent = rootA; - else { + else + { rootB.parent = rootA; rootA.rank++; } diff --git a/ILSpy.AddIn/AssemblyFileFinder.cs b/ILSpy.AddIn/AssemblyFileFinder.cs index cc6676782..96141015b 100644 --- a/ILSpy.AddIn/AssemblyFileFinder.cs +++ b/ILSpy.AddIn/AssemblyFileFinder.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Text.RegularExpressions; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; @@ -12,9 +13,12 @@ namespace ICSharpCode.ILSpy.AddIn { string tfi = DetectTargetFrameworkId(assemblyDefinition, assemblyFile); UniversalAssemblyResolver assemblyResolver; - if (IsReferenceAssembly(assemblyDefinition, assemblyFile)) { + if (IsReferenceAssembly(assemblyDefinition, assemblyFile)) + { assemblyResolver = new UniversalAssemblyResolver(null, throwOnError: false, tfi); - } else { + } + else + { assemblyResolver = new UniversalAssemblyResolver(assemblyFile, throwOnError: false, tfi); } @@ -44,17 +48,20 @@ namespace ICSharpCode.ILSpy.AddIn const string TargetFrameworkAttributeName = "System.Runtime.Versioning.TargetFrameworkAttribute"; - foreach (var attribute in assembly.CustomAttributes) { + foreach (var attribute in assembly.CustomAttributes) + { if (attribute.AttributeType.FullName != TargetFrameworkAttributeName) continue; - if (attribute.HasConstructorArguments) { + if (attribute.HasConstructorArguments) + { if (attribute.ConstructorArguments[0].Value is string value) return value; } } // Optionally try to detect target version through assembly path as a fallback (use case: reference assemblies) - if (assemblyPath != null) { + if (assemblyPath != null) + { /* * Detected path patterns (examples): * @@ -65,15 +72,21 @@ namespace ICSharpCode.ILSpy.AddIn */ var pathMatch = Regex.Match(assemblyPath, DetectTargetFrameworkIdRefPathPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture); - if (pathMatch.Success) { + if (pathMatch.Success) + { var type = pathMatch.Groups[1].Value; var version = pathMatch.Groups[2].Value; - if (type == ".NETFramework") { + if (type == ".NETFramework") + { return $".NETFramework,Version=v{version}"; - } else if (type.ToLower().Contains("netcore")) { + } + else if (type.ToLower().Contains("netcore")) + { return $".NETCoreApp,Version=v{version}"; - } else if (type.ToLower().Contains("netstandard")) { + } + else if (type.ToLower().Contains("netstandard")) + { return $".NETStandard,Version=v{version}"; } } diff --git a/ILSpy.AddIn/Commands/AssemblyReferenceForILSpy.cs b/ILSpy.AddIn/Commands/AssemblyReferenceForILSpy.cs index e5aaa592a..e81e71838 100644 --- a/ILSpy.AddIn/Commands/AssemblyReferenceForILSpy.cs +++ b/ILSpy.AddIn/Commands/AssemblyReferenceForILSpy.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; + using VSLangProj; namespace ICSharpCode.ILSpy.AddIn.Commands diff --git a/ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs b/ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs index 84ee74af5..45b183c4b 100644 --- a/ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs +++ b/ILSpy.AddIn/Commands/NuGetReferenceForILSpy.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; + using EnvDTE; + using Microsoft.VisualStudio.Shell; namespace ICSharpCode.ILSpy.AddIn.Commands @@ -29,9 +31,11 @@ namespace ICSharpCode.ILSpy.AddIn.Commands { ThreadHelper.ThrowIfNotOnUIThread(); - if (itemData is ProjectItem projectItem) { + if (itemData is ProjectItem projectItem) + { var properties = Utils.GetProperties(projectItem.Properties, "Type"); - if ((properties[0] as string) == "Package") { + if ((properties[0] as string) == "Package") + { return new NuGetReferenceForILSpy(projectItem); } } @@ -48,7 +52,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands ThreadHelper.ThrowIfNotOnUIThread(); var properties = Utils.GetProperties(projectItem.Properties, "Name", "Version", "Path"); - if (properties[0] != null && properties[1] != null && properties[2] != null) { + if (properties[0] != null && properties[1] != null && properties[2] != null) + { return new ILSpyParameters(new[] { $"{properties[2]}\\{properties[0]}.{properties[1]}.nupkg" }); } diff --git a/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs b/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs index 07cdd9989..718304a33 100644 --- a/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs +++ b/ILSpy.AddIn/Commands/OpenCodeItemCommand.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; + using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Shell; @@ -25,7 +26,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands { ThreadHelper.ThrowIfNotOnUIThread(); - if (sender is OleMenuCommand menuItem) { + if (sender is OleMenuCommand menuItem) + { menuItem.Visible = false; // Enable this item only if this is a .cs file! @@ -65,20 +67,23 @@ namespace ICSharpCode.ILSpy.AddIn.Commands SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; var roslynDocument = GetRoslynDocument(); - if (roslynDocument == null) { + if (roslynDocument == null) + { owner.ShowMessage("This element is not analyzable in current view."); return; } var ast = await roslynDocument.GetSyntaxRootAsync().ConfigureAwait(false); var model = await roslynDocument.GetSemanticModelAsync().ConfigureAwait(false); var node = ast.FindNode(new TextSpan(caretPosition.Position, 0), false, true); - if (node == null) { + if (node == null) + { owner.ShowMessage(OLEMSGICON.OLEMSGICON_WARNING, "Can't show ILSpy for this code element!"); return; } var symbol = GetSymbolResolvableByILSpy(model, node); - if (symbol == null) { + if (symbol == null) + { owner.ShowMessage(OLEMSGICON.OLEMSGICON_WARNING, "Can't show ILSpy for this code element!"); return; } @@ -90,7 +95,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands // Add our own project as well (not among references) var project = FindProject(owner.DTE.Solution.Projects.OfType(), roslynProject.FilePath); - if (project == null) { + if (project == null) + { owner.ShowMessage(OLEMSGICON.OLEMSGICON_WARNING, "Can't show ILSpy for this code element!"); return; } @@ -102,22 +108,29 @@ namespace ICSharpCode.ILSpy.AddIn.Commands // Divide into valid and invalid (= not found) referenced assemblies CheckAssemblies(refsmap, out var validRefs, out var invalidRefs); var invalidSymbolReference = invalidRefs.FirstOrDefault(r => r.IsProjectReference && (r.Name == symbolAssemblyName)); - if (invalidSymbolReference != null) { - if (string.IsNullOrEmpty(invalidSymbolReference.AssemblyFile)) { + if (invalidSymbolReference != null) + { + if (string.IsNullOrEmpty(invalidSymbolReference.AssemblyFile)) + { // No assembly file given at all. This has been seen while project is still loading after opening... owner.ShowMessage(OLEMSGICON.OLEMSGICON_WARNING, "Symbol can't be opened. This might happen while project is loading.", Environment.NewLine, invalidSymbolReference.AssemblyFile); - } else if (invalidSymbolReference.IsProjectReference) { + } + else if (invalidSymbolReference.IsProjectReference) + { // Some project references don't have assemblies, maybe not compiled yet? if (owner.ShowMessage( OLEMSGBUTTON.OLEMSGBUTTON_YESNO, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST, OLEMSGICON.OLEMSGICON_WARNING, "The project output for '{1}' could not be found for analysis.{0}{0}Expected path:{0}{0}{2}{0}{0}Would you like to build the solution?", Environment.NewLine, symbolAssemblyName, invalidSymbolReference.AssemblyFile - ) == (int)MessageButtonResult.IDYES) { + ) == (int)MessageButtonResult.IDYES) + { owner.DTE.ExecuteCommand("Build.BuildSolution"); } - } else { + } + else + { // External assembly is missing, we should abort owner.ShowMessage(OLEMSGICON.OLEMSGICON_WARNING, "Referenced assembly{0}{0}'{1}'{0}{0} could not be found.", @@ -138,10 +151,14 @@ namespace ICSharpCode.ILSpy.AddIn.Commands validRefs = new List(); invalidRefs = new List(); - foreach (var reference in inputReferenceList.Select(r => r.Value)) { - if ((reference.AssemblyFile == null) || !File.Exists(reference.AssemblyFile)) { + foreach (var reference in inputReferenceList.Select(r => r.Value)) + { + if ((reference.AssemblyFile == null) || !File.Exists(reference.AssemblyFile)) + { invalidRefs.Add(reference); - } else { + } + else + { validRefs.Add(reference); } } @@ -150,15 +167,19 @@ namespace ICSharpCode.ILSpy.AddIn.Commands ISymbol GetSymbolResolvableByILSpy(SemanticModel model, SyntaxNode node) { var current = node; - while (current != null) { + while (current != null) + { var symbol = model.GetSymbolInfo(current).Symbol; - if (symbol == null) { + if (symbol == null) + { symbol = model.GetDeclaredSymbol(current); } // ILSpy can only resolve some symbol types, so allow them, discard everything else - if (symbol != null) { - switch (symbol.Kind) { + if (symbol != null) + { + switch (symbol.Kind) + { case SymbolKind.ArrayType: case SymbolKind.Event: case SymbolKind.Field: diff --git a/ILSpy.AddIn/Commands/OpenILSpyCommand.cs b/ILSpy.AddIn/Commands/OpenILSpyCommand.cs index 13ef992b0..07555c92c 100644 --- a/ILSpy.AddIn/Commands/OpenILSpyCommand.cs +++ b/ILSpy.AddIn/Commands/OpenILSpyCommand.cs @@ -6,8 +6,11 @@ using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; + using Microsoft.VisualStudio.Shell; + using Mono.Cecil; + using DTEConstants = EnvDTE.Constants; namespace ICSharpCode.ILSpy.AddIn.Commands @@ -60,8 +63,10 @@ namespace ICSharpCode.ILSpy.AddIn.Commands if (parameters == null) return; - foreach (string assemblyFileName in parameters.AssemblyFileNames) { - if (!File.Exists(assemblyFileName)) { + foreach (string assemblyFileName in parameters.AssemblyFileNames) + { + if (!File.Exists(assemblyFileName)) + { owner.ShowMessage("Could not find assembly '{0}', please ensure the project and all references were built correctly!", assemblyFileName); return; } @@ -76,14 +81,17 @@ namespace ICSharpCode.ILSpy.AddIn.Commands ThreadHelper.ThrowIfNotOnUIThread(); var dict = new Dictionary(); - foreach (var reference in parentProject.MetadataReferences) { - using (var assemblyDef = AssemblyDefinition.ReadAssembly(reference.Display)) { + foreach (var reference in parentProject.MetadataReferences) + { + using (var assemblyDef = AssemblyDefinition.ReadAssembly(reference.Display)) + { string assemblyName = assemblyDef.Name.Name; string resolvedAssemblyFile = AssemblyFileFinder.FindAssemblyFile(assemblyDef, reference.Display); dict.Add(assemblyName, new DetectedReference(assemblyName, resolvedAssemblyFile, false)); } } - foreach (var projectReference in parentProject.ProjectReferences) { + foreach (var projectReference in parentProject.ProjectReferences) + { var roslynProject = owner.Workspace.CurrentSolution.GetProject(projectReference.ProjectId); var project = FindProject(owner.DTE.Solution.Projects.OfType(), roslynProject.FilePath); if (roslynProject != null && project != null) @@ -97,8 +105,10 @@ namespace ICSharpCode.ILSpy.AddIn.Commands { ThreadHelper.ThrowIfNotOnUIThread(); - foreach (var project in projects) { - switch (project.Kind) { + foreach (var project in projects) + { + switch (project.Kind) + { case DTEConstants.vsProjectKindSolutionItems: // This is a solution folder -> search in sub-projects var subProject = FindProject( diff --git a/ILSpy.AddIn/Commands/OpenProjectOutputCommand.cs b/ILSpy.AddIn/Commands/OpenProjectOutputCommand.cs index 937d1601a..abc2c68b2 100644 --- a/ILSpy.AddIn/Commands/OpenProjectOutputCommand.cs +++ b/ILSpy.AddIn/Commands/OpenProjectOutputCommand.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; + using Microsoft.VisualStudio.Shell; namespace ICSharpCode.ILSpy.AddIn.Commands @@ -19,7 +20,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands { ThreadHelper.ThrowIfNotOnUIThread(); - if (sender is OleMenuCommand menuItem) { + if (sender is OleMenuCommand menuItem) + { menuItem.Visible = false; var selectedItem = owner.DTE.SelectedItems.Item(1); @@ -34,7 +36,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands if (owner.DTE.SelectedItems.Count != 1) return; var projectItemWrapper = ProjectItemForILSpy.Detect(owner, owner.DTE.SelectedItems.Item(1)); - if (projectItemWrapper != null) { + if (projectItemWrapper != null) + { OpenAssembliesInILSpy(projectItemWrapper.GetILSpyParameters(owner)); } } diff --git a/ILSpy.AddIn/Commands/OpenReferenceCommand.cs b/ILSpy.AddIn/Commands/OpenReferenceCommand.cs index e97a2af35..c01e5e077 100644 --- a/ILSpy.AddIn/Commands/OpenReferenceCommand.cs +++ b/ILSpy.AddIn/Commands/OpenReferenceCommand.cs @@ -1,11 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; + using EnvDTE; + using ICSharpCode.Decompiler.Metadata; + using Microsoft.CodeAnalysis; using Microsoft.VisualStudio.Shell; + using Mono.Cecil; + using VSLangProj; namespace ICSharpCode.ILSpy.AddIn.Commands @@ -24,7 +29,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands { ThreadHelper.ThrowIfNotOnUIThread(); - if (sender is OleMenuCommand menuItem) { + if (sender is OleMenuCommand menuItem) + { menuItem.Visible = false; var selectedItemData = owner.GetSelectedItemsData().FirstOrDefault(); @@ -38,7 +44,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands */ if ((AssemblyReferenceForILSpy.Detect(selectedItemData) != null) || (ProjectReferenceForILSpy.Detect(selectedItemData) != null) - || (NuGetReferenceForILSpy.Detect(selectedItemData) != null)) { + || (NuGetReferenceForILSpy.Detect(selectedItemData) != null)) + { menuItem.Visible = true; } } @@ -53,7 +60,8 @@ namespace ICSharpCode.ILSpy.AddIn.Commands return; var referenceItem = AssemblyReferenceForILSpy.Detect(itemObject); - if (referenceItem != null) { + if (referenceItem != null) + { Reference reference = itemObject as Reference; var project = reference.ContainingProject; var roslynProject = owner.Workspace.CurrentSolution.Projects.FirstOrDefault(p => p.FilePath == project.FileName); @@ -68,20 +76,24 @@ namespace ICSharpCode.ILSpy.AddIn.Commands // Handle NuGet references var nugetRefItem = NuGetReferenceForILSpy.Detect(itemObject); - if (nugetRefItem != null) { + if (nugetRefItem != null) + { OpenAssembliesInILSpy(nugetRefItem.GetILSpyParameters()); return; } // Handle project references var projectRefItem = ProjectReferenceForILSpy.Detect(itemObject); - if (projectRefItem != null) { + if (projectRefItem != null) + { var projectItem = itemObject as ProjectItem; string fileName = projectItem.ContainingProject?.FileName; - if (!string.IsNullOrEmpty(fileName)) { + if (!string.IsNullOrEmpty(fileName)) + { var roslynProject = owner.Workspace.CurrentSolution.Projects.FirstOrDefault(p => p.FilePath == fileName); var references = GetReferences(roslynProject); - if (references.TryGetValue(projectItem.Name, out DetectedReference path)) { + if (references.TryGetValue(projectItem.Name, out DetectedReference path)) + { OpenAssembliesInILSpy(projectRefItem.GetILSpyParameters(references)); return; } diff --git a/ILSpy.AddIn/Commands/ProjectItemForILSpy.cs b/ILSpy.AddIn/Commands/ProjectItemForILSpy.cs index 182565b35..e420e1e98 100644 --- a/ILSpy.AddIn/Commands/ProjectItemForILSpy.cs +++ b/ILSpy.AddIn/Commands/ProjectItemForILSpy.cs @@ -1,6 +1,8 @@ using System.IO; using System.Linq; + using EnvDTE; + using Microsoft.VisualStudio.Shell; namespace ICSharpCode.ILSpy.AddIn.Commands diff --git a/ILSpy.AddIn/Commands/ProjectReferenceForILSpy.cs b/ILSpy.AddIn/Commands/ProjectReferenceForILSpy.cs index ebeeb61fe..07a53ddac 100644 --- a/ILSpy.AddIn/Commands/ProjectReferenceForILSpy.cs +++ b/ILSpy.AddIn/Commands/ProjectReferenceForILSpy.cs @@ -3,9 +3,13 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; + using EnvDTE; + using ICSharpCode.Decompiler.Metadata; + using Microsoft.VisualStudio.Shell; + using Mono.Cecil; namespace ICSharpCode.ILSpy.AddIn.Commands @@ -35,11 +39,13 @@ namespace ICSharpCode.ILSpy.AddIn.Commands { ThreadHelper.ThrowIfNotOnUIThread(); - if (itemData is ProjectItem projectItem) { + if (itemData is ProjectItem projectItem) + { var properties = Utils.GetProperties(projectItem.Properties, "FusionName", "ResolvedPath"); string fusionName = properties[0] as string; string resolvedPath = properties[1] as string; - if ((fusionName != null) || (resolvedPath != null)) { + if ((fusionName != null) || (resolvedPath != null)) + { return new ProjectReferenceForILSpy(projectItem, fusionName, resolvedPath); } } @@ -57,8 +63,10 @@ namespace ICSharpCode.ILSpy.AddIn.Commands ThreadHelper.ThrowIfNotOnUIThread(); string fileName = projectItem.ContainingProject?.FileName; - if (!string.IsNullOrEmpty(fileName)) { - if (projectReferences.TryGetValue(projectItem.Name, out DetectedReference path)) { + if (!string.IsNullOrEmpty(fileName)) + { + if (projectReferences.TryGetValue(projectItem.Name, out DetectedReference path)) + { return new ILSpyParameters(new[] { path.AssemblyFile }); } } @@ -72,9 +80,12 @@ namespace ICSharpCode.ILSpy.AddIn.Commands /// Parameters object or null, if not applicable. public ILSpyParameters GetILSpyParameters() { - if (resolvedPath != null) { + if (resolvedPath != null) + { return new ILSpyParameters(new[] { $"{resolvedPath}" }); - } else if (!string.IsNullOrWhiteSpace(fusionName)) { + } + else if (!string.IsNullOrWhiteSpace(fusionName)) + { return new ILSpyParameters(new string[] { UniversalAssemblyResolver.GetAssemblyInGac(Decompiler.Metadata.AssemblyNameReference.Parse(fusionName)) }); } diff --git a/ILSpy.AddIn/ILSpyAddInPackage.cs b/ILSpy.AddIn/ILSpyAddInPackage.cs index 950cdc0d5..195940b68 100644 --- a/ILSpy.AddIn/ILSpyAddInPackage.cs +++ b/ILSpy.AddIn/ILSpyAddInPackage.cs @@ -1,18 +1,22 @@ using System; +using System.Collections.Generic; +using System.ComponentModel.Design; using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; -using System.ComponentModel.Design; using System.Threading; + +using EnvDTE; + +using ICSharpCode.ILSpy.AddIn.Commands; + using Microsoft; using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.Shell; -using ICSharpCode.ILSpy.AddIn.Commands; using Microsoft.VisualStudio.ComponentModelHost; using Microsoft.VisualStudio.LanguageServices; -using EnvDTE; -using System.Collections.Generic; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + using Task = System.Threading.Tasks.Task; namespace ICSharpCode.ILSpy.AddIn @@ -114,7 +118,8 @@ namespace ICSharpCode.ILSpy.AddIn ThreadHelper.ThrowIfNotOnUIThread(); IVsUIShell uiShell = (IVsUIShell)GetService(typeof(SVsUIShell)); - if (uiShell == null) { + if (uiShell == null) + { return 0; } @@ -143,9 +148,12 @@ namespace ICSharpCode.ILSpy.AddIn { ThreadHelper.ThrowIfNotOnUIThread(); - if (DTE.ToolWindows.SolutionExplorer.SelectedItems is IEnumerable hierarchyItems) { - foreach (var item in hierarchyItems) { - if (item.Object is T typedItem) { + if (DTE.ToolWindows.SolutionExplorer.SelectedItems is IEnumerable hierarchyItems) + { + foreach (var item in hierarchyItems) + { + if (item.Object is T typedItem) + { yield return typedItem; } } diff --git a/ILSpy.AddIn/ILSpyInstance.cs b/ILSpy.AddIn/ILSpyInstance.cs index 182ee3e9e..8144eb140 100644 --- a/ILSpy.AddIn/ILSpyInstance.cs +++ b/ILSpy.AddIn/ILSpyInstance.cs @@ -48,7 +48,8 @@ namespace ICSharpCode.ILSpy.AddIn }; process.Start(); - if ((commandLineArguments != null) && commandLineArguments.Any()) { + if ((commandLineArguments != null) && commandLineArguments.Any()) + { // Only need a message to started process if there are any parameters to pass SendMessage(ilSpyExe, "ILSpy:\r\n" + string.Join(Environment.NewLine, commandLineArguments), true); } @@ -62,17 +63,21 @@ namespace ICSharpCode.ILSpy.AddIn Task.Run(async () => { bool success = false; int remainingAttempts = 20; - do { + do + { NativeMethods.EnumWindows( (hWnd, lParam) => { string windowTitle = NativeMethods.GetWindowText(hWnd, 100); - if (windowTitle.StartsWith("ILSpy", StringComparison.Ordinal)) { + if (windowTitle.StartsWith("ILSpy", StringComparison.Ordinal)) + { string processName = NativeMethods.GetProcessNameFromWindow(hWnd); Debug.WriteLine("Found {0:x4}: '{1}' in '{2}'", hWnd, windowTitle, processName); - if (string.Equals(processName, expectedProcessName, StringComparison.OrdinalIgnoreCase)) { + if (string.Equals(processName, expectedProcessName, StringComparison.OrdinalIgnoreCase)) + { IntPtr result = Send(hWnd, message); Debug.WriteLine("WM_COPYDATA result: {0:x8}", result); - if (result == (IntPtr)1) { + if (result == (IntPtr)1) + { if (activate) NativeMethods.SetForegroundWindow(hWnd); success = true; @@ -97,15 +102,19 @@ namespace ICSharpCode.ILSpy.AddIn CopyDataStruct lParam; lParam.Padding = IntPtr.Zero; lParam.Size = message.Length * 2; - fixed (char* buffer = message) { + fixed (char* buffer = message) + { lParam.Buffer = (IntPtr)buffer; IntPtr result; // SendMessage with 3s timeout (e.g. when the target process is stopped in the debugger) if (NativeMethods.SendMessageTimeout( hWnd, NativeMethods.WM_COPYDATA, IntPtr.Zero, ref lParam, - SMTO_NORMAL, 3000, out result) != IntPtr.Zero) { + SMTO_NORMAL, 3000, out result) != IntPtr.Zero) + { return result; - } else { + } + else + { return IntPtr.Zero; } } diff --git a/ILSpy.AddIn/SyntaxNodeExtensions.cs b/ILSpy.AddIn/SyntaxNodeExtensions.cs index f6ecc87ae..50f3b6039 100644 --- a/ILSpy.AddIn/SyntaxNodeExtensions.cs +++ b/ILSpy.AddIn/SyntaxNodeExtensions.cs @@ -3,517 +3,519 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; +using System.Threading.Tasks; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; + using Roslyn.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using System.Threading.Tasks; namespace ICSharpCode.ILSpy.AddIn { static class SyntaxNodeExtensions - { - public static IEnumerable GetAncestors(this SyntaxNode node) - { - var current = node.Parent; - - while (current != null) - { - yield return current; - - current = current is IStructuredTriviaSyntax - ? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent - : current.Parent; - } - } - - public static IEnumerable GetAncestors(this SyntaxNode node) - where TNode : SyntaxNode - { - var current = node.Parent; - while (current != null) - { - if (current is TNode) - { - yield return (TNode)current; - } - - current = current is IStructuredTriviaSyntax - ? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent - : current.Parent; - } - } - - public static TNode GetAncestor(this SyntaxNode node) - where TNode : SyntaxNode - { - if (node == null) - { - return default(TNode); - } - - return node.GetAncestors().FirstOrDefault(); - } - - public static TNode GetAncestorOrThis(this SyntaxNode node) - where TNode : SyntaxNode - { - if (node == null) - { - return default(TNode); - } - - return node.GetAncestorsOrThis().FirstOrDefault(); - } - - public static IEnumerable GetAncestorsOrThis(this SyntaxNode node) - where TNode : SyntaxNode - { - var current = node; - while (current != null) - { - if (current is TNode) - { - yield return (TNode)current; - } - - current = current is IStructuredTriviaSyntax - ? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent - : current.Parent; - } - } + { + public static IEnumerable GetAncestors(this SyntaxNode node) + { + var current = node.Parent; + + while (current != null) + { + yield return current; + + current = current is IStructuredTriviaSyntax + ? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent + : current.Parent; + } + } + + public static IEnumerable GetAncestors(this SyntaxNode node) + where TNode : SyntaxNode + { + var current = node.Parent; + while (current != null) + { + if (current is TNode) + { + yield return (TNode)current; + } + + current = current is IStructuredTriviaSyntax + ? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent + : current.Parent; + } + } + + public static TNode GetAncestor(this SyntaxNode node) + where TNode : SyntaxNode + { + if (node == null) + { + return default(TNode); + } + + return node.GetAncestors().FirstOrDefault(); + } + + public static TNode GetAncestorOrThis(this SyntaxNode node) + where TNode : SyntaxNode + { + if (node == null) + { + return default(TNode); + } + + return node.GetAncestorsOrThis().FirstOrDefault(); + } + + public static IEnumerable GetAncestorsOrThis(this SyntaxNode node) + where TNode : SyntaxNode + { + var current = node; + while (current != null) + { + if (current is TNode) + { + yield return (TNode)current; + } + + current = current is IStructuredTriviaSyntax + ? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent + : current.Parent; + } + } public static bool HasAncestor(this SyntaxNode node) - where TNode : SyntaxNode - { - return node.GetAncestors().Any(); - } - - public static bool CheckParent(this SyntaxNode node, Func valueChecker) where T : SyntaxNode - { - if (node == null) - { - return false; - } - - var parentNode = node.Parent as T; - if (parentNode == null) - { - return false; - } - - return valueChecker(parentNode); - } - - /// - /// Returns true if is a given token is a child token of of a certain type of parent node. - /// - /// The type of the parent node. - /// The node that we are testing. - /// A function that, when given the parent node, returns the child token we are interested in. - public static bool IsChildNode(this SyntaxNode node, Func childGetter) - where TParent : SyntaxNode - { - var ancestor = node.GetAncestor(); - if (ancestor == null) - { - return false; - } - - var ancestorNode = childGetter(ancestor); - - return node == ancestorNode; - } - - /// - /// Returns true if this node is found underneath the specified child in the given parent. - /// - public static bool IsFoundUnder(this SyntaxNode node, Func childGetter) - where TParent : SyntaxNode - { - var ancestor = node.GetAncestor(); - if (ancestor == null) - { - return false; - } - - var child = childGetter(ancestor); - - // See if node passes through child on the way up to ancestor. - return node.GetAncestorsOrThis().Contains(child); - } - - public static SyntaxNode GetCommonRoot(this SyntaxNode node1, SyntaxNode node2) - { - //Contract.ThrowIfTrue(node1.RawKind == 0 || node2.RawKind == 0); - - // find common starting node from two nodes. - // as long as two nodes belong to same tree, there must be at least one common root (Ex, compilation unit) - var ancestors = node1.GetAncestorsOrThis(); - var set = new HashSet(node2.GetAncestorsOrThis()); - - return ancestors.First(set.Contains); - } - - public static int Width(this SyntaxNode node) - { - return node.Span.Length; - } - - public static int FullWidth(this SyntaxNode node) - { - return node.FullSpan.Length; - } - - public static SyntaxNode FindInnermostCommonNode( - this IEnumerable nodes, - Func predicate) - { - IEnumerable blocks = null; - foreach (var node in nodes) - { - blocks = blocks == null - ? node.AncestorsAndSelf().Where(predicate) - : blocks.Intersect(node.AncestorsAndSelf().Where(predicate)); - } - - return blocks == null ? null : blocks.First(); - } - - public static TSyntaxNode FindInnermostCommonNode(this IEnumerable nodes) - where TSyntaxNode : SyntaxNode - { - return (TSyntaxNode)nodes.FindInnermostCommonNode(n => n is TSyntaxNode); - } - - /// - /// create a new root node from the given root after adding annotations to the tokens - /// - /// tokens should belong to the given root - /// - public static SyntaxNode AddAnnotations(this SyntaxNode root, IEnumerable> pairs) - { - // Contract.ThrowIfNull(root); - // Contract.ThrowIfNull(pairs); - - var tokenMap = pairs.GroupBy(p => p.Item1, p => p.Item2).ToDictionary(g => g.Key, g => g.ToArray()); - return root.ReplaceTokens(tokenMap.Keys, (o, n) => o.WithAdditionalAnnotations(tokenMap[o])); - } - - /// - /// create a new root node from the given root after adding annotations to the nodes - /// - /// nodes should belong to the given root - /// - public static SyntaxNode AddAnnotations(this SyntaxNode root, IEnumerable> pairs) - { - // Contract.ThrowIfNull(root); - // Contract.ThrowIfNull(pairs); - - var tokenMap = pairs.GroupBy(p => p.Item1, p => p.Item2).ToDictionary(g => g.Key, g => g.ToArray()); - return root.ReplaceNodes(tokenMap.Keys, (o, n) => o.WithAdditionalAnnotations(tokenMap[o])); - } - - public static TextSpan GetContainedSpan(this IEnumerable nodes) - { - // Contract.ThrowIfNull(nodes); - // Contract.ThrowIfFalse(nodes.Any()); - - TextSpan fullSpan = nodes.First().Span; - foreach (var node in nodes) - { - fullSpan = TextSpan.FromBounds( - Math.Min(fullSpan.Start, node.SpanStart), - Math.Max(fullSpan.End, node.Span.End)); - } - - return fullSpan; - } - - public static IEnumerable GetContiguousSpans( - this IEnumerable nodes, Func getLastToken = null) - { - SyntaxNode lastNode = null; - TextSpan? textSpan = null; - foreach (var node in nodes) - { - if (lastNode == null) - { - textSpan = node.Span; - } - else - { - var lastToken = getLastToken == null - ? lastNode.GetLastToken() - : getLastToken(lastNode); - if (lastToken.GetNextToken(includeDirectives: true) == node.GetFirstToken()) - { - // Expand the span - textSpan = TextSpan.FromBounds(textSpan.Value.Start, node.Span.End); - } - else - { - // Return the last span, and start a new one - yield return textSpan.Value; - textSpan = node.Span; - } - } - - lastNode = node; - } - - if (textSpan.HasValue) - { - yield return textSpan.Value; - } - } - - //public static bool OverlapsHiddenPosition(this SyntaxNode node, CancellationToken cancellationToken) - //{ - // return node.OverlapsHiddenPosition(node.Span, cancellationToken); - //} - - //public static bool OverlapsHiddenPosition(this SyntaxNode node, TextSpan span, CancellationToken cancellationToken) - //{ - // return node.SyntaxTree.OverlapsHiddenPosition(span, cancellationToken); - //} - - //public static bool OverlapsHiddenPosition(this SyntaxNode declaration, SyntaxNode startNode, SyntaxNode endNode, CancellationToken cancellationToken) - //{ - // var start = startNode.Span.End; - // var end = endNode.SpanStart; - - // var textSpan = TextSpan.FromBounds(start, end); - // return declaration.OverlapsHiddenPosition(textSpan, cancellationToken); - //} - - public static IEnumerable GetAnnotatedNodes(this SyntaxNode node, SyntaxAnnotation syntaxAnnotation) where T : SyntaxNode - { - return node.GetAnnotatedNodesAndTokens(syntaxAnnotation).Select(n => n.AsNode()).OfType(); - } - - public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2) - { - if (node == null) - { - return false; - } - - var csharpKind = node.Kind(); - return csharpKind == kind1 || csharpKind == kind2; - } - - public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3) - { - if (node == null) - { - return false; - } - - var csharpKind = node.Kind(); - return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3; - } - - public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3, SyntaxKind kind4) - { - if (node == null) - { - return false; - } - - var csharpKind = node.Kind(); - return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3 || csharpKind == kind4; - } - - public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3, SyntaxKind kind4, SyntaxKind kind5) - { - if (node == null) - { - return false; - } - - var csharpKind = node.Kind(); - return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3 || csharpKind == kind4 || csharpKind == kind5; - } - - /// - /// Returns the list of using directives that affect . The list will be returned in - /// top down order. - /// - public static IEnumerable GetEnclosingUsingDirectives(this SyntaxNode node) - { - return node.GetAncestorOrThis().Usings - .Concat(node.GetAncestorsOrThis() - .Reverse() - .SelectMany(n => n.Usings)); - } - - public static bool IsUnsafeContext(this SyntaxNode node) - { - if (node.GetAncestor() != null) - { - return true; - } - - return node.GetAncestors().Any( - m => m.GetModifiers().Any(SyntaxKind.UnsafeKeyword)); - } - - public static bool IsInStaticContext(this SyntaxNode node) - { - // this/base calls are always static. - if (node.FirstAncestorOrSelf() != null) - { - return true; - } - - var memberDeclaration = node.FirstAncestorOrSelf(); - if (memberDeclaration == null) - { - return false; - } - - switch (memberDeclaration.Kind()) - { - case SyntaxKind.MethodDeclaration: - case SyntaxKind.ConstructorDeclaration: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.EventDeclaration: - case SyntaxKind.IndexerDeclaration: - return memberDeclaration.GetModifiers().Any(SyntaxKind.StaticKeyword); - - case SyntaxKind.FieldDeclaration: - // Inside a field one can only access static members of a type. - return true; - - case SyntaxKind.DestructorDeclaration: - return false; - } - - // Global statements are not a static context. - if (node.FirstAncestorOrSelf() != null) - { - return false; - } - - // any other location is considered static - return true; - } - - public static NamespaceDeclarationSyntax GetInnermostNamespaceDeclarationWithUsings(this SyntaxNode contextNode) - { - var usingDirectiveAncestor = contextNode.GetAncestor(); - if (usingDirectiveAncestor == null) - { - return contextNode.GetAncestorsOrThis().FirstOrDefault(n => n.Usings.Count > 0); - } - else - { - // We are inside a using directive. In this case, we should find and return the first 'parent' namespace with usings. - var containingNamespace = usingDirectiveAncestor.GetAncestor(); - if (containingNamespace == null) - { - // We are inside a top level using directive (i.e. one that's directly in the compilation unit). - return null; - } - else - { - return containingNamespace.GetAncestors().FirstOrDefault(n => n.Usings.Count > 0); - } - } - } - - /// - /// Returns all of the trivia to the left of this token up to the previous token (concatenates - /// the previous token's trailing trivia and this token's leading trivia). - /// - public static IEnumerable GetAllPrecedingTriviaToPreviousToken(this SyntaxToken token) - { - var prevToken = token.GetPreviousToken(includeSkipped: true); - if (prevToken.Kind() == SyntaxKind.None) - { - return token.LeadingTrivia; - } - - return prevToken.TrailingTrivia.Concat(token.LeadingTrivia); - } - - public static bool IsBreakableConstruct(this SyntaxNode node) - { - switch (node.Kind()) - { - case SyntaxKind.DoStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.SwitchStatement: - case SyntaxKind.ForStatement: - case SyntaxKind.ForEachStatement: - return true; - } - - return false; - } - - public static bool IsContinuableConstruct(this SyntaxNode node) - { - switch (node.Kind()) - { - case SyntaxKind.DoStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.ForStatement: - case SyntaxKind.ForEachStatement: - return true; - } - - return false; - } - - public static bool IsReturnableConstruct(this SyntaxNode node) - { - switch (node.Kind()) - { - case SyntaxKind.AnonymousMethodExpression: - case SyntaxKind.SimpleLambdaExpression: - case SyntaxKind.ParenthesizedLambdaExpression: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.ConstructorDeclaration: - case SyntaxKind.DestructorDeclaration: - case SyntaxKind.GetAccessorDeclaration: - case SyntaxKind.SetAccessorDeclaration: - case SyntaxKind.OperatorDeclaration: - case SyntaxKind.AddAccessorDeclaration: - case SyntaxKind.RemoveAccessorDeclaration: - return true; - } - - return false; - } - - public static bool IsAnyArgumentList(this SyntaxNode node) - { - return node.IsKind(SyntaxKind.ArgumentList) || - node.IsKind(SyntaxKind.AttributeArgumentList) || - node.IsKind(SyntaxKind.BracketedArgumentList) || - node.IsKind(SyntaxKind.TypeArgumentList); - } - - public static bool IsAnyLambda(this SyntaxNode node) - { - return - node.IsKind(SyntaxKind.ParenthesizedLambdaExpression) || - node.IsKind(SyntaxKind.SimpleLambdaExpression); - } - - public static bool IsAnyLambdaOrAnonymousMethod(this SyntaxNode node) - { - return node.IsAnyLambda() || node.IsKind(SyntaxKind.AnonymousMethodExpression); - } - - public static bool IsAnyAssignExpression(this SyntaxNode node) - { - return SyntaxFacts.IsAssignmentExpression(node.Kind()); - } + where TNode : SyntaxNode + { + return node.GetAncestors().Any(); + } + + public static bool CheckParent(this SyntaxNode node, Func valueChecker) where T : SyntaxNode + { + if (node == null) + { + return false; + } + + var parentNode = node.Parent as T; + if (parentNode == null) + { + return false; + } + + return valueChecker(parentNode); + } + + /// + /// Returns true if is a given token is a child token of of a certain type of parent node. + /// + /// The type of the parent node. + /// The node that we are testing. + /// A function that, when given the parent node, returns the child token we are interested in. + public static bool IsChildNode(this SyntaxNode node, Func childGetter) + where TParent : SyntaxNode + { + var ancestor = node.GetAncestor(); + if (ancestor == null) + { + return false; + } + + var ancestorNode = childGetter(ancestor); + + return node == ancestorNode; + } + + /// + /// Returns true if this node is found underneath the specified child in the given parent. + /// + public static bool IsFoundUnder(this SyntaxNode node, Func childGetter) + where TParent : SyntaxNode + { + var ancestor = node.GetAncestor(); + if (ancestor == null) + { + return false; + } + + var child = childGetter(ancestor); + + // See if node passes through child on the way up to ancestor. + return node.GetAncestorsOrThis().Contains(child); + } + + public static SyntaxNode GetCommonRoot(this SyntaxNode node1, SyntaxNode node2) + { + //Contract.ThrowIfTrue(node1.RawKind == 0 || node2.RawKind == 0); + + // find common starting node from two nodes. + // as long as two nodes belong to same tree, there must be at least one common root (Ex, compilation unit) + var ancestors = node1.GetAncestorsOrThis(); + var set = new HashSet(node2.GetAncestorsOrThis()); + + return ancestors.First(set.Contains); + } + + public static int Width(this SyntaxNode node) + { + return node.Span.Length; + } + + public static int FullWidth(this SyntaxNode node) + { + return node.FullSpan.Length; + } + + public static SyntaxNode FindInnermostCommonNode( + this IEnumerable nodes, + Func predicate) + { + IEnumerable blocks = null; + foreach (var node in nodes) + { + blocks = blocks == null + ? node.AncestorsAndSelf().Where(predicate) + : blocks.Intersect(node.AncestorsAndSelf().Where(predicate)); + } + + return blocks == null ? null : blocks.First(); + } + + public static TSyntaxNode FindInnermostCommonNode(this IEnumerable nodes) + where TSyntaxNode : SyntaxNode + { + return (TSyntaxNode)nodes.FindInnermostCommonNode(n => n is TSyntaxNode); + } + + /// + /// create a new root node from the given root after adding annotations to the tokens + /// + /// tokens should belong to the given root + /// + public static SyntaxNode AddAnnotations(this SyntaxNode root, IEnumerable> pairs) + { + // Contract.ThrowIfNull(root); + // Contract.ThrowIfNull(pairs); + + var tokenMap = pairs.GroupBy(p => p.Item1, p => p.Item2).ToDictionary(g => g.Key, g => g.ToArray()); + return root.ReplaceTokens(tokenMap.Keys, (o, n) => o.WithAdditionalAnnotations(tokenMap[o])); + } + + /// + /// create a new root node from the given root after adding annotations to the nodes + /// + /// nodes should belong to the given root + /// + public static SyntaxNode AddAnnotations(this SyntaxNode root, IEnumerable> pairs) + { + // Contract.ThrowIfNull(root); + // Contract.ThrowIfNull(pairs); + + var tokenMap = pairs.GroupBy(p => p.Item1, p => p.Item2).ToDictionary(g => g.Key, g => g.ToArray()); + return root.ReplaceNodes(tokenMap.Keys, (o, n) => o.WithAdditionalAnnotations(tokenMap[o])); + } + + public static TextSpan GetContainedSpan(this IEnumerable nodes) + { + // Contract.ThrowIfNull(nodes); + // Contract.ThrowIfFalse(nodes.Any()); + + TextSpan fullSpan = nodes.First().Span; + foreach (var node in nodes) + { + fullSpan = TextSpan.FromBounds( + Math.Min(fullSpan.Start, node.SpanStart), + Math.Max(fullSpan.End, node.Span.End)); + } + + return fullSpan; + } + + public static IEnumerable GetContiguousSpans( + this IEnumerable nodes, Func getLastToken = null) + { + SyntaxNode lastNode = null; + TextSpan? textSpan = null; + foreach (var node in nodes) + { + if (lastNode == null) + { + textSpan = node.Span; + } + else + { + var lastToken = getLastToken == null + ? lastNode.GetLastToken() + : getLastToken(lastNode); + if (lastToken.GetNextToken(includeDirectives: true) == node.GetFirstToken()) + { + // Expand the span + textSpan = TextSpan.FromBounds(textSpan.Value.Start, node.Span.End); + } + else + { + // Return the last span, and start a new one + yield return textSpan.Value; + textSpan = node.Span; + } + } + + lastNode = node; + } + + if (textSpan.HasValue) + { + yield return textSpan.Value; + } + } + + //public static bool OverlapsHiddenPosition(this SyntaxNode node, CancellationToken cancellationToken) + //{ + // return node.OverlapsHiddenPosition(node.Span, cancellationToken); + //} + + //public static bool OverlapsHiddenPosition(this SyntaxNode node, TextSpan span, CancellationToken cancellationToken) + //{ + // return node.SyntaxTree.OverlapsHiddenPosition(span, cancellationToken); + //} + + //public static bool OverlapsHiddenPosition(this SyntaxNode declaration, SyntaxNode startNode, SyntaxNode endNode, CancellationToken cancellationToken) + //{ + // var start = startNode.Span.End; + // var end = endNode.SpanStart; + + // var textSpan = TextSpan.FromBounds(start, end); + // return declaration.OverlapsHiddenPosition(textSpan, cancellationToken); + //} + + public static IEnumerable GetAnnotatedNodes(this SyntaxNode node, SyntaxAnnotation syntaxAnnotation) where T : SyntaxNode + { + return node.GetAnnotatedNodesAndTokens(syntaxAnnotation).Select(n => n.AsNode()).OfType(); + } + + public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2) + { + if (node == null) + { + return false; + } + + var csharpKind = node.Kind(); + return csharpKind == kind1 || csharpKind == kind2; + } + + public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3) + { + if (node == null) + { + return false; + } + + var csharpKind = node.Kind(); + return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3; + } + + public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3, SyntaxKind kind4) + { + if (node == null) + { + return false; + } + + var csharpKind = node.Kind(); + return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3 || csharpKind == kind4; + } + + public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3, SyntaxKind kind4, SyntaxKind kind5) + { + if (node == null) + { + return false; + } + + var csharpKind = node.Kind(); + return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3 || csharpKind == kind4 || csharpKind == kind5; + } + + /// + /// Returns the list of using directives that affect . The list will be returned in + /// top down order. + /// + public static IEnumerable GetEnclosingUsingDirectives(this SyntaxNode node) + { + return node.GetAncestorOrThis().Usings + .Concat(node.GetAncestorsOrThis() + .Reverse() + .SelectMany(n => n.Usings)); + } + + public static bool IsUnsafeContext(this SyntaxNode node) + { + if (node.GetAncestor() != null) + { + return true; + } + + return node.GetAncestors().Any( + m => m.GetModifiers().Any(SyntaxKind.UnsafeKeyword)); + } + + public static bool IsInStaticContext(this SyntaxNode node) + { + // this/base calls are always static. + if (node.FirstAncestorOrSelf() != null) + { + return true; + } + + var memberDeclaration = node.FirstAncestorOrSelf(); + if (memberDeclaration == null) + { + return false; + } + + switch (memberDeclaration.Kind()) + { + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ConstructorDeclaration: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.EventDeclaration: + case SyntaxKind.IndexerDeclaration: + return memberDeclaration.GetModifiers().Any(SyntaxKind.StaticKeyword); + + case SyntaxKind.FieldDeclaration: + // Inside a field one can only access static members of a type. + return true; + + case SyntaxKind.DestructorDeclaration: + return false; + } + + // Global statements are not a static context. + if (node.FirstAncestorOrSelf() != null) + { + return false; + } + + // any other location is considered static + return true; + } + + public static NamespaceDeclarationSyntax GetInnermostNamespaceDeclarationWithUsings(this SyntaxNode contextNode) + { + var usingDirectiveAncestor = contextNode.GetAncestor(); + if (usingDirectiveAncestor == null) + { + return contextNode.GetAncestorsOrThis().FirstOrDefault(n => n.Usings.Count > 0); + } + else + { + // We are inside a using directive. In this case, we should find and return the first 'parent' namespace with usings. + var containingNamespace = usingDirectiveAncestor.GetAncestor(); + if (containingNamespace == null) + { + // We are inside a top level using directive (i.e. one that's directly in the compilation unit). + return null; + } + else + { + return containingNamespace.GetAncestors().FirstOrDefault(n => n.Usings.Count > 0); + } + } + } + + /// + /// Returns all of the trivia to the left of this token up to the previous token (concatenates + /// the previous token's trailing trivia and this token's leading trivia). + /// + public static IEnumerable GetAllPrecedingTriviaToPreviousToken(this SyntaxToken token) + { + var prevToken = token.GetPreviousToken(includeSkipped: true); + if (prevToken.Kind() == SyntaxKind.None) + { + return token.LeadingTrivia; + } + + return prevToken.TrailingTrivia.Concat(token.LeadingTrivia); + } + + public static bool IsBreakableConstruct(this SyntaxNode node) + { + switch (node.Kind()) + { + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForEachStatement: + return true; + } + + return false; + } + + public static bool IsContinuableConstruct(this SyntaxNode node) + { + switch (node.Kind()) + { + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForEachStatement: + return true; + } + + return false; + } + + public static bool IsReturnableConstruct(this SyntaxNode node) + { + switch (node.Kind()) + { + case SyntaxKind.AnonymousMethodExpression: + case SyntaxKind.SimpleLambdaExpression: + case SyntaxKind.ParenthesizedLambdaExpression: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ConstructorDeclaration: + case SyntaxKind.DestructorDeclaration: + case SyntaxKind.GetAccessorDeclaration: + case SyntaxKind.SetAccessorDeclaration: + case SyntaxKind.OperatorDeclaration: + case SyntaxKind.AddAccessorDeclaration: + case SyntaxKind.RemoveAccessorDeclaration: + return true; + } + + return false; + } + + public static bool IsAnyArgumentList(this SyntaxNode node) + { + return node.IsKind(SyntaxKind.ArgumentList) || + node.IsKind(SyntaxKind.AttributeArgumentList) || + node.IsKind(SyntaxKind.BracketedArgumentList) || + node.IsKind(SyntaxKind.TypeArgumentList); + } + + public static bool IsAnyLambda(this SyntaxNode node) + { + return + node.IsKind(SyntaxKind.ParenthesizedLambdaExpression) || + node.IsKind(SyntaxKind.SimpleLambdaExpression); + } + + public static bool IsAnyLambdaOrAnonymousMethod(this SyntaxNode node) + { + return node.IsAnyLambda() || node.IsKind(SyntaxKind.AnonymousMethodExpression); + } + + public static bool IsAnyAssignExpression(this SyntaxNode node) + { + return SyntaxFacts.IsAssignmentExpression(node.Kind()); + } public static bool IsParentKind(this SyntaxNode node, SyntaxKind kind) { @@ -526,296 +528,296 @@ namespace ICSharpCode.ILSpy.AddIn } public static bool IsCompoundAssignExpression(this SyntaxNode node) - { - switch (node.Kind()) - { - case SyntaxKind.AddAssignmentExpression: - case SyntaxKind.SubtractAssignmentExpression: - case SyntaxKind.MultiplyAssignmentExpression: - case SyntaxKind.DivideAssignmentExpression: - case SyntaxKind.ModuloAssignmentExpression: - case SyntaxKind.AndAssignmentExpression: - case SyntaxKind.ExclusiveOrAssignmentExpression: - case SyntaxKind.OrAssignmentExpression: - case SyntaxKind.LeftShiftAssignmentExpression: - case SyntaxKind.RightShiftAssignmentExpression: - return true; - } - - return false; - } - - public static bool IsLeftSideOfAssignExpression(this SyntaxNode node) - { - return node.IsParentKind(SyntaxKind.SimpleAssignmentExpression) && - ((AssignmentExpressionSyntax)node.Parent).Left == node; - } - - public static bool IsLeftSideOfAnyAssignExpression(this SyntaxNode node) - { - return node.Parent.IsAnyAssignExpression() && - ((AssignmentExpressionSyntax)node.Parent).Left == node; - } - - public static bool IsRightSideOfAnyAssignExpression(this SyntaxNode node) - { - return node.Parent.IsAnyAssignExpression() && - ((AssignmentExpressionSyntax)node.Parent).Right == node; - } - - public static bool IsVariableDeclaratorValue(this SyntaxNode node) - { - return - node.IsParentKind(SyntaxKind.EqualsValueClause) && - node.Parent.IsParentKind(SyntaxKind.VariableDeclarator) && - ((EqualsValueClauseSyntax)node.Parent).Value == node; - } - - public static BlockSyntax FindInnermostCommonBlock(this IEnumerable nodes) - { - return nodes.FindInnermostCommonNode(); - } - - public static IEnumerable GetAncestorsOrThis(this SyntaxNode node, Func predicate) - { - var current = node; - while (current != null) - { - if (predicate(current)) - { - yield return current; - } - - current = current.Parent; - } - } - - public static SyntaxNode GetParent(this SyntaxNode node) - { - return node != null ? node.Parent : null; - } - - public static ValueTuple GetBraces(this SyntaxNode node) - { - var namespaceNode = node as NamespaceDeclarationSyntax; - if (namespaceNode != null) - { - return ValueTuple.Create(namespaceNode.OpenBraceToken, namespaceNode.CloseBraceToken); - } - - var baseTypeNode = node as BaseTypeDeclarationSyntax; - if (baseTypeNode != null) - { - return ValueTuple.Create(baseTypeNode.OpenBraceToken, baseTypeNode.CloseBraceToken); - } - - var accessorListNode = node as AccessorListSyntax; - if (accessorListNode != null) - { - return ValueTuple.Create(accessorListNode.OpenBraceToken, accessorListNode.CloseBraceToken); - } - - var blockNode = node as BlockSyntax; - if (blockNode != null) - { - return ValueTuple.Create(blockNode.OpenBraceToken, blockNode.CloseBraceToken); - } - - var switchStatementNode = node as SwitchStatementSyntax; - if (switchStatementNode != null) - { - return ValueTuple.Create(switchStatementNode.OpenBraceToken, switchStatementNode.CloseBraceToken); - } - - var anonymousObjectCreationExpression = node as AnonymousObjectCreationExpressionSyntax; - if (anonymousObjectCreationExpression != null) - { - return ValueTuple.Create(anonymousObjectCreationExpression.OpenBraceToken, anonymousObjectCreationExpression.CloseBraceToken); - } - - var initializeExpressionNode = node as InitializerExpressionSyntax; - if (initializeExpressionNode != null) - { - return ValueTuple.Create(initializeExpressionNode.OpenBraceToken, initializeExpressionNode.CloseBraceToken); - } - - return new ValueTuple(); - } - - public static SyntaxTokenList GetModifiers(this SyntaxNode member) - { - if (member != null) - { - switch (member.Kind()) - { - case SyntaxKind.EnumDeclaration: - return ((EnumDeclarationSyntax)member).Modifiers; - case SyntaxKind.ClassDeclaration: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.StructDeclaration: - return ((TypeDeclarationSyntax)member).Modifiers; - case SyntaxKind.DelegateDeclaration: - return ((DelegateDeclarationSyntax)member).Modifiers; - case SyntaxKind.FieldDeclaration: - return ((FieldDeclarationSyntax)member).Modifiers; - case SyntaxKind.EventFieldDeclaration: - return ((EventFieldDeclarationSyntax)member).Modifiers; - case SyntaxKind.ConstructorDeclaration: - return ((ConstructorDeclarationSyntax)member).Modifiers; - case SyntaxKind.DestructorDeclaration: - return ((DestructorDeclarationSyntax)member).Modifiers; - case SyntaxKind.PropertyDeclaration: - return ((PropertyDeclarationSyntax)member).Modifiers; - case SyntaxKind.EventDeclaration: - return ((EventDeclarationSyntax)member).Modifiers; - case SyntaxKind.IndexerDeclaration: - return ((IndexerDeclarationSyntax)member).Modifiers; - case SyntaxKind.OperatorDeclaration: - return ((OperatorDeclarationSyntax)member).Modifiers; - case SyntaxKind.ConversionOperatorDeclaration: - return ((ConversionOperatorDeclarationSyntax)member).Modifiers; - case SyntaxKind.MethodDeclaration: - return ((MethodDeclarationSyntax)member).Modifiers; - case SyntaxKind.GetAccessorDeclaration: - case SyntaxKind.SetAccessorDeclaration: - case SyntaxKind.AddAccessorDeclaration: - case SyntaxKind.RemoveAccessorDeclaration: - return ((AccessorDeclarationSyntax)member).Modifiers; - } - } - - return default(SyntaxTokenList); - } - - public static SyntaxNode WithModifiers(this SyntaxNode member, SyntaxTokenList modifiers) - { - if (member != null) - { - switch (member.Kind()) - { - case SyntaxKind.EnumDeclaration: - return ((EnumDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.ClassDeclaration: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.StructDeclaration: - return ((TypeDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.DelegateDeclaration: - return ((DelegateDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.FieldDeclaration: - return ((FieldDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.EventFieldDeclaration: - return ((EventFieldDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.ConstructorDeclaration: - return ((ConstructorDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.DestructorDeclaration: - return ((DestructorDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.PropertyDeclaration: - return ((PropertyDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.EventDeclaration: - return ((EventDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.IndexerDeclaration: - return ((IndexerDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.OperatorDeclaration: - return ((OperatorDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.ConversionOperatorDeclaration: - return ((ConversionOperatorDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.MethodDeclaration: - return ((MethodDeclarationSyntax)member).WithModifiers(modifiers); - case SyntaxKind.GetAccessorDeclaration: - case SyntaxKind.SetAccessorDeclaration: - case SyntaxKind.AddAccessorDeclaration: - case SyntaxKind.RemoveAccessorDeclaration: - return ((AccessorDeclarationSyntax)member).WithModifiers(modifiers); - } - } - - return null; - } - - public static TypeDeclarationSyntax WithModifiers( - this TypeDeclarationSyntax node, SyntaxTokenList modifiers) - { - switch (node.Kind()) - { - case SyntaxKind.ClassDeclaration: - return ((ClassDeclarationSyntax)node).WithModifiers(modifiers); - case SyntaxKind.InterfaceDeclaration: - return ((InterfaceDeclarationSyntax)node).WithModifiers(modifiers); - case SyntaxKind.StructDeclaration: - return ((StructDeclarationSyntax)node).WithModifiers(modifiers); - } - - throw new InvalidOperationException(); - } - - public static bool CheckTopLevel(this SyntaxNode node, TextSpan span) - { - var block = node as BlockSyntax; - if (block != null) - { - return block.ContainsInBlockBody(span); - } - - var field = node as FieldDeclarationSyntax; - if (field != null) - { - foreach (var variable in field.Declaration.Variables) - { - if (variable.Initializer != null && variable.Initializer.Span.Contains(span)) - { - return true; - } - } - } - - var global = node as GlobalStatementSyntax; - if (global != null) - { - return true; - } - - var constructorInitializer = node as ConstructorInitializerSyntax; - if (constructorInitializer != null) - { - return constructorInitializer.ContainsInArgument(span); - } - - return false; - } - - public static bool ContainsInArgument(this ConstructorInitializerSyntax initializer, TextSpan textSpan) - { - if (initializer == null) - { - return false; - } - - return initializer.ArgumentList.Arguments.Any(a => a.Span.Contains(textSpan)); - } - - public static bool ContainsInBlockBody(this BlockSyntax block, TextSpan textSpan) - { - if (block == null) - { - return false; - } - - var blockSpan = TextSpan.FromBounds(block.OpenBraceToken.Span.End, block.CloseBraceToken.SpanStart); - return blockSpan.Contains(textSpan); - } - - public static bool IsDelegateOrConstructorOrMethodParameterList(this SyntaxNode node) - { - if (!node.IsKind(SyntaxKind.ParameterList)) - { - return false; - } - - return - node.IsParentKind(SyntaxKind.MethodDeclaration) || - node.IsParentKind(SyntaxKind.ConstructorDeclaration) || - node.IsParentKind(SyntaxKind.DelegateDeclaration); - } - - } + { + switch (node.Kind()) + { + case SyntaxKind.AddAssignmentExpression: + case SyntaxKind.SubtractAssignmentExpression: + case SyntaxKind.MultiplyAssignmentExpression: + case SyntaxKind.DivideAssignmentExpression: + case SyntaxKind.ModuloAssignmentExpression: + case SyntaxKind.AndAssignmentExpression: + case SyntaxKind.ExclusiveOrAssignmentExpression: + case SyntaxKind.OrAssignmentExpression: + case SyntaxKind.LeftShiftAssignmentExpression: + case SyntaxKind.RightShiftAssignmentExpression: + return true; + } + + return false; + } + + public static bool IsLeftSideOfAssignExpression(this SyntaxNode node) + { + return node.IsParentKind(SyntaxKind.SimpleAssignmentExpression) && + ((AssignmentExpressionSyntax)node.Parent).Left == node; + } + + public static bool IsLeftSideOfAnyAssignExpression(this SyntaxNode node) + { + return node.Parent.IsAnyAssignExpression() && + ((AssignmentExpressionSyntax)node.Parent).Left == node; + } + + public static bool IsRightSideOfAnyAssignExpression(this SyntaxNode node) + { + return node.Parent.IsAnyAssignExpression() && + ((AssignmentExpressionSyntax)node.Parent).Right == node; + } + + public static bool IsVariableDeclaratorValue(this SyntaxNode node) + { + return + node.IsParentKind(SyntaxKind.EqualsValueClause) && + node.Parent.IsParentKind(SyntaxKind.VariableDeclarator) && + ((EqualsValueClauseSyntax)node.Parent).Value == node; + } + + public static BlockSyntax FindInnermostCommonBlock(this IEnumerable nodes) + { + return nodes.FindInnermostCommonNode(); + } + + public static IEnumerable GetAncestorsOrThis(this SyntaxNode node, Func predicate) + { + var current = node; + while (current != null) + { + if (predicate(current)) + { + yield return current; + } + + current = current.Parent; + } + } + + public static SyntaxNode GetParent(this SyntaxNode node) + { + return node != null ? node.Parent : null; + } + + public static ValueTuple GetBraces(this SyntaxNode node) + { + var namespaceNode = node as NamespaceDeclarationSyntax; + if (namespaceNode != null) + { + return ValueTuple.Create(namespaceNode.OpenBraceToken, namespaceNode.CloseBraceToken); + } + + var baseTypeNode = node as BaseTypeDeclarationSyntax; + if (baseTypeNode != null) + { + return ValueTuple.Create(baseTypeNode.OpenBraceToken, baseTypeNode.CloseBraceToken); + } + + var accessorListNode = node as AccessorListSyntax; + if (accessorListNode != null) + { + return ValueTuple.Create(accessorListNode.OpenBraceToken, accessorListNode.CloseBraceToken); + } + + var blockNode = node as BlockSyntax; + if (blockNode != null) + { + return ValueTuple.Create(blockNode.OpenBraceToken, blockNode.CloseBraceToken); + } + + var switchStatementNode = node as SwitchStatementSyntax; + if (switchStatementNode != null) + { + return ValueTuple.Create(switchStatementNode.OpenBraceToken, switchStatementNode.CloseBraceToken); + } + + var anonymousObjectCreationExpression = node as AnonymousObjectCreationExpressionSyntax; + if (anonymousObjectCreationExpression != null) + { + return ValueTuple.Create(anonymousObjectCreationExpression.OpenBraceToken, anonymousObjectCreationExpression.CloseBraceToken); + } + + var initializeExpressionNode = node as InitializerExpressionSyntax; + if (initializeExpressionNode != null) + { + return ValueTuple.Create(initializeExpressionNode.OpenBraceToken, initializeExpressionNode.CloseBraceToken); + } + + return new ValueTuple(); + } + + public static SyntaxTokenList GetModifiers(this SyntaxNode member) + { + if (member != null) + { + switch (member.Kind()) + { + case SyntaxKind.EnumDeclaration: + return ((EnumDeclarationSyntax)member).Modifiers; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.StructDeclaration: + return ((TypeDeclarationSyntax)member).Modifiers; + case SyntaxKind.DelegateDeclaration: + return ((DelegateDeclarationSyntax)member).Modifiers; + case SyntaxKind.FieldDeclaration: + return ((FieldDeclarationSyntax)member).Modifiers; + case SyntaxKind.EventFieldDeclaration: + return ((EventFieldDeclarationSyntax)member).Modifiers; + case SyntaxKind.ConstructorDeclaration: + return ((ConstructorDeclarationSyntax)member).Modifiers; + case SyntaxKind.DestructorDeclaration: + return ((DestructorDeclarationSyntax)member).Modifiers; + case SyntaxKind.PropertyDeclaration: + return ((PropertyDeclarationSyntax)member).Modifiers; + case SyntaxKind.EventDeclaration: + return ((EventDeclarationSyntax)member).Modifiers; + case SyntaxKind.IndexerDeclaration: + return ((IndexerDeclarationSyntax)member).Modifiers; + case SyntaxKind.OperatorDeclaration: + return ((OperatorDeclarationSyntax)member).Modifiers; + case SyntaxKind.ConversionOperatorDeclaration: + return ((ConversionOperatorDeclarationSyntax)member).Modifiers; + case SyntaxKind.MethodDeclaration: + return ((MethodDeclarationSyntax)member).Modifiers; + case SyntaxKind.GetAccessorDeclaration: + case SyntaxKind.SetAccessorDeclaration: + case SyntaxKind.AddAccessorDeclaration: + case SyntaxKind.RemoveAccessorDeclaration: + return ((AccessorDeclarationSyntax)member).Modifiers; + } + } + + return default(SyntaxTokenList); + } + + public static SyntaxNode WithModifiers(this SyntaxNode member, SyntaxTokenList modifiers) + { + if (member != null) + { + switch (member.Kind()) + { + case SyntaxKind.EnumDeclaration: + return ((EnumDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.StructDeclaration: + return ((TypeDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.DelegateDeclaration: + return ((DelegateDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.FieldDeclaration: + return ((FieldDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.EventFieldDeclaration: + return ((EventFieldDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.ConstructorDeclaration: + return ((ConstructorDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.DestructorDeclaration: + return ((DestructorDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.PropertyDeclaration: + return ((PropertyDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.EventDeclaration: + return ((EventDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.IndexerDeclaration: + return ((IndexerDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.OperatorDeclaration: + return ((OperatorDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.ConversionOperatorDeclaration: + return ((ConversionOperatorDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.MethodDeclaration: + return ((MethodDeclarationSyntax)member).WithModifiers(modifiers); + case SyntaxKind.GetAccessorDeclaration: + case SyntaxKind.SetAccessorDeclaration: + case SyntaxKind.AddAccessorDeclaration: + case SyntaxKind.RemoveAccessorDeclaration: + return ((AccessorDeclarationSyntax)member).WithModifiers(modifiers); + } + } + + return null; + } + + public static TypeDeclarationSyntax WithModifiers( + this TypeDeclarationSyntax node, SyntaxTokenList modifiers) + { + switch (node.Kind()) + { + case SyntaxKind.ClassDeclaration: + return ((ClassDeclarationSyntax)node).WithModifiers(modifiers); + case SyntaxKind.InterfaceDeclaration: + return ((InterfaceDeclarationSyntax)node).WithModifiers(modifiers); + case SyntaxKind.StructDeclaration: + return ((StructDeclarationSyntax)node).WithModifiers(modifiers); + } + + throw new InvalidOperationException(); + } + + public static bool CheckTopLevel(this SyntaxNode node, TextSpan span) + { + var block = node as BlockSyntax; + if (block != null) + { + return block.ContainsInBlockBody(span); + } + + var field = node as FieldDeclarationSyntax; + if (field != null) + { + foreach (var variable in field.Declaration.Variables) + { + if (variable.Initializer != null && variable.Initializer.Span.Contains(span)) + { + return true; + } + } + } + + var global = node as GlobalStatementSyntax; + if (global != null) + { + return true; + } + + var constructorInitializer = node as ConstructorInitializerSyntax; + if (constructorInitializer != null) + { + return constructorInitializer.ContainsInArgument(span); + } + + return false; + } + + public static bool ContainsInArgument(this ConstructorInitializerSyntax initializer, TextSpan textSpan) + { + if (initializer == null) + { + return false; + } + + return initializer.ArgumentList.Arguments.Any(a => a.Span.Contains(textSpan)); + } + + public static bool ContainsInBlockBody(this BlockSyntax block, TextSpan textSpan) + { + if (block == null) + { + return false; + } + + var blockSpan = TextSpan.FromBounds(block.OpenBraceToken.Span.End, block.CloseBraceToken.SpanStart); + return blockSpan.Contains(textSpan); + } + + public static bool IsDelegateOrConstructorOrMethodParameterList(this SyntaxNode node) + { + if (!node.IsKind(SyntaxKind.ParameterList)) + { + return false; + } + + return + node.IsParentKind(SyntaxKind.MethodDeclaration) || + node.IsParentKind(SyntaxKind.ConstructorDeclaration) || + node.IsParentKind(SyntaxKind.DelegateDeclaration); + } + + } } diff --git a/ILSpy.AddIn/Utils.cs b/ILSpy.AddIn/Utils.cs index 65d3dc4b0..9b0164fd5 100644 --- a/ILSpy.AddIn/Utils.cs +++ b/ILSpy.AddIn/Utils.cs @@ -5,7 +5,9 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; + using EnvDTE; + using Microsoft.VisualStudio.Editor; using Microsoft.VisualStudio.LanguageServices; using Microsoft.VisualStudio.Shell; @@ -35,7 +37,8 @@ namespace ICSharpCode.ILSpy.AddIn if (hex == null) throw new ArgumentNullException(nameof(hex)); var result = new byte[hex.Length / 2]; - for (int i = 0; i < hex.Length / 2; i++) { + for (int i = 0; i < hex.Length / 2; i++) + { result[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16); } return result; @@ -43,10 +46,13 @@ namespace ICSharpCode.ILSpy.AddIn public static bool TryGetProjectFileName(dynamic referenceObject, out string fileName) { - try { + try + { fileName = referenceObject.Project.FileName; return true; - } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) { + } + catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) + { fileName = null; return false; } @@ -57,17 +63,24 @@ namespace ICSharpCode.ILSpy.AddIn ThreadHelper.ThrowIfNotOnUIThread(); var values = new object[names.Length]; - foreach (object p in properties) { - try { - if (p is Property property) { - for (int i = 0; i < names.Length; i++) { - if (names[i] == property.Name) { + foreach (object p in properties) + { + try + { + if (p is Property property) + { + for (int i = 0; i < names.Length; i++) + { + if (names[i] == property.Name) + { values[i] = property.Value; break; } } } - } catch { + } + catch + { continue; } } @@ -79,12 +92,17 @@ namespace ICSharpCode.ILSpy.AddIn ThreadHelper.ThrowIfNotOnUIThread(); var result = new List<(string, object)>(); - for (int i = 0; i < properties.Count; i++) { - try { - if (properties.Item(i) is Property p) { + for (int i = 0; i < properties.Count; i++) + { + try + { + if (properties.Item(i) is Property p) + { result.Add((p.Name, p.Value)); } - } catch { + } + catch + { continue; } } @@ -117,7 +135,8 @@ namespace ICSharpCode.ILSpy.AddIn public static IWpfTextViewHost GetCurrentViewHost(IServiceProvider serviceProvider) { IVsTextManager txtMgr = (IVsTextManager)serviceProvider.GetService(typeof(SVsTextManager)); - if (txtMgr == null) { + if (txtMgr == null) + { return null; } diff --git a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs index 42921963e..e5b5c06b7 100644 --- a/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs +++ b/ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs @@ -22,9 +22,11 @@ using System.IO; using System.Linq; using System.Threading; using System.Xml.Linq; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Tests.Helpers; using ICSharpCode.Decompiler.Util; + using NUnit.Framework; namespace ILSpy.BamlDecompiler.Tests @@ -151,7 +153,8 @@ namespace ILSpy.BamlDecompiler.Tests void RunTest(string name, string asmPath, string sourcePath) { - using (var fileStream = new FileStream(asmPath, FileMode.Open, FileAccess.Read)) { + using (var fileStream = new FileStream(asmPath, FileMode.Open, FileAccess.Read)) + { var module = new PEFile(asmPath, fileStream); var resolver = new UniversalAssemblyResolver(asmPath, false, module.Reader.DetectTargetFrameworkId()); resolver.RemoveSearchDirectory("."); @@ -168,7 +171,8 @@ namespace ILSpy.BamlDecompiler.Tests void XamlIsEqual(string input1, string input2) { var diff = new StringWriter(); - if (!CodeComparer.Compare(input1, input2, diff, NormalizeLine)) { + if (!CodeComparer.Compare(input1, input2, diff, NormalizeLine)) + { Assert.Fail(diff.ToString()); } } @@ -180,18 +184,25 @@ namespace ILSpy.BamlDecompiler.Tests Stream LoadBaml(Resource res, string name) { - if (res.ResourceType != ResourceType.Embedded) return null; + if (res.ResourceType != ResourceType.Embedded) + return null; Stream s = res.TryOpenStream(); - if (s == null) return null; + if (s == null) + return null; s.Position = 0; ResourcesFile resources; - try { + try + { resources = new ResourcesFile(s); - } catch (ArgumentException) { + } + catch (ArgumentException) + { return null; } - foreach (var entry in resources.OrderBy(e => e.Key)) { - if (entry.Key == name) { + foreach (var entry in resources.OrderBy(e => e.Key)) + { + if (entry.Key == name) + { if (entry.Value is Stream) return (Stream)entry.Value; if (entry.Value is byte[]) diff --git a/ILSpy.BamlDecompiler.Tests/Cases/AttachedEvent.xaml.cs b/ILSpy.BamlDecompiler.Tests/Cases/AttachedEvent.xaml.cs index 4c60a9340..568e25cc1 100644 --- a/ILSpy.BamlDecompiler.Tests/Cases/AttachedEvent.xaml.cs +++ b/ILSpy.BamlDecompiler.Tests/Cases/AttachedEvent.xaml.cs @@ -31,7 +31,7 @@ namespace ILSpy.BamlDecompiler.Tests.Cases { InitializeComponent(); } - + void GridAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { throw new NotImplementedException(); diff --git a/ILSpy.BamlDecompiler.Tests/Cases/CustomControl.cs b/ILSpy.BamlDecompiler.Tests/Cases/CustomControl.cs index ffe282e6f..3502c33d7 100644 --- a/ILSpy.BamlDecompiler.Tests/Cases/CustomControl.cs +++ b/ILSpy.BamlDecompiler.Tests/Cases/CustomControl.cs @@ -26,12 +26,12 @@ namespace ILSpy.BamlDecompiler.Tests.Cases public static string SimpleProperty = "Hi!"; public static readonly DependencyProperty CustomNameProperty = DependencyProperty.RegisterAttached("CustomName", typeof(string), typeof(CustomControl)); - + public static string GetCustomName(DependencyObject target) { return (string)target.GetValue(CustomNameProperty); } - + public static void SetCustomName(DependencyObject target, string value) { target.SetValue(CustomNameProperty, value); diff --git a/ILSpy.BamlDecompiler.Tests/Mocks/AvalonDock.cs b/ILSpy.BamlDecompiler.Tests/Mocks/AvalonDock.cs index 9a3563e7a..cdabc4fa0 100644 --- a/ILSpy.BamlDecompiler.Tests/Mocks/AvalonDock.cs +++ b/ILSpy.BamlDecompiler.Tests/Mocks/AvalonDock.cs @@ -27,7 +27,7 @@ namespace AvalonDock { } } - + public class Resizer : Thumb { static Resizer() @@ -42,7 +42,7 @@ namespace AvalonDock } } - + public enum AvalonDockBrushes { DefaultBackgroundBrush, @@ -73,7 +73,7 @@ namespace AvalonDock NavigatorWindowSelectionBorderbrush, NavigatorWindowBottomBackground } - + public enum ContextMenuElement { DockablePane, diff --git a/ILSpy.BamlDecompiler/Baml/BamlContext.cs b/ILSpy.BamlDecompiler/Baml/BamlContext.cs index d41b42f2c..186191bf8 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlContext.cs +++ b/ILSpy.BamlDecompiler/Baml/BamlContext.cs @@ -21,14 +21,18 @@ */ using System; -using System.Linq; using System.Collections.Generic; +using System.Linq; using System.Threading; + using ICSharpCode.Decompiler.TypeSystem; + using Metadata = ICSharpCode.Decompiler.Metadata; -namespace ILSpy.BamlDecompiler.Baml { - internal class BamlContext { +namespace ILSpy.BamlDecompiler.Baml +{ + internal class BamlContext + { public IDecompilerTypeSystem TypeSystem { get; } public KnownThings KnownThings { get; } @@ -39,7 +43,8 @@ namespace ILSpy.BamlDecompiler.Baml { public Dictionary StringIdMap { get; } public Dictionary TypeIdMap { get; } - BamlContext(IDecompilerTypeSystem typeSystem) { + BamlContext(IDecompilerTypeSystem typeSystem) + { this.TypeSystem = typeSystem; KnownThings = new KnownThings(typeSystem); @@ -49,25 +54,31 @@ namespace ILSpy.BamlDecompiler.Baml { TypeIdMap = new Dictionary(); } - public static BamlContext ConstructContext(IDecompilerTypeSystem typeSystem, BamlDocument document, CancellationToken token) { + public static BamlContext ConstructContext(IDecompilerTypeSystem typeSystem, BamlDocument document, CancellationToken token) + { var ctx = new BamlContext(typeSystem); - foreach (var record in document) { + foreach (var record in document) + { token.ThrowIfCancellationRequested(); - if (record is AssemblyInfoRecord assemblyInfo) { + if (record is AssemblyInfoRecord assemblyInfo) + { if (assemblyInfo.AssemblyId == ctx.AssemblyIdMap.Count) ctx.AssemblyIdMap.Add(assemblyInfo.AssemblyId, assemblyInfo); } - else if (record is AttributeInfoRecord attrInfo) { + else if (record is AttributeInfoRecord attrInfo) + { if (attrInfo.AttributeId == ctx.AttributeIdMap.Count) ctx.AttributeIdMap.Add(attrInfo.AttributeId, attrInfo); } - else if (record is StringInfoRecord strInfo) { + else if (record is StringInfoRecord strInfo) + { if (strInfo.StringId == ctx.StringIdMap.Count) ctx.StringIdMap.Add(strInfo.StringId, strInfo); } - else if (record is TypeInfoRecord typeInfo) { + else if (record is TypeInfoRecord typeInfo) + { if (typeInfo.TypeId == ctx.TypeIdMap.Count) ctx.TypeIdMap.Add(typeInfo.TypeId, typeInfo); } @@ -76,17 +87,21 @@ namespace ILSpy.BamlDecompiler.Baml { return ctx; } - public (string FullAssemblyName, IModule Assembly) ResolveAssembly(ushort id) { + public (string FullAssemblyName, IModule Assembly) ResolveAssembly(ushort id) + { id &= 0xfff; - if (!assemblyMap.TryGetValue(id, out var assembly)) { - if (AssemblyIdMap.TryGetValue(id, out var assemblyRec)) { + if (!assemblyMap.TryGetValue(id, out var assembly)) + { + if (AssemblyIdMap.TryGetValue(id, out var assemblyRec)) + { var assemblyName = Metadata.AssemblyNameReference.Parse(assemblyRec.AssemblyFullName); if (assemblyName.Name == TypeSystem.MainModule.AssemblyName) assembly = (assemblyRec.AssemblyFullName, TypeSystem.MainModule); else assembly = (assemblyRec.AssemblyFullName, TypeSystem.ReferencedModules.FirstOrDefault(m => m.FullAssemblyName == assemblyName.FullName)); - } else + } + else assembly = (null, null); assemblyMap[id] = assembly; diff --git a/ILSpy.BamlDecompiler/Baml/BamlDocument.cs b/ILSpy.BamlDecompiler/Baml/BamlDocument.cs index 1bf2bb58d..6126c003d 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlDocument.cs +++ b/ILSpy.BamlDecompiler/Baml/BamlDocument.cs @@ -22,8 +22,10 @@ using System.Collections.Generic; -namespace ILSpy.BamlDecompiler.Baml { - internal class BamlDocument : List { +namespace ILSpy.BamlDecompiler.Baml +{ + internal class BamlDocument : List + { public string DocumentName { get; set; } public string Signature { get; set; } @@ -31,7 +33,8 @@ namespace ILSpy.BamlDecompiler.Baml { public BamlVersion UpdaterVersion { get; set; } public BamlVersion WriterVersion { get; set; } - public struct BamlVersion { + public struct BamlVersion + { public ushort Major; public ushort Minor; } diff --git a/ILSpy.BamlDecompiler/Baml/BamlNode.cs b/ILSpy.BamlDecompiler/Baml/BamlNode.cs index 8aee3552f..a09c55851 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlNode.cs +++ b/ILSpy.BamlDecompiler/Baml/BamlNode.cs @@ -25,16 +25,20 @@ using System.Collections.Generic; using System.Diagnostics; using System.Threading; -namespace ILSpy.BamlDecompiler.Baml { - internal abstract class BamlNode { +namespace ILSpy.BamlDecompiler.Baml +{ + internal abstract class BamlNode + { public BamlBlockNode Parent { get; set; } public abstract BamlRecordType Type { get; } public object Annotation { get; set; } public abstract BamlRecord Record { get; } - public static bool IsHeader(BamlRecord rec) { - switch (rec.Type) { + public static bool IsHeader(BamlRecord rec) + { + switch (rec.Type) + { case BamlRecordType.ConstructorParametersStart: case BamlRecordType.DocumentStart: case BamlRecordType.ElementStart: @@ -50,8 +54,10 @@ namespace ILSpy.BamlDecompiler.Baml { return false; } - public static bool IsFooter(BamlRecord rec) { - switch (rec.Type) { + public static bool IsFooter(BamlRecord rec) + { + switch (rec.Type) + { case BamlRecordType.ConstructorParametersEnd: case BamlRecordType.DocumentEnd: case BamlRecordType.ElementEnd: @@ -66,8 +72,10 @@ namespace ILSpy.BamlDecompiler.Baml { return false; } - public static bool IsMatch(BamlRecord header, BamlRecord footer) { - switch (header.Type) { + public static bool IsMatch(BamlRecord header, BamlRecord footer) + { + switch (header.Type) + { case BamlRecordType.ConstructorParametersStart: return footer.Type == BamlRecordType.ConstructorParametersEnd; @@ -99,33 +107,39 @@ namespace ILSpy.BamlDecompiler.Baml { return false; } - public static BamlNode Parse(BamlDocument document, CancellationToken token) { + public static BamlNode Parse(BamlDocument document, CancellationToken token) + { Debug.Assert(document.Count > 0 && document[0].Type == BamlRecordType.DocumentStart); BamlBlockNode current = null; var stack = new Stack(); - for (int i = 0; i < document.Count; i++) { + for (int i = 0; i < document.Count; i++) + { token.ThrowIfCancellationRequested(); - if (IsHeader(document[i])) { + if (IsHeader(document[i])) + { var prev = current; current = new BamlBlockNode { Header = document[i] }; - if (prev != null) { + if (prev != null) + { prev.Children.Add(current); current.Parent = prev; stack.Push(prev); } } - else if (IsFooter(document[i])) { + else if (IsFooter(document[i])) + { if (current == null) throw new Exception("Unexpected footer."); - while (!IsMatch(current.Header, document[i])) { + while (!IsMatch(current.Header, document[i])) + { // End record can be omited (sometimes). if (stack.Count > 0) current = stack.Pop(); @@ -142,7 +156,8 @@ namespace ILSpy.BamlDecompiler.Baml { } } - internal class BamlRecordNode : BamlNode { + internal class BamlRecordNode : BamlNode + { BamlRecord record; public override BamlRecord Record => record; @@ -151,7 +166,8 @@ namespace ILSpy.BamlDecompiler.Baml { public BamlRecordNode(BamlRecord record) => this.record = record; } - internal class BamlBlockNode : BamlNode { + internal class BamlBlockNode : BamlNode + { public BamlRecord Header { get; set; } public IList Children { get; } public BamlRecord Footer { get; set; } diff --git a/ILSpy.BamlDecompiler/Baml/BamlReader.cs b/ILSpy.BamlDecompiler/Baml/BamlReader.cs index 64d0832d0..8f1c6f861 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlReader.cs +++ b/ILSpy.BamlDecompiler/Baml/BamlReader.cs @@ -26,21 +26,27 @@ using System.IO; using System.Text; using System.Threading; -namespace ILSpy.BamlDecompiler.Baml { - internal class BamlBinaryReader : BinaryReader { +namespace ILSpy.BamlDecompiler.Baml +{ + internal class BamlBinaryReader : BinaryReader + { public BamlBinaryReader(Stream stream) - : base(stream) { + : base(stream) + { } public int ReadEncodedInt() => Read7BitEncodedInt(); } - internal class BamlReader { + internal class BamlReader + { const string MSBAML_SIG = "MSBAML"; - internal static bool IsBamlHeader(Stream str) { + internal static bool IsBamlHeader(Stream str) + { var pos = str.Position; - try { + try + { var rdr = new BinaryReader(str, Encoding.Unicode); int len = (int)(rdr.ReadUInt32() >> 1); if (len != MSBAML_SIG.Length) @@ -48,12 +54,14 @@ namespace ILSpy.BamlDecompiler.Baml { var sig = new string(rdr.ReadChars(len)); return sig == MSBAML_SIG; } - finally { + finally + { str.Position = pos; } } - static string ReadSignature(Stream str) { + static string ReadSignature(Stream str) + { var rdr = new BinaryReader(str, Encoding.Unicode); uint len = rdr.ReadUInt32(); var sig = new string(rdr.ReadChars((int)(len >> 1))); @@ -61,27 +69,31 @@ namespace ILSpy.BamlDecompiler.Baml { return sig; } - public static BamlDocument ReadDocument(Stream str, CancellationToken token) { + public static BamlDocument ReadDocument(Stream str, CancellationToken token) + { var ret = new BamlDocument(); var reader = new BamlBinaryReader(str); ret.Signature = ReadSignature(str); - if (ret.Signature != MSBAML_SIG) throw new NotSupportedException(); + if (ret.Signature != MSBAML_SIG) + throw new NotSupportedException(); ret.ReaderVersion = new BamlDocument.BamlVersion { Major = reader.ReadUInt16(), Minor = reader.ReadUInt16() }; ret.UpdaterVersion = new BamlDocument.BamlVersion { Major = reader.ReadUInt16(), Minor = reader.ReadUInt16() }; ret.WriterVersion = new BamlDocument.BamlVersion { Major = reader.ReadUInt16(), Minor = reader.ReadUInt16() }; if (ret.ReaderVersion.Major != 0 || ret.ReaderVersion.Minor != 0x60 || - ret.UpdaterVersion.Major != 0 || ret.UpdaterVersion.Minor != 0x60 || - ret.WriterVersion.Major != 0 || ret.WriterVersion.Minor != 0x60) + ret.UpdaterVersion.Major != 0 || ret.UpdaterVersion.Minor != 0x60 || + ret.WriterVersion.Major != 0 || ret.WriterVersion.Minor != 0x60) throw new NotSupportedException(); var recs = new Dictionary(); - while (str.Position < str.Length) { + while (str.Position < str.Length) + { token.ThrowIfCancellationRequested(); long pos = str.Position; var type = (BamlRecordType)reader.ReadByte(); BamlRecord rec = null; - switch (type) { + switch (type) + { case BamlRecordType.AssemblyInfo: rec = new AssemblyInfoRecord(); break; @@ -248,7 +260,8 @@ namespace ILSpy.BamlDecompiler.Baml { ret.Add(rec); recs.Add(pos, rec); } - for (int i = 0; i < ret.Count; i++) { + for (int i = 0; i < ret.Count; i++) + { if (ret[i] is IBamlDeferRecord defer) defer.ReadDefer(ret, i, _ => recs[_]); } diff --git a/ILSpy.BamlDecompiler/Baml/BamlRecords.cs b/ILSpy.BamlDecompiler/Baml/BamlRecords.cs index 1ff43f079..dc64128a2 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlRecords.cs +++ b/ILSpy.BamlDecompiler/Baml/BamlRecords.cs @@ -24,8 +24,10 @@ using System; using System.Diagnostics; using System.IO; -namespace ILSpy.BamlDecompiler.Baml { - internal enum BamlRecordType : byte { +namespace ILSpy.BamlDecompiler.Baml +{ + internal enum BamlRecordType : byte + { ClrEvent = 0x13, Comment = 0x17, AssemblyInfo = 0x1c, @@ -85,38 +87,47 @@ namespace ILSpy.BamlDecompiler.Baml { XmlnsProperty = 0x14 } - internal abstract class BamlRecord { + internal abstract class BamlRecord + { public abstract BamlRecordType Type { get; } public long Position { get; internal set; } public abstract void Read(BamlBinaryReader reader); public abstract void Write(BamlBinaryWriter writer); } - internal abstract class SizedBamlRecord : BamlRecord { - public override void Read(BamlBinaryReader reader) { + internal abstract class SizedBamlRecord : BamlRecord + { + public override void Read(BamlBinaryReader reader) + { long pos = reader.BaseStream.Position; int size = reader.ReadEncodedInt(); ReadData(reader, size - (int)(reader.BaseStream.Position - pos)); } - int SizeofEncodedInt(int val) { - if ((val & ~0x7F) == 0) { + int SizeofEncodedInt(int val) + { + if ((val & ~0x7F) == 0) + { return 1; } - if ((val & ~0x3FFF) == 0) { + if ((val & ~0x3FFF) == 0) + { return 2; } - if ((val & ~0x1FFFFF) == 0) { + if ((val & ~0x1FFFFF) == 0) + { return 3; } - if ((val & ~0xFFFFFFF) == 0) { + if ((val & ~0xFFFFFFF) == 0) + { return 4; } return 5; } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { long pos = writer.BaseStream.Position; WriteData(writer); var size = (int)(writer.BaseStream.Position - pos); @@ -130,21 +141,24 @@ namespace ILSpy.BamlDecompiler.Baml { protected abstract void WriteData(BamlBinaryWriter writer); } - internal interface IBamlDeferRecord { + internal interface IBamlDeferRecord + { long Position { get; } BamlRecord Record { get; set; } void ReadDefer(BamlDocument doc, int index, Func resolve); void WriteDefer(BamlDocument doc, int index, BinaryWriter wtr); } - internal class XmlnsPropertyRecord : SizedBamlRecord { + internal class XmlnsPropertyRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.XmlnsProperty; public string Prefix { get; set; } public string XmlNamespace { get; set; } public ushort[] AssemblyIds { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { Prefix = reader.ReadString(); XmlNamespace = reader.ReadString(); AssemblyIds = new ushort[reader.ReadUInt16()]; @@ -152,7 +166,8 @@ namespace ILSpy.BamlDecompiler.Baml { AssemblyIds[i] = reader.ReadUInt16(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(Prefix); writer.Write(XmlNamespace); writer.Write((ushort)AssemblyIds.Length); @@ -161,132 +176,154 @@ namespace ILSpy.BamlDecompiler.Baml { } } - internal class PresentationOptionsAttributeRecord : SizedBamlRecord { + internal class PresentationOptionsAttributeRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.PresentationOptionsAttribute; public string Value { get; set; } public ushort NameId { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { Value = reader.ReadString(); NameId = reader.ReadUInt16(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(Value); writer.Write(NameId); } } - internal class PIMappingRecord : SizedBamlRecord { + internal class PIMappingRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.PIMapping; public string XmlNamespace { get; set; } public string ClrNamespace { get; set; } public ushort AssemblyId { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { XmlNamespace = reader.ReadString(); ClrNamespace = reader.ReadString(); AssemblyId = reader.ReadUInt16(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(XmlNamespace); writer.Write(ClrNamespace); writer.Write(AssemblyId); } } - internal class AssemblyInfoRecord : SizedBamlRecord { + internal class AssemblyInfoRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.AssemblyInfo; public ushort AssemblyId { get; set; } public string AssemblyFullName { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { AssemblyId = reader.ReadUInt16(); AssemblyFullName = reader.ReadString(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(AssemblyId); writer.Write(AssemblyFullName); } } - internal class PropertyRecord : SizedBamlRecord { + internal class PropertyRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.Property; public ushort AttributeId { get; set; } public string Value { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { AttributeId = reader.ReadUInt16(); Value = reader.ReadString(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(AttributeId); writer.Write(Value); } } - internal class PropertyWithConverterRecord : PropertyRecord { + internal class PropertyWithConverterRecord : PropertyRecord + { public override BamlRecordType Type => BamlRecordType.PropertyWithConverter; public ushort ConverterTypeId { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { base.ReadData(reader, size); ConverterTypeId = reader.ReadUInt16(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { base.WriteData(writer); writer.Write(ConverterTypeId); } } - internal class PropertyCustomRecord : SizedBamlRecord { + internal class PropertyCustomRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.PropertyCustom; public ushort AttributeId { get; set; } public ushort SerializerTypeId { get; set; } public byte[] Data { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { long pos = reader.BaseStream.Position; AttributeId = reader.ReadUInt16(); SerializerTypeId = reader.ReadUInt16(); Data = reader.ReadBytes(size - (int)(reader.BaseStream.Position - pos)); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(AttributeId); writer.Write(SerializerTypeId); writer.Write(Data); } } - internal class DefAttributeRecord : SizedBamlRecord { + internal class DefAttributeRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.DefAttribute; public string Value { get; set; } public ushort NameId { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { Value = reader.ReadString(); NameId = reader.ReadUInt16(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(Value); writer.Write(NameId); } } - internal class DefAttributeKeyStringRecord : SizedBamlRecord, IBamlDeferRecord { + internal class DefAttributeKeyStringRecord : SizedBamlRecord, IBamlDeferRecord + { internal uint pos = 0xffffffff; public override BamlRecordType Type => BamlRecordType.DefAttributeKeyString; @@ -297,10 +334,13 @@ namespace ILSpy.BamlDecompiler.Baml { public BamlRecord Record { get; set; } - public void ReadDefer(BamlDocument doc, int index, Func resolve) { + public void ReadDefer(BamlDocument doc, int index, Func resolve) + { bool keys = true; - do { - switch (doc[index].Type) { + do + { + switch (doc[index].Type) + { case BamlRecordType.DefAttributeKeyString: case BamlRecordType.DefAttributeKeyType: case BamlRecordType.OptimizedStaticResource: @@ -324,10 +364,13 @@ namespace ILSpy.BamlDecompiler.Baml { Record = resolve(doc[index].Position + pos); } - public void WriteDefer(BamlDocument doc, int index, BinaryWriter wtr) { + public void WriteDefer(BamlDocument doc, int index, BinaryWriter wtr) + { bool keys = true; - do { - switch (doc[index].Type) { + do + { + switch (doc[index].Type) + { case BamlRecordType.DefAttributeKeyString: case BamlRecordType.DefAttributeKeyType: case BamlRecordType.OptimizedStaticResource: @@ -352,14 +395,16 @@ namespace ILSpy.BamlDecompiler.Baml { wtr.Write((uint)(Record.Position - doc[index].Position)); } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { ValueId = reader.ReadUInt16(); pos = reader.ReadUInt32(); Shared = reader.ReadBoolean(); SharedSet = reader.ReadBoolean(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(ValueId); pos = (uint)writer.BaseStream.Position; writer.Write((uint)0); @@ -367,7 +412,8 @@ namespace ILSpy.BamlDecompiler.Baml { writer.Write(SharedSet); } - static void NavigateTree(BamlDocument doc, BamlRecordType start, BamlRecordType end, ref int index) { + static void NavigateTree(BamlDocument doc, BamlRecordType start, BamlRecordType end, ref int index) + { index++; while (true) //Assume there alway is a end { @@ -380,43 +426,50 @@ namespace ILSpy.BamlDecompiler.Baml { } } - internal class TypeInfoRecord : SizedBamlRecord { + internal class TypeInfoRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.TypeInfo; public ushort TypeId { get; set; } public ushort AssemblyId { get; set; } public string TypeFullName { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { TypeId = reader.ReadUInt16(); AssemblyId = reader.ReadUInt16(); TypeFullName = reader.ReadString(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(TypeId); writer.Write(AssemblyId); writer.Write(TypeFullName); } } - internal class TypeSerializerInfoRecord : TypeInfoRecord { + internal class TypeSerializerInfoRecord : TypeInfoRecord + { public override BamlRecordType Type => BamlRecordType.TypeSerializerInfo; public ushort SerializerTypeId { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { base.ReadData(reader, size); SerializerTypeId = reader.ReadUInt16(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { base.WriteData(writer); writer.Write(SerializerTypeId); } } - internal class AttributeInfoRecord : SizedBamlRecord { + internal class AttributeInfoRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.AttributeInfo; public ushort AttributeId { get; set; } @@ -424,14 +477,16 @@ namespace ILSpy.BamlDecompiler.Baml { public byte AttributeUsage { get; set; } public string Name { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { AttributeId = reader.ReadUInt16(); OwnerTypeId = reader.ReadUInt16(); AttributeUsage = reader.ReadByte(); Name = reader.ReadString(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(AttributeId); writer.Write(OwnerTypeId); writer.Write(AttributeUsage); @@ -439,24 +494,28 @@ namespace ILSpy.BamlDecompiler.Baml { } } - internal class StringInfoRecord : SizedBamlRecord { + internal class StringInfoRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.StringInfo; public ushort StringId { get; set; } public string Value { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { StringId = reader.ReadUInt16(); Value = reader.ReadString(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(StringId); writer.Write(Value); } } - internal class TextRecord : SizedBamlRecord { + internal class TextRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.Text; public string Value { get; set; } @@ -466,23 +525,27 @@ namespace ILSpy.BamlDecompiler.Baml { protected override void WriteData(BamlBinaryWriter writer) => writer.Write(Value); } - internal class TextWithConverterRecord : TextRecord { + internal class TextWithConverterRecord : TextRecord + { public override BamlRecordType Type => BamlRecordType.TextWithConverter; public ushort ConverterTypeId { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { base.ReadData(reader, size); ConverterTypeId = reader.ReadUInt16(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { base.WriteData(writer); writer.Write(ConverterTypeId); } } - internal class TextWithIdRecord : SizedBamlRecord { + internal class TextWithIdRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.TextWithId; public ushort ValueId { get; set; } @@ -492,116 +555,139 @@ namespace ILSpy.BamlDecompiler.Baml { protected override void WriteData(BamlBinaryWriter writer) => writer.Write(ValueId); } - internal class LiteralContentRecord : SizedBamlRecord { + internal class LiteralContentRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.LiteralContent; public string Value { get; set; } public uint Reserved0 { get; set; } public uint Reserved1 { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { Value = reader.ReadString(); Reserved0 = reader.ReadUInt32(); Reserved1 = reader.ReadUInt32(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(Value); writer.Write(Reserved0); writer.Write(Reserved1); } } - internal class RoutedEventRecord : SizedBamlRecord { + internal class RoutedEventRecord : SizedBamlRecord + { public override BamlRecordType Type => BamlRecordType.RoutedEvent; public string Value { get; set; } public ushort AttributeId { get; set; } public uint Reserved1 { get; set; } - protected override void ReadData(BamlBinaryReader reader, int size) { + protected override void ReadData(BamlBinaryReader reader, int size) + { AttributeId = reader.ReadUInt16(); Value = reader.ReadString(); } - protected override void WriteData(BamlBinaryWriter writer) { + protected override void WriteData(BamlBinaryWriter writer) + { writer.Write(Value); writer.Write(AttributeId); } } - internal class DocumentStartRecord : BamlRecord { + internal class DocumentStartRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.DocumentStart; public bool LoadAsync { get; set; } public uint MaxAsyncRecords { get; set; } public bool DebugBaml { get; set; } - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { LoadAsync = reader.ReadBoolean(); MaxAsyncRecords = reader.ReadUInt32(); DebugBaml = reader.ReadBoolean(); } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { writer.Write(LoadAsync); writer.Write(MaxAsyncRecords); writer.Write(DebugBaml); } } - internal class DocumentEndRecord : BamlRecord { + internal class DocumentEndRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.DocumentEnd; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { } } - internal class ElementStartRecord : BamlRecord { + internal class ElementStartRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.ElementStart; public ushort TypeId { get; set; } public byte Flags { get; set; } - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { TypeId = reader.ReadUInt16(); Flags = reader.ReadByte(); } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { writer.Write(TypeId); writer.Write(Flags); } } - internal class ElementEndRecord : BamlRecord { + internal class ElementEndRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.ElementEnd; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { } } - internal class KeyElementStartRecord : DefAttributeKeyTypeRecord { + internal class KeyElementStartRecord : DefAttributeKeyTypeRecord + { public override BamlRecordType Type => BamlRecordType.KeyElementStart; } - internal class KeyElementEndRecord : BamlRecord { + internal class KeyElementEndRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.KeyElementEnd; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { } } - internal class ConnectionIdRecord : BamlRecord { + internal class ConnectionIdRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.ConnectionId; public uint ConnectionId { get; set; } @@ -611,75 +697,88 @@ namespace ILSpy.BamlDecompiler.Baml { public override void Write(BamlBinaryWriter writer) => writer.Write(ConnectionId); } - internal class PropertyWithExtensionRecord : BamlRecord { + internal class PropertyWithExtensionRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.PropertyWithExtension; public ushort AttributeId { get; set; } public ushort Flags { get; set; } public ushort ValueId { get; set; } - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { AttributeId = reader.ReadUInt16(); Flags = reader.ReadUInt16(); ValueId = reader.ReadUInt16(); } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { writer.Write(AttributeId); writer.Write(Flags); writer.Write(ValueId); } } - internal class PropertyTypeReferenceRecord : PropertyComplexStartRecord { + internal class PropertyTypeReferenceRecord : PropertyComplexStartRecord + { public override BamlRecordType Type => BamlRecordType.PropertyTypeReference; public ushort TypeId { get; set; } - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { base.Read(reader); TypeId = reader.ReadUInt16(); } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { base.Write(writer); writer.Write(TypeId); } } - internal class PropertyStringReferenceRecord : PropertyComplexStartRecord { + internal class PropertyStringReferenceRecord : PropertyComplexStartRecord + { public override BamlRecordType Type => BamlRecordType.PropertyStringReference; public ushort StringId { get; set; } - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { base.Read(reader); StringId = reader.ReadUInt16(); } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { base.Write(writer); writer.Write(StringId); } } - internal class PropertyWithStaticResourceIdRecord : StaticResourceIdRecord { + internal class PropertyWithStaticResourceIdRecord : StaticResourceIdRecord + { public override BamlRecordType Type => BamlRecordType.PropertyWithStaticResourceId; public ushort AttributeId { get; set; } - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { AttributeId = reader.ReadUInt16(); base.Read(reader); } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { writer.Write(AttributeId); base.Write(writer); } } - internal class ContentPropertyRecord : BamlRecord { + internal class ContentPropertyRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.ContentProperty; public ushort AttributeId { get; set; } @@ -689,7 +788,8 @@ namespace ILSpy.BamlDecompiler.Baml { public override void Write(BamlBinaryWriter writer) => writer.Write(AttributeId); } - internal class DefAttributeKeyTypeRecord : ElementStartRecord, IBamlDeferRecord { + internal class DefAttributeKeyTypeRecord : ElementStartRecord, IBamlDeferRecord + { internal uint pos = 0xffffffff; public override BamlRecordType Type => BamlRecordType.DefAttributeKeyType; @@ -699,10 +799,13 @@ namespace ILSpy.BamlDecompiler.Baml { public BamlRecord Record { get; set; } - public void ReadDefer(BamlDocument doc, int index, Func resolve) { + public void ReadDefer(BamlDocument doc, int index, Func resolve) + { bool keys = true; - do { - switch (doc[index].Type) { + do + { + switch (doc[index].Type) + { case BamlRecordType.DefAttributeKeyString: case BamlRecordType.DefAttributeKeyType: case BamlRecordType.OptimizedStaticResource: @@ -726,10 +829,13 @@ namespace ILSpy.BamlDecompiler.Baml { Record = resolve(doc[index].Position + pos); } - public void WriteDefer(BamlDocument doc, int index, BinaryWriter wtr) { + public void WriteDefer(BamlDocument doc, int index, BinaryWriter wtr) + { bool keys = true; - do { - switch (doc[index].Type) { + do + { + switch (doc[index].Type) + { case BamlRecordType.DefAttributeKeyString: case BamlRecordType.DefAttributeKeyType: case BamlRecordType.OptimizedStaticResource: @@ -754,14 +860,16 @@ namespace ILSpy.BamlDecompiler.Baml { wtr.Write((uint)(Record.Position - doc[index].Position)); } - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { base.Read(reader); pos = reader.ReadUInt32(); Shared = reader.ReadBoolean(); SharedSet = reader.ReadBoolean(); } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { base.Write(writer); pos = (uint)writer.BaseStream.Position; writer.Write((uint)0); @@ -769,9 +877,11 @@ namespace ILSpy.BamlDecompiler.Baml { writer.Write(SharedSet); } - static void NavigateTree(BamlDocument doc, BamlRecordType start, BamlRecordType end, ref int index) { + static void NavigateTree(BamlDocument doc, BamlRecordType start, BamlRecordType end, ref int index) + { index++; - while (true) { + while (true) + { if (doc[index].Type == start) NavigateTree(doc, start, end, ref index); else if (doc[index].Type == end) @@ -781,49 +891,62 @@ namespace ILSpy.BamlDecompiler.Baml { } } - internal class PropertyListStartRecord : PropertyComplexStartRecord { + internal class PropertyListStartRecord : PropertyComplexStartRecord + { public override BamlRecordType Type => BamlRecordType.PropertyListStart; } - internal class PropertyListEndRecord : BamlRecord { + internal class PropertyListEndRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.PropertyListEnd; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { } } - internal class PropertyDictionaryStartRecord : PropertyComplexStartRecord { + internal class PropertyDictionaryStartRecord : PropertyComplexStartRecord + { public override BamlRecordType Type => BamlRecordType.PropertyDictionaryStart; } - internal class PropertyDictionaryEndRecord : BamlRecord { + internal class PropertyDictionaryEndRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.PropertyDictionaryEnd; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { } } - internal class PropertyArrayStartRecord : PropertyComplexStartRecord { + internal class PropertyArrayStartRecord : PropertyComplexStartRecord + { public override BamlRecordType Type => BamlRecordType.PropertyArrayStart; } - internal class PropertyArrayEndRecord : BamlRecord { + internal class PropertyArrayEndRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.PropertyArrayEnd; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { } } - internal class PropertyComplexStartRecord : BamlRecord { + internal class PropertyComplexStartRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.PropertyComplexStart; public ushort AttributeId { get; set; } @@ -833,37 +956,47 @@ namespace ILSpy.BamlDecompiler.Baml { public override void Write(BamlBinaryWriter writer) => writer.Write(AttributeId); } - internal class PropertyComplexEndRecord : BamlRecord { + internal class PropertyComplexEndRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.PropertyComplexEnd; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { } } - internal class ConstructorParametersStartRecord : BamlRecord { + internal class ConstructorParametersStartRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.ConstructorParametersStart; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { } } - internal class ConstructorParametersEndRecord : BamlRecord { + internal class ConstructorParametersEndRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.ConstructorParametersEnd; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { } } - internal class ConstructorParameterTypeRecord : BamlRecord { + internal class ConstructorParameterTypeRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.ConstructorParameterType; public ushort TypeId { get; set; } @@ -873,7 +1006,8 @@ namespace ILSpy.BamlDecompiler.Baml { public override void Write(BamlBinaryWriter writer) => writer.Write(TypeId); } - internal class DeferableContentStartRecord : BamlRecord, IBamlDeferRecord { + internal class DeferableContentStartRecord : BamlRecord, IBamlDeferRecord + { long pos; internal uint size = 0xffffffff; @@ -883,37 +1017,45 @@ namespace ILSpy.BamlDecompiler.Baml { public void ReadDefer(BamlDocument doc, int index, Func resolve) => Record = resolve(pos + size); - public void WriteDefer(BamlDocument doc, int index, BinaryWriter wtr) { + public void WriteDefer(BamlDocument doc, int index, BinaryWriter wtr) + { wtr.BaseStream.Seek(pos, SeekOrigin.Begin); wtr.Write((uint)(Record.Position - (pos + 4))); } - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { size = reader.ReadUInt32(); pos = reader.BaseStream.Position; } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { pos = writer.BaseStream.Position; writer.Write((uint)0); } } - internal class StaticResourceStartRecord : ElementStartRecord { + internal class StaticResourceStartRecord : ElementStartRecord + { public override BamlRecordType Type => BamlRecordType.StaticResourceStart; } - internal class StaticResourceEndRecord : BamlRecord { + internal class StaticResourceEndRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.StaticResourceEnd; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { } } - internal class StaticResourceIdRecord : BamlRecord { + internal class StaticResourceIdRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.StaticResourceId; public ushort StaticResourceId { get; set; } @@ -923,7 +1065,8 @@ namespace ILSpy.BamlDecompiler.Baml { public override void Write(BamlBinaryWriter writer) => writer.Write(StaticResourceId); } - internal class OptimizedStaticResourceRecord : BamlRecord { + internal class OptimizedStaticResourceRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.OptimizedStaticResource; public byte Flags { get; set; } @@ -933,35 +1076,41 @@ namespace ILSpy.BamlDecompiler.Baml { public bool IsStatic => (Flags & 2) != 0; - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { Flags = reader.ReadByte(); ValueId = reader.ReadUInt16(); } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { writer.Write(Flags); writer.Write(ValueId); } } - internal class LineNumberAndPositionRecord : BamlRecord { + internal class LineNumberAndPositionRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.LineNumberAndPosition; public uint LineNumber { get; set; } public uint LinePosition { get; set; } - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { LineNumber = reader.ReadUInt32(); LinePosition = reader.ReadUInt32(); } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { writer.Write(LineNumber); writer.Write(LinePosition); } } - internal class LinePositionRecord : BamlRecord { + internal class LinePositionRecord : BamlRecord + { public override BamlRecordType Type => BamlRecordType.LinePosition; public uint LinePosition { get; set; } @@ -971,19 +1120,23 @@ namespace ILSpy.BamlDecompiler.Baml { public override void Write(BamlBinaryWriter writer) => writer.Write(LinePosition); } - internal class NamedElementStartRecord : ElementStartRecord { + internal class NamedElementStartRecord : ElementStartRecord + { public override BamlRecordType Type => BamlRecordType.NamedElementStart; public string RuntimeName { get; set; } - public override void Read(BamlBinaryReader reader) { + public override void Read(BamlBinaryReader reader) + { TypeId = reader.ReadUInt16(); RuntimeName = reader.ReadString(); } - public override void Write(BamlBinaryWriter writer) { + public override void Write(BamlBinaryWriter writer) + { writer.Write(TypeId); - if (RuntimeName != null) { + if (RuntimeName != null) + { writer.Write(RuntimeName); } } diff --git a/ILSpy.BamlDecompiler/Baml/BamlWriter.cs b/ILSpy.BamlDecompiler/Baml/BamlWriter.cs index 910eacc94..f350b8edf 100644 --- a/ILSpy.BamlDecompiler/Baml/BamlWriter.cs +++ b/ILSpy.BamlDecompiler/Baml/BamlWriter.cs @@ -24,17 +24,22 @@ using System.Collections.Generic; using System.IO; using System.Text; -namespace ILSpy.BamlDecompiler.Baml { - internal class BamlBinaryWriter : BinaryWriter { +namespace ILSpy.BamlDecompiler.Baml +{ + internal class BamlBinaryWriter : BinaryWriter + { public BamlBinaryWriter(Stream stream) - : base(stream) { + : base(stream) + { } public void WriteEncodedInt(int val) => Write7BitEncodedInt(val); } - internal class BamlWriter { - public static void WriteDocument(BamlDocument doc, Stream str) { + internal class BamlWriter + { + public static void WriteDocument(BamlDocument doc, Stream str) + { var writer = new BamlBinaryWriter(str); { var wtr = new BinaryWriter(str, Encoding.Unicode); @@ -51,12 +56,14 @@ namespace ILSpy.BamlDecompiler.Baml { writer.Write(doc.WriterVersion.Minor); var defers = new List(); - for (int i = 0; i < doc.Count; i++) { + for (int i = 0; i < doc.Count; i++) + { BamlRecord rec = doc[i]; rec.Position = str.Position; writer.Write((byte)rec.Type); rec.Write(writer); - if (rec is IBamlDeferRecord) defers.Add(i); + if (rec is IBamlDeferRecord) + defers.Add(i); } foreach (int i in defers) (doc[i] as IBamlDeferRecord).WriteDefer(doc, i, writer); diff --git a/ILSpy.BamlDecompiler/Baml/KnownMembers.cs b/ILSpy.BamlDecompiler/Baml/KnownMembers.cs index d33f04139..e6b7c4cb3 100644 --- a/ILSpy.BamlDecompiler/Baml/KnownMembers.cs +++ b/ILSpy.BamlDecompiler/Baml/KnownMembers.cs @@ -20,10 +20,12 @@ THE SOFTWARE. */ -namespace ILSpy.BamlDecompiler.Baml { +namespace ILSpy.BamlDecompiler.Baml +{ // Auto generated. Do not modify. - internal enum KnownMembers : short { + internal enum KnownMembers : short + { Unknown = 0, AccessText_Text = 1, BeginStoryboard_Storyboard = 2, diff --git a/ILSpy.BamlDecompiler/Baml/KnownThings.cs b/ILSpy.BamlDecompiler/Baml/KnownThings.cs index c5ab16072..2572cc808 100644 --- a/ILSpy.BamlDecompiler/Baml/KnownThings.cs +++ b/ILSpy.BamlDecompiler/Baml/KnownThings.cs @@ -23,11 +23,14 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler.Baml { - internal partial class KnownThings { +namespace ILSpy.BamlDecompiler.Baml +{ + internal partial class KnownThings + { readonly IDecompilerTypeSystem typeSystem; readonly Dictionary assemblies; @@ -36,7 +39,8 @@ namespace ILSpy.BamlDecompiler.Baml { readonly Dictionary strings; readonly Dictionary resources; - public KnownThings(IDecompilerTypeSystem typeSystem) { + public KnownThings(IDecompilerTypeSystem typeSystem) + { this.typeSystem = typeSystem; assemblies = new Dictionary(); @@ -45,13 +49,16 @@ namespace ILSpy.BamlDecompiler.Baml { strings = new Dictionary(); resources = new Dictionary(); - try { + try + { InitAssemblies(); InitTypes(); InitMembers(); InitStrings(); InitResources(); - } catch (Exception ex) { + } + catch (Exception ex) + { throw new ICSharpCode.Decompiler.DecompilerException(typeSystem.MainModule.PEFile, ex.Message, ex); } } @@ -73,8 +80,10 @@ namespace ILSpy.BamlDecompiler.Baml { KnownMember InitMember(KnownTypes parent, string name, ITypeDefinition type) => new KnownMember(parent, types[parent], name, type); } - internal class KnownMember { - public KnownMember(KnownTypes parent, ITypeDefinition declType, string name, ITypeDefinition type) { + internal class KnownMember + { + public KnownMember(KnownTypes parent, ITypeDefinition declType, string name, ITypeDefinition type) + { Parent = parent; Property = declType.GetProperties(p => p.Name == name, GetMemberOptions.IgnoreInheritedMembers).SingleOrDefault(); DeclaringType = declType; diff --git a/ILSpy.BamlDecompiler/Baml/KnownTypes.cs b/ILSpy.BamlDecompiler/Baml/KnownTypes.cs index 8c0b9b4d4..892ef17c5 100644 --- a/ILSpy.BamlDecompiler/Baml/KnownTypes.cs +++ b/ILSpy.BamlDecompiler/Baml/KnownTypes.cs @@ -20,10 +20,12 @@ THE SOFTWARE. */ -namespace ILSpy.BamlDecompiler.Baml { +namespace ILSpy.BamlDecompiler.Baml +{ // Auto generated. Do not modify. - internal enum KnownTypes : short { + internal enum KnownTypes : short + { Unknown = 0, AccessText = 1, AdornedElementPlaceholder = 2, diff --git a/ILSpy.BamlDecompiler/BamlElement.cs b/ILSpy.BamlDecompiler/BamlElement.cs index 222bdd1d6..7728a99fb 100644 --- a/ILSpy.BamlDecompiler/BamlElement.cs +++ b/ILSpy.BamlDecompiler/BamlElement.cs @@ -22,16 +22,21 @@ using System.Collections.Generic; using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler { - internal readonly struct XamlNode { - XamlNode(XElement value) { +namespace ILSpy.BamlDecompiler +{ + internal readonly struct XamlNode + { + XamlNode(XElement value) + { Element = value; String = null; } - XamlNode(string value) { + XamlNode(string value) + { Element = null; String = value; } @@ -45,14 +50,16 @@ namespace ILSpy.BamlDecompiler { public static implicit operator string(XamlNode node) => node.String; } - internal class BamlElement { + internal class BamlElement + { public BamlNode Node { get; } public XamlNode Xaml { get; set; } public BamlElement Parent { get; set; } public IList Children { get; } - public BamlElement(BamlNode node) { + public BamlElement(BamlNode node) + { Node = node; Children = new List(); } diff --git a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs index 3e135ae2f..af79c363e 100644 --- a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs +++ b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs @@ -20,7 +20,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using SRM = System.Reflection.Metadata; using System.Threading; using System.Threading.Tasks; using System.Xml.Linq; @@ -33,9 +32,12 @@ using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpy; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; -using ILSpy.BamlDecompiler.Baml; using ICSharpCode.ILSpy.ViewModels; +using ILSpy.BamlDecompiler.Baml; + +using SRM = System.Reflection.Metadata; + namespace ILSpy.BamlDecompiler { public sealed class BamlResourceEntryNode : ResourceEntryNode @@ -43,7 +45,7 @@ namespace ILSpy.BamlDecompiler public BamlResourceEntryNode(string key, Stream data) : base(key, data) { } - + public override bool View(TabPageModel tabPage) { IHighlightingDefinition highlighting = null; @@ -53,10 +55,13 @@ namespace ILSpy.BamlDecompiler token => Task.Factory.StartNew( () => { AvalonEditTextOutput output = new AvalonEditTextOutput(); - try { + try + { if (LoadBaml(output, token)) highlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml"); - } catch (Exception ex) { + } + catch (Exception ex) + { output.Write(ex.ToString()); } return output; @@ -65,7 +70,7 @@ namespace ILSpy.BamlDecompiler .HandleExceptions()); return true; } - + bool LoadBaml(AvalonEditTextOutput output, CancellationToken cancellationToken) { var asm = this.Ancestors().OfType().FirstOrDefault().LoadedAssembly; @@ -107,43 +112,55 @@ namespace ILSpy.BamlDecompiler var referencedAssemblies = new List(); var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference)>(); var mainMetadata = mainModule.Metadata; - foreach (var h in mainMetadata.GetModuleReferences()) { + foreach (var h in mainMetadata.GetModuleReferences()) + { var moduleRef = mainMetadata.GetModuleReference(h); var moduleName = mainMetadata.GetString(moduleRef.Name); - foreach (var fileHandle in mainMetadata.AssemblyFiles) { + foreach (var fileHandle in mainMetadata.AssemblyFiles) + { var file = mainMetadata.GetAssemblyFile(fileHandle); - if (mainMetadata.StringComparer.Equals(file.Name, moduleName) && file.ContainsMetadata) { + if (mainMetadata.StringComparer.Equals(file.Name, moduleName) && file.ContainsMetadata) + { assemblyReferenceQueue.Enqueue((false, mainModule, moduleName)); break; } } } - foreach (var refs in mainModule.AssemblyReferences) { + foreach (var refs in mainModule.AssemblyReferences) + { assemblyReferenceQueue.Enqueue((true, mainModule, refs)); } - foreach (var bamlReference in defaultBamlReferences) { + foreach (var bamlReference in defaultBamlReferences) + { assemblyReferenceQueue.Enqueue((true, mainModule, AssemblyNameReference.Parse(bamlReference))); } var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) => reference.IsAssembly ? "A:" + ((IAssemblyReference)reference.Reference).FullName : "M:" + reference.Reference); var processedAssemblyReferences = new HashSet<(bool IsAssembly, PEFile Parent, object Reference)>(comparer); - while (assemblyReferenceQueue.Count > 0) { + while (assemblyReferenceQueue.Count > 0) + { var asmRef = assemblyReferenceQueue.Dequeue(); if (!processedAssemblyReferences.Add(asmRef)) continue; PEFile asm; - if (asmRef.IsAssembly) { + if (asmRef.IsAssembly) + { asm = assemblyResolver.Resolve((IAssemblyReference)asmRef.Reference); - } else { + } + else + { asm = assemblyResolver.ResolveModule(asmRef.MainModule, (string)asmRef.Reference); } - if (asm != null) { + if (asm != null) + { referencedAssemblies.Add(asm); var metadata = asm.Metadata; - foreach (var h in metadata.ExportedTypes) { + foreach (var h in metadata.ExportedTypes) + { var exportedType = metadata.GetExportedType(h); - switch (exportedType.Implementation.Kind) { + switch (exportedType.Implementation.Kind) + { case SRM.HandleKind.AssemblyReference: assemblyReferenceQueue.Enqueue((true, asm, new AssemblyReference(asm, (SRM.AssemblyReferenceHandle)exportedType.Implementation))); break; @@ -159,9 +176,12 @@ namespace ILSpy.BamlDecompiler var referencedAssembliesWithOptions = referencedAssemblies.Select(file => file.WithOptions(TypeSystemOptions.Default)); // Primitive types are necessary to avoid assertions in ILReader. // Fallback to MinimalCorlib to provide the primitive types. - if (!HasType(KnownTypeCode.Void) || !HasType(KnownTypeCode.Int32)) { + if (!HasType(KnownTypeCode.Void) || !HasType(KnownTypeCode.Int32)) + { Init(mainModule.WithOptions(TypeSystemOptions.Default), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.Instance })); - } else { + } + else + { Init(mainModuleWithOptions, referencedAssembliesWithOptions); } this.MainModule = (MetadataModule)base.MainModule; @@ -171,7 +191,8 @@ namespace ILSpy.BamlDecompiler TopLevelTypeName name = KnownTypeReference.Get(code).TypeName; if (mainModule.GetTypeDefinition(name) != null) return true; - foreach (var file in referencedAssemblies) { + foreach (var file in referencedAssemblies) + { if (file.GetTypeDefinition(name) != null) return true; } diff --git a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs index 3bdf633a2..551874112 100644 --- a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs +++ b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs @@ -20,9 +20,9 @@ using System; using System.ComponentModel.Composition; using System.IO; -using ICSharpCode.ILSpy.TreeNodes; -using ICSharpCode.ILSpy; using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.ILSpy; +using ICSharpCode.ILSpy.TreeNodes; namespace ILSpy.BamlDecompiler { @@ -33,7 +33,7 @@ namespace ILSpy.BamlDecompiler { return null; } - + public ILSpyTreeNode CreateNode(string key, object data) { if (key.EndsWith(".baml", StringComparison.OrdinalIgnoreCase) && data is Stream stream) diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/ConstructorParametersHandler.cs b/ILSpy.BamlDecompiler/Handlers/Blocks/ConstructorParametersHandler.cs index b74276ec6..d8351f253 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/ConstructorParametersHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Blocks/ConstructorParametersHandler.cs @@ -21,13 +21,17 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class ConstructorParametersStartHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class ConstructorParametersStartHandler : IHandler + { public BamlRecordType Type => BamlRecordType.ConstructorParametersStart; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var doc = new BamlElement(node); doc.Xaml = new XElement(ctx.GetPseudoName("Ctor")); parent.Xaml.Element.Add(doc.Xaml.Element); diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/DocumentHandler.cs b/ILSpy.BamlDecompiler/Handlers/Blocks/DocumentHandler.cs index 155d15037..632769a1b 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/DocumentHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Blocks/DocumentHandler.cs @@ -21,13 +21,17 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class DocumentHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class DocumentHandler : IHandler + { public BamlRecordType Type => BamlRecordType.DocumentStart; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var doc = new BamlElement(node); doc.Xaml = new XElement(ctx.GetPseudoName("Document")); diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/ElementHandler.cs b/ILSpy.BamlDecompiler/Handlers/Blocks/ElementHandler.cs index eb7f5e3c2..418fc8ba8 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/ElementHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Blocks/ElementHandler.cs @@ -21,14 +21,18 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class ElementHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class ElementHandler : IHandler + { public BamlRecordType Type => BamlRecordType.ElementStart; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (ElementStartRecord)((BamlBlockNode)node).Header; var doc = new BamlElement(node); @@ -39,7 +43,8 @@ namespace ILSpy.BamlDecompiler.Handlers { parent.Xaml.Element.Add(doc.Xaml.Element); HandlerMap.ProcessChildren(ctx, (BamlBlockNode)node, doc); - if (node.Annotation is XamlResourceKey key && key.KeyNode.Record != node.Record) { + if (node.Annotation is XamlResourceKey key && key.KeyNode.Record != node.Record) + { var handler = (IDeferHandler)HandlerMap.LookupHandler(key.KeyNode.Record.Type); var keyElem = handler.TranslateDefer(ctx, key.KeyNode, doc); diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/KeyElementStartHandler.cs b/ILSpy.BamlDecompiler/Handlers/Blocks/KeyElementStartHandler.cs index f5844bd41..68a543acb 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/KeyElementStartHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Blocks/KeyElementStartHandler.cs @@ -21,19 +21,24 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class KeyElementStartHandler : ElementHandler, IHandler, IDeferHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class KeyElementStartHandler : ElementHandler, IHandler, IDeferHandler + { BamlRecordType IHandler.Type => BamlRecordType.KeyElementStart; - BamlElement IHandler.Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + BamlElement IHandler.Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { XamlResourceKey.Create(node); return null; } - public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (KeyElementStartRecord)((BamlBlockNode)node).Header; var key = (XamlResourceKey)node.Annotation; diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyArrayHandler.cs b/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyArrayHandler.cs index 5873012d9..49dfe1af6 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyArrayHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyArrayHandler.cs @@ -21,13 +21,17 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PropertyArrayHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PropertyArrayHandler : IHandler + { public BamlRecordType Type => BamlRecordType.PropertyArrayStart; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (PropertyArrayStartRecord)((BamlBlockNode)node).Header; var doc = new BamlElement(node); diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyComplexHandler.cs b/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyComplexHandler.cs index d470da355..ecfb46114 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyComplexHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyComplexHandler.cs @@ -21,13 +21,17 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PropertyComplexHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PropertyComplexHandler : IHandler + { public BamlRecordType Type => BamlRecordType.PropertyComplexStart; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (PropertyComplexStartRecord)((BamlBlockNode)node).Header; var doc = new BamlElement(node); diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyDictionaryHandler.cs b/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyDictionaryHandler.cs index 7e4a0f5e3..e6c26c0d0 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyDictionaryHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyDictionaryHandler.cs @@ -21,13 +21,17 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PropertyDictionaryHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PropertyDictionaryHandler : IHandler + { public BamlRecordType Type => BamlRecordType.PropertyDictionaryStart; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (PropertyDictionaryStartRecord)((BamlBlockNode)node).Header; var doc = new BamlElement(node); diff --git a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyListHandler.cs b/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyListHandler.cs index 7d0a986f6..bdc7a114b 100644 --- a/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyListHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Blocks/PropertyListHandler.cs @@ -21,13 +21,17 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PropertyListHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PropertyListHandler : IHandler + { public BamlRecordType Type => BamlRecordType.PropertyListStart; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (PropertyListStartRecord)((BamlBlockNode)node).Header; var doc = new BamlElement(node); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/AssemblyInfoHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/AssemblyInfoHandler.cs index 48e39937d..a0b92cb3b 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/AssemblyInfoHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/AssemblyInfoHandler.cs @@ -22,8 +22,10 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class AssemblyInfoHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class AssemblyInfoHandler : IHandler + { public BamlRecordType Type => BamlRecordType.AssemblyInfo; public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) => null; diff --git a/ILSpy.BamlDecompiler/Handlers/Records/AttributeInfoHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/AttributeInfoHandler.cs index 0f2c4f6bc..5165648f8 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/AttributeInfoHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/AttributeInfoHandler.cs @@ -22,8 +22,10 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class AttributeInfoHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class AttributeInfoHandler : IHandler + { public BamlRecordType Type => BamlRecordType.AttributeInfo; public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) => null; diff --git a/ILSpy.BamlDecompiler/Handlers/Records/ConnectionIdHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/ConnectionIdHandler.cs index 5c2cbe751..adc3e23f4 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/ConnectionIdHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/ConnectionIdHandler.cs @@ -22,11 +22,14 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class ConnectionIdHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class ConnectionIdHandler : IHandler + { public BamlRecordType Type => BamlRecordType.ConnectionId; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (ConnectionIdRecord)((BamlRecordNode)node).Record; parent.Xaml.Element.AddAnnotation(new BamlConnectionId(record.ConnectionId)); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/ConstructorParameterTypeHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/ConstructorParameterTypeHandler.cs index 278586687..7f3a60337 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/ConstructorParameterTypeHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/ConstructorParameterTypeHandler.cs @@ -21,14 +21,18 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class ConstructorParameterTypeHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class ConstructorParameterTypeHandler : IHandler + { public BamlRecordType Type => BamlRecordType.ConstructorParameterType; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (ConstructorParameterTypeRecord)((BamlRecordNode)node).Record; var elem = new XElement(ctx.GetKnownNamespace("TypeExtension", XamlContext.KnownNamespace_Xaml, parent.Xaml)); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/ContentPropertyHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/ContentPropertyHandler.cs index 2705ac8d0..5d2cb13aa 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/ContentPropertyHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/ContentPropertyHandler.cs @@ -22,11 +22,14 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class ContentPropertyHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class ContentPropertyHandler : IHandler + { public BamlRecordType Type => BamlRecordType.ContentProperty; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (ContentPropertyRecord)((BamlRecordNode)node).Record; // TODO: What to do here? diff --git a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeHandler.cs index 8b141d002..fe54cd63b 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeHandler.cs @@ -21,13 +21,17 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class DefAttributeHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class DefAttributeHandler : IHandler + { public BamlRecordType Type => BamlRecordType.DefAttribute; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (DefAttributeRecord)((BamlRecordNode)node).Record; var attrName = ctx.ResolveString(record.NameId); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyStringHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyStringHandler.cs index 0068ba4ac..8cae7decc 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyStringHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyStringHandler.cs @@ -21,19 +21,24 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class DefAttributeStringHandler : IHandler, IDeferHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class DefAttributeStringHandler : IHandler, IDeferHandler + { public BamlRecordType Type => BamlRecordType.DefAttributeKeyString; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { XamlResourceKey.Create(node); return null; } - public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (DefAttributeKeyStringRecord)((BamlRecordNode)node).Record; var key = (XamlResourceKey)node.Annotation; diff --git a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyTypeHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyTypeHandler.cs index 8b6080248..5bd50e9f6 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyTypeHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/DefAttributeKeyTypeHandler.cs @@ -21,19 +21,24 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class DefAttributeTypeHandler : IHandler, IDeferHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class DefAttributeTypeHandler : IHandler, IDeferHandler + { public BamlRecordType Type => BamlRecordType.DefAttributeKeyType; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { XamlResourceKey.Create(node); return null; } - public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (DefAttributeKeyTypeRecord)((BamlRecordNode)node).Record; var type = ctx.ResolveType(record.TypeId); var typeName = ctx.ToString(parent.Xaml, type); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/DeferableContentStartHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/DeferableContentStartHandler.cs index 32af2c33c..98a695e16 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/DeferableContentStartHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/DeferableContentStartHandler.cs @@ -21,13 +21,17 @@ */ using System.Diagnostics; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class DeferableContentStartHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class DeferableContentStartHandler : IHandler + { public BamlRecordType Type => BamlRecordType.DeferableContentStart; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (DeferableContentStartRecord)((BamlRecordNode)node).Record; Debug.Assert(record.Record == ((BamlBlockNode)parent.Node).Footer); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/LineNumberAndPositionHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/LineNumberAndPositionHandler.cs index 0796a88ed..ea7d68e5f 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/LineNumberAndPositionHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/LineNumberAndPositionHandler.cs @@ -22,8 +22,10 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class LineNumberAndPositionHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class LineNumberAndPositionHandler : IHandler + { public BamlRecordType Type => BamlRecordType.LineNumberAndPosition; public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) => null; diff --git a/ILSpy.BamlDecompiler/Handlers/Records/LinePositionHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/LinePositionHandler.cs index 16b339001..25655e218 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/LinePositionHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/LinePositionHandler.cs @@ -22,8 +22,10 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class LinePositionHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class LinePositionHandler : IHandler + { public BamlRecordType Type => BamlRecordType.LinePosition; public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) => null; diff --git a/ILSpy.BamlDecompiler/Handlers/Records/LiteralContentHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/LiteralContentHandler.cs index ab36554b4..432aa68c4 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/LiteralContentHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/LiteralContentHandler.cs @@ -21,13 +21,17 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class LiteralContentHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class LiteralContentHandler : IHandler + { public BamlRecordType Type => BamlRecordType.LiteralContent; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (LiteralContentRecord)((BamlRecordNode)node).Record; var elem = new XElement(ctx.GetKnownNamespace("XData", XamlContext.KnownNamespace_Xaml, parent.Xaml)); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs index 463acedc2..85b275966 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/OptimizedStaticResourceHandler.cs @@ -21,14 +21,18 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class OptimizedStaticResourceHandler : IHandler, IDeferHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class OptimizedStaticResourceHandler : IHandler, IDeferHandler + { public BamlRecordType Type => BamlRecordType.OptimizedStaticResource; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (OptimizedStaticResourceRecord)((BamlRecordNode)node).Record; var key = XamlResourceKey.FindKeyInSiblings(node); @@ -36,11 +40,13 @@ namespace ILSpy.BamlDecompiler.Handlers { return null; } - public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (OptimizedStaticResourceRecord)((BamlRecordNode)node).Record; var bamlElem = new BamlElement(node); object key; - if (record.IsType) { + if (record.IsType) + { var value = ctx.ResolveType(record.ValueId); var typeElem = new XElement(ctx.GetKnownNamespace("TypeExtension", XamlContext.KnownNamespace_Xaml, parent.Xaml)); @@ -48,19 +54,24 @@ namespace ILSpy.BamlDecompiler.Handlers { typeElem.Add(new XElement(ctx.GetPseudoName("Ctor"), ctx.ToString(parent.Xaml, value))); key = typeElem; } - else if (record.IsStatic) { + else if (record.IsStatic) + { string attrName; - if (record.ValueId > 0x7fff) { + if (record.ValueId > 0x7fff) + { bool isKey = true; short bamlId = unchecked((short)-record.ValueId); - if (bamlId > 232 && bamlId < 464) { + if (bamlId > 232 && bamlId < 464) + { bamlId -= 232; isKey = false; } - else if (bamlId > 464 && bamlId < 467) { + else if (bamlId > 464 && bamlId < 467) + { bamlId -= 231; } - else if (bamlId > 467 && bamlId < 470) { + else if (bamlId > 467 && bamlId < 470) + { bamlId -= 234; isKey = false; } @@ -73,7 +84,8 @@ namespace ILSpy.BamlDecompiler.Handlers { var xmlns = ctx.GetXmlNamespace("http://schemas.microsoft.com/winfx/2006/xaml/presentation"); attrName = ctx.ToString(parent.Xaml, xmlns.GetName(name)); } - else { + else + { var value = ctx.ResolveProperty(record.ValueId); value.DeclaringType.ResolveNamespace(parent.Xaml, ctx); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PIMappingHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/PIMappingHandler.cs index 919277ddb..86e12f576 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PIMappingHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/PIMappingHandler.cs @@ -22,8 +22,10 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PIMappingHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PIMappingHandler : IHandler + { public BamlRecordType Type => BamlRecordType.PIMapping; public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) => null; diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PresentationOptionsAttributeHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/PresentationOptionsAttributeHandler.cs index e0f3f728a..849f0a91b 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PresentationOptionsAttributeHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/PresentationOptionsAttributeHandler.cs @@ -21,13 +21,17 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PresentationOptionsAttributeHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PresentationOptionsAttributeHandler : IHandler + { public BamlRecordType Type => BamlRecordType.PresentationOptionsAttribute; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (PresentationOptionsAttributeRecord)((BamlRecordNode)node).Record; var attrName = ctx.ResolveString(record.NameId); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyCustomHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/PropertyCustomHandler.cs index 7c0d92d8c..aca9bfd8e 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyCustomHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/PropertyCustomHandler.cs @@ -26,14 +26,18 @@ using System.Globalization; using System.IO; using System.Text; using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PropertyCustomHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PropertyCustomHandler : IHandler + { public BamlRecordType Type => BamlRecordType.PropertyCustom; - enum IntegerCollectionType : byte { + enum IntegerCollectionType : byte + { Unknown, Consecutive, U1, @@ -41,15 +45,21 @@ namespace ILSpy.BamlDecompiler.Handlers { I4 } - string Deserialize(XamlContext ctx, XElement elem, KnownTypes ser, byte[] value) { - using (BinaryReader reader = new BinaryReader(new MemoryStream(value))) { - switch (ser) { - case KnownTypes.DependencyPropertyConverter: { - if (value.Length == 2) { + string Deserialize(XamlContext ctx, XElement elem, KnownTypes ser, byte[] value) + { + using (BinaryReader reader = new BinaryReader(new MemoryStream(value))) + { + switch (ser) + { + case KnownTypes.DependencyPropertyConverter: + { + if (value.Length == 2) + { var property = ctx.ResolveProperty(reader.ReadUInt16()); return ctx.ToString(elem, property.ToXName(ctx, elem, NeedsFullName(property, ctx, elem))); } - else { + else + { var type = ctx.ResolveType(reader.ReadUInt16()); var name = reader.ReadString(); var typeName = ctx.ToString(elem, type); @@ -57,19 +67,23 @@ namespace ILSpy.BamlDecompiler.Handlers { } } - case KnownTypes.EnumConverter: { + case KnownTypes.EnumConverter: + { uint enumVal = reader.ReadUInt32(); // TODO: Convert to enum names return enumVal.ToString("D", CultureInfo.InvariantCulture); } - case KnownTypes.BooleanConverter: { + case KnownTypes.BooleanConverter: + { Debug.Assert(value.Length == 1); return (reader.ReadByte() == 1).ToString(CultureInfo.InvariantCulture); } - case KnownTypes.XamlBrushSerializer: { - switch (reader.ReadByte()) { + case KnownTypes.XamlBrushSerializer: + { + switch (reader.ReadByte()) + { case 1: // KnownSolidColor return string.Format(CultureInfo.InvariantCulture, "#{0:X8}", reader.ReadUInt32()); case 2: // OtherColor @@ -82,10 +96,12 @@ namespace ILSpy.BamlDecompiler.Handlers { return XamlPathDeserializer.Deserialize(reader); case KnownTypes.XamlPoint3DCollectionSerializer: - case KnownTypes.XamlVector3DCollectionSerializer: { + case KnownTypes.XamlVector3DCollectionSerializer: + { var sb = new StringBuilder(); var count = reader.ReadUInt32(); - for (uint i = 0; i < count; i++) { + for (uint i = 0; i < count; i++) + { sb.AppendFormat(CultureInfo.InvariantCulture, "{0:R},{1:R},{2:R} ", reader.ReadXamlDouble(), reader.ReadXamlDouble(), @@ -94,10 +110,12 @@ namespace ILSpy.BamlDecompiler.Handlers { return sb.ToString().Trim(); } - case KnownTypes.XamlPointCollectionSerializer: { + case KnownTypes.XamlPointCollectionSerializer: + { var sb = new StringBuilder(); var count = reader.ReadUInt32(); - for (uint i = 0; i < count; i++) { + for (uint i = 0; i < count; i++) + { sb.AppendFormat(CultureInfo.InvariantCulture, "{0:R},{1:R} ", reader.ReadXamlDouble(), reader.ReadXamlDouble()); @@ -105,33 +123,39 @@ namespace ILSpy.BamlDecompiler.Handlers { return sb.ToString().Trim(); } - case KnownTypes.XamlInt32CollectionSerializer: { + case KnownTypes.XamlInt32CollectionSerializer: + { var sb = new StringBuilder(); var type = (IntegerCollectionType)reader.ReadByte(); var count = reader.ReadInt32(); - switch (type) { - case IntegerCollectionType.Consecutive: { + switch (type) + { + case IntegerCollectionType.Consecutive: + { var start = reader.ReadInt32(); for (int i = 0; i < count; i++) sb.AppendFormat(CultureInfo.InvariantCulture, "{0:D}", start + i); } - break; - case IntegerCollectionType.U1: { + break; + case IntegerCollectionType.U1: + { for (int i = 0; i < count; i++) sb.AppendFormat(CultureInfo.InvariantCulture, "{0:D}", reader.ReadByte()); } - break; - case IntegerCollectionType.U2: { + break; + case IntegerCollectionType.U2: + { for (int i = 0; i < count; i++) sb.AppendFormat(CultureInfo.InvariantCulture, "{0:D}", reader.ReadUInt16()); } - break; - case IntegerCollectionType.I4: { + break; + case IntegerCollectionType.I4: + { for (int i = 0; i < count; i++) sb.AppendFormat(CultureInfo.InvariantCulture, "{0:D}", reader.ReadInt32()); } - break; + break; default: throw new NotSupportedException(type.ToString()); } @@ -145,7 +169,8 @@ namespace ILSpy.BamlDecompiler.Handlers { private bool NeedsFullName(XamlProperty property, XamlContext ctx, XElement elem) { XElement p = elem.Parent; - while (p != null && p.Annotation()?.ResolvedType.FullName != "System.Windows.Style") { + while (p != null && p.Annotation()?.ResolvedType.FullName != "System.Windows.Style") + { p = p.Parent; } var type = p?.Annotation()?.Type; @@ -154,7 +179,8 @@ namespace ILSpy.BamlDecompiler.Handlers { return property.IsAttachedTo(type); } - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (PropertyCustomRecord)((BamlRecordNode)node).Record; var serTypeId = ((short)record.SerializerTypeId & 0xfff); bool valueType = ((short)record.SerializerTypeId & 0x4000) == 0x4000; diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/PropertyHandler.cs index 822fc0627..25494ab66 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/PropertyHandler.cs @@ -21,14 +21,18 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PropertyHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PropertyHandler : IHandler + { public virtual BamlRecordType Type => BamlRecordType.Property; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (PropertyRecord)((BamlRecordNode)node).Record; var elemType = parent.Xaml.Element.Annotation(); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyTypeReferenceHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/PropertyTypeReferenceHandler.cs index 148ded0e2..51d5b8ae4 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyTypeReferenceHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/PropertyTypeReferenceHandler.cs @@ -21,15 +21,20 @@ */ using System.Xml.Linq; + +using ICSharpCode.Decompiler.TypeSystem; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PropertyTypeReferenceHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PropertyTypeReferenceHandler : IHandler + { public BamlRecordType Type => BamlRecordType.PropertyTypeReference; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (PropertyTypeReferenceRecord)((BamlRecordNode)node).Record; var attr = ctx.ResolveProperty(record.AttributeId); var type = ctx.ResolveType(record.TypeId); @@ -40,7 +45,8 @@ namespace ILSpy.BamlDecompiler.Handlers { var elemAttr = ctx.ResolveProperty(record.AttributeId); elem.Xaml = new XElement(elemAttr.ToXName(ctx, null)); - if (attr.ResolvedMember?.FullNameIs("System.Windows.Style", "TargetType") == true) { + if (attr.ResolvedMember?.FullNameIs("System.Windows.Style", "TargetType") == true) + { parent.Xaml.Element.AddAnnotation(new TargetTypeAnnotation(type)); } diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithConverterHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithConverterHandler.cs index 117e64445..ca171f403 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithConverterHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithConverterHandler.cs @@ -22,8 +22,10 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PropertyWithConverterHandler : PropertyHandler, IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PropertyWithConverterHandler : PropertyHandler, IHandler + { BamlRecordType IHandler.Type => BamlRecordType.PropertyWithConverter; } } \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs index 9b487b9de..c7fe61ca5 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithExtensionHandler.cs @@ -21,14 +21,18 @@ */ using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PropertyWithExtensionHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PropertyWithExtensionHandler : IHandler + { public BamlRecordType Type => BamlRecordType.PropertyWithExtension; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (PropertyWithExtensionRecord)((BamlRecordNode)node).Record; var extTypeId = ((short)record.Flags & 0xfff); bool valTypeExt = ((short)record.Flags & 0x4000) == 0x4000; @@ -40,11 +44,13 @@ namespace ILSpy.BamlDecompiler.Handlers { extType.ResolveNamespace(parent.Xaml, ctx); var ext = new XamlExtension(extType); - if (valTypeExt || extTypeId == (short)KnownTypes.TypeExtension) { + if (valTypeExt || extTypeId == (short)KnownTypes.TypeExtension) + { var value = ctx.ResolveType(record.ValueId); ext.Initializer = new object[] { ctx.ToString(parent.Xaml, value) }; } - else if (extTypeId == (short)KnownTypes.TemplateBindingExtension) { + else if (extTypeId == (short)KnownTypes.TemplateBindingExtension) + { var value = ctx.ResolveProperty(record.ValueId); value.DeclaringType.ResolveNamespace(parent.Xaml, ctx); @@ -52,19 +58,24 @@ namespace ILSpy.BamlDecompiler.Handlers { ext.Initializer = new object[] { ctx.ToString(parent.Xaml, xName) }; } - else if (valStaticExt || extTypeId == (short)KnownTypes.StaticExtension) { + else if (valStaticExt || extTypeId == (short)KnownTypes.StaticExtension) + { string attrName; - if (record.ValueId > 0x7fff) { + if (record.ValueId > 0x7fff) + { bool isKey = true; short bamlId = unchecked((short)-record.ValueId); - if (bamlId > 232 && bamlId < 464) { + if (bamlId > 232 && bamlId < 464) + { bamlId -= 232; isKey = false; } - else if (bamlId > 464 && bamlId < 467) { + else if (bamlId > 464 && bamlId < 467) + { bamlId -= 231; } - else if (bamlId > 467 && bamlId < 470) { + else if (bamlId > 467 && bamlId < 470) + { bamlId -= 234; isKey = false; } @@ -77,7 +88,8 @@ namespace ILSpy.BamlDecompiler.Handlers { var xmlns = ctx.GetXmlNamespace("http://schemas.microsoft.com/winfx/2006/xaml/presentation"); attrName = ctx.ToString(parent.Xaml, xmlns.GetName(name)); } - else { + else + { var value = ctx.ResolveProperty(record.ValueId); value.DeclaringType.ResolveNamespace(parent.Xaml, ctx); @@ -87,7 +99,8 @@ namespace ILSpy.BamlDecompiler.Handlers { } ext.Initializer = new object[] { attrName }; } - else { + else + { ext.Initializer = new object[] { XamlUtils.Escape(ctx.ResolveString(record.ValueId)) }; } diff --git a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithStaticResourceIdHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithStaticResourceIdHandler.cs index 573118a06..627ec1c8f 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithStaticResourceIdHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/PropertyWithStaticResourceIdHandler.cs @@ -22,14 +22,18 @@ using System; using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class PropertyWithStaticResourceIdHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class PropertyWithStaticResourceIdHandler : IHandler + { public BamlRecordType Type => BamlRecordType.PropertyWithStaticResourceId; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (PropertyWithStaticResourceIdRecord)((BamlRecordNode)node).Record; var doc = new BamlElement(node); @@ -41,7 +45,8 @@ namespace ILSpy.BamlDecompiler.Handlers { BamlNode found = node; XamlResourceKey key; - do { + do + { key = XamlResourceKey.FindKeyInAncestors(found.Parent, out found); } while (key != null && record.StaticResourceId >= key.StaticResources.Count); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceIdHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceIdHandler.cs index c52dcc771..94e4fc614 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceIdHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceIdHandler.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; @@ -32,7 +33,8 @@ namespace ILSpy.BamlDecompiler.Handlers BamlNode found = node; XamlResourceKey key; - do { + do + { key = XamlResourceKey.FindKeyInAncestors(found.Parent, out found); } while (key != null && record.StaticResourceId >= key.StaticResources.Count); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceStartHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceStartHandler.cs index ad627f3de..302839a9b 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceStartHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/StaticResourceStartHandler.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; diff --git a/ILSpy.BamlDecompiler/Handlers/Records/TextHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/TextHandler.cs index 95cf3c3f7..72843f024 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/TextHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/TextHandler.cs @@ -22,11 +22,14 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class TextHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class TextHandler : IHandler + { public BamlRecordType Type => BamlRecordType.Text; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (TextRecord)((BamlRecordNode)node).Record; parent.Xaml.Element.Add(record.Value); @@ -35,10 +38,12 @@ namespace ILSpy.BamlDecompiler.Handlers { } } - internal class TextWithIdHandler : IHandler { + internal class TextWithIdHandler : IHandler + { public BamlRecordType Type => BamlRecordType.TextWithId; - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (TextWithIdRecord)((BamlRecordNode)node).Record; parent.Xaml.Element.Add(ctx.ResolveString(record.ValueId)); diff --git a/ILSpy.BamlDecompiler/Handlers/Records/TextWithConverterHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/TextWithConverterHandler.cs index e54ed439f..41c34850f 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/TextWithConverterHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/TextWithConverterHandler.cs @@ -22,8 +22,10 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class TextWithConverterHandler : TextHandler, IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class TextWithConverterHandler : TextHandler, IHandler + { BamlRecordType IHandler.Type => BamlRecordType.TextWithConverter; } } \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Handlers/Records/TypeInfoHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/TypeInfoHandler.cs index 219500bf2..90bbb776f 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/TypeInfoHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/TypeInfoHandler.cs @@ -22,14 +22,17 @@ using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class TypeInfoHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class TypeInfoHandler : IHandler + { public BamlRecordType Type => BamlRecordType.TypeInfo; public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) => null; } - internal class TypeSerializerInfoHandler : IHandler { + internal class TypeSerializerInfoHandler : IHandler + { public BamlRecordType Type => BamlRecordType.TypeSerializerInfo; public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) => null; diff --git a/ILSpy.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs b/ILSpy.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs index c66656ba5..777327fcf 100644 --- a/ILSpy.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs +++ b/ILSpy.BamlDecompiler/Handlers/Records/XmlnsPropertyHandler.cs @@ -25,16 +25,22 @@ using System.Diagnostics; using System.Linq; using System.Xml; using System.Xml.Linq; + using ICSharpCode.Decompiler.TypeSystem; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Handlers { - internal class XmlnsPropertyHandler : IHandler { +namespace ILSpy.BamlDecompiler.Handlers +{ + internal class XmlnsPropertyHandler : IHandler + { public BamlRecordType Type => BamlRecordType.XmlnsProperty; - IEnumerable ResolveCLRNamespaces(IModule assembly, string ns) { - foreach (var attr in assembly.GetAssemblyAttributes().Where(a => a.AttributeType.FullName == "System.Windows.Markup.XmlnsDefinitionAttribute")) { + IEnumerable ResolveCLRNamespaces(IModule assembly, string ns) + { + foreach (var attr in assembly.GetAssemblyAttributes().Where(a => a.AttributeType.FullName == "System.Windows.Markup.XmlnsDefinitionAttribute")) + { Debug.Assert(attr.FixedArguments.Length == 2); var xmlNs = attr.FixedArguments[0].Value; @@ -46,13 +52,16 @@ namespace ILSpy.BamlDecompiler.Handlers { } } - public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) { + public BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent) + { var record = (XmlnsPropertyRecord)((BamlRecordNode)node).Record; - foreach (var asmId in record.AssemblyIds) { + foreach (var asmId in record.AssemblyIds) + { var assembly = ctx.Baml.ResolveAssembly(asmId); ctx.XmlNs.Add(new NamespaceMap(record.Prefix, assembly.FullAssemblyName, record.XmlNamespace)); - if (assembly.Assembly?.IsMainModule == true) { + if (assembly.Assembly?.IsMainModule == true) + { foreach (var clrNs in ResolveCLRNamespaces(assembly.Assembly, record.XmlNamespace)) ctx.XmlNs.Add(new NamespaceMap(record.Prefix, assembly.FullAssemblyName, record.XmlNamespace, clrNs)); } diff --git a/ILSpy.BamlDecompiler/IHandlers.cs b/ILSpy.BamlDecompiler/IHandlers.cs index 243448653..27db2853e 100644 --- a/ILSpy.BamlDecompiler/IHandlers.cs +++ b/ILSpy.BamlDecompiler/IHandlers.cs @@ -23,36 +23,46 @@ using System; using System.Collections.Generic; using System.Diagnostics; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler { - internal interface IHandler { +namespace ILSpy.BamlDecompiler +{ + internal interface IHandler + { BamlRecordType Type { get; } BamlElement Translate(XamlContext ctx, BamlNode node, BamlElement parent); } - internal interface IDeferHandler { + internal interface IDeferHandler + { BamlElement TranslateDefer(XamlContext ctx, BamlNode node, BamlElement parent); } - internal static class HandlerMap { + internal static class HandlerMap + { static readonly Dictionary handlers; - static HandlerMap() { + static HandlerMap() + { handlers = new Dictionary(); - foreach (var type in typeof(IHandler).Assembly.GetTypes()) { + foreach (var type in typeof(IHandler).Assembly.GetTypes()) + { if (typeof(IHandler).IsAssignableFrom(type) && - !type.IsInterface && !type.IsAbstract) { + !type.IsInterface && !type.IsAbstract) + { var handler = (IHandler)Activator.CreateInstance(type); handlers.Add(handler.Type, handler); } } } - public static IHandler LookupHandler(BamlRecordType type) { + public static IHandler LookupHandler(BamlRecordType type) + { #if DEBUG - switch (type) { + switch (type) + { case BamlRecordType.AssemblyInfo: case BamlRecordType.TypeInfo: case BamlRecordType.AttributeInfo: @@ -67,18 +77,22 @@ namespace ILSpy.BamlDecompiler { return handlers.ContainsKey(type) ? handlers[type] : null; } - public static void ProcessChildren(XamlContext ctx, BamlBlockNode node, BamlElement nodeElem) { + public static void ProcessChildren(XamlContext ctx, BamlBlockNode node, BamlElement nodeElem) + { ctx.XmlNs.PushScope(nodeElem); if (nodeElem.Xaml.Element != null) nodeElem.Xaml.Element.AddAnnotation(ctx.XmlNs.CurrentScope); - foreach (var child in node.Children) { + foreach (var child in node.Children) + { var handler = LookupHandler(child.Type); - if (handler == null) { + if (handler == null) + { Debug.WriteLine("BAML Handler {0} not implemented.", child.Type); continue; } var elem = handler.Translate(ctx, (BamlNode)child, nodeElem); - if (elem != null) { + if (elem != null) + { nodeElem.Children.Add(elem); elem.Parent = nodeElem; } diff --git a/ILSpy.BamlDecompiler/IRewritePass.cs b/ILSpy.BamlDecompiler/IRewritePass.cs index 082f09dff..a139dd4b2 100644 --- a/ILSpy.BamlDecompiler/IRewritePass.cs +++ b/ILSpy.BamlDecompiler/IRewritePass.cs @@ -22,8 +22,10 @@ using System.Xml.Linq; -namespace ILSpy.BamlDecompiler { - internal interface IRewritePass { +namespace ILSpy.BamlDecompiler +{ + internal interface IRewritePass + { void Run(XamlContext ctx, XDocument document); } } \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs b/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs index 248266b94..537d10e6b 100644 --- a/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs +++ b/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs @@ -1,8 +1,8 @@ #region Using directives using System.Reflection; -using System.Runtime.InteropServices; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; #endregion diff --git a/ILSpy.BamlDecompiler/Rewrite/AttributeRewritePass.cs b/ILSpy.BamlDecompiler/Rewrite/AttributeRewritePass.cs index a8c5ac22b..06139367e 100644 --- a/ILSpy.BamlDecompiler/Rewrite/AttributeRewritePass.cs +++ b/ILSpy.BamlDecompiler/Rewrite/AttributeRewritePass.cs @@ -22,34 +22,43 @@ using System.Collections.Generic; using System.Xml.Linq; + using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Rewrite { - internal class AttributeRewritePass : IRewritePass { +namespace ILSpy.BamlDecompiler.Rewrite +{ + internal class AttributeRewritePass : IRewritePass + { XName key; - public void Run(XamlContext ctx, XDocument document) { + public void Run(XamlContext ctx, XDocument document) + { key = ctx.GetKnownNamespace("Key", XamlContext.KnownNamespace_Xaml); bool doWork; - do { + do + { doWork = false; - foreach (var elem in document.Elements()) { + foreach (var elem in document.Elements()) + { doWork |= ProcessElement(ctx, elem); } } while (doWork); } - bool ProcessElement(XamlContext ctx, XElement elem) { + bool ProcessElement(XamlContext ctx, XElement elem) + { bool doWork = false; - foreach (var child in elem.Elements()) { + foreach (var child in elem.Elements()) + { doWork |= RewriteElement(ctx, elem, child); doWork |= ProcessElement(ctx, child); } return doWork; } - bool RewriteElement(XamlContext ctx, XElement parent, XElement elem) { + bool RewriteElement(XamlContext ctx, XElement parent, XElement elem) + { var property = elem.Annotation(); if (property == null && elem.Name != key) return false; diff --git a/ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs b/ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs index e403a18b7..26c088e85 100644 --- a/ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs +++ b/ILSpy.BamlDecompiler/Rewrite/ConnectionIdRewritePass.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; using System.Xml.Linq; + using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.Transforms; @@ -46,10 +47,13 @@ namespace ILSpy.BamlDecompiler.Rewrite foreach (var child in element.Elements()) ProcessConnectionIds(child, eventMappings); - foreach (var annotation in element.Annotations()) { + foreach (var annotation in element.Annotations()) + { int index; - if ((index = eventMappings.FindIndex(item => item.key.Contains(annotation.Id))) > -1) { - foreach (var entry in eventMappings[index].value) { + if ((index = eventMappings.FindIndex(item => item.key.Contains(annotation.Id))) > -1) + { + foreach (var entry in eventMappings[index].value) + { string xmlns = ""; // TODO : implement xmlns resolver! element.Add(new XAttribute(xmlns + entry.EventName, entry.MethodName)); } @@ -78,8 +82,10 @@ namespace ILSpy.BamlDecompiler.Rewrite MethodDefinition metadataEntry = default; var module = ctx.TypeSystem.MainModule.PEFile; - foreach (IMethod m in type.Methods) { - if (m.ExplicitlyImplementedInterfaceMembers.Any(md => md.MemberDefinition.Equals(connect))) { + foreach (IMethod m in type.Methods) + { + if (m.ExplicitlyImplementedInterfaceMembers.Any(md => md.MemberDefinition.Equals(connect))) + { method = m; metadataEntry = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); break; @@ -106,13 +112,18 @@ namespace ILSpy.BamlDecompiler.Rewrite var block = function.Body.Children.OfType().First(); var ilSwitch = block.Descendants.OfType().FirstOrDefault(); - if (ilSwitch != null) { - foreach (var section in ilSwitch.Sections) { + if (ilSwitch != null) + { + foreach (var section in ilSwitch.Sections) + { var events = FindEvents(section.Body); result.Add((section.Labels, events)); } - } else { - foreach (var ifInst in function.Descendants.OfType()) { + } + else + { + foreach (var ifInst in function.Descendants.OfType()) + { if (!(ifInst.Condition is Comp comp)) continue; if (comp.Kind != ComparisonKind.Inequality && comp.Kind != ComparisonKind.Equality) @@ -130,9 +141,11 @@ namespace ILSpy.BamlDecompiler.Rewrite { var events = new List(); - switch (inst) { + switch (inst) + { case Block _: - foreach (var node in ((Block)inst).Instructions) { + foreach (var node in ((Block)inst).Instructions) + { FindEvents(node, events); } FindEvents(((Block)inst).FinalInstruction, events); @@ -161,7 +174,8 @@ namespace ILSpy.BamlDecompiler.Rewrite eventName = ""; handlerName = ""; - if (call.Arguments.Count == 3) { + if (call.Arguments.Count == 3) + { var addMethod = call.Method; if (addMethod.Name != "AddHandler" || addMethod.Parameters.Count != 2) return false; @@ -188,7 +202,8 @@ namespace ILSpy.BamlDecompiler.Rewrite eventName = ""; handlerName = ""; - if (call.Arguments.Count == 2) { + if (call.Arguments.Count == 2) + { var addMethod = call.Method; if (!addMethod.Name.StartsWith("add_", StringComparison.Ordinal) || addMethod.Parameters.Count != 1) return false; diff --git a/ILSpy.BamlDecompiler/Rewrite/DocumentRewritePass.cs b/ILSpy.BamlDecompiler/Rewrite/DocumentRewritePass.cs index db5a00eb5..80849609b 100644 --- a/ILSpy.BamlDecompiler/Rewrite/DocumentRewritePass.cs +++ b/ILSpy.BamlDecompiler/Rewrite/DocumentRewritePass.cs @@ -24,15 +24,20 @@ using System.Diagnostics; using System.Linq; using System.Xml.Linq; -namespace ILSpy.BamlDecompiler.Rewrite { - internal class DocumentRewritePass : IRewritePass { - public void Run(XamlContext ctx, XDocument document) { - foreach (var elem in document.Elements(ctx.GetPseudoName("Document")).ToList()) { +namespace ILSpy.BamlDecompiler.Rewrite +{ + internal class DocumentRewritePass : IRewritePass + { + public void Run(XamlContext ctx, XDocument document) + { + foreach (var elem in document.Elements(ctx.GetPseudoName("Document")).ToList()) + { if (elem.Elements().Count() != 1) continue; var docElem = elem.Elements().Single(); - foreach (var attr in elem.Attributes()) { + foreach (var attr in elem.Attributes()) + { Debug.Assert(attr.IsNamespaceDeclaration); attr.Remove(); docElem.Add(attr); diff --git a/ILSpy.BamlDecompiler/Rewrite/MarkupExtensionRewritePass.cs b/ILSpy.BamlDecompiler/Rewrite/MarkupExtensionRewritePass.cs index bd2bf8e31..492646eb2 100644 --- a/ILSpy.BamlDecompiler/Rewrite/MarkupExtensionRewritePass.cs +++ b/ILSpy.BamlDecompiler/Rewrite/MarkupExtensionRewritePass.cs @@ -23,36 +23,45 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; + using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Rewrite { - internal class MarkupExtensionRewritePass : IRewritePass { +namespace ILSpy.BamlDecompiler.Rewrite +{ + internal class MarkupExtensionRewritePass : IRewritePass + { XName key; XName ctor; - public void Run(XamlContext ctx, XDocument document) { + public void Run(XamlContext ctx, XDocument document) + { key = ctx.GetKnownNamespace("Key", XamlContext.KnownNamespace_Xaml); ctor = ctx.GetPseudoName("Ctor"); bool doWork; - do { + do + { doWork = false; - foreach (var elem in document.Elements()) { + foreach (var elem in document.Elements()) + { doWork |= ProcessElement(ctx, elem); } } while (doWork); } - bool ProcessElement(XamlContext ctx, XElement elem) { + bool ProcessElement(XamlContext ctx, XElement elem) + { bool doWork = false; - foreach (var child in elem.Elements()) { + foreach (var child in elem.Elements()) + { doWork |= RewriteElement(ctx, elem, child); doWork |= ProcessElement(ctx, child); } return doWork; } - bool RewriteElement(XamlContext ctx, XElement parent, XElement elem) { + bool RewriteElement(XamlContext ctx, XElement parent, XElement elem) + { var type = parent.Annotation(); var property = elem.Annotation(); if ((property == null || type == null) && elem.Name != key) @@ -77,7 +86,8 @@ namespace ILSpy.BamlDecompiler.Rewrite { var attrName = elem.Name; if (attrName != key) attrName = property.ToXName(ctx, parent, property.IsAttachedTo(type)); - if (!parent.Attributes(attrName).Any()) { + if (!parent.Attributes(attrName).Any()) + { var attr = new XAttribute(attrName, extValue); var list = new List(parent.Attributes()); if (attrName == key) @@ -92,13 +102,17 @@ namespace ILSpy.BamlDecompiler.Rewrite { return true; } - bool CanInlineExt(XamlContext ctx, XElement ctxElement) { + bool CanInlineExt(XamlContext ctx, XElement ctxElement) + { var type = ctxElement.Annotation(); - if (type != null && type.ResolvedType != null) { + if (type != null && type.ResolvedType != null) + { var typeDef = type.ResolvedType.GetDefinition()?.DirectBaseTypes.FirstOrDefault(); bool isExt = false; - while (typeDef != null) { - if (typeDef.FullName == "System.Windows.Markup.MarkupExtension") { + while (typeDef != null) + { + if (typeDef.FullName == "System.Windows.Markup.MarkupExtension") + { isExt = true; break; } @@ -108,17 +122,19 @@ namespace ILSpy.BamlDecompiler.Rewrite { return false; } else if (ctxElement.Annotation() == null && - ctxElement.Name != ctor) + ctxElement.Name != ctor) return false; - foreach (var child in ctxElement.Elements()) { + foreach (var child in ctxElement.Elements()) + { if (!CanInlineExt(ctx, child)) return false; } return true; } - object InlineObject(XamlContext ctx, XNode obj) { + object InlineObject(XamlContext ctx, XNode obj) + { if (obj is XText) return ((XText)obj).Value; else if (obj is XElement) @@ -127,11 +143,13 @@ namespace ILSpy.BamlDecompiler.Rewrite { return null; } - object[] InlineCtor(XamlContext ctx, XElement ctor) { + object[] InlineCtor(XamlContext ctx, XElement ctor) + { if (ctor.HasAttributes) return null; var args = new List(); - foreach (var child in ctor.Nodes()) { + foreach (var child in ctor.Nodes()) + { var arg = InlineObject(ctx, child); if (arg == null) return null; @@ -140,7 +158,8 @@ namespace ILSpy.BamlDecompiler.Rewrite { return args.ToArray(); } - XamlExtension InlineExtension(XamlContext ctx, XElement ctxElement) { + XamlExtension InlineExtension(XamlContext ctx, XElement ctxElement) + { var type = ctxElement.Annotation(); if (type == null) return null; @@ -150,12 +169,14 @@ namespace ILSpy.BamlDecompiler.Rewrite { foreach (var attr in ctxElement.Attributes().Where(attr => attr.Name.Namespace != XNamespace.Xmlns)) ext.NamedArguments[attr.Name.LocalName] = attr.Value; - foreach (var child in ctxElement.Nodes()) { + foreach (var child in ctxElement.Nodes()) + { var elem = child as XElement; if (elem == null) return null; - if (elem.Name == ctor) { + if (elem.Name == ctor) + { if (ext.Initializer != null) return null; @@ -169,7 +190,7 @@ namespace ILSpy.BamlDecompiler.Rewrite { var property = elem.Annotation(); if (property == null || elem.Nodes().Count() != 1 || - elem.Attributes().Any(attr => attr.Name.Namespace != XNamespace.Xmlns)) + elem.Attributes().Any(attr => attr.Name.Namespace != XNamespace.Xmlns)) return null; var name = property.PropertyName; diff --git a/ILSpy.BamlDecompiler/Rewrite/XClassRewritePass.cs b/ILSpy.BamlDecompiler/Rewrite/XClassRewritePass.cs index 2e2d25e59..8dbebfc56 100644 --- a/ILSpy.BamlDecompiler/Rewrite/XClassRewritePass.cs +++ b/ILSpy.BamlDecompiler/Rewrite/XClassRewritePass.cs @@ -22,16 +22,21 @@ using System.Linq; using System.Xml.Linq; + using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler.Rewrite { - internal class XClassRewritePass : IRewritePass { - public void Run(XamlContext ctx, XDocument document) { +namespace ILSpy.BamlDecompiler.Rewrite +{ + internal class XClassRewritePass : IRewritePass + { + public void Run(XamlContext ctx, XDocument document) + { foreach (var elem in document.Elements(ctx.GetPseudoName("Document")).Elements()) RewriteClass(ctx, elem); } - void RewriteClass(XamlContext ctx, XElement elem) { + void RewriteClass(XamlContext ctx, XElement elem) + { var type = elem.Annotation(); if (type == null || type.ResolvedType == null) return; @@ -51,7 +56,8 @@ namespace ILSpy.BamlDecompiler.Rewrite { var attrName = ctx.GetKnownNamespace("Class", XamlContext.KnownNamespace_Xaml, elem); var attrs = elem.Attributes().ToList(); - if (typeDef.Accessibility != ICSharpCode.Decompiler.TypeSystem.Accessibility.Public) { + if (typeDef.Accessibility != ICSharpCode.Decompiler.TypeSystem.Accessibility.Public) + { var classModifierName = ctx.GetKnownNamespace("ClassModifier", XamlContext.KnownNamespace_Xaml, elem); attrs.Insert(0, new XAttribute(classModifierName, "internal")); } diff --git a/ILSpy.BamlDecompiler/Xaml/NamespaceMap.cs b/ILSpy.BamlDecompiler/Xaml/NamespaceMap.cs index eb17fc45b..290fe8e41 100644 --- a/ILSpy.BamlDecompiler/Xaml/NamespaceMap.cs +++ b/ILSpy.BamlDecompiler/Xaml/NamespaceMap.cs @@ -21,21 +21,26 @@ */ using System; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler.Xaml { - internal class NamespaceMap { +namespace ILSpy.BamlDecompiler.Xaml +{ + internal class NamespaceMap + { public string XmlnsPrefix { get; set; } public string FullAssemblyName { get; set; } public string XMLNamespace { get; set; } public string CLRNamespace { get; set; } public NamespaceMap(string prefix, string fullAssemblyName, string xmlNs) - : this(prefix, fullAssemblyName, xmlNs, null) { + : this(prefix, fullAssemblyName, xmlNs, null) + { } - public NamespaceMap(string prefix, string fullAssemblyName, string xmlNs, string clrNs) { + public NamespaceMap(string prefix, string fullAssemblyName, string xmlNs, string clrNs) + { XmlnsPrefix = prefix; FullAssemblyName = fullAssemblyName; XMLNamespace = xmlNs; diff --git a/ILSpy.BamlDecompiler/Xaml/XamlExtension.cs b/ILSpy.BamlDecompiler/Xaml/XamlExtension.cs index 968236cdf..78d8f5176 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlExtension.cs +++ b/ILSpy.BamlDecompiler/Xaml/XamlExtension.cs @@ -24,25 +24,30 @@ using System.Collections.Generic; using System.Text; using System.Xml.Linq; -namespace ILSpy.BamlDecompiler.Xaml { - internal class XamlExtension { +namespace ILSpy.BamlDecompiler.Xaml +{ + internal class XamlExtension + { public XamlType ExtensionType { get; } public object[] Initializer { get; set; } public IDictionary NamedArguments { get; } - public XamlExtension(XamlType type) { + public XamlExtension(XamlType type) + { ExtensionType = type; NamedArguments = new Dictionary(); } - static void WriteObject(StringBuilder sb, XamlContext ctx, XElement ctxElement, object value) { + static void WriteObject(StringBuilder sb, XamlContext ctx, XElement ctxElement, object value) + { if (value is XamlExtension) sb.Append(((XamlExtension)value).ToString(ctx, ctxElement)); else sb.Append(value.ToString()); } - public string ToString(XamlContext ctx, XElement ctxElement) { + public string ToString(XamlContext ctx, XElement ctxElement) + { var sb = new StringBuilder(); sb.Append('{'); @@ -53,9 +58,11 @@ namespace ILSpy.BamlDecompiler.Xaml { sb.Append(typeName); bool comma = false; - if (Initializer != null && Initializer.Length > 0) { + if (Initializer != null && Initializer.Length > 0) + { sb.Append(' '); - for (int i = 0; i < Initializer.Length; i++) { + for (int i = 0; i < Initializer.Length; i++) + { if (comma) sb.Append(", "); WriteObject(sb, ctx, ctxElement, Initializer[i]); @@ -63,11 +70,14 @@ namespace ILSpy.BamlDecompiler.Xaml { } } - if (NamedArguments.Count > 0) { - foreach (var kvp in NamedArguments) { + if (NamedArguments.Count > 0) + { + foreach (var kvp in NamedArguments) + { if (comma) sb.Append(", "); - else { + else + { sb.Append(' '); comma = true; } diff --git a/ILSpy.BamlDecompiler/Xaml/XamlPathDeserializer.cs b/ILSpy.BamlDecompiler/Xaml/XamlPathDeserializer.cs index dd9901397..4c2b20172 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlPathDeserializer.cs +++ b/ILSpy.BamlDecompiler/Xaml/XamlPathDeserializer.cs @@ -94,90 +94,101 @@ namespace ILSpy.BamlDecompiler.Xaml Point pt1, pt2, pt3; IList pts; - while (!end) { + while (!end) + { var b = reader.ReadByte(); - switch ((PathOpCodes)(b & 0xf)) { - case PathOpCodes.BeginFigure: { - ReadPointBoolBool(reader, b, out pt1, out bool filled, out bool closed); - - sb.AppendFormat("M{0} ", pt1); - break; - } - - case PathOpCodes.LineTo: { - ReadPointBoolBool(reader, b, out pt1, out bool stroked, out bool smoothJoin); - - sb.AppendFormat("L{0} ", pt1); - break; - } - - case PathOpCodes.QuadraticBezierTo: { - ReadPointBoolBool(reader, b, out pt1, out bool stroked, out bool smoothJoin); - pt2 = ReadPoint(reader); - - sb.AppendFormat("Q{0} {1} ", pt1, pt2); - break; - } - - case PathOpCodes.BezierTo: { - ReadPointBoolBool(reader, b, out pt1, out bool stroked, out bool smoothJoin); - pt2 = ReadPoint(reader); - pt3 = ReadPoint(reader); - - sb.AppendFormat("C{0} {1} {2} ", pt1, pt2, pt3); - break; - } - - case PathOpCodes.PolyLineTo: { - pts = ReadPointsBoolBool(reader, b, out bool stroked, out bool smoothJoin); - - sb.Append('L'); - foreach (var pt in pts) - sb.AppendFormat("{0} ", pt); - break; - } - - case PathOpCodes.PolyQuadraticBezierTo: { - pts = ReadPointsBoolBool(reader, b, out bool stroked, out bool smoothJoin); - - sb.Append('Q'); - foreach (var pt in pts) - sb.AppendFormat("{0} ", pt); - break; - } - - case PathOpCodes.PolyBezierTo: { - pts = ReadPointsBoolBool(reader, b, out bool stroked, out bool smoothJoin); - - sb.Append('C'); - foreach (var pt in pts) - sb.AppendFormat("{0} ", pt); - break; - } - - case PathOpCodes.ArcTo: { - ReadPointBoolBool(reader, b, out pt1, out bool stroked, out bool smoothJoin); - byte b2 = reader.ReadByte(); - bool largeArc = (b2 & 0x0f) != 0; - bool sweepDirection = (b2 & 0xf0) != 0; - var size = ReadPoint(reader); - double angle = reader.ReadXamlDouble(); - - sb.AppendFormat(CultureInfo.InvariantCulture, "A{0} {2:R} {2} {3} {4}", - size, angle, largeArc ? '1' : '0', sweepDirection ? '1' : '0', pt1); - break; - } + switch ((PathOpCodes)(b & 0xf)) + { + case PathOpCodes.BeginFigure: + { + ReadPointBoolBool(reader, b, out pt1, out bool filled, out bool closed); + + sb.AppendFormat("M{0} ", pt1); + break; + } + + case PathOpCodes.LineTo: + { + ReadPointBoolBool(reader, b, out pt1, out bool stroked, out bool smoothJoin); + + sb.AppendFormat("L{0} ", pt1); + break; + } + + case PathOpCodes.QuadraticBezierTo: + { + ReadPointBoolBool(reader, b, out pt1, out bool stroked, out bool smoothJoin); + pt2 = ReadPoint(reader); + + sb.AppendFormat("Q{0} {1} ", pt1, pt2); + break; + } + + case PathOpCodes.BezierTo: + { + ReadPointBoolBool(reader, b, out pt1, out bool stroked, out bool smoothJoin); + pt2 = ReadPoint(reader); + pt3 = ReadPoint(reader); + + sb.AppendFormat("C{0} {1} {2} ", pt1, pt2, pt3); + break; + } + + case PathOpCodes.PolyLineTo: + { + pts = ReadPointsBoolBool(reader, b, out bool stroked, out bool smoothJoin); + + sb.Append('L'); + foreach (var pt in pts) + sb.AppendFormat("{0} ", pt); + break; + } + + case PathOpCodes.PolyQuadraticBezierTo: + { + pts = ReadPointsBoolBool(reader, b, out bool stroked, out bool smoothJoin); + + sb.Append('Q'); + foreach (var pt in pts) + sb.AppendFormat("{0} ", pt); + break; + } + + case PathOpCodes.PolyBezierTo: + { + pts = ReadPointsBoolBool(reader, b, out bool stroked, out bool smoothJoin); + + sb.Append('C'); + foreach (var pt in pts) + sb.AppendFormat("{0} ", pt); + break; + } + + case PathOpCodes.ArcTo: + { + ReadPointBoolBool(reader, b, out pt1, out bool stroked, out bool smoothJoin); + byte b2 = reader.ReadByte(); + bool largeArc = (b2 & 0x0f) != 0; + bool sweepDirection = (b2 & 0xf0) != 0; + var size = ReadPoint(reader); + double angle = reader.ReadXamlDouble(); + + sb.AppendFormat(CultureInfo.InvariantCulture, "A{0} {2:R} {2} {3} {4}", + size, angle, largeArc ? '1' : '0', sweepDirection ? '1' : '0', pt1); + break; + } case PathOpCodes.Closed: end = true; break; - case PathOpCodes.FillRule: { - UnpackBools(b, out bool fillRule, out bool b2, out bool b3, out bool b4); - if (fillRule) - sb.Insert(0, "F1 "); - break; - } + case PathOpCodes.FillRule: + { + UnpackBools(b, out bool fillRule, out bool b2, out bool b3, out bool b4); + if (fillRule) + sb.Insert(0, "F1 "); + break; + } } } diff --git a/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs b/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs index f6264d1cf..a6f3575fa 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs +++ b/ILSpy.BamlDecompiler/Xaml/XamlProperty.cs @@ -23,21 +23,26 @@ using System.Linq; using System.Xml; using System.Xml.Linq; + using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler.Xaml { - internal class XamlProperty { +namespace ILSpy.BamlDecompiler.Xaml +{ + internal class XamlProperty + { public XamlType DeclaringType { get; } public string PropertyName { get; } public IMember ResolvedMember { get; set; } - public XamlProperty(XamlType type, string name) { + public XamlProperty(XamlType type, string name) + { DeclaringType = type; PropertyName = name; } - public void TryResolve() { + public void TryResolve() + { if (ResolvedMember != null) return; @@ -60,14 +65,16 @@ namespace ILSpy.BamlDecompiler.Xaml { ResolvedMember = typeDef.GetFields(f => f.Name == PropertyName + "Event").FirstOrDefault(); } - public bool IsAttachedTo(XamlType type) { + public bool IsAttachedTo(XamlType type) + { if (type == null || ResolvedMember == null || type.ResolvedType == null) return true; var declType = ResolvedMember.DeclaringType; var t = type.ResolvedType; - do { + do + { if (t.FullName == declType.FullName && t.TypeParameterCount == declType.TypeParameterCount) return false; t = t.DirectBaseTypes.FirstOrDefault(); @@ -75,12 +82,14 @@ namespace ILSpy.BamlDecompiler.Xaml { return true; } - public XName ToXName(XamlContext ctx, XElement parent, bool isFullName = true) { + public XName ToXName(XamlContext ctx, XElement parent, bool isFullName = true) + { var typeName = DeclaringType.ToXName(ctx); XName name; if (!isFullName) name = XmlConvert.EncodeLocalName(PropertyName); - else { + else + { name = typeName.LocalName + "." + XmlConvert.EncodeLocalName(PropertyName); if (parent == null || parent.GetDefaultNamespace() != typeName.Namespace) name = typeName.Namespace + name.LocalName; diff --git a/ILSpy.BamlDecompiler/Xaml/XamlResourceKey.cs b/ILSpy.BamlDecompiler/Xaml/XamlResourceKey.cs index 501ed1a03..5f4288b07 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlResourceKey.cs +++ b/ILSpy.BamlDecompiler/Xaml/XamlResourceKey.cs @@ -22,11 +22,15 @@ using System.Collections.Generic; using System.Diagnostics; + using ILSpy.BamlDecompiler.Baml; -namespace ILSpy.BamlDecompiler.Xaml { - internal class XamlResourceKey { - XamlResourceKey(BamlNode node) { +namespace ILSpy.BamlDecompiler.Xaml +{ + internal class XamlResourceKey + { + XamlResourceKey(BamlNode node) + { KeyNode = node; StaticResources = new List(); @@ -36,24 +40,28 @@ namespace ILSpy.BamlDecompiler.Xaml { else keyRecord = (IBamlDeferRecord)((BamlRecordNode)node).Record; - if (keyRecord.Record.Type == BamlRecordType.ElementEnd) { + if (keyRecord.Record.Type == BamlRecordType.ElementEnd) + { Debug.Assert(node.Parent.Footer == keyRecord.Record); node.Parent.Annotation = this; node.Annotation = this; return; } - if (keyRecord.Record.Type != BamlRecordType.ElementStart && node.Parent.Type == BamlRecordType.ElementStart) { + if (keyRecord.Record.Type != BamlRecordType.ElementStart && node.Parent.Type == BamlRecordType.ElementStart) + { node.Parent.Annotation = this; node.Annotation = this; return; } - if (keyRecord.Record.Type != BamlRecordType.ElementStart) { + if (keyRecord.Record.Type != BamlRecordType.ElementStart) + { Debug.WriteLine($"Key record @{keyRecord.Position} must be attached to ElementStart (actual {keyRecord.Record.Type})"); } - foreach (var child in node.Parent.Children) { + foreach (var child in node.Parent.Children) + { if (child.Record != keyRecord.Record) continue; @@ -70,10 +78,12 @@ namespace ILSpy.BamlDecompiler.Xaml { public BamlElement KeyElement { get; set; } public IList StaticResources { get; } - public static XamlResourceKey FindKeyInSiblings(BamlNode node) { + public static XamlResourceKey FindKeyInSiblings(BamlNode node) + { var children = node.Parent.Children; var index = children.IndexOf(node); - for (int i = index; i >= 0; i--) { + for (int i = index; i >= 0; i--) + { if (children[i].Annotation is XamlResourceKey) return (XamlResourceKey)children[i].Annotation; } @@ -82,10 +92,13 @@ namespace ILSpy.BamlDecompiler.Xaml { public static XamlResourceKey FindKeyInAncestors(BamlNode node) => FindKeyInAncestors(node, out var found); - public static XamlResourceKey FindKeyInAncestors(BamlNode node, out BamlNode found) { + public static XamlResourceKey FindKeyInAncestors(BamlNode node, out BamlNode found) + { BamlNode n = node; - do { - if (n.Annotation is XamlResourceKey) { + do + { + if (n.Annotation is XamlResourceKey) + { found = n; return (XamlResourceKey)n.Annotation; } diff --git a/ILSpy.BamlDecompiler/Xaml/XamlType.cs b/ILSpy.BamlDecompiler/Xaml/XamlType.cs index e5a1df842..b3b7a18d7 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlType.cs +++ b/ILSpy.BamlDecompiler/Xaml/XamlType.cs @@ -22,9 +22,11 @@ using System.Xml; using System.Xml.Linq; + using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler.Xaml { +namespace ILSpy.BamlDecompiler.Xaml +{ internal class XamlType { /// @@ -39,10 +41,12 @@ namespace ILSpy.BamlDecompiler.Xaml { public IType ResolvedType { get; set; } public XamlType(IModule assembly, string fullAssemblyName, string ns, string name) - : this(assembly, fullAssemblyName, ns, name, null) { + : this(assembly, fullAssemblyName, ns, name, null) + { } - public XamlType(IModule assembly, string fullAssemblyName, string ns, string name, XNamespace xmlns) { + public XamlType(IModule assembly, string fullAssemblyName, string ns, string name, XNamespace xmlns) + { Assembly = assembly; FullAssemblyName = fullAssemblyName; TypeNamespace = ns; @@ -50,7 +54,8 @@ namespace ILSpy.BamlDecompiler.Xaml { Namespace = xmlns; } - public void ResolveNamespace(XElement elem, XamlContext ctx) { + public void ResolveNamespace(XElement elem, XamlContext ctx) + { if (Namespace != null) return; @@ -66,17 +71,20 @@ namespace ILSpy.BamlDecompiler.Xaml { if (xmlNs == null) xmlNs = ctx.TryGetXmlNamespace(Assembly, TypeNamespace); - if (xmlNs == null) { + if (xmlNs == null) + { if (FullAssemblyName == ctx.TypeSystem.MainModule.FullAssemblyName) xmlNs = $"clr-namespace:{TypeNamespace}"; - else { + else + { var name = ICSharpCode.Decompiler.Metadata.AssemblyNameReference.Parse(FullAssemblyName); xmlNs = $"clr-namespace:{TypeNamespace};assembly={name.Name}"; } - var nsSeg = TypeNamespace.Split('.'); + var nsSeg = TypeNamespace.Split('.'); var prefix = nsSeg[nsSeg.Length - 1].ToLowerInvariant(); - if (string.IsNullOrEmpty(prefix)) { + if (string.IsNullOrEmpty(prefix)) + { if (string.IsNullOrEmpty(TypeNamespace)) prefix = "global"; else @@ -85,12 +93,14 @@ namespace ILSpy.BamlDecompiler.Xaml { int count = 0; var truePrefix = prefix; XNamespace prefixNs, ns = ctx.GetXmlNamespace(xmlNs); - while ((prefixNs = elem.GetNamespaceOfPrefix(truePrefix)) != null && prefixNs != ns) { + while ((prefixNs = elem.GetNamespaceOfPrefix(truePrefix)) != null && prefixNs != ns) + { count++; truePrefix = prefix + count; } - if (prefixNs == null) { + if (prefixNs == null) + { elem.Add(new XAttribute(XNamespace.Xmlns + XmlConvert.EncodeLocalName(truePrefix), ns)); if (string.IsNullOrEmpty(TypeNamespace)) elem.AddBeforeSelf(new XComment(string.Format("'{0}' is prefix for the global namespace", truePrefix))); @@ -99,7 +109,8 @@ namespace ILSpy.BamlDecompiler.Xaml { Namespace = ctx.GetXmlNamespace(xmlNs); } - public XName ToXName(XamlContext ctx) { + public XName ToXName(XamlContext ctx) + { if (Namespace == null) return XmlConvert.EncodeLocalName(TypeName); return Namespace + XmlConvert.EncodeLocalName(TypeName); diff --git a/ILSpy.BamlDecompiler/Xaml/XamlUtils.cs b/ILSpy.BamlDecompiler/Xaml/XamlUtils.cs index f165922ae..878d8214e 100644 --- a/ILSpy.BamlDecompiler/Xaml/XamlUtils.cs +++ b/ILSpy.BamlDecompiler/Xaml/XamlUtils.cs @@ -24,9 +24,12 @@ using System.IO; using System.Text; using System.Xml.Linq; -namespace ILSpy.BamlDecompiler.Xaml { - internal static class XamlUtils { - public static string Escape(string value) { +namespace ILSpy.BamlDecompiler.Xaml +{ + internal static class XamlUtils + { + public static string Escape(string value) + { if (value.Length == 0) return value; if (value[0] == '{') @@ -34,16 +37,20 @@ namespace ILSpy.BamlDecompiler.Xaml { return value; } - public static string ToString(this XamlContext ctx, XElement elem, XamlType type) { + public static string ToString(this XamlContext ctx, XElement elem, XamlType type) + { type.ResolveNamespace(elem, ctx); return ctx.ToString(elem, type.ToXName(ctx)); } - public static string ToString(this XamlContext ctx, XElement elem, XName name) { + public static string ToString(this XamlContext ctx, XElement elem, XName name) + { var sb = new StringBuilder(); - if (name.Namespace != elem.GetDefaultNamespace()) { + if (name.Namespace != elem.GetDefaultNamespace()) + { var prefix = elem.GetPrefixOfNamespace(name.Namespace); - if (!string.IsNullOrEmpty(prefix)) { + if (!string.IsNullOrEmpty(prefix)) + { sb.Append(prefix); sb.Append(':'); } @@ -52,9 +59,12 @@ namespace ILSpy.BamlDecompiler.Xaml { return sb.ToString(); } - public static double ReadXamlDouble(this BinaryReader reader, bool scaledInt = false) { - if (!scaledInt) { - switch (reader.ReadByte()) { + public static double ReadXamlDouble(this BinaryReader reader, bool scaledInt = false) + { + if (!scaledInt) + { + switch (reader.ReadByte()) + { case 1: return 0; case 2: @@ -80,7 +90,8 @@ namespace ILSpy.BamlDecompiler.Xaml { /// public static StringBuilder EscapeName(StringBuilder sb, string name) { - foreach (char ch in name) { + foreach (char ch in name) + { if (char.IsWhiteSpace(ch) || char.IsControl(ch) || char.IsSurrogate(ch)) sb.AppendFormat("\\u{0:x4}", (int)ch); else diff --git a/ILSpy.BamlDecompiler/XamlContext.cs b/ILSpy.BamlDecompiler/XamlContext.cs index 50063cf6e..4b281bac3 100644 --- a/ILSpy.BamlDecompiler/XamlContext.cs +++ b/ILSpy.BamlDecompiler/XamlContext.cs @@ -25,13 +25,18 @@ using System.Diagnostics; using System.Linq; using System.Threading; using System.Xml.Linq; + using ICSharpCode.Decompiler.TypeSystem; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler { - internal class XamlContext { - XamlContext(IDecompilerTypeSystem typeSystem) { +namespace ILSpy.BamlDecompiler +{ + internal class XamlContext + { + XamlContext(IDecompilerTypeSystem typeSystem) + { TypeSystem = typeSystem; NodeMap = new Dictionary(); XmlNs = new XmlnsDictionary(); @@ -51,7 +56,8 @@ namespace ILSpy.BamlDecompiler { public XmlnsDictionary XmlNs { get; } - public static XamlContext Construct(IDecompilerTypeSystem typeSystem, BamlDocument document, CancellationToken token, BamlDecompilerOptions bamlDecompilerOptions) { + public static XamlContext Construct(IDecompilerTypeSystem typeSystem, BamlDocument document, CancellationToken token, BamlDecompilerOptions bamlDecompilerOptions) + { var ctx = new XamlContext(typeSystem); ctx.CancellationToken = token; ctx.BamlDecompilerOptions = bamlDecompilerOptions ?? new BamlDecompilerOptions(); @@ -65,20 +71,24 @@ namespace ILSpy.BamlDecompiler { return ctx; } - void BuildNodeMap(BamlBlockNode node) { + void BuildNodeMap(BamlBlockNode node) + { if (node == null) return; NodeMap[node.Header] = node; - foreach (var child in node.Children) { + foreach (var child in node.Children) + { if (child is BamlBlockNode childBlock) BuildNodeMap(childBlock); } } - void BuildPIMappings(BamlDocument document) { - foreach (var record in document) { + void BuildPIMappings(BamlDocument document) + { + foreach (var record in document) + { var piMap = record as PIMappingRecord; if (piMap == null) continue; @@ -87,7 +97,8 @@ namespace ILSpy.BamlDecompiler { } } - public XamlType ResolveType(ushort id) { + public XamlType ResolveType(ushort id) + { if (typeMap.TryGetValue(id, out var xamlType)) return xamlType; @@ -95,12 +106,14 @@ namespace ILSpy.BamlDecompiler { IModule assembly; string fullAssemblyName; - if (id > 0x7fff) { + if (id > 0x7fff) + { type = Baml.KnownThings.Types((KnownTypes)(short)-unchecked((short)id)); assembly = type.GetDefinition().ParentModule; fullAssemblyName = assembly.FullAssemblyName; } - else { + else + { var typeRec = Baml.TypeIdMap[id]; (fullAssemblyName, assembly) = Baml.ResolveAssembly(typeRec.AssemblyId); type = ReflectionHelper.ParseReflectionName(typeRec.TypeFullName).Resolve(new SimpleTypeResolveContext(TypeSystem)); @@ -116,7 +129,8 @@ namespace ILSpy.BamlDecompiler { return xamlType; } - public XamlProperty ResolveProperty(ushort id) { + public XamlProperty ResolveProperty(ushort id) + { if (propertyMap.TryGetValue(id, out var xamlProp)) return xamlProp; @@ -124,13 +138,15 @@ namespace ILSpy.BamlDecompiler { string name; IMember member; - if (id > 0x7fff) { + if (id > 0x7fff) + { var knownProp = Baml.KnownThings.Members((KnownMembers)unchecked((short)-(short)id)); type = ResolveType(unchecked((ushort)(short)-(short)knownProp.Parent)); name = knownProp.Name; member = knownProp.Property; } - else { + else + { var attrRec = Baml.AttributeIdMap[id]; type = ResolveType(attrRec.OwnerTypeId); name = attrRec.Name; @@ -146,7 +162,8 @@ namespace ILSpy.BamlDecompiler { return xamlProp; } - public string ResolveString(ushort id) { + public string ResolveString(ushort id) + { if (id > 0x7fff) return Baml.KnownThings.Strings(unchecked((short)-id)); else if (Baml.StringIdMap.ContainsKey(id)) @@ -155,7 +172,8 @@ namespace ILSpy.BamlDecompiler { return null; } - public XNamespace GetXmlNamespace(string xmlns) { + public XNamespace GetXmlNamespace(string xmlns) + { if (xmlns == null) return null; @@ -168,13 +186,15 @@ namespace ILSpy.BamlDecompiler { public const string KnownNamespace_Presentation = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; public const string KnownNamespace_PresentationOptions = "http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"; - public string TryGetXmlNamespace(IModule assembly, string typeNamespace) { + public string TryGetXmlNamespace(IModule assembly, string typeNamespace) + { if (assembly == null) return null; HashSet possibleXmlNs = new HashSet(); - foreach (var attr in assembly.GetAssemblyAttributes().Where(a => a.AttributeType.FullName == "System.Windows.Markup.XmlnsDefinitionAttribute")) { + foreach (var attr in assembly.GetAssemblyAttributes().Where(a => a.AttributeType.FullName == "System.Windows.Markup.XmlnsDefinitionAttribute")) + { Debug.Assert(attr.FixedArguments.Length == 2); if (attr.FixedArguments.Length != 2) continue; @@ -194,7 +214,8 @@ namespace ILSpy.BamlDecompiler { return possibleXmlNs.FirstOrDefault(); } - public XName GetKnownNamespace(string name, string xmlNamespace, XElement context = null) { + public XName GetKnownNamespace(string name, string xmlNamespace, XElement context = null) + { var xNs = GetXmlNamespace(xmlNamespace); XName xName; if (context != null && xNs == context.GetDefaultNamespace()) diff --git a/ILSpy.BamlDecompiler/XamlDecompiler.cs b/ILSpy.BamlDecompiler/XamlDecompiler.cs index b1227e979..dafe597f6 100644 --- a/ILSpy.BamlDecompiler/XamlDecompiler.cs +++ b/ILSpy.BamlDecompiler/XamlDecompiler.cs @@ -24,12 +24,16 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Xml.Linq; + +using ICSharpCode.Decompiler.TypeSystem; + using ILSpy.BamlDecompiler.Baml; using ILSpy.BamlDecompiler.Rewrite; -using ICSharpCode.Decompiler.TypeSystem; -namespace ILSpy.BamlDecompiler { - internal class XamlDecompiler { +namespace ILSpy.BamlDecompiler +{ + internal class XamlDecompiler + { static readonly IRewritePass[] rewritePasses = new IRewritePass[] { new XClassRewritePass(), new MarkupExtensionRewritePass(), @@ -38,7 +42,8 @@ namespace ILSpy.BamlDecompiler { new DocumentRewritePass(), }; - public XDocument Decompile(IDecompilerTypeSystem typeSystem, BamlDocument document, CancellationToken token, BamlDecompilerOptions bamlDecompilerOptions, List assemblyReferences) { + public XDocument Decompile(IDecompilerTypeSystem typeSystem, BamlDocument document, CancellationToken token, BamlDecompilerOptions bamlDecompilerOptions, List assemblyReferences) + { var ctx = XamlContext.Construct(typeSystem, document, token, bamlDecompilerOptions); var handler = HandlerMap.LookupHandler(ctx.RootNode.Type); @@ -47,7 +52,8 @@ namespace ILSpy.BamlDecompiler { var xaml = new XDocument(); xaml.Add(elem.Xaml.Element); - foreach (var pass in rewritePasses) { + foreach (var pass in rewritePasses) + { token.ThrowIfCancellationRequested(); pass.Run(ctx, xaml); } diff --git a/ILSpy.BamlDecompiler/XmlnsDictionary.cs b/ILSpy.BamlDecompiler/XmlnsDictionary.cs index 4d42dd9aa..74ada5815 100644 --- a/ILSpy.BamlDecompiler/XmlnsDictionary.cs +++ b/ILSpy.BamlDecompiler/XmlnsDictionary.cs @@ -21,22 +21,29 @@ */ using System.Collections.Generic; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; + using ILSpy.BamlDecompiler.Xaml; -namespace ILSpy.BamlDecompiler { - internal class XmlnsScope : List { +namespace ILSpy.BamlDecompiler +{ + internal class XmlnsScope : List + { public BamlElement Element { get; } public XmlnsScope PreviousScope { get; } - public XmlnsScope(XmlnsScope prev, BamlElement elem) { + public XmlnsScope(XmlnsScope prev, BamlElement elem) + { PreviousScope = prev; Element = elem; } - public string LookupXmlns(string fullAssemblyName, string clrNs) { - foreach (var ns in this) { + public string LookupXmlns(string fullAssemblyName, string clrNs) + { + foreach (var ns in this) + { if (fullAssemblyName == ns.FullAssemblyName && ns.CLRNamespace == clrNs) return ns.XMLNamespace; } @@ -45,7 +52,8 @@ namespace ILSpy.BamlDecompiler { } } - internal class XmlnsDictionary { + internal class XmlnsDictionary + { Dictionary piMappings = new Dictionary(); public XmlnsDictionary() => CurrentScope = null; @@ -58,25 +66,32 @@ namespace ILSpy.BamlDecompiler { public void Add(NamespaceMap map) => CurrentScope.Add(map); - public void SetPIMapping(string xmlNs, string clrNs, string fullAssemblyName) { - if (!piMappings.ContainsKey(xmlNs)) { + public void SetPIMapping(string xmlNs, string clrNs, string fullAssemblyName) + { + if (!piMappings.ContainsKey(xmlNs)) + { var map = new NamespaceMap(null, fullAssemblyName, xmlNs, clrNs); piMappings[xmlNs] = map; } } - NamespaceMap PIFixup(NamespaceMap map) { - if (piMappings.TryGetValue(map.XMLNamespace, out var piMap)) { + NamespaceMap PIFixup(NamespaceMap map) + { + if (piMappings.TryGetValue(map.XMLNamespace, out var piMap)) + { map.FullAssemblyName = piMap.FullAssemblyName; map.CLRNamespace = piMap.CLRNamespace; } return map; } - public NamespaceMap LookupNamespaceFromPrefix(string prefix) { + public NamespaceMap LookupNamespaceFromPrefix(string prefix) + { var scope = CurrentScope; - while (scope != null) { - foreach (var ns in scope) { + while (scope != null) + { + foreach (var ns in scope) + { if (ns.XmlnsPrefix == prefix) return PIFixup(ns); } @@ -87,10 +102,13 @@ namespace ILSpy.BamlDecompiler { return null; } - public NamespaceMap LookupNamespaceFromXmlns(string xmlNs) { + public NamespaceMap LookupNamespaceFromXmlns(string xmlNs) + { var scope = CurrentScope; - while (scope != null) { - foreach (var ns in scope) { + while (scope != null) + { + foreach (var ns in scope) + { if (ns.XMLNamespace == xmlNs) return ns; } @@ -101,15 +119,19 @@ namespace ILSpy.BamlDecompiler { return null; } - public string LookupXmlns(string fullAssemblyName, string clrNs) { - foreach (var map in piMappings) { + public string LookupXmlns(string fullAssemblyName, string clrNs) + { + foreach (var map in piMappings) + { if (fullAssemblyName == map.Value.FullAssemblyName && map.Value.CLRNamespace == clrNs) return map.Key; } var scope = CurrentScope; - while (scope != null) { - foreach (var ns in scope) { + while (scope != null) + { + foreach (var ns in scope) + { if (fullAssemblyName == ns.FullAssemblyName && ns.CLRNamespace == clrNs) return ns.XMLNamespace; } diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 56da02dcd..c33d22116 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -26,13 +26,16 @@ using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using System.Resources; using System.Runtime.CompilerServices; + using Iced.Intel; + using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; + using ILCompiler.Reflection.ReadyToRun; using ILCompiler.Reflection.ReadyToRun.Amd64; @@ -52,9 +55,12 @@ namespace ICSharpCode.ILSpy.ReadyToRun { PEFile module = assembly.GetPEFileOrNull(); ReadyToRunReaderCacheEntry cacheEntry = GetReader(assembly, module); - if (cacheEntry.readyToRunReader == null) { + if (cacheEntry.readyToRunReader == null) + { WriteCommentLine(output, cacheEntry.failureReason); - } else { + } + else + { ReadyToRunReader reader = cacheEntry.readyToRunReader; WriteCommentLine(output, reader.Machine.ToString()); WriteCommentLine(output, reader.OperatingSystem.ToString()); @@ -69,18 +75,25 @@ namespace ICSharpCode.ILSpy.ReadyToRun { PEFile module = method.ParentModule.PEFile; ReadyToRunReaderCacheEntry cacheEntry = GetReader(module.GetLoadedAssembly(), module); - if (cacheEntry.readyToRunReader == null) { + if (cacheEntry.readyToRunReader == null) + { WriteCommentLine(output, cacheEntry.failureReason); - } else { + } + else + { ReadyToRunReader reader = cacheEntry.readyToRunReader; int bitness = -1; - if (reader.Machine == Machine.Amd64) { + if (reader.Machine == Machine.Amd64) + { bitness = 64; - } else { + } + else + { Debug.Assert(reader.Machine == Machine.I386); bitness = 32; } - if (cacheEntry.methodMap == null) { + if (cacheEntry.methodMap == null) + { cacheEntry.methodMap = reader.Methods.Values .SelectMany(m => m) .GroupBy(m => m.MethodHandle) @@ -88,9 +101,12 @@ namespace ICSharpCode.ILSpy.ReadyToRun } bool showMetadataTokens = ILSpy.Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens; bool showMetadataTokensInBase10 = ILSpy.Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokensInBase10; - if (cacheEntry.methodMap.TryGetValue(method.MetadataToken, out var methods)) { - foreach (var readyToRunMethod in methods) { - foreach (RuntimeFunction runtimeFunction in readyToRunMethod.RuntimeFunctions) { + if (cacheEntry.methodMap.TryGetValue(method.MetadataToken, out var methods)) + { + foreach (var readyToRunMethod in methods) + { + foreach (RuntimeFunction runtimeFunction in readyToRunMethod.RuntimeFunctions) + { Disassemble(method.ParentModule.PEFile, output, reader, readyToRunMethod, runtimeFunction, bitness, (ulong)runtimeFunction.StartAddress, showMetadataTokens, showMetadataTokensInBase10); } } @@ -107,34 +123,45 @@ namespace ICSharpCode.ILSpy.ReadyToRun { Dictionary> debugInfoDict = new Dictionary>(); IReadOnlyList runTimeList = readyToRunMethod.RuntimeFunctions; - foreach (RuntimeFunction runtimeFunction in runTimeList) { + foreach (RuntimeFunction runtimeFunction in runTimeList) + { DebugInfo debugInfo = runtimeFunction.DebugInfo; - if (debugInfo != null && debugInfo.BoundsList.Count > 0) { - for (int i = 0; i < debugInfo.VariablesList.Count; ++i) { + if (debugInfo != null && debugInfo.BoundsList.Count > 0) + { + for (int i = 0; i < debugInfo.VariablesList.Count; ++i) + { var varLoc = debugInfo.VariablesList[i]; - try { + try + { var typeSet = new HashSet>(); bool found = debugInfoDict.TryGetValue(varLoc.VariableLocation.VarLocType, out typeSet); - if (found) { + if (found) + { (DebugInfo debugInfo, NativeVarInfo varLoc) newTuple = (debugInfo, varLoc); typeSet.Add(newTuple); - } else { + } + else + { typeSet = new HashSet>(); debugInfoDict.Add(varLoc.VariableLocation.VarLocType, typeSet); (DebugInfo debugInfo, NativeVarInfo varLoc) newTuple = (debugInfo, varLoc); typeSet.Add(newTuple); } - } catch (ArgumentNullException) { + } + catch (ArgumentNullException) + { output.WriteLine("Failed to find hash set of Debug info type"); } if (varLoc.VariableLocation.VarLocType != VarLocType.VLT_REG && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK - && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK_BYREF) { + && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK_BYREF) + { output.WriteLine($" Variable Number: {varLoc.VariableNumber}"); output.WriteLine($" Start Offset: 0x{varLoc.StartOffset:X}"); output.WriteLine($" End Offset: 0x{varLoc.EndOffset:X}"); output.WriteLine($" Loc Type: {varLoc.VariableLocation.VarLocType}"); - switch (varLoc.VariableLocation.VarLocType) { + switch (varLoc.VariableLocation.VarLocType) + { case VarLocType.VLT_REG: case VarLocType.VLT_REG_FP: case VarLocType.VLT_REG_BYREF: @@ -184,25 +211,31 @@ namespace ICSharpCode.ILSpy.ReadyToRun private Dictionary WriteUnwindInfo(RuntimeFunction runtimeFunction, ITextOutput output) { Dictionary unwindCodes = new Dictionary(); - if (runtimeFunction.UnwindInfo is UnwindInfo amd64UnwindInfo) { + if (runtimeFunction.UnwindInfo is UnwindInfo amd64UnwindInfo) + { string parsedFlags = ""; - if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_EHANDLER) != 0) { + if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_EHANDLER) != 0) + { parsedFlags += " EHANDLER"; } - if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_UHANDLER) != 0) { + if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_UHANDLER) != 0) + { parsedFlags += " UHANDLER"; } - if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_CHAININFO) != 0) { + if ((amd64UnwindInfo.Flags & (int)UnwindFlags.UNW_FLAG_CHAININFO) != 0) + { parsedFlags += " CHAININFO"; } - if (parsedFlags.Length == 0) { + if (parsedFlags.Length == 0) + { parsedFlags = " NHANDLER"; } WriteCommentLine(output, $"UnwindInfo:"); WriteCommentLine(output, $"Version: {amd64UnwindInfo.Version}"); WriteCommentLine(output, $"Flags: 0x{amd64UnwindInfo.Flags:X2}{parsedFlags}"); WriteCommentLine(output, $"FrameRegister: {((amd64UnwindInfo.FrameRegister == 0) ? "none" : amd64UnwindInfo.FrameRegister.ToString().ToLower())}"); - for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++) { + for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++) + { unwindCodes.Add((ulong)(amd64UnwindInfo.UnwindCodes[unwindCodeIndex].CodeOffset), amd64UnwindInfo.UnwindCodes[unwindCodeIndex]); } } @@ -215,18 +248,21 @@ namespace ICSharpCode.ILSpy.ReadyToRun WriteCommentLine(output, readyToRunMethod.SignatureString); Dictionary unwindInfo = null; - if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) { + if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64) + { unwindInfo = WriteUnwindInfo(runtimeFunction, output); } bool isShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(null); Dictionary>> debugInfo = null; - if (isShowDebugInfo) { + if (isShowDebugInfo) + { debugInfo = WriteDebugInfo(readyToRunMethod, output); } byte[] codeBytes = new byte[runtimeFunction.Size]; - for (int i = 0; i < runtimeFunction.Size; i++) { + for (int i = 0; i < runtimeFunction.Size; i++) + { codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i]; } @@ -236,15 +272,19 @@ namespace ICSharpCode.ILSpy.ReadyToRun ulong endRip = decoder.IP + (uint)codeBytes.Length; var instructions = new InstructionList(); - while (decoder.IP < endRip) { + while (decoder.IP < endRip) + { decoder.Decode(out instructions.AllocUninitializedElement()); } string disassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(null); Formatter formatter = null; - if (disassemblyFormat.Equals(ReadyToRunOptions.intel)) { + if (disassemblyFormat.Equals(ReadyToRunOptions.intel)) + { formatter = new NasmFormatter(); - } else { + } + else + { Debug.Assert(disassemblyFormat.Equals(ReadyToRunOptions.gas)); formatter = new GasFormatter(); } @@ -252,16 +292,25 @@ namespace ICSharpCode.ILSpy.ReadyToRun formatter.Options.FirstOperandCharIndex = 10; var tempOutput = new StringOutput(); ulong baseInstrIP = instructions[0].IP; - foreach (var instr in instructions) { + foreach (var instr in instructions) + { int byteBaseIndex = (int)(instr.IP - address); - if (isShowDebugInfo && runtimeFunction.DebugInfo != null) { - foreach (var bound in runtimeFunction.DebugInfo.BoundsList) { - if (bound.NativeOffset == byteBaseIndex) { - if (bound.ILOffset == (uint)DebugInfoBoundsType.Prolog) { + if (isShowDebugInfo && runtimeFunction.DebugInfo != null) + { + foreach (var bound in runtimeFunction.DebugInfo.BoundsList) + { + if (bound.NativeOffset == byteBaseIndex) + { + if (bound.ILOffset == (uint)DebugInfoBoundsType.Prolog) + { WriteCommentLine(output, "Prolog"); - } else if (bound.ILOffset == (uint)DebugInfoBoundsType.Epilog) { + } + else if (bound.ILOffset == (uint)DebugInfoBoundsType.Epilog) + { WriteCommentLine(output, "Epilog"); - } else { + } + else + { WriteCommentLine(output, $"IL_{bound.ILOffset:x4}"); } } @@ -271,11 +320,13 @@ namespace ICSharpCode.ILSpy.ReadyToRun output.Write(instr.IP.ToString("X16")); output.Write(" "); int instrLen = instr.Length; - for (int i = 0; i < instrLen; i++) { + for (int i = 0; i < instrLen; i++) + { output.Write(codeBytes[byteBaseIndex + i].ToString("X2")); } int missingBytes = 10 - instrLen; - for (int i = 0; i < missingBytes; i++) { + for (int i = 0; i < missingBytes; i++) + { output.Write(" "); } output.Write(" "); @@ -290,7 +341,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun private static void DecorateUnwindInfo(ITextOutput output, Dictionary unwindInfo, ulong baseInstrIP, Instruction instr) { ulong nextInstructionOffset = instr.NextIP - baseInstrIP; - if (unwindInfo != null && unwindInfo.ContainsKey(nextInstructionOffset)) { + if (unwindInfo != null && unwindInfo.ContainsKey(nextInstructionOffset)) + { UnwindCode unwindCode = unwindInfo[nextInstructionOffset]; output.Write($" ; {unwindCode.UnwindOp}({unwindCode.OpInfoStr})"); } @@ -298,57 +350,74 @@ namespace ICSharpCode.ILSpy.ReadyToRun private static void DecorateDebugInfo(ITextOutput output, Instruction instr, Dictionary> debugInfoDict, ulong baseInstrIP) { - if (debugInfoDict != null) { + if (debugInfoDict != null) + { InstructionInfoFactory factory = new InstructionInfoFactory(); InstructionInfo info = factory.GetInfo(instr); HashSet> stkSet = new HashSet>(); - if (debugInfoDict.ContainsKey(VarLocType.VLT_STK)) { + if (debugInfoDict.ContainsKey(VarLocType.VLT_STK)) + { stkSet.UnionWith(debugInfoDict[VarLocType.VLT_STK]); } - if (debugInfoDict.ContainsKey(VarLocType.VLT_STK_BYREF)) { + if (debugInfoDict.ContainsKey(VarLocType.VLT_STK_BYREF)) + { stkSet.UnionWith(debugInfoDict[VarLocType.VLT_STK_BYREF]); } - if (stkSet != null) { - foreach (UsedMemory usedMemInfo in info.GetUsedMemory()) { //for each time a [register +- value] is used - foreach ((DebugInfo debugInfo, NativeVarInfo varLoc) tuple in stkSet) { //for each VLT_STK variable + if (stkSet != null) + { + foreach (UsedMemory usedMemInfo in info.GetUsedMemory()) + { //for each time a [register +- value] is used + foreach ((DebugInfo debugInfo, NativeVarInfo varLoc) tuple in stkSet) + { //for each VLT_STK variable var debugInfo = tuple.debugInfo; var varInfo = tuple.varLoc; int stackOffset = varInfo.VariableLocation.Data2; ulong adjOffset; bool negativeOffset; - if (stackOffset < 0) { + if (stackOffset < 0) + { int absValue = -1 * stackOffset; adjOffset = ulong.MaxValue - (ulong)absValue + 1; negativeOffset = true; - } else { + } + else + { adjOffset = (ulong)stackOffset; negativeOffset = false; } if (varInfo.StartOffset < instr.IP - baseInstrIP && varInfo.EndOffset > instr.IP - baseInstrIP && DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Base.ToString() && - adjOffset == usedMemInfo.Displacement) { + adjOffset == usedMemInfo.Displacement) + { output.Write($"; [{usedMemInfo.Base.ToString().ToLower()}{(negativeOffset ? '-' : '+')}{Math.Abs(stackOffset):X}h] = {varInfo.Variable.Type} {varInfo.Variable.Index}"); } } } } HashSet> regSet = new HashSet>(); - if (debugInfoDict.ContainsKey(VarLocType.VLT_REG)) { + if (debugInfoDict.ContainsKey(VarLocType.VLT_REG)) + { regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG]); } - if (debugInfoDict.ContainsKey(VarLocType.VLT_REG_BYREF)) { + if (debugInfoDict.ContainsKey(VarLocType.VLT_REG_BYREF)) + { regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG_BYREF]); } - if (debugInfoDict.ContainsKey(VarLocType.VLT_REG_FP)) { + if (debugInfoDict.ContainsKey(VarLocType.VLT_REG_FP)) + { regSet.UnionWith(debugInfoDict[VarLocType.VLT_REG_FP]); } - if (regSet != null) { - foreach (UsedRegister usedMemInfo in info.GetUsedRegisters()) { - foreach ((DebugInfo debugInfo, NativeVarInfo varLoc) tuple in regSet) { + if (regSet != null) + { + foreach (UsedRegister usedMemInfo in info.GetUsedRegisters()) + { + foreach ((DebugInfo debugInfo, NativeVarInfo varLoc) tuple in regSet) + { var debugInfo = tuple.debugInfo; var varInfo = tuple.varLoc; if (varInfo.StartOffset <= (instr.IP - baseInstrIP) && (instr.IP - baseInstrIP) < varInfo.EndOffset && - DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Register.ToString()) { + DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varInfo.VariableLocation.Data1) == usedMemInfo.Register.ToString()) + { output.Write($"; {usedMemInfo.Register.ToString().ToLower()} = {varInfo.Variable.Type} {varInfo.Variable.Index}"); } } @@ -360,16 +429,22 @@ namespace ICSharpCode.ILSpy.ReadyToRun private static void DecorateCallSite(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, bool showMetadataTokens, bool showMetadataTokensInBase10, Instruction instr) { int importCellAddress = (int)instr.IPRelativeMemoryAddress; - if (instr.IsCallNearIndirect && reader.ImportCellNames.ContainsKey(importCellAddress)) { + if (instr.IsCallNearIndirect && reader.ImportCellNames.ContainsKey(importCellAddress)) + { output.Write(" ; "); ReadyToRunSignature signature = reader.ImportSignatures[(int)instr.IPRelativeMemoryAddress]; - switch (signature) { + switch (signature) + { case MethodDefEntrySignature methodDefSignature: var methodDefToken = MetadataTokens.EntityHandle(unchecked((int)methodDefSignature.MethodDefToken)); - if (showMetadataTokens) { - if (showMetadataTokensInBase10) { + if (showMetadataTokens) + { + if (showMetadataTokensInBase10) + { output.WriteReference(currentFile, methodDefToken, $"({MetadataTokens.GetToken(methodDefToken)}) ", "metadata"); - } else { + } + else + { output.WriteReference(currentFile, methodDefToken, $"({MetadataTokens.GetToken(methodDefToken):X8}) ", "metadata"); } } @@ -377,10 +452,14 @@ namespace ICSharpCode.ILSpy.ReadyToRun break; case MethodRefEntrySignature methodRefSignature: var methodRefToken = MetadataTokens.EntityHandle(unchecked((int)methodRefSignature.MethodRefToken)); - if (showMetadataTokens) { - if (showMetadataTokensInBase10) { + if (showMetadataTokens) + { + if (showMetadataTokensInBase10) + { output.WriteReference(currentFile, methodRefToken, $"({MetadataTokens.GetToken(methodRefToken)}) ", "metadata"); - } else { + } + else + { output.WriteReference(currentFile, methodRefToken, $"({MetadataTokens.GetToken(methodRefToken):X8}) ", "metadata"); } } @@ -391,7 +470,9 @@ namespace ICSharpCode.ILSpy.ReadyToRun break; } output.WriteLine(); - } else { + } + else + { output.WriteLine(); } } @@ -404,16 +485,22 @@ namespace ICSharpCode.ILSpy.ReadyToRun private ReadyToRunReaderCacheEntry GetReader(LoadedAssembly assembly, PEFile module) { ReadyToRunReaderCacheEntry result; - lock (readyToRunReaders) { - if (!readyToRunReaders.TryGetValue(module, out result)) { + lock (readyToRunReaders) + { + if (!readyToRunReaders.TryGetValue(module, out result)) + { result = new ReadyToRunReaderCacheEntry(); - try { + try + { result.readyToRunReader = new ReadyToRunReader(new ReadyToRunAssemblyResolver(assembly), new StandaloneAssemblyMetadata(module.Reader), module.Reader, module.FileName); - if (result.readyToRunReader.Machine != Machine.Amd64 && result.readyToRunReader.Machine != Machine.I386) { + if (result.readyToRunReader.Machine != Machine.Amd64 && result.readyToRunReader.Machine != Machine.I386) + { result.failureReason = $"Architecture {result.readyToRunReader.Machine} is not currently supported."; result.readyToRunReader = null; } - } catch (BadImageFormatException e) { + } + catch (BadImageFormatException e) + { result.failureReason = e.Message; } readyToRunReaders.Add(module, result); diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs index 7abcb69a1..415d3f729 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs @@ -19,11 +19,13 @@ using System.ComponentModel; using System.Windows.Controls; using System.Xml.Linq; + using ICSharpCode.ILSpy.Options; + using ILSpy.ReadyToRun; namespace ICSharpCode.ILSpy.ReadyToRun { - [ExportOptionPage(Title = nameof(global::ILSpy.ReadyToRun.Properties.Resources.ReadyToRun), Order = 40)] + [ExportOptionPage(Title = nameof(global::ILSpy.ReadyToRun.Properties.Resources.ReadyToRun), Order = 40)] partial class ReadyToRunOptionPage : UserControl, IOptionPage { public ReadyToRunOptionPage() @@ -89,7 +91,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun public string DisassemblyFormat { get { return disassemblyFormat; } set { - if (disassemblyFormat != value) { + if (disassemblyFormat != value) + { disassemblyFormat = value; OnPropertyChanged(nameof(DisassemblyFormat)); } @@ -100,7 +103,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun protected virtual void OnPropertyChanged(string propertyName) { - if (PropertyChanged != null) { + if (PropertyChanged != null) + { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } diff --git a/ILSpy.ReadyToRun/ReadyToRunOptions.cs b/ILSpy.ReadyToRun/ReadyToRunOptions.cs index f82535e63..3fbd6df6c 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptions.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptions.cs @@ -30,44 +30,56 @@ namespace ICSharpCode.ILSpy.ReadyToRun public static string GetDisassemblyFormat(ILSpySettings settings) { - if (settings == null) { + if (settings == null) + { settings = ILSpySettings.Load(); } XElement e = settings[ns + "ReadyToRunOptions"]; XAttribute a = e.Attribute("DisassemblyFormat"); - if (a == null) { + if (a == null) + { return ReadyToRunOptions.intel; - } else { + } + else + { return (string)a; } } public static bool GetIsShowUnwindInfo(ILSpySettings settings) { - if (settings == null) { + if (settings == null) + { settings = ILSpySettings.Load(); } XElement e = settings[ns + "ReadyToRunOptions"]; XAttribute a = e.Attribute("IsShowUnwindInfo"); - if (a == null) { + if (a == null) + { return false; - } else { + } + else + { return (bool)a; } } public static bool GetIsShowDebugInfo(ILSpySettings settings) { - if (settings == null) { + if (settings == null) + { settings = ILSpySettings.Load(); } XElement e = settings[ns + "ReadyToRunOptions"]; XAttribute a = e.Attribute("IsShowDebugInfo"); - if (a == null) { + if (a == null) + { return true; - } else { + } + else + { return (bool)a; } } @@ -79,9 +91,12 @@ namespace ICSharpCode.ILSpy.ReadyToRun section.SetAttributeValue("IsShowUnwindInfo", isShowUnwindInfo); section.SetAttributeValue("IsShowDebugInfo", isShowDebugInfo); XElement existingElement = root.Element(ns + "ReadyToRunOptions"); - if (existingElement != null) { + if (existingElement != null) + { existingElement.ReplaceWith(section); - } else { + } + else + { root.Add(section); } } diff --git a/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs b/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs index 1380cbf49..33735acc4 100644 --- a/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs +++ b/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs @@ -21,12 +21,15 @@ using System.IO; using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.ILSpy.Analyzers; using ICSharpCode.ILSpy.Analyzers.Builtin; + using Moq; + using NUnit.Framework; namespace ICSharpCode.ILSpy.Tests.Analyzers @@ -40,7 +43,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers static readonly TypeKind[] ValidTypeKinds = { TypeKind.Class, TypeKind.Struct }; static readonly TypeKind[] InvalidTypeKinds = Enum.GetValues(typeof(TypeKind)).Cast().Except(ValidTypeKinds).ToArray(); - + private ICompilation testAssembly; [OneTimeSetUp] @@ -48,7 +51,8 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers { string fileName = GetType().Assembly.Location; - using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { + using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) + { var module = new PEFile(fileName, stream, PEStreamOptions.PrefetchEntireImage, MetadataReaderOptions.None); testAssembly = new SimpleCompilation(module.WithOptions(TypeSystemOptions.Default), MinimalCorlib.Instance); @@ -63,7 +67,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers // Act var shouldShow = analyzer.Show(symbol: null); - + // Assert Assert.IsFalse(shouldShow, $"The analyzer will be unexpectedly shown for no symbol"); } @@ -160,7 +164,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers } private static Mock SetupMemberMock(SymbolKind symbolKind, TypeKind typeKind, bool isStatic) - { + { var memberMock = new Mock(); memberMock.Setup(m => m.SymbolKind).Returns(symbolKind); memberMock.Setup(m => m.DeclaringTypeDefinition.Kind).Returns(typeKind); diff --git a/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs b/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs index 0b234541d..e502891ac 100644 --- a/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs +++ b/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs @@ -3,11 +3,13 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using NUnit.Framework; +using System.Windows; + +using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Analyzers; using ICSharpCode.ILSpy.Analyzers.Builtin; -using ICSharpCode.Decompiler.TypeSystem; -using System.Windows; + +using NUnit.Framework; namespace ICSharpCode.ILSpy.Tests.Analyzers { diff --git a/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs b/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs index 03672d7c1..6a57daa8c 100644 --- a/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs +++ b/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs @@ -22,10 +22,12 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.ILSpy.Analyzers; using ICSharpCode.ILSpy.Analyzers.Builtin; + using NUnit.Framework; namespace ICSharpCode.ILSpy.Tests.Analyzers diff --git a/ILSpy.Tests/Stub.cs b/ILSpy.Tests/Stub.cs index 53afccfe1..940bf1786 100644 --- a/ILSpy.Tests/Stub.cs +++ b/ILSpy.Tests/Stub.cs @@ -30,7 +30,8 @@ namespace ICSharpCode.ILSpy.Tests internal static void SetupApplication() { - lock (sync) { + lock (sync) + { if (Application.Current == null) new Application(); } diff --git a/ILSpy/AboutPage.cs b/ILSpy/AboutPage.cs index 1916abee5..8d4671139 100644 --- a/ILSpy/AboutPage.cs +++ b/ILSpy/AboutPage.cs @@ -46,27 +46,33 @@ namespace ICSharpCode.ILSpy { MainWindow.Instance.NavigateTo(new RequestNavigateEventArgs(new Uri("resource://aboutpage"), null)); } - + static readonly Uri UpdateUrl = new Uri("https://ilspy.net/updates.xml"); const string band = "stable"; - + static AvailableVersionInfo latestAvailableVersion; - + public static void Display(DecompilerTextView textView) { AvalonEditTextOutput output = new AvalonEditTextOutput() { Title = Resources.About, EnableHyperlinks = true }; output.WriteLine(Resources.ILSpyVersion + RevisionClass.FullVersion); - if(WindowsVersionHelper.HasPackageIdentity) { + if (WindowsVersionHelper.HasPackageIdentity) + { output.WriteLine($"Package Name: {WindowsVersionHelper.GetPackageFamilyName()}"); - } else {// if we're running in an MSIX, updates work differently + } + else + {// if we're running in an MSIX, updates work differently output.AddUIElement( delegate { StackPanel stackPanel = new StackPanel(); stackPanel.HorizontalAlignment = HorizontalAlignment.Center; stackPanel.Orientation = Orientation.Horizontal; - if (latestAvailableVersion == null) { + if (latestAvailableVersion == null) + { AddUpdateCheckButton(stackPanel, textView); - } else { + } + else + { // we already retrieved the latest version sometime earlier ShowAvailableVersion(latestAvailableVersion, stackPanel); } @@ -83,15 +89,18 @@ namespace ICSharpCode.ILSpy }); output.WriteLine(); } - + foreach (var plugin in App.ExportProvider.GetExportedValues()) plugin.Write(output); output.WriteLine(); output.Address = new Uri("resource://AboutPage"); - using (Stream s = typeof(AboutPage).Assembly.GetManifestResourceStream(typeof(AboutPage), Resources.ILSpyAboutPageTxt)) { - using (StreamReader r = new StreamReader(s)) { + using (Stream s = typeof(AboutPage).Assembly.GetManifestResourceStream(typeof(AboutPage), Resources.ILSpyAboutPageTxt)) + { + using (StreamReader r = new StreamReader(s)) + { string line; - while ((line = r.ReadLine()) != null) { + while ((line = r.ReadLine()) != null) + { output.WriteLine(line); } } @@ -100,70 +109,77 @@ namespace ICSharpCode.ILSpy output.AddVisualLineElementGenerator(new MyLinkElementGenerator("third-party notices", "resource:third-party-notices.txt")); textView.ShowText(output); } - + sealed class MyLinkElementGenerator : LinkElementGenerator { readonly Uri uri; - + public MyLinkElementGenerator(string matchText, string url) : base(new Regex(Regex.Escape(matchText))) { this.uri = new Uri(url); this.RequireControlModifierForClick = false; } - + protected override Uri GetUriFromMatch(Match match) { return uri; } } - + static void AddUpdateCheckButton(StackPanel stackPanel, DecompilerTextView textView) { Button button = new Button(); button.Content = Resources.CheckUpdates; button.Cursor = Cursors.Arrow; stackPanel.Children.Add(button); - + button.Click += async delegate { button.Content = Resources.Checking; button.IsEnabled = false; - - try { + + try + { AvailableVersionInfo vInfo = await GetLatestVersionAsync(); stackPanel.Children.Clear(); ShowAvailableVersion(vInfo, stackPanel); - } catch (Exception ex) { + } + catch (Exception ex) + { AvalonEditTextOutput exceptionOutput = new AvalonEditTextOutput(); exceptionOutput.WriteLine(ex.ToString()); textView.ShowText(exceptionOutput); } }; } - + static readonly Version currentVersion = new Version(RevisionClass.Major + "." + RevisionClass.Minor + "." + RevisionClass.Build + "." + RevisionClass.Revision); - + static void ShowAvailableVersion(AvailableVersionInfo availableVersion, StackPanel stackPanel) { - if (currentVersion == availableVersion.Version) { + if (currentVersion == availableVersion.Version) + { stackPanel.Children.Add( new Image { Width = 16, Height = 16, Source = Images.OK, - Margin = new Thickness(4,0,4,0) + Margin = new Thickness(4, 0, 4, 0) }); stackPanel.Children.Add( new TextBlock { Text = Resources.UsingLatestRelease, VerticalAlignment = VerticalAlignment.Bottom }); - } else if (currentVersion < availableVersion.Version) { + } + else if (currentVersion < availableVersion.Version) + { stackPanel.Children.Add( new TextBlock { - Text = string.Format(Resources.VersionAvailable, availableVersion.Version ), - Margin = new Thickness(0,0,8,0), + Text = string.Format(Resources.VersionAvailable, availableVersion.Version), + Margin = new Thickness(0, 0, 8, 0), VerticalAlignment = VerticalAlignment.Bottom }); - if (availableVersion.DownloadUrl != null) { + if (availableVersion.DownloadUrl != null) + { Button button = new Button(); button.Content = Resources.Download; button.Cursor = Cursors.Arrow; @@ -172,11 +188,13 @@ namespace ICSharpCode.ILSpy }; stackPanel.Children.Add(button); } - } else { + } + else + { stackPanel.Children.Add(new TextBlock { Text = Resources.UsingNightlyBuildNewerThanLatestRelease }); } } - + static async Task GetLatestVersionAsync() { WebClient wc = new WebClient(); @@ -197,53 +215,58 @@ namespace ICSharpCode.ILSpy latestAvailableVersion = new AvailableVersionInfo { Version = version, DownloadUrl = url }; return latestAvailableVersion; } - + sealed class AvailableVersionInfo { public Version Version; public string DownloadUrl; } - + sealed class UpdateSettings : INotifyPropertyChanged { public UpdateSettings(ILSpySettings spySettings) { XElement s = spySettings["UpdateSettings"]; this.automaticUpdateCheckEnabled = (bool?)s.Element("AutomaticUpdateCheckEnabled") ?? true; - try { + try + { this.lastSuccessfulUpdateCheck = (DateTime?)s.Element("LastSuccessfulUpdateCheck"); - } catch (FormatException) { + } + catch (FormatException) + { // avoid crashing on settings files invalid due to // https://github.com/icsharpcode/ILSpy/issues/closed/#issue/2 } } - + bool automaticUpdateCheckEnabled; - + public bool AutomaticUpdateCheckEnabled { get { return automaticUpdateCheckEnabled; } set { - if (automaticUpdateCheckEnabled != value) { + if (automaticUpdateCheckEnabled != value) + { automaticUpdateCheckEnabled = value; Save(); OnPropertyChanged(nameof(AutomaticUpdateCheckEnabled)); } } } - + DateTime? lastSuccessfulUpdateCheck; - + public DateTime? LastSuccessfulUpdateCheck { get { return lastSuccessfulUpdateCheck; } set { - if (lastSuccessfulUpdateCheck != value) { + if (lastSuccessfulUpdateCheck != value) + { lastSuccessfulUpdateCheck = value; Save(); OnPropertyChanged(nameof(LastSuccessfulUpdateCheck)); } } } - + public void Save() { XElement updateSettings = new XElement("UpdateSettings"); @@ -252,15 +275,15 @@ namespace ICSharpCode.ILSpy updateSettings.Add(new XElement("LastSuccessfulUpdateCheck", lastSuccessfulUpdateCheck)); ILSpySettings.SaveSettings(updateSettings); } - + public event PropertyChangedEventHandler PropertyChanged; - + void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } - + /// /// If automatic update checking is enabled, checks if there are any updates available. /// Returns the download URL if an update is available. @@ -271,18 +294,23 @@ namespace ICSharpCode.ILSpy UpdateSettings s = new UpdateSettings(spySettings); // If we're in an MSIX package, updates work differently - if (s.AutomaticUpdateCheckEnabled && !WindowsVersionHelper.HasPackageIdentity) { + if (s.AutomaticUpdateCheckEnabled && !WindowsVersionHelper.HasPackageIdentity) + { // perform update check if we never did one before; // or if the last check wasn't in the past 7 days if (s.LastSuccessfulUpdateCheck == null - || s.LastSuccessfulUpdateCheck < DateTime.UtcNow.AddDays(-7) - || s.LastSuccessfulUpdateCheck > DateTime.UtcNow) + || s.LastSuccessfulUpdateCheck < DateTime.UtcNow.AddDays(-7) + || s.LastSuccessfulUpdateCheck > DateTime.UtcNow) { return await CheckForUpdateInternal(s); - } else { + } + else + { return null; } - } else { + } + else + { return null; } } @@ -295,20 +323,23 @@ namespace ICSharpCode.ILSpy static async Task CheckForUpdateInternal(UpdateSettings s) { - try { + try + { var v = await GetLatestVersionAsync(); s.LastSuccessfulUpdateCheck = DateTime.UtcNow; if (v.Version > currentVersion) return v.DownloadUrl; else return null; - } catch (Exception) { + } + catch (Exception) + { // ignore errors getting the version info return null; } } } - + /// /// Interface that allows plugins to extend the about page. /// diff --git a/ILSpy/Analyzers/AnalyzeCommand.cs b/ILSpy/Analyzers/AnalyzeCommand.cs index 35ae8a987..71a041539 100644 --- a/ILSpy/Analyzers/AnalyzeCommand.cs +++ b/ILSpy/Analyzers/AnalyzeCommand.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Properties; @@ -41,7 +42,8 @@ namespace ICSharpCode.ILSpy.Analyzers { if (context.SelectedTreeNodes == null) return context.Reference != null && context.Reference.Reference is IEntity; - foreach (IMemberTreeNode node in context.SelectedTreeNodes) { + foreach (IMemberTreeNode node in context.SelectedTreeNodes) + { if (!IsValidReference(node.Member)) return false; } @@ -56,32 +58,44 @@ namespace ICSharpCode.ILSpy.Analyzers public void Execute(TextViewContext context) { - if (context.SelectedTreeNodes != null) { - foreach (IMemberTreeNode node in context.SelectedTreeNodes) { + if (context.SelectedTreeNodes != null) + { + foreach (IMemberTreeNode node in context.SelectedTreeNodes) + { MainWindow.Instance.AnalyzerTreeView.Analyze(node.Member); } - } else if (context.Reference != null && context.Reference.Reference is IEntity entity) { + } + else if (context.Reference != null && context.Reference.Reference is IEntity entity) + { MainWindow.Instance.AnalyzerTreeView.Analyze(entity); } } public override bool CanExecute(object parameter) { - if (MainWindow.Instance.AnalyzerTreeView.IsKeyboardFocusWithin) { + if (MainWindow.Instance.AnalyzerTreeView.IsKeyboardFocusWithin) + { return MainWindow.Instance.AnalyzerTreeView.SelectedItems.OfType().All(n => n is IMemberTreeNode); - } else { + } + else + { return MainWindow.Instance.SelectedNodes.All(n => n is IMemberTreeNode); } } public override void Execute(object parameter) { - if (MainWindow.Instance.AnalyzerTreeView.IsKeyboardFocusWithin) { - foreach (IMemberTreeNode node in MainWindow.Instance.AnalyzerTreeView.SelectedItems.OfType().ToArray()) { + if (MainWindow.Instance.AnalyzerTreeView.IsKeyboardFocusWithin) + { + foreach (IMemberTreeNode node in MainWindow.Instance.AnalyzerTreeView.SelectedItems.OfType().ToArray()) + { MainWindow.Instance.AnalyzerTreeView.Analyze(node.Member); } - } else { - foreach (IMemberTreeNode node in MainWindow.Instance.SelectedNodes) { + } + else + { + foreach (IMemberTreeNode node in MainWindow.Instance.SelectedNodes) + { MainWindow.Instance.AnalyzerTreeView.Analyze(node.Member); } } diff --git a/ILSpy/Analyzers/AnalyzerContext.cs b/ILSpy/Analyzers/AnalyzerContext.cs index 651375954..915c1cfa8 100644 --- a/ILSpy/Analyzers/AnalyzerContext.cs +++ b/ILSpy/Analyzers/AnalyzerContext.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Concurrent; using System.Reflection.Metadata; using System.Threading; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -48,9 +49,12 @@ namespace ICSharpCode.ILSpy.Analyzers return null; var module = method.ParentModule.PEFile; var md = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); - try { + try + { return module.Reader.GetMethodBody(md.RelativeVirtualAddress); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { return null; } } diff --git a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs index 61067d5f7..17053016c 100644 --- a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Reflection.Metadata; using System.Windows; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.TreeView; @@ -31,25 +32,27 @@ namespace ICSharpCode.ILSpy.Analyzers public abstract class AnalyzerEntityTreeNode : AnalyzerTreeNode, IMemberTreeNode { public abstract IEntity Member { get; } - + public override void ActivateItem(System.Windows.RoutedEventArgs e) { e.Handled = true; - if (this.Member.MetadataToken.IsNil) { + if (this.Member.MetadataToken.IsNil) + { MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy"); return; } MainWindow.Instance.JumpToReference(this.Member); } - + public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies) { - foreach (LoadedAssembly asm in removedAssemblies) { + foreach (LoadedAssembly asm in removedAssemblies) + { if (this.Member.ParentModule.PEFile == asm.GetPEFileOrNull()) return false; // remove this node } this.Children.RemoveAll( - delegate(SharpTreeNode n) { + delegate (SharpTreeNode n) { AnalyzerTreeNode an = n as AnalyzerTreeNode; return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies); }); diff --git a/ILSpy/Analyzers/AnalyzerScope.cs b/ILSpy/Analyzers/AnalyzerScope.cs index bcc2722d1..3aba1ca36 100644 --- a/ILSpy/Analyzers/AnalyzerScope.cs +++ b/ILSpy/Analyzers/AnalyzerScope.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; using System.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -48,10 +49,13 @@ namespace ICSharpCode.ILSpy.Analyzers { AssemblyList = assemblyList; AnalyzedSymbol = entity; - if (entity is ITypeDefinition type) { + if (entity is ITypeDefinition type) + { typeScope = type; effectiveAccessibility = DetermineEffectiveAccessibility(ref typeScope); - } else { + } + else + { typeScope = entity.DeclaringTypeDefinition; effectiveAccessibility = DetermineEffectiveAccessibility(ref typeScope, entity.Accessibility); } @@ -71,23 +75,31 @@ namespace ICSharpCode.ILSpy.Analyzers public IEnumerable GetAllModules() { - foreach (var module in AssemblyList.GetAssemblies()) { + foreach (var module in AssemblyList.GetAssemblies()) + { var file = module.GetPEFileOrNull(); - if (file == null) continue; + if (file == null) + continue; yield return file; } } public IEnumerable GetTypesInScope(CancellationToken ct) { - if (IsLocal) { - foreach (var type in TreeTraversal.PreOrder(typeScope, t => t.NestedTypes)) { + if (IsLocal) + { + foreach (var type in TreeTraversal.PreOrder(typeScope, t => t.NestedTypes)) + { yield return type; } - } else { - foreach (var module in GetModulesInScope(ct)) { + } + else + { + foreach (var module in GetModulesInScope(ct)) + { var typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver()); - foreach (var type in typeSystem.MainModule.TypeDefinitions) { + foreach (var type in typeSystem.MainModule.TypeDefinitions) + { yield return type; } } @@ -97,7 +109,8 @@ namespace ICSharpCode.ILSpy.Analyzers static Accessibility DetermineEffectiveAccessibility(ref ITypeDefinition typeScope, Accessibility memberAccessibility = Accessibility.Public) { Accessibility accessibility = memberAccessibility; - while (typeScope.DeclaringTypeDefinition != null && !accessibility.LessThanOrEqual(Accessibility.Private)) { + while (typeScope.DeclaringTypeDefinition != null && !accessibility.LessThanOrEqual(Accessibility.Private)) + { accessibility = accessibility.Intersect(typeScope.Accessibility); typeScope = typeScope.DeclaringTypeDefinition; } @@ -122,9 +135,11 @@ namespace ICSharpCode.ILSpy.Analyzers toWalkFiles.Push(self); checkedFiles.Add(self); - do { + do + { PEFile curFile = toWalkFiles.Pop(); - foreach (var assembly in AssemblyList.GetAssemblies()) { + foreach (var assembly in AssemblyList.GetAssemblies()) + { ct.ThrowIfCancellationRequested(); bool found = false; var module = assembly.GetPEFileOrNull(); @@ -133,15 +148,19 @@ namespace ICSharpCode.ILSpy.Analyzers if (checkedFiles.Contains(module)) continue; var resolver = assembly.GetAssemblyResolver(); - foreach (var reference in module.AssemblyReferences) { - using (LoadedAssembly.DisableAssemblyLoad(AssemblyList)) { - if (resolver.Resolve(reference) == curFile) { + foreach (var reference in module.AssemblyReferences) + { + using (LoadedAssembly.DisableAssemblyLoad(AssemblyList)) + { + if (resolver.Resolve(reference) == curFile) + { found = true; break; } } } - if (found && checkedFiles.Add(module)) { + if (found && checkedFiles.Add(module)) + { if (ModuleReferencesScopeType(module.Metadata, reflectionTypeScopeName, typeScope.Namespace)) yield return module; if (ModuleForwardsScopeType(module.Metadata, reflectionTypeScopeName, typeScope.Namespace)) @@ -161,18 +180,22 @@ namespace ICSharpCode.ILSpy.Analyzers var attributes = self.Metadata.CustomAttributes.Select(h => self.Metadata.GetCustomAttribute(h)) .Where(ca => ca.GetAttributeType(self.Metadata).GetFullTypeName(self.Metadata).ToString() == "System.Runtime.CompilerServices.InternalsVisibleToAttribute"); var friendAssemblies = new HashSet(); - foreach (var attribute in attributes) { + foreach (var attribute in attributes) + { string assemblyName = attribute.DecodeValue(typeProvider).FixedArguments[0].Value as string; assemblyName = assemblyName.Split(',')[0]; // strip off any public key info friendAssemblies.Add(assemblyName); } - if (friendAssemblies.Count > 0) { + if (friendAssemblies.Count > 0) + { IEnumerable assemblies = AssemblyList.GetAssemblies(); - foreach (var assembly in assemblies) { + foreach (var assembly in assemblies) + { ct.ThrowIfCancellationRequested(); - if (friendAssemblies.Contains(assembly.ShortName)) { + if (friendAssemblies.Contains(assembly.ShortName)) + { var module = assembly.GetPEFileOrNull(); if (module == null) continue; @@ -186,9 +209,11 @@ namespace ICSharpCode.ILSpy.Analyzers bool ModuleReferencesScopeType(MetadataReader metadata, string typeScopeName, string typeScopeNamespace) { bool hasRef = false; - foreach (var h in metadata.TypeReferences) { + foreach (var h in metadata.TypeReferences) + { var typeRef = metadata.GetTypeReference(h); - if (metadata.StringComparer.Equals(typeRef.Name, typeScopeName) && metadata.StringComparer.Equals(typeRef.Namespace, typeScopeNamespace)) { + if (metadata.StringComparer.Equals(typeRef.Name, typeScopeName) && metadata.StringComparer.Equals(typeRef.Namespace, typeScopeNamespace)) + { hasRef = true; break; } @@ -199,9 +224,11 @@ namespace ICSharpCode.ILSpy.Analyzers bool ModuleForwardsScopeType(MetadataReader metadata, string typeScopeName, string typeScopeNamespace) { bool hasForward = false; - foreach (var h in metadata.ExportedTypes) { + foreach (var h in metadata.ExportedTypes) + { var exportedType = metadata.GetExportedType(h); - if (exportedType.IsForwarder && metadata.StringComparer.Equals(exportedType.Name, typeScopeName) && metadata.StringComparer.Equals(exportedType.Namespace, typeScopeNamespace)) { + if (exportedType.IsForwarder && metadata.StringComparer.Equals(exportedType.Name, typeScopeName) && metadata.StringComparer.Equals(exportedType.Namespace, typeScopeNamespace)) + { hasForward = true; break; } diff --git a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs index a49051aba..72cee784e 100644 --- a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Analyzers.TreeNodes; using ICSharpCode.ILSpy.TreeNodes; @@ -52,27 +53,33 @@ namespace ICSharpCode.ILSpy.Analyzers protected IEnumerable FetchChildren(CancellationToken ct) { - if (symbol is IEntity) { + if (symbol is IEntity) + { var context = new AnalyzerContext() { CancellationToken = ct, Language = Language, AssemblyList = MainWindow.Instance.CurrentAssemblyList }; - foreach (var result in analyzer.Analyze(symbol, context)) { + foreach (var result in analyzer.Analyze(symbol, context)) + { yield return SymbolTreeNodeFactory(result); } - } else { + } + else + { throw new NotSupportedException("Currently symbols that are not entities are not supported!"); } } AnalyzerTreeNode SymbolTreeNodeFactory(ISymbol symbol) { - if (symbol == null) { + if (symbol == null) + { throw new ArgumentNullException(nameof(symbol)); } - switch (symbol) { + switch (symbol) + { case IModule module: return new AnalyzedModuleTreeNode(module) { Language = this.Language @@ -105,7 +112,8 @@ namespace ICSharpCode.ILSpy.Analyzers protected override void OnIsVisibleChanged() { base.OnIsVisibleChanged(); - if (!this.IsVisible && threading.IsRunning) { + if (!this.IsVisible && threading.IsRunning) + { this.LazyLoading = true; threading.Cancel(); this.Children.Clear(); @@ -116,11 +124,13 @@ namespace ICSharpCode.ILSpy.Analyzers { // only cancel a running analysis if user has manually added/removed assemblies bool manualAdd = false; - foreach (var asm in addedAssemblies) { + foreach (var asm in addedAssemblies) + { if (!asm.IsAutoLoaded) manualAdd = true; } - if (removedAssemblies.Count > 0 || manualAdd) { + if (removedAssemblies.Count > 0 || manualAdd) + { this.LazyLoading = true; threading.Cancel(); this.Children.Clear(); diff --git a/ILSpy/Analyzers/AnalyzerTreeNode.cs b/ILSpy/Analyzers/AnalyzerTreeNode.cs index 5b14c6a0e..96a1a1a5e 100644 --- a/ILSpy/Analyzers/AnalyzerTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerTreeNode.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; + using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy.Analyzers @@ -30,7 +31,8 @@ namespace ICSharpCode.ILSpy.Analyzers public Language Language { get { return language; } set { - if (language != value) { + if (language != value) + { language = value; foreach (var child in this.Children.OfType()) child.Language = value; @@ -55,7 +57,8 @@ namespace ICSharpCode.ILSpy.Analyzers protected override void OnChildrenChanged(NotifyCollectionChangedEventArgs e) { - if (e.NewItems != null) { + if (e.NewItems != null) + { foreach (AnalyzerTreeNode a in e.NewItems.OfType()) a.Language = this.Language; } diff --git a/ILSpy/Analyzers/AnalyzerTreeView.cs b/ILSpy/Analyzers/AnalyzerTreeView.cs index 8bc21a665..cf55491f0 100644 --- a/ILSpy/Analyzers/AnalyzerTreeView.cs +++ b/ILSpy/Analyzers/AnalyzerTreeView.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Windows; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Analyzers.TreeNodes; using ICSharpCode.ILSpy.Docking; @@ -45,9 +46,12 @@ namespace ICSharpCode.ILSpy.Analyzers void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e) { - if (e.Action == NotifyCollectionChangedAction.Reset) { + if (e.Action == NotifyCollectionChangedAction.Reset) + { this.Root.Children.Clear(); - } else { + } + else + { List removedAssemblies = new List(); if (e.OldItems != null) removedAssemblies.AddRange(e.OldItems.Cast()); @@ -75,12 +79,14 @@ namespace ICSharpCode.ILSpy.Analyzers public void ShowOrFocus(AnalyzerTreeNode node) { - if (node is AnalyzerEntityTreeNode) { + if (node is AnalyzerEntityTreeNode) + { var an = node as AnalyzerEntityTreeNode; var found = this.Root.Children.OfType().FirstOrDefault(n => n.Member == an.Member); - if (found != null) { + if (found != null) + { Show(); - + found.IsExpanded = true; this.SelectedItem = found; this.FocusNode(found); @@ -92,16 +98,19 @@ namespace ICSharpCode.ILSpy.Analyzers public void Analyze(IEntity entity) { - if (entity == null) { + if (entity == null) + { throw new ArgumentNullException(nameof(entity)); } - if (entity.MetadataToken.IsNil) { + if (entity.MetadataToken.IsNil) + { MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy"); return; } - switch (entity) { + switch (entity) + { case ITypeDefinition td: ShowOrFocus(new AnalyzedTypeTreeNode(td)); break; @@ -122,13 +131,13 @@ namespace ICSharpCode.ILSpy.Analyzers throw new ArgumentOutOfRangeException(nameof(entity), $"Entity {entity.GetType().FullName} is not supported."); } } - + sealed class AnalyzerRootNode : AnalyzerTreeNode { public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies) { this.Children.RemoveAll( - delegate(SharpTreeNode n) { + delegate (SharpTreeNode n) { AnalyzerTreeNode an = n as AnalyzerTreeNode; return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies); }); diff --git a/ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs b/ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs index 1f35d1867..ba5b216db 100644 --- a/ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs @@ -22,6 +22,7 @@ using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Runtime.InteropServices; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -38,9 +39,12 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var scope = context.GetScopeOf(attributeType); // TODO: DeclSecurity attributes are not supported. - if (!IsBuiltinAttribute(attributeType, out var knownAttribute)) { + if (!IsBuiltinAttribute(attributeType, out var knownAttribute)) + { return HandleCustomAttribute(attributeType, scope); - } else { + } + else + { return HandleBuiltinAttribute(knownAttribute, scope).SelectMany(s => s); } } @@ -48,7 +52,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin bool IsBuiltinAttribute(ITypeDefinition attributeType, out KnownAttribute knownAttribute) { knownAttribute = attributeType.IsBuiltinAttribute(); - switch (knownAttribute) { + switch (knownAttribute) + { case KnownAttribute.Serializable: case KnownAttribute.ComImport: case KnownAttribute.StructLayout: @@ -107,10 +112,12 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin .Select(m => m.AccessorOwner ?? m); } - foreach (Decompiler.Metadata.PEFile module in scope.GetAllModules()) { + foreach (Decompiler.Metadata.PEFile module in scope.GetAllModules()) + { var ts = new DecompilerTypeSystem(module, module.GetAssemblyResolver()); - switch (attribute) { + switch (attribute) + { case KnownAttribute.Serializable: case KnownAttribute.ComImport: case KnownAttribute.StructLayout: @@ -145,31 +152,42 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { var genericContext = new GenericContext(); // type arguments do not matter for this analyzer. - foreach (var module in scope.GetAllModules()) { + foreach (var module in scope.GetAllModules()) + { var ts = new DecompilerTypeSystem(module, module.GetAssemblyResolver()); var referencedParameters = new HashSet(); - foreach (var h in module.Metadata.CustomAttributes) { + foreach (var h in module.Metadata.CustomAttributes) + { var customAttribute = module.Metadata.GetCustomAttribute(h); var attributeCtor = ts.MainModule.ResolveMethod(customAttribute.Constructor, genericContext); if (attributeCtor.DeclaringTypeDefinition != null && attributeCtor.ParentModule.PEFile == attributeType.ParentModule.PEFile - && attributeCtor.DeclaringTypeDefinition.MetadataToken == attributeType.MetadataToken) { - if (customAttribute.Parent.Kind == HandleKind.Parameter) { + && attributeCtor.DeclaringTypeDefinition.MetadataToken == attributeType.MetadataToken) + { + if (customAttribute.Parent.Kind == HandleKind.Parameter) + { referencedParameters.Add((ParameterHandle)customAttribute.Parent); - } else { + } + else + { var parent = GetParentEntity(ts, customAttribute); if (parent != null) yield return parent; } } } - if (referencedParameters.Count > 0) { - foreach (var h in module.Metadata.MethodDefinitions) { + if (referencedParameters.Count > 0) + { + foreach (var h in module.Metadata.MethodDefinitions) + { var md = module.Metadata.GetMethodDefinition(h); - foreach (var p in md.GetParameters()) { - if (referencedParameters.Contains(p)) { + foreach (var p in md.GetParameters()) + { + if (referencedParameters.Contains(p)) + { var method = ts.MainModule.ResolveMethod(h, genericContext); - if (method != null) { + if (method != null) + { if (method.IsAccessor) yield return method.AccessorOwner; else @@ -186,7 +204,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin ISymbol GetParentEntity(DecompilerTypeSystem ts, CustomAttribute customAttribute) { var metadata = ts.MainModule.PEFile.Metadata; - switch (customAttribute.Parent.Kind) { + switch (customAttribute.Parent.Kind) + { case HandleKind.MethodDefinition: case HandleKind.FieldDefinition: case HandleKind.PropertyDefinition: diff --git a/ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs index ce8760f68..4e87a0f30 100644 --- a/ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/EventImplementedByAnalyzer.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -34,7 +35,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is IEvent); var scope = context.GetScopeOf((IEvent)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { foreach (var result in AnalyzeType((IEvent)analyzedSymbol, type)) yield return result; } @@ -49,7 +51,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) yield break; - foreach (var @event in type.Events) { + foreach (var @event in type.Events) + { var baseMembers = InheritanceHelper.GetBaseMembers(@event, true); if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module)) yield return @event; diff --git a/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs b/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs index 29df80155..f6c41dc18 100644 --- a/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/EventOverriddenByAnalyzer.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -34,7 +35,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is IEvent); var scope = context.GetScopeOf((IEvent)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { foreach (var result in AnalyzeType((IEvent)analyzedSymbol, type)) yield return result; } @@ -49,10 +51,13 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) yield break; - foreach (var @event in type.Events) { - if (!@event.IsOverride) continue; + foreach (var @event in type.Events) + { + if (!@event.IsOverride) + continue; var baseMembers = InheritanceHelper.GetBaseMembers(@event, false); - if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) { + if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) + { yield return @event; } } diff --git a/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs b/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs index 906b6acf1..38228bc72 100644 --- a/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/FieldAccessAnalyzer.cs @@ -25,11 +25,13 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Analyzers; + using ILOpCode = System.Reflection.Metadata.ILOpCode; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -75,35 +77,44 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is IField); var scope = context.GetScopeOf((IEntity)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.PEFile, type.MetadataToken); var methods = type.GetMembers(m => m is IMethod, Options).OfType(); - foreach (var method in methods) { + foreach (var method in methods) + { if (IsUsedInMethod((IField)analyzedSymbol, method, mappingInfo, context)) yield return method; } - foreach (var property in type.Properties) { - if (property.CanGet && IsUsedInMethod((IField)analyzedSymbol, property.Getter, mappingInfo, context)) { + foreach (var property in type.Properties) + { + if (property.CanGet && IsUsedInMethod((IField)analyzedSymbol, property.Getter, mappingInfo, context)) + { yield return property; continue; } - if (property.CanSet && IsUsedInMethod((IField)analyzedSymbol, property.Setter, mappingInfo, context)) { + if (property.CanSet && IsUsedInMethod((IField)analyzedSymbol, property.Setter, mappingInfo, context)) + { yield return property; continue; } } - foreach (var @event in type.Events) { - if (@event.CanAdd && IsUsedInMethod((IField)analyzedSymbol, @event.AddAccessor, mappingInfo, context)) { + foreach (var @event in type.Events) + { + if (@event.CanAdd && IsUsedInMethod((IField)analyzedSymbol, @event.AddAccessor, mappingInfo, context)) + { yield return @event; continue; } - if (@event.CanRemove && IsUsedInMethod((IField)analyzedSymbol, @event.RemoveAccessor, mappingInfo, context)) { + if (@event.CanRemove && IsUsedInMethod((IField)analyzedSymbol, @event.RemoveAccessor, mappingInfo, context)) + { yield return @event; continue; } - if (@event.CanInvoke && IsUsedInMethod((IField)analyzedSymbol, @event.InvokeAccessor, mappingInfo, context)) { + if (@event.CanInvoke && IsUsedInMethod((IField)analyzedSymbol, @event.InvokeAccessor, mappingInfo, context)) + { yield return @event; continue; } @@ -116,13 +127,18 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (method.MetadataToken.IsNil) return false; var module = method.ParentModule.PEFile; - foreach (var part in mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken)) { + foreach (var part in mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken)) + { var md = module.Metadata.GetMethodDefinition(part); - if (!md.HasBody()) continue; + if (!md.HasBody()) + continue; MethodBodyBlock body; - try { + try + { body = module.Reader.GetMethodBody(md.RelativeVirtualAddress); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { return false; } if (ScanMethodBody(analyzedField, method, body)) @@ -140,24 +156,32 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var blob = methodBody.GetILReader(); var genericContext = new Decompiler.TypeSystem.GenericContext(); // type parameters don't matter for this analyzer - while (blob.RemainingBytes > 0) { + while (blob.RemainingBytes > 0) + { ILOpCode opCode; - try { + try + { opCode = blob.DecodeOpCode(); - if (!CanBeReference(opCode)) { + if (!CanBeReference(opCode)) + { blob.SkipOperand(opCode); continue; } - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { return false; } EntityHandle fieldHandle = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); if (!fieldHandle.Kind.IsMemberKind()) continue; IField field; - try { + try + { field = mainModule.ResolveEntity(fieldHandle, genericContext) as IField; - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { continue; } if (field == null) @@ -173,7 +197,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin bool CanBeReference(ILOpCode code) { - switch (code) { + switch (code) + { case ILOpCode.Ldfld: case ILOpCode.Ldsfld: return !showWrites; diff --git a/ILSpy/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs b/ILSpy/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs index ccc738f65..b1e1e8aef 100644 --- a/ILSpy/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MemberImplementsInterfaceAnalyzer.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -42,7 +43,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin public bool Show(ISymbol symbol) { - switch (symbol?.SymbolKind) { + switch (symbol?.SymbolKind) + { case SymbolKind.Event: case SymbolKind.Indexer: case SymbolKind.Method: diff --git a/ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs index 8f1c16e0a..db9073e2a 100644 --- a/ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MethodImplementedByAnalyzer.cs @@ -23,6 +23,7 @@ using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -37,7 +38,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is IMethod); var scope = context.GetScopeOf((IEntity)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { foreach (var result in AnalyzeType((IMethod)analyzedSymbol, type)) yield return result; } @@ -52,7 +54,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) yield break; - foreach (var method in type.Methods) { + foreach (var method in type.Methods) + { var baseMembers = InheritanceHelper.GetBaseMembers(method, true); if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module)) yield return method; diff --git a/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs index 830cc02ba..7a90f48fa 100644 --- a/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -36,7 +37,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is IMethod); var scope = context.GetScopeOf((IEntity)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { foreach (var result in AnalyzeType((IMethod)analyzedSymbol, type)) yield return result; } @@ -51,10 +53,13 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) yield break; - foreach (var method in type.Methods) { - if (!method.IsOverride) continue; + foreach (var method in type.Methods) + { + if (!method.IsOverride) + continue; var baseMembers = InheritanceHelper.GetBaseMembers(method, false); - if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) { + if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) + { yield return method; } } diff --git a/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs index 425f7d765..c0c01fe65 100644 --- a/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MethodUsedByAnalyzer.cs @@ -22,6 +22,7 @@ using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; @@ -43,35 +44,44 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is IMethod); var scope = context.GetScopeOf((IEntity)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.PEFile, type.MetadataToken); var methods = type.GetMembers(m => m is IMethod, Options).OfType(); - foreach (var method in methods) { + foreach (var method in methods) + { if (IsUsedInMethod((IMethod)analyzedSymbol, method, mappingInfo, context)) yield return method; } - foreach (var property in type.Properties) { - if (property.CanGet && IsUsedInMethod((IMethod)analyzedSymbol, property.Getter, mappingInfo, context)) { + foreach (var property in type.Properties) + { + if (property.CanGet && IsUsedInMethod((IMethod)analyzedSymbol, property.Getter, mappingInfo, context)) + { yield return property; continue; } - if (property.CanSet && IsUsedInMethod((IMethod)analyzedSymbol, property.Setter, mappingInfo, context)) { + if (property.CanSet && IsUsedInMethod((IMethod)analyzedSymbol, property.Setter, mappingInfo, context)) + { yield return property; continue; } } - foreach (var @event in type.Events) { - if (@event.CanAdd && IsUsedInMethod((IMethod)analyzedSymbol, @event.AddAccessor, mappingInfo, context)) { + foreach (var @event in type.Events) + { + if (@event.CanAdd && IsUsedInMethod((IMethod)analyzedSymbol, @event.AddAccessor, mappingInfo, context)) + { yield return @event; continue; } - if (@event.CanRemove && IsUsedInMethod((IMethod)analyzedSymbol, @event.RemoveAccessor, mappingInfo, context)) { + if (@event.CanRemove && IsUsedInMethod((IMethod)analyzedSymbol, @event.RemoveAccessor, mappingInfo, context)) + { yield return @event; continue; } - if (@event.CanInvoke && IsUsedInMethod((IMethod)analyzedSymbol, @event.InvokeAccessor, mappingInfo, context)) { + if (@event.CanInvoke && IsUsedInMethod((IMethod)analyzedSymbol, @event.InvokeAccessor, mappingInfo, context)) + { yield return @event; continue; } @@ -95,35 +105,49 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var baseMethod = InheritanceHelper.GetBaseMember(analyzedMethod); var genericContext = new Decompiler.TypeSystem.GenericContext(); // type parameters don't matter for this analyzer - while (blob.RemainingBytes > 0) { + while (blob.RemainingBytes > 0) + { ILOpCode opCode; - try { + try + { opCode = blob.DecodeOpCode(); - if (!IsSupportedOpCode(opCode)) { + if (!IsSupportedOpCode(opCode)) + { ILParser.SkipOperand(ref blob, opCode); continue; } - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { return false; // unexpected end of blob } var member = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); - if (member.IsNil || !member.Kind.IsMemberKind()) continue; + if (member.IsNil || !member.Kind.IsMemberKind()) + continue; IMember m; - try { + try + { m = (mainModule.ResolveEntity(member, genericContext) as IMember)?.MemberDefinition; - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { continue; } if (m == null) continue; - if (opCode == ILOpCode.Callvirt && baseMethod != null) { - if (IsSameMember(baseMethod, m)) { + if (opCode == ILOpCode.Callvirt && baseMethod != null) + { + if (IsSameMember(baseMethod, m)) + { return true; } - } else { - if (IsSameMember(analyzedMethod, m)) { + } + else + { + if (IsSameMember(analyzedMethod, m)) + { return true; } } @@ -134,7 +158,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin static bool IsSupportedOpCode(ILOpCode opCode) { - switch (opCode) { + switch (opCode) + { case ILOpCode.Call: case ILOpCode.Callvirt: case ILOpCode.Ldtoken: diff --git a/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs index e6ae54534..c3e892419 100644 --- a/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MethodUsesAnalyzer.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; @@ -37,7 +38,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin public IEnumerable Analyze(ISymbol symbol, AnalyzerContext context) { - if (symbol is IMethod method) { + if (symbol is IMethod method) + { var typeSystem = context.GetOrCreateTypeSystem(method.ParentModule.PEFile); return context.Language.GetCodeMappingInfo(method.ParentModule.PEFile, method.MetadataToken) .GetMethodParts((MethodDefinitionHandle)method.MetadataToken) @@ -50,42 +52,56 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { var module = typeSystem.MainModule; var md = module.PEFile.Metadata.GetMethodDefinition(handle); - if (!md.HasBody()) yield break; + if (!md.HasBody()) + yield break; BlobReader blob; - try { + try + { blob = module.PEFile.Reader.GetMethodBody(md.RelativeVirtualAddress).GetILReader(); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { yield break; } var visitor = new TypeDefinitionCollector(); var genericContext = new Decompiler.TypeSystem.GenericContext(); // type parameters don't matter for this analyzer - while (blob.RemainingBytes > 0) { + while (blob.RemainingBytes > 0) + { ILOpCode opCode; - try { + try + { opCode = blob.DecodeOpCode(); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { yield break; } - switch (opCode.GetOperandType()) { + switch (opCode.GetOperandType()) + { case OperandType.Field: case OperandType.Method: case OperandType.Sig: case OperandType.Tok: var member = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); - if (member.IsNil) continue; + if (member.IsNil) + continue; - switch (member.Kind) { + switch (member.Kind) + { case HandleKind.StandaloneSignature: break; case HandleKind.TypeDefinition: case HandleKind.TypeReference: case HandleKind.TypeSpecification: IType ty; - try { + try + { ty = module.ResolveType(member, genericContext); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { ty = null; } ty?.AcceptVisitor(visitor); @@ -95,9 +111,12 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin case HandleKind.MemberReference: case HandleKind.FieldDefinition: IEntity m; - try { + try + { m = module.ResolveEntity(member, genericContext); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { m = null; } if (m != null) @@ -106,23 +125,27 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin } break; default: - try { + try + { ILParser.SkipOperand(ref blob, opCode); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { yield break; } break; } } - foreach (var type in visitor.UsedTypes) { + foreach (var type in visitor.UsedTypes) + { yield return type; } } class TypeDefinitionCollector : TypeVisitor { - public readonly List UsedTypes = new List(); + public readonly List UsedTypes = new List(); public override IType VisitTypeDefinition(ITypeDefinition type) { diff --git a/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs index b03d804e5..a778aacd4 100644 --- a/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/MethodVirtualUsedByAnalyzer.cs @@ -21,6 +21,7 @@ using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; @@ -42,35 +43,44 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is IMethod); var scope = context.GetScopeOf((IEntity)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.PEFile, type.MetadataToken); var methods = type.GetMembers(m => m is IMethod, Options).OfType(); - foreach (var method in methods) { + foreach (var method in methods) + { if (IsUsedInMethod((IMethod)analyzedSymbol, method, mappingInfo, context)) yield return method; } - foreach (var property in type.Properties) { - if (property.CanGet && IsUsedInMethod((IMethod)analyzedSymbol, property.Getter, mappingInfo, context)) { + foreach (var property in type.Properties) + { + if (property.CanGet && IsUsedInMethod((IMethod)analyzedSymbol, property.Getter, mappingInfo, context)) + { yield return property; continue; } - if (property.CanSet && IsUsedInMethod((IMethod)analyzedSymbol, property.Setter, mappingInfo, context)) { + if (property.CanSet && IsUsedInMethod((IMethod)analyzedSymbol, property.Setter, mappingInfo, context)) + { yield return property; continue; } } - foreach (var @event in type.Events) { - if (@event.CanAdd && IsUsedInMethod((IMethod)analyzedSymbol, @event.AddAccessor, mappingInfo, context)) { + foreach (var @event in type.Events) + { + if (@event.CanAdd && IsUsedInMethod((IMethod)analyzedSymbol, @event.AddAccessor, mappingInfo, context)) + { yield return @event; continue; } - if (@event.CanRemove && IsUsedInMethod((IMethod)analyzedSymbol, @event.RemoveAccessor, mappingInfo, context)) { + if (@event.CanRemove && IsUsedInMethod((IMethod)analyzedSymbol, @event.RemoveAccessor, mappingInfo, context)) + { yield return @event; continue; } - if (@event.CanInvoke && IsUsedInMethod((IMethod)analyzedSymbol, @event.InvokeAccessor, mappingInfo, context)) { + if (@event.CanInvoke && IsUsedInMethod((IMethod)analyzedSymbol, @event.InvokeAccessor, mappingInfo, context)) + { yield return @event; continue; } @@ -92,22 +102,27 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var blob = methodBody.GetILReader(); var genericContext = new Decompiler.TypeSystem.GenericContext(); - while (blob.RemainingBytes > 0) { + while (blob.RemainingBytes > 0) + { var opCode = blob.DecodeOpCode(); - switch (opCode.GetOperandType()) { + switch (opCode.GetOperandType()) + { case OperandType.Field: case OperandType.Method: case OperandType.Sig: case OperandType.Tok: var member = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); - if (member.IsNil) continue; + if (member.IsNil) + continue; - switch (member.Kind) { + switch (member.Kind) + { case HandleKind.MethodDefinition: case HandleKind.MethodSpecification: case HandleKind.MemberReference: var m = (mainModule.ResolveEntity(member, genericContext) as IMember)?.MemberDefinition; - if (m.MetadataToken == analyzedMethod.MetadataToken && m.ParentModule.PEFile == analyzedMethod.ParentModule.PEFile) { + if (m.MetadataToken == analyzedMethod.MetadataToken && m.ParentModule.PEFile == analyzedMethod.ParentModule.PEFile) + { return true; } break; diff --git a/ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs index c9f040507..2b8cb8f84 100644 --- a/ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/PropertyImplementedByAnalyzer.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -34,7 +35,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is IProperty); var scope = context.GetScopeOf((IProperty)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { foreach (var result in AnalyzeType((IProperty)analyzedSymbol, type)) yield return result; } @@ -49,7 +51,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) yield break; - foreach (var property in type.Properties) { + foreach (var property in type.Properties) + { var baseMembers = InheritanceHelper.GetBaseMembers(property, true); if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module)) yield return property; diff --git a/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs b/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs index 7d310c078..7ec8b5cee 100644 --- a/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs @@ -23,6 +23,7 @@ using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -37,7 +38,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is IProperty); var scope = context.GetScopeOf((IProperty)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { foreach (var result in AnalyzeType((IProperty)analyzedSymbol, type)) yield return result; } @@ -52,10 +54,13 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module)) yield break; - foreach (var property in type.Properties) { - if (!property.IsOverride) continue; + foreach (var property in type.Properties) + { + if (!property.IsOverride) + continue; var baseMembers = InheritanceHelper.GetBaseMembers(property, false); - if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) { + if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) + { yield return property; } } diff --git a/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs index 87bd95e01..f69bb8743 100644 --- a/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/TypeExposedByAnalyzer.cs @@ -23,6 +23,7 @@ using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -39,7 +40,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is ITypeDefinition); var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { foreach (var result in ScanType((ITypeDefinition)analyzedSymbol, type, context)) yield return result; } @@ -57,22 +59,26 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var visitor = new TypeDefinitionUsedVisitor(analyzedType, true); - foreach (IField field in type.Fields) { + foreach (IField field in type.Fields) + { if (TypeIsExposedBy(visitor, field)) yield return field; } - foreach (IProperty property in type.Properties) { + foreach (IProperty property in type.Properties) + { if (TypeIsExposedBy(visitor, property)) yield return property; } - foreach (IEvent @event in type.Events) { + foreach (IEvent @event in type.Events) + { if (TypeIsExposedBy(visitor, @event)) yield return @event; } - foreach (IMethod method in type.Methods) { + foreach (IMethod method in type.Methods) + { if (TypeIsExposedBy(visitor, method)) yield return method; } @@ -91,7 +97,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin bool TypeIsExposedBy(TypeDefinitionUsedVisitor visitor, IProperty property) { - if (property.Accessibility == Accessibility.Private) { + if (property.Accessibility == Accessibility.Private) + { if (!property.IsExplicitInterfaceImplementation) return false; } @@ -99,7 +106,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin visitor.Found = false; property.ReturnType.AcceptVisitor(visitor); - foreach (var p in property.Parameters) { + foreach (var p in property.Parameters) + { p.Type.AcceptVisitor(visitor); } @@ -108,7 +116,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin bool TypeIsExposedBy(TypeDefinitionUsedVisitor visitor, IEvent @event) { - if (@event.Accessibility == Accessibility.Private) { + if (@event.Accessibility == Accessibility.Private) + { if (!@event.IsExplicitInterfaceImplementation) return false; } @@ -121,7 +130,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin bool TypeIsExposedBy(TypeDefinitionUsedVisitor visitor, IMethod method) { - if (method.Accessibility == Accessibility.Private) { + if (method.Accessibility == Accessibility.Private) + { if (!method.IsExplicitInterfaceImplementation) return false; } @@ -129,7 +139,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin visitor.Found = false; method.ReturnType.AcceptVisitor(visitor); - foreach (var p in method.Parameters) { + foreach (var p in method.Parameters) + { p.Type.AcceptVisitor(visitor); } diff --git a/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs index 1d2a1d960..4d1d5bc30 100644 --- a/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/TypeExtensionMethodsAnalyzer.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.Diagnostics; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -17,7 +18,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is ITypeDefinition); var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { foreach (var result in ScanType((ITypeDefinition)analyzedSymbol, type, context)) yield return result; } @@ -28,8 +30,10 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin if (!type.HasExtensionMethods) yield break; - foreach (IMethod method in type.Methods) { - if (!method.IsExtensionMethod) continue; + foreach (IMethod method in type.Methods) + { + if (!method.IsExtensionMethod) + continue; var firstParamType = method.Parameters[0].Type.GetDefinition(); if (firstParamType != null && diff --git a/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs index a8a7e9794..cd5b68f1f 100644 --- a/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/TypeInstantiatedByAnalyzer.cs @@ -24,6 +24,7 @@ using System.Linq; using System.Reflection.Metadata; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; @@ -43,35 +44,44 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is ITypeDefinition); var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { var mappingInfo = context.Language.GetCodeMappingInfo(type.ParentModule.PEFile, type.MetadataToken); var methods = type.GetMembers(m => m is IMethod, Options).OfType(); - foreach (var method in methods) { + foreach (var method in methods) + { if (IsUsedInMethod((ITypeDefinition)analyzedSymbol, method, mappingInfo, context)) yield return method; } - foreach (var property in type.Properties) { - if (property.CanGet && IsUsedInMethod((ITypeDefinition)analyzedSymbol, property.Getter, mappingInfo, context)) { + foreach (var property in type.Properties) + { + if (property.CanGet && IsUsedInMethod((ITypeDefinition)analyzedSymbol, property.Getter, mappingInfo, context)) + { yield return property; continue; } - if (property.CanSet && IsUsedInMethod((ITypeDefinition)analyzedSymbol, property.Setter, mappingInfo, context)) { + if (property.CanSet && IsUsedInMethod((ITypeDefinition)analyzedSymbol, property.Setter, mappingInfo, context)) + { yield return property; continue; } } - foreach (var @event in type.Events) { - if (@event.CanAdd && IsUsedInMethod((ITypeDefinition)analyzedSymbol, @event.AddAccessor, mappingInfo, context)) { + foreach (var @event in type.Events) + { + if (@event.CanAdd && IsUsedInMethod((ITypeDefinition)analyzedSymbol, @event.AddAccessor, mappingInfo, context)) + { yield return @event; continue; } - if (@event.CanRemove && IsUsedInMethod((ITypeDefinition)analyzedSymbol, @event.RemoveAccessor, mappingInfo, context)) { + if (@event.CanRemove && IsUsedInMethod((ITypeDefinition)analyzedSymbol, @event.RemoveAccessor, mappingInfo, context)) + { yield return @event; continue; } - if (@event.CanInvoke && IsUsedInMethod((ITypeDefinition)analyzedSymbol, @event.InvokeAccessor, mappingInfo, context)) { + if (@event.CanInvoke && IsUsedInMethod((ITypeDefinition)analyzedSymbol, @event.InvokeAccessor, mappingInfo, context)) + { yield return @event; continue; } @@ -92,24 +102,32 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var module = (MetadataModule)method.ParentModule; var genericContext = new Decompiler.TypeSystem.GenericContext(); // type parameters don't matter for this analyzer - while (blob.RemainingBytes > 0) { + while (blob.RemainingBytes > 0) + { ILOpCode opCode; - try { + try + { opCode = blob.DecodeOpCode(); - if (!CanBeReference(opCode)) { + if (!CanBeReference(opCode)) + { blob.SkipOperand(opCode); continue; } - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { return false; } EntityHandle methodHandle = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); if (!methodHandle.Kind.IsMemberKind()) continue; IMethod ctor; - try { + try + { ctor = module.ResolveMethod(methodHandle, genericContext); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { continue; } if (ctor == null || !ctor.IsConstructor) diff --git a/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs b/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs index 744a46991..60b513e14 100644 --- a/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs +++ b/ILSpy/Analyzers/Builtin/TypeUsedByAnalyzer.cs @@ -22,6 +22,7 @@ using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; @@ -39,7 +40,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin { Debug.Assert(analyzedSymbol is ITypeDefinition); var scope = context.GetScopeOf((ITypeDefinition)analyzedSymbol); - foreach (var type in scope.GetTypesInScope(context.CancellationToken)) { + foreach (var type in scope.GetTypesInScope(context.CancellationToken)) + { foreach (var result in ScanType((ITypeDefinition)analyzedSymbol, type, context)) yield return result; } @@ -53,14 +55,16 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var visitor = new TypeDefinitionUsedVisitor(analyzedEntity, false); - foreach (var bt in type.DirectBaseTypes) { + foreach (var bt in type.DirectBaseTypes) + { bt.AcceptVisitor(visitor); } if (visitor.Found) yield return type; - foreach (var member in type.Members) { + foreach (var member in type.Members) + { visitor.Found = false; VisitMember(visitor, member, context, scanBodies: true); if (visitor.Found) @@ -71,18 +75,21 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin void VisitMember(TypeDefinitionUsedVisitor visitor, IMember member, AnalyzerContext context, bool scanBodies = false) { member.DeclaringType.AcceptVisitor(visitor); - switch (member) { + switch (member) + { case IField field: field.ReturnType.AcceptVisitor(visitor); break; case IMethod method: - foreach (var p in method.Parameters) { + foreach (var p in method.Parameters) + { p.Type.AcceptVisitor(visitor); } method.ReturnType.AcceptVisitor(visitor); - foreach (var t in method.TypeArguments) { + foreach (var t in method.TypeArguments) + { t.AcceptVisitor(visitor); } @@ -91,7 +98,8 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin break; case IProperty property: - foreach (var p in property.Parameters) { + foreach (var p in property.Parameters) + { p.Type.AcceptVisitor(visitor); } @@ -127,32 +135,40 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin var module = (MetadataModule)method.ParentModule; var genericContext = new Decompiler.TypeSystem.GenericContext(); // type parameters don't matter for this analyzer - if (!methodBody.LocalSignature.IsNil) { - foreach (var type in module.DecodeLocalSignature(methodBody.LocalSignature, genericContext)) { + if (!methodBody.LocalSignature.IsNil) + { + foreach (var type in module.DecodeLocalSignature(methodBody.LocalSignature, genericContext)) + { type.AcceptVisitor(visitor); - if (visitor.Found) return; + if (visitor.Found) + return; } } var blob = methodBody.GetILReader(); - while (!visitor.Found && blob.RemainingBytes > 0) { + while (!visitor.Found && blob.RemainingBytes > 0) + { var opCode = blob.DecodeOpCode(); - switch (opCode.GetOperandType()) { + switch (opCode.GetOperandType()) + { case OperandType.Field: case OperandType.Method: case OperandType.Sig: case OperandType.Tok: case OperandType.Type: var member = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32()); - if (member.IsNil) continue; - switch (member.Kind) { + if (member.IsNil) + continue; + switch (member.Kind) + { case HandleKind.TypeReference: case HandleKind.TypeSpecification: case HandleKind.TypeDefinition: module.ResolveType(member, genericContext).AcceptVisitor(visitor); - if (visitor.Found) return; + if (visitor.Found) + return; break; case HandleKind.FieldDefinition: @@ -161,18 +177,21 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin case HandleKind.MethodSpecification: VisitMember(visitor, module.ResolveEntity(member, genericContext) as IMember, context); - if (visitor.Found) return; + if (visitor.Found) + return; break; case HandleKind.StandaloneSignature: var signature = module.DecodeMethodSignature((StandaloneSignatureHandle)member, genericContext); - foreach (var type in signature.ParameterTypes) { + foreach (var type in signature.ParameterTypes) + { type.AcceptVisitor(visitor); } signature.ReturnType.AcceptVisitor(visitor); - if (visitor.Found) return; + if (visitor.Found) + return; break; default: diff --git a/ILSpy/Analyzers/IAnalyzer.cs b/ILSpy/Analyzers/IAnalyzer.cs index ed3b7652f..335e5e13d 100644 --- a/ILSpy/Analyzers/IAnalyzer.cs +++ b/ILSpy/Analyzers/IAnalyzer.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.Composition; + using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.ILSpy.Analyzers diff --git a/ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs b/ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs index 48a2d592e..d3ed19a46 100644 --- a/ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs +++ b/ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs @@ -37,8 +37,10 @@ namespace ICSharpCode.ILSpy.Analyzers public void Execute(TextViewContext context) { - if (context.SelectedTreeNodes != null) { - foreach (var node in context.SelectedTreeNodes) { + if (context.SelectedTreeNodes != null) + { + foreach (var node in context.SelectedTreeNodes) + { node.Parent.Children.Remove(node); } } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs index 7a787e40c..e268b6459 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs @@ -27,7 +27,8 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes public AnalyzedAccessorTreeNode(IMethod analyzedMethod, string name) : base(analyzedMethod) { - if (string.IsNullOrWhiteSpace(name)) { + if (string.IsNullOrWhiteSpace(name)) + { throw new System.ArgumentException("name must be a non-empty string", nameof(name)); } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs index 07e73c157..737495a7c 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -55,9 +56,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes // this.Children.Add(new AnalyzedAccessorTreeNode(accessor, null)); var analyzers = App.ExportProvider.GetExports("Analyzer"); - foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) { + foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) + { var analyzer = lazy.Value; - if (analyzer.Show(analyzedEvent)) { + if (analyzer.Show(analyzedEvent)) + { this.Children.Add(new AnalyzerSearchTreeNode(analyzedEvent, analyzer, lazy.Metadata.Header)); } } @@ -66,8 +69,10 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes bool TryFindBackingField(IEvent analyzedEvent, out IField backingField) { backingField = null; - foreach (var field in analyzedEvent.DeclaringTypeDefinition.GetFields(options: GetMemberOptions.IgnoreInheritedMembers)) { - if (field.Name == analyzedEvent.Name && field.Accessibility == Accessibility.Private) { + foreach (var field in analyzedEvent.DeclaringTypeDefinition.GetFields(options: GetMemberOptions.IgnoreInheritedMembers)) + { + if (field.Name == analyzedEvent.Name && field.Accessibility == Accessibility.Private) + { backingField = field; return true; } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs index c429e14ab..a3619b7bf 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -40,9 +41,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes protected override void LoadChildren() { var analyzers = App.ExportProvider.GetExports("Analyzer"); - foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) { + foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) + { var analyzer = lazy.Value; - if (analyzer.Show(analyzedField)) { + if (analyzer.Show(analyzedField)) + { this.Children.Add(new AnalyzerSearchTreeNode(analyzedField, analyzer, lazy.Metadata.Header)); } } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs index 783427b16..19ce7fa8e 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -42,9 +43,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes protected override void LoadChildren() { var analyzers = App.ExportProvider.GetExports("Analyzer"); - foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) { + foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) + { var analyzer = lazy.Value; - if (analyzer.Show(analyzedMethod)) { + if (analyzer.Show(analyzedMethod)) + { this.Children.Add(new AnalyzerSearchTreeNode(analyzedMethod, analyzer, lazy.Metadata.Header)); } } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs index 606b72f80..23bb562e9 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -40,9 +41,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes protected override void LoadChildren() { var analyzers = App.ExportProvider.GetExports("Analyzer"); - foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) { + foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) + { var analyzer = lazy.Value; - if (analyzer.Show(analyzedModule)) { + if (analyzer.Show(analyzedModule)) + { this.Children.Add(new AnalyzerSearchTreeNode(analyzedModule, analyzer, lazy.Metadata.Header)); } } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs index c1c81541e..d6504f6b9 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -50,9 +51,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes // this.Children.Add(new AnalyzedPropertyAccessorTreeNode(accessor, null)); var analyzers = App.ExportProvider.GetExports("Analyzer"); - foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) { + foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) + { var analyzer = lazy.Value; - if (analyzer.Show(analyzedProperty)) { + if (analyzer.Show(analyzedProperty)) + { this.Children.Add(new AnalyzerSearchTreeNode(analyzedProperty, analyzer, lazy.Metadata.Header)); } } diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs index 6c9622d7b..52757d134 100644 --- a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs +++ b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -40,9 +41,11 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes protected override void LoadChildren() { var analyzers = App.ExportProvider.GetExports("Analyzer"); - foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) { + foreach (var lazy in analyzers.OrderBy(item => item.Metadata.Order)) + { var analyzer = lazy.Value; - if (analyzer.Show(analyzedType)) { + if (analyzer.Show(analyzedType)) + { this.Children.Add(new AnalyzerSearchTreeNode(analyzedType, analyzer, lazy.Metadata.Header)); } } diff --git a/ILSpy/App.xaml.cs b/ILSpy/App.xaml.cs index 2fa17861a..d6d8f834c 100644 --- a/ILSpy/App.xaml.cs +++ b/ILSpy/App.xaml.cs @@ -51,21 +51,24 @@ namespace ICSharpCode.ILSpy public Exception Exception; public string PluginName; } - + public App() { var cmdArgs = Environment.GetCommandLineArgs().Skip(1); App.CommandLineArguments = new CommandLineArguments(cmdArgs); - if ((App.CommandLineArguments.SingleInstance ?? true) && !MiscSettingsPanel.CurrentMiscSettings.AllowMultipleInstances) { + if ((App.CommandLineArguments.SingleInstance ?? true) && !MiscSettingsPanel.CurrentMiscSettings.AllowMultipleInstances) + { cmdArgs = cmdArgs.Select(FullyQualifyPath); string message = string.Join(Environment.NewLine, cmdArgs); - if (SendToPreviousInstance("ILSpy:\r\n" + message, !App.CommandLineArguments.NoActivate)) { + if (SendToPreviousInstance("ILSpy:\r\n" + message, !App.CommandLineArguments.NoActivate)) + { Environment.Exit(0); } } InitializeComponent(); - if (!System.Diagnostics.Debugger.IsAttached) { + if (!System.Diagnostics.Debugger.IsAttached) + { AppDomain.CurrentDomain.UnhandledException += ShowErrorBox; Dispatcher.CurrentDispatcher.UnhandledException += Dispatcher_UnhandledException; } @@ -82,7 +85,8 @@ namespace ICSharpCode.ILSpy { // Cannot show MessageBox here, because WPF would crash with a XamlParseException // Remember and show exceptions in text output, once MainWindow is properly initialized - try { + try + { // Set up VS MEF. For now, only do MEF1 part discovery, since that was in use before. // To support both MEF1 and MEF2 parts, just change this to: // var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(Resolver.DefaultInstance), @@ -90,14 +94,19 @@ namespace ICSharpCode.ILSpy var discovery = new AttributedPartDiscoveryV1(Resolver.DefaultInstance); var catalog = ComposableCatalog.Create(Resolver.DefaultInstance); var pluginDir = Path.GetDirectoryName(typeof(App).Module.FullyQualifiedName); - if (pluginDir != null) { - foreach (var plugin in Directory.GetFiles(pluginDir, "*.Plugin.dll")) { + if (pluginDir != null) + { + foreach (var plugin in Directory.GetFiles(pluginDir, "*.Plugin.dll")) + { var name = Path.GetFileNameWithoutExtension(plugin); - try { + try + { var asm = Assembly.Load(name); var parts = await discovery.CreatePartsAsync(asm); catalog = catalog.AddParts(parts); - } catch (Exception ex) { + } + catch (Exception ex) + { StartupExceptions.Add(new ExceptionData { Exception = ex, PluginName = name }); } } @@ -116,7 +125,9 @@ namespace ICSharpCode.ILSpy // This throws exceptions for composition failures. Alternatively, the configuration's CompositionErrors property // could be used to log the errors directly. Used at the end so that it does not prevent the export provider setup. config.ThrowOnErrors(); - } catch (Exception ex) { + } + catch (Exception ex) + { StartupExceptions.Add(new ExceptionData { Exception = ex }); } } @@ -124,7 +135,8 @@ namespace ICSharpCode.ILSpy protected override void OnStartup(StartupEventArgs e) { var output = new StringBuilder(); - if (ILSpy.MainWindow.FormatExceptions(StartupExceptions.ToArray(), output)) { + if (ILSpy.MainWindow.FormatExceptions(StartupExceptions.ToArray(), output)) + { MessageBox.Show(output.ToString(), "Sorry we crashed!"); Environment.Exit(1); } @@ -137,9 +149,12 @@ namespace ICSharpCode.ILSpy // because that process might use a different current directory. if (string.IsNullOrEmpty(argument) || argument[0] == '/') return argument; - try { + try + { return Path.Combine(Environment.CurrentDirectory, argument); - } catch (ArgumentException) { + } + catch (ArgumentException) + { return argument; } } @@ -149,18 +164,19 @@ namespace ICSharpCode.ILSpy // On .NET 4.0, an unobserved exception in a task terminates the process unless we mark it as observed e.SetObserved(); } - + #region Exception Handling static void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { UnhandledException(e.Exception); e.Handled = true; } - + static void ShowErrorBox(object sender, UnhandledExceptionEventArgs e) { Exception ex = e.ExceptionObject as Exception; - if (ex != null) { + if (ex != null) + { UnhandledException(ex); } } @@ -171,23 +187,29 @@ namespace ICSharpCode.ILSpy static void UnhandledException(Exception exception) { Debug.WriteLine(exception.ToString()); - for (Exception ex = exception; ex != null; ex = ex.InnerException) { + for (Exception ex = exception; ex != null; ex = ex.InnerException) + { ReflectionTypeLoadException rtle = ex as ReflectionTypeLoadException; - if (rtle != null && rtle.LoaderExceptions.Length > 0) { + if (rtle != null && rtle.LoaderExceptions.Length > 0) + { exception = rtle.LoaderExceptions[0]; Debug.WriteLine(exception.ToString()); break; } } - if (showingError) { + if (showingError) + { // Ignore re-entrant calls // We run the risk of opening an infinite number of exception dialogs. return; } showingError = true; - try { + try + { MessageBox.Show(exception.ToString(), "Sorry, we crashed"); - } finally { + } + finally + { showingError = false; } } @@ -197,7 +219,8 @@ namespace ICSharpCode.ILSpy bool SendToPreviousInstance(string message, bool activate) { string ownProcessName; - using (var ownProcess = Process.GetCurrentProcess()) { + using (var ownProcess = Process.GetCurrentProcess()) + { ownProcessName = ownProcess.ProcessName; } @@ -205,13 +228,16 @@ namespace ICSharpCode.ILSpy NativeMethods.EnumWindows( (hWnd, lParam) => { string windowTitle = NativeMethods.GetWindowText(hWnd, 100); - if (windowTitle.StartsWith("ILSpy", StringComparison.Ordinal)) { + if (windowTitle.StartsWith("ILSpy", StringComparison.Ordinal)) + { string processName = NativeMethods.GetProcessNameFromWindow(hWnd); Debug.WriteLine("Found {0:x4}: '{1}' in '{2}'", hWnd, windowTitle, processName); - if (string.Equals(processName, ownProcessName, StringComparison.OrdinalIgnoreCase)) { + if (string.Equals(processName, ownProcessName, StringComparison.OrdinalIgnoreCase)) + { IntPtr result = Send(hWnd, message); Debug.WriteLine("WM_COPYDATA result: {0:x8}", result); - if (result == (IntPtr)1) { + if (result == (IntPtr)1) + { if (activate) NativeMethods.SetForegroundWindow(hWnd); success = true; @@ -223,15 +249,16 @@ namespace ICSharpCode.ILSpy }, IntPtr.Zero); return success; } - + unsafe static IntPtr Send(IntPtr hWnd, string message) { const uint SMTO_NORMAL = 0; - + CopyDataStruct lParam; lParam.Padding = IntPtr.Zero; lParam.Size = message.Length * 2; - fixed (char *buffer = message) { + fixed (char* buffer = message) + { lParam.Buffer = (IntPtr)buffer; IntPtr result; // SendMessage with 3s timeout (e.g. when the target process is stopped in the debugger) @@ -240,13 +267,15 @@ namespace ICSharpCode.ILSpy SMTO_NORMAL, 3000, out result) != IntPtr.Zero) { return result; - } else { + } + else + { return IntPtr.Zero; } } } #endregion - + void Window_RequestNavigate(object sender, RequestNavigateEventArgs e) { ILSpy.MainWindow.Instance.NavigateTo(e); diff --git a/ILSpy/AssemblyList.cs b/ILSpy/AssemblyList.cs index 8fa425b18..a57606e17 100644 --- a/ILSpy/AssemblyList.cs +++ b/ILSpy/AssemblyList.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.ILSpy public sealed class AssemblyList { readonly string listName; - + /// Dirty flag, used to mark modifications so that the list is saved later bool dirty; @@ -52,20 +52,21 @@ namespace ICSharpCode.ILSpy /// thread-safe method. /// internal readonly ObservableCollection assemblies = new ObservableCollection(); - + public AssemblyList(string listName) { this.listName = listName; assemblies.CollectionChanged += Assemblies_CollectionChanged; } - + /// /// Loads an assembly list from XML. /// public AssemblyList(XElement listElement) : this((string)listElement.Attribute("name")) { - foreach (var asm in listElement.Elements("Assembly")) { + foreach (var asm in listElement.Elements("Assembly")) + { OpenAssembly((string)asm); } this.dirty = false; // OpenAssembly() sets dirty, so reset it afterwards @@ -79,17 +80,18 @@ namespace ICSharpCode.ILSpy { this.assemblies.AddRange(list.assemblies); } - + /// /// Gets the loaded assemblies. This method is thread-safe. /// public LoadedAssembly[] GetAssemblies() { - lock (assemblies) { + lock (assemblies) + { return assemblies.ToArray(); } } - + /// /// Saves this assembly list to XML. /// @@ -101,26 +103,28 @@ namespace ICSharpCode.ILSpy assemblies.Where(asm => !asm.IsAutoLoaded).Select(asm => new XElement("Assembly", asm.FileName)) ); } - + /// /// Gets the name of this list. /// public string ListName { get { return listName; } } - + void Assemblies_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { ClearCache(); - if (CollectionChangeHasEffectOnSave(e)) { + if (CollectionChangeHasEffectOnSave(e)) + { RefreshSave(); } } - static bool CollectionChangeHasEffectOnSave(NotifyCollectionChangedEventArgs e ) + static bool CollectionChangeHasEffectOnSave(NotifyCollectionChangedEventArgs e) { // Auto-loading dependent assemblies shouldn't trigger saving the assembly list - switch (e.Action) { + switch (e.Action) + { case NotifyCollectionChangedAction.Add: return e.NewItems.Cast().Any(asm => !asm.IsAutoLoaded); case NotifyCollectionChangedAction.Remove: @@ -134,13 +138,15 @@ namespace ICSharpCode.ILSpy { // Whenever the assembly list is modified, mark it as dirty // and enqueue a task that saves it once the UI has finished modifying the assembly list. - if (!dirty) { + if (!dirty) + { dirty = true; App.Current.Dispatcher.BeginInvoke( DispatcherPriority.Background, new Action( delegate { - if (dirty) { + if (dirty) + { dirty = false; AssemblyListManager.SaveList(this); } @@ -148,7 +154,7 @@ namespace ICSharpCode.ILSpy ); } } - + internal void ClearCache() { assemblyLookupCache.Clear(); @@ -157,21 +163,26 @@ namespace ICSharpCode.ILSpy public LoadedAssembly Open(string assemblyUri, bool isAutoLoaded = false) { - if (assemblyUri.StartsWith("nupkg://", StringComparison.OrdinalIgnoreCase)) { + if (assemblyUri.StartsWith("nupkg://", StringComparison.OrdinalIgnoreCase)) + { string fileName = assemblyUri.Substring("nupkg://".Length); int separator = fileName.LastIndexOf(';'); string componentName = null; - if (separator > -1) { + if (separator > -1) + { componentName = fileName.Substring(separator + 1); fileName = fileName.Substring(0, separator); LoadedNugetPackage package = new LoadedNugetPackage(fileName); var entry = package.Entries.FirstOrDefault(e => e.Name == componentName); - if (entry != null) { + if (entry != null) + { return OpenAssembly(assemblyUri, entry.Stream, true); } } return null; - } else { + } + else + { return OpenAssembly(assemblyUri, isAutoLoaded); } } @@ -183,17 +194,19 @@ namespace ICSharpCode.ILSpy public LoadedAssembly OpenAssembly(string file, bool isAutoLoaded = false) { App.Current.Dispatcher.VerifyAccess(); - + file = Path.GetFullPath(file); - - foreach (LoadedAssembly asm in this.assemblies) { + + foreach (LoadedAssembly asm in this.assemblies) + { if (file.Equals(asm.FileName, StringComparison.OrdinalIgnoreCase)) return asm; } - + var newAsm = new LoadedAssembly(this, file); newAsm.IsAutoLoaded = isAutoLoaded; - lock (assemblies) { + lock (assemblies) + { this.assemblies.Add(newAsm); } return newAsm; @@ -206,14 +219,16 @@ namespace ICSharpCode.ILSpy { App.Current.Dispatcher.VerifyAccess(); - foreach (LoadedAssembly asm in this.assemblies) { + foreach (LoadedAssembly asm in this.assemblies) + { if (file.Equals(asm.FileName, StringComparison.OrdinalIgnoreCase)) return asm; } var newAsm = new LoadedAssembly(this, file, stream); newAsm.IsAutoLoaded = isAutoLoaded; - lock (assemblies) { + lock (assemblies) + { this.assemblies.Add(newAsm); } return newAsm; @@ -235,7 +250,8 @@ namespace ICSharpCode.ILSpy var index = this.assemblies.IndexOf(target); var newAsm = new LoadedAssembly(this, file, stream); newAsm.IsAutoLoaded = target.IsAutoLoaded; - lock (assemblies) { + lock (assemblies) + { this.assemblies.Remove(target); this.assemblies.Insert(index, newAsm); } @@ -260,7 +276,8 @@ namespace ICSharpCode.ILSpy var newAsm = new LoadedAssembly(this, target.FileName); newAsm.IsAutoLoaded = target.IsAutoLoaded; newAsm.PdbFileOverride = target.PdbFileOverride; - lock (assemblies) { + lock (assemblies) + { this.assemblies.Remove(target); this.assemblies.Insert(index, newAsm); } @@ -270,17 +287,19 @@ namespace ICSharpCode.ILSpy public void Unload(LoadedAssembly assembly) { App.Current.Dispatcher.VerifyAccess(); - lock (assemblies) { + lock (assemblies) + { assemblies.Remove(assembly); } RequestGC(); } - + static bool gcRequested; - + void RequestGC() { - if (gcRequested) return; + if (gcRequested) + return; gcRequested = true; App.Current.Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action( delegate { @@ -288,16 +307,17 @@ namespace ICSharpCode.ILSpy GC.Collect(); })); } - + public void Sort(IComparer comparer) { Sort(0, int.MaxValue, comparer); } - + public void Sort(int index, int count, IComparer comparer) { App.Current.Dispatcher.VerifyAccess(); - lock (assemblies) { + lock (assemblies) + { List list = new List(assemblies); list.Sort(index, Math.Min(count, list.Count - index), comparer); assemblies.Clear(); diff --git a/ILSpy/AssemblyListManager.cs b/ILSpy/AssemblyListManager.cs index 2b28f4e61..3a57f4ab4 100644 --- a/ILSpy/AssemblyListManager.cs +++ b/ILSpy/AssemblyListManager.cs @@ -20,6 +20,7 @@ using System; using System.Collections.ObjectModel; using System.Linq; using System.Xml.Linq; + using ICSharpCode.ILSpy.ViewModels; namespace ICSharpCode.ILSpy @@ -37,13 +38,14 @@ namespace ICSharpCode.ILSpy { this.spySettings = spySettings; XElement doc = spySettings["AssemblyLists"]; - foreach (var list in doc.Elements("List")) { + foreach (var list in doc.Elements("List")) + { AssemblyLists.Add((string)list.Attribute("name")); } } - + public ObservableCollection AssemblyLists { get; } = new ObservableCollection(); - + /// /// Loads an assembly list from the ILSpySettings. /// If no list with the specified name is found, the default list is loaded instead. @@ -56,13 +58,16 @@ namespace ICSharpCode.ILSpy AssemblyLists.Add(list.ListName); return list; } - + AssemblyList DoLoadList(ILSpySettings spySettings, string listName) { XElement doc = spySettings["AssemblyLists"]; - if (listName != null) { - foreach (var list in doc.Elements("List")) { - if ((string)list.Attribute("name") == listName) { + if (listName != null) + { + foreach (var list in doc.Elements("List")) + { + if ((string)list.Attribute("name") == listName) + { return new AssemblyList(list); } } @@ -85,7 +90,7 @@ namespace ICSharpCode.ILSpy } public const string DefaultListName = "(Default)"; - + /// /// Saves the specifies assembly list into the config file. /// @@ -94,7 +99,8 @@ namespace ICSharpCode.ILSpy ILSpySettings.Update( delegate (XElement root) { XElement doc = root.Element("AssemblyLists"); - if (doc == null) { + if (doc == null) + { doc = new XElement("AssemblyLists"); root.Add(doc); } @@ -122,8 +128,7 @@ namespace ICSharpCode.ILSpy if (AssemblyLists.Remove(Name)) { ILSpySettings.Update( - delegate(XElement root) - { + delegate (XElement root) { XElement doc = root.Element("AssemblyLists"); if (doc == null) { @@ -144,7 +149,8 @@ namespace ICSharpCode.ILSpy ILSpySettings.Update( delegate (XElement root) { XElement doc = root.Element("AssemblyLists"); - if (doc == null) { + if (doc == null) + { return; } doc.Remove(); @@ -156,23 +162,29 @@ namespace ICSharpCode.ILSpy if (AssemblyLists.Count > 0) return; - if (!AssemblyLists.Contains(ManageAssemblyListsViewModel.DotNet4List)) { + if (!AssemblyLists.Contains(ManageAssemblyListsViewModel.DotNet4List)) + { AssemblyList dotnet4 = ManageAssemblyListsViewModel.CreateDefaultList(ManageAssemblyListsViewModel.DotNet4List); - if (dotnet4.assemblies.Count > 0) { + if (dotnet4.assemblies.Count > 0) + { CreateList(dotnet4); } } - if (!AssemblyLists.Contains(ManageAssemblyListsViewModel.DotNet35List)) { + if (!AssemblyLists.Contains(ManageAssemblyListsViewModel.DotNet35List)) + { AssemblyList dotnet35 = ManageAssemblyListsViewModel.CreateDefaultList(ManageAssemblyListsViewModel.DotNet35List); - if (dotnet35.assemblies.Count > 0) { + if (dotnet35.assemblies.Count > 0) + { CreateList(dotnet35); } } - if (!AssemblyLists.Contains(ManageAssemblyListsViewModel.ASPDotNetMVC3List)) { + if (!AssemblyLists.Contains(ManageAssemblyListsViewModel.ASPDotNetMVC3List)) + { AssemblyList mvc = ManageAssemblyListsViewModel.CreateDefaultList(ManageAssemblyListsViewModel.ASPDotNetMVC3List); - if (mvc.assemblies.Count > 0) { + if (mvc.assemblies.Count > 0) + { CreateList(mvc); } } diff --git a/ILSpy/AvalonEdit/ITextMarker.cs b/ILSpy/AvalonEdit/ITextMarker.cs index e263b3dcf..2340e6a6f 100644 --- a/ILSpy/AvalonEdit/ITextMarker.cs +++ b/ILSpy/AvalonEdit/ITextMarker.cs @@ -32,73 +32,73 @@ namespace ICSharpCode.ILSpy.AvalonEdit /// Gets the start offset of the marked text region. /// int StartOffset { get; } - + /// /// Gets the end offset of the marked text region. /// int EndOffset { get; } - + /// /// Gets the length of the marked region. /// int Length { get; } - + /// /// Deletes the text marker. /// void Delete(); - + /// /// Gets whether the text marker was deleted. /// bool IsDeleted { get; } - + /// /// Event that occurs when the text marker is deleted. /// event EventHandler Deleted; - + /// /// Gets/Sets the background color. /// Color? BackgroundColor { get; set; } - + /// /// Gets/Sets the foreground color. /// Color? ForegroundColor { get; set; } - + /// /// Gets/Sets the font weight. /// FontWeight? FontWeight { get; set; } - + /// /// Gets/Sets the font style. /// FontStyle? FontStyle { get; set; } - + /// /// Gets/Sets the type of the marker. Use TextMarkerType.None for normal markers. /// TextMarkerTypes MarkerTypes { get; set; } - + /// /// Gets/Sets the color of the marker. /// Color MarkerColor { get; set; } - + /// /// Gets/Sets an object with additional data for this text marker. /// object Tag { get; set; } - + /// /// Gets/Sets an object that will be displayed as tooltip in the text editor. /// object ToolTip { get; set; } } - + [Flags] public enum TextMarkerTypes { @@ -118,7 +118,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit /// Dotted underline. /// DottedUnderline = 0x004, - + /// /// Horizontal line in the scroll bar. /// @@ -136,7 +136,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit /// CircleInScrollBar = 0x1000 } - + public interface ITextMarkerService { /// @@ -144,22 +144,22 @@ namespace ICSharpCode.ILSpy.AvalonEdit /// you need to set one of the Color properties to make it visible. /// ITextMarker Create(int startOffset, int length); - + /// /// Gets the list of text markers. /// IEnumerable TextMarkers { get; } - + /// /// Removes the specified text marker. /// void Remove(ITextMarker marker); - + /// /// Removes all text markers that match the condition. /// void RemoveAll(Predicate predicate); - + /// /// Finds all text markers at the specified offset. /// diff --git a/ILSpy/AvalonEdit/TextMarkerService.cs b/ILSpy/AvalonEdit/TextMarkerService.cs index b7eec889a..a6bd3ef6c 100644 --- a/ILSpy/AvalonEdit/TextMarkerService.cs +++ b/ILSpy/AvalonEdit/TextMarkerService.cs @@ -22,6 +22,7 @@ using System.Linq; using System.Windows; using System.Windows.Media; using System.Windows.Threading; + using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; @@ -35,7 +36,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit { TextSegmentCollection markers; TextView textView; - + public TextMarkerService(TextView textView) { if (textView == null) @@ -52,25 +53,25 @@ namespace ICSharpCode.ILSpy.AvalonEdit else markers = null; } - + #region ITextMarkerService public ITextMarker Create(int startOffset, int length) { if (markers == null) throw new InvalidOperationException("Cannot create a marker when not attached to a document"); - + int textLength = textView.Document.TextLength; if (startOffset < 0 || startOffset > textLength) throw new ArgumentOutOfRangeException(nameof(startOffset), startOffset, "Value must be between 0 and " + textLength); if (length < 0 || startOffset + length > textLength) throw new ArgumentOutOfRangeException(nameof(length), length, "length must not be negative and startOffset+length must not be after the end of the document"); - + TextMarker m = new TextMarker(this, startOffset, length); markers.Add(m); // no need to mark segment for redraw: the text marker is invisible until a property is set return m; } - + public IEnumerable GetMarkersAtOffset(int offset) { if (markers == null) @@ -78,34 +79,37 @@ namespace ICSharpCode.ILSpy.AvalonEdit else return markers.FindSegmentsContaining(offset); } - + public IEnumerable TextMarkers { get { return markers ?? Enumerable.Empty(); } } - + public void RemoveAll(Predicate predicate) { if (predicate == null) throw new ArgumentNullException(nameof(predicate)); - if (markers != null) { - foreach (TextMarker m in markers.ToArray()) { + if (markers != null) + { + foreach (TextMarker m in markers.ToArray()) + { if (predicate(m)) Remove(m); } } } - + public void Remove(ITextMarker marker) { if (marker == null) throw new ArgumentNullException(nameof(marker)); TextMarker m = marker as TextMarker; - if (markers != null && markers.Remove(m)) { + if (markers != null && markers.Remove(m)) + { Redraw(m); m.OnDeleted(); } } - + /// /// Redraws the specified text segment. /// @@ -115,10 +119,10 @@ namespace ICSharpCode.ILSpy.AvalonEdit if (RedrawRequested != null) RedrawRequested(this, EventArgs.Empty); } - + public event EventHandler RedrawRequested; #endregion - + #region DocumentColorizingTransformer protected override void ColorizeLine(DocumentLine line) { @@ -126,9 +130,11 @@ namespace ICSharpCode.ILSpy.AvalonEdit return; int lineStart = line.Offset; int lineEnd = lineStart + line.Length; - foreach (TextMarker marker in markers.FindOverlappingSegments(lineStart, line.Length)) { + foreach (TextMarker marker in markers.FindOverlappingSegments(lineStart, line.Length)) + { Brush foregroundBrush = null; - if (marker.ForegroundColor != null) { + if (marker.ForegroundColor != null) + { foregroundBrush = new SolidColorBrush(marker.ForegroundColor.Value); foregroundBrush.Freeze(); } @@ -136,7 +142,8 @@ namespace ICSharpCode.ILSpy.AvalonEdit Math.Max(marker.StartOffset, lineStart), Math.Min(marker.EndOffset, lineEnd), element => { - if (foregroundBrush != null) { + if (foregroundBrush != null) + { element.TextRunProperties.SetForegroundBrush(foregroundBrush); } Typeface tf = element.TextRunProperties.Typeface; @@ -151,7 +158,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit } } #endregion - + #region IBackgroundRenderer public KnownLayer Layer { get { @@ -159,7 +166,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit return KnownLayer.Selection; } } - + public void Draw(ICSharpCode.AvalonEdit.Rendering.TextView textView, DrawingContext drawingContext) { if (textView == null) @@ -173,14 +180,17 @@ namespace ICSharpCode.ILSpy.AvalonEdit return; int viewStart = visualLines.First().FirstDocumentLine.Offset; int viewEnd = visualLines.Last().LastDocumentLine.EndOffset; - foreach (TextMarker marker in markers.FindOverlappingSegments(viewStart, viewEnd - viewStart)) { - if (marker.BackgroundColor != null) { + foreach (TextMarker marker in markers.FindOverlappingSegments(viewStart, viewEnd - viewStart)) + { + if (marker.BackgroundColor != null) + { BackgroundGeometryBuilder geoBuilder = new BackgroundGeometryBuilder(); geoBuilder.AlignToWholePixels = true; geoBuilder.CornerRadius = 3; geoBuilder.AddSegment(textView, marker); Geometry geometry = geoBuilder.CreateGeometry(); - if (geometry != null) { + if (geometry != null) + { Color color = marker.BackgroundColor.Value; SolidColorBrush brush = new SolidColorBrush(color); brush.Freeze(); @@ -188,37 +198,43 @@ namespace ICSharpCode.ILSpy.AvalonEdit } } var underlineMarkerTypes = TextMarkerTypes.SquigglyUnderline | TextMarkerTypes.NormalUnderline | TextMarkerTypes.DottedUnderline; - if ((marker.MarkerTypes & underlineMarkerTypes) != 0) { - foreach (Rect r in BackgroundGeometryBuilder.GetRectsForSegment(textView, marker)) { + if ((marker.MarkerTypes & underlineMarkerTypes) != 0) + { + foreach (Rect r in BackgroundGeometryBuilder.GetRectsForSegment(textView, marker)) + { Point startPoint = r.BottomLeft; Point endPoint = r.BottomRight; - + Brush usedBrush = new SolidColorBrush(marker.MarkerColor); usedBrush.Freeze(); - if ((marker.MarkerTypes & TextMarkerTypes.SquigglyUnderline) != 0) { + if ((marker.MarkerTypes & TextMarkerTypes.SquigglyUnderline) != 0) + { double offset = 2.5; - + int count = Math.Max((int)((endPoint.X - startPoint.X) / offset) + 1, 4); - + StreamGeometry geometry = new StreamGeometry(); - - using (StreamGeometryContext ctx = geometry.Open()) { + + using (StreamGeometryContext ctx = geometry.Open()) + { ctx.BeginFigure(startPoint, false, false); ctx.PolyLineTo(CreatePoints(startPoint, endPoint, offset, count).ToArray(), true, false); } - + geometry.Freeze(); - + Pen usedPen = new Pen(usedBrush, 1); usedPen.Freeze(); drawingContext.DrawGeometry(Brushes.Transparent, usedPen, geometry); } - if ((marker.MarkerTypes & TextMarkerTypes.NormalUnderline) != 0) { + if ((marker.MarkerTypes & TextMarkerTypes.NormalUnderline) != 0) + { Pen usedPen = new Pen(usedBrush, 1); usedPen.Freeze(); drawingContext.DrawLine(usedPen, startPoint, endPoint); } - if ((marker.MarkerTypes & TextMarkerTypes.DottedUnderline) != 0) { + if ((marker.MarkerTypes & TextMarkerTypes.DottedUnderline) != 0) + { Pen usedPen = new Pen(usedBrush, 1); usedPen.DashStyle = DashStyles.Dot; usedPen.Freeze(); @@ -228,7 +244,7 @@ namespace ICSharpCode.ILSpy.AvalonEdit } } } - + IEnumerable CreatePoints(Point start, Point end, double offset, int count) { for (int i = 0; i < count; i++) @@ -236,11 +252,11 @@ namespace ICSharpCode.ILSpy.AvalonEdit } #endregion } - + sealed class TextMarker : TextSegment, ITextMarker { readonly TextMarkerService service; - + public TextMarker(TextMarkerService service, int startOffset, int length) { if (service == null) @@ -250,103 +266,109 @@ namespace ICSharpCode.ILSpy.AvalonEdit this.Length = length; this.markerTypes = TextMarkerTypes.None; } - + public event EventHandler Deleted; - + public bool IsDeleted { get { return !this.IsConnectedToCollection; } } - + public void Delete() { service.Remove(this); } - + internal void OnDeleted() { if (Deleted != null) Deleted(this, EventArgs.Empty); } - + void Redraw() { service.Redraw(this); } - + Color? backgroundColor; - + public Color? BackgroundColor { get { return backgroundColor; } set { - if (backgroundColor != value) { + if (backgroundColor != value) + { backgroundColor = value; Redraw(); } } } - + Color? foregroundColor; - + public Color? ForegroundColor { get { return foregroundColor; } set { - if (foregroundColor != value) { + if (foregroundColor != value) + { foregroundColor = value; Redraw(); } } } - + FontWeight? fontWeight; - + public FontWeight? FontWeight { get { return fontWeight; } set { - if (fontWeight != value) { + if (fontWeight != value) + { fontWeight = value; Redraw(); } } } - + FontStyle? fontStyle; - + public FontStyle? FontStyle { get { return fontStyle; } set { - if (fontStyle != value) { + if (fontStyle != value) + { fontStyle = value; Redraw(); } } } - + public object Tag { get; set; } - + TextMarkerTypes markerTypes; - + public TextMarkerTypes MarkerTypes { get { return markerTypes; } set { - if (markerTypes != value) { + if (markerTypes != value) + { markerTypes = value; Redraw(); } } } - + Color markerColor; - + public Color MarkerColor { get { return markerColor; } set { - if (markerColor != value) { + if (markerColor != value) + { markerColor = value; Redraw(); } } } - + public object ToolTip { get; set; } } } diff --git a/ILSpy/CommandLineArguments.cs b/ILSpy/CommandLineArguments.cs index f0a05015f..c6c1b5947 100644 --- a/ILSpy/CommandLineArguments.cs +++ b/ILSpy/CommandLineArguments.cs @@ -31,13 +31,15 @@ namespace ICSharpCode.ILSpy public string Language; public bool NoActivate; public string ConfigFile; - + public CommandLineArguments(IEnumerable arguments) { - foreach (string arg in arguments) { + foreach (string arg in arguments) + { if (arg.Length == 0) continue; - if (arg[0] == '/') { + if (arg[0] == '/') + { if (arg.Equals("/singleInstance", StringComparison.OrdinalIgnoreCase)) this.SingleInstance = true; else if (arg.Equals("/separate", StringComparison.OrdinalIgnoreCase)) @@ -52,7 +54,9 @@ namespace ICSharpCode.ILSpy this.NoActivate = true; else if (arg.StartsWith("/config:", StringComparison.OrdinalIgnoreCase)) this.ConfigFile = arg.Substring("/config:".Length); - } else { + } + else + { this.AssembliesToLoad.Add(arg); } } diff --git a/ILSpy/Commands/BrowseBackCommand.cs b/ILSpy/Commands/BrowseBackCommand.cs index e3fe411b5..bb8580495 100644 --- a/ILSpy/Commands/BrowseBackCommand.cs +++ b/ILSpy/Commands/BrowseBackCommand.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Windows.Input; + using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy diff --git a/ILSpy/Commands/BrowseForwardCommand.cs b/ILSpy/Commands/BrowseForwardCommand.cs index e16b871fc..5935bd666 100644 --- a/ILSpy/Commands/BrowseForwardCommand.cs +++ b/ILSpy/Commands/BrowseForwardCommand.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Windows.Input; + using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy diff --git a/ILSpy/Commands/CheckForUpdatesCommand.cs b/ILSpy/Commands/CheckForUpdatesCommand.cs index 00480cc9f..7cdc2ee86 100644 --- a/ILSpy/Commands/CheckForUpdatesCommand.cs +++ b/ILSpy/Commands/CheckForUpdatesCommand.cs @@ -18,16 +18,18 @@ using ICSharpCode.ILSpy.Properties; + using OSVersionHelper; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = nameof(Resources._Help), Header = nameof(Resources._CheckUpdates), MenuOrder = 5000)] + [ExportMainMenuCommand(Menu = nameof(Resources._Help), Header = nameof(Resources._CheckUpdates), MenuOrder = 5000)] sealed class CheckForUpdatesCommand : SimpleCommand { public override bool CanExecute(object parameter) { - if(WindowsVersionHelper.HasPackageIdentity) { + if (WindowsVersionHelper.HasPackageIdentity) + { return false; } diff --git a/ILSpy/Commands/CommandWrapper.cs b/ILSpy/Commands/CommandWrapper.cs index 89890b68b..42b34ee05 100644 --- a/ILSpy/Commands/CommandWrapper.cs +++ b/ILSpy/Commands/CommandWrapper.cs @@ -39,8 +39,7 @@ namespace ICSharpCode.ILSpy return command; } - public event EventHandler CanExecuteChanged - { + public event EventHandler CanExecuteChanged { add { wrappedCommand.CanExecuteChanged += value; } remove { wrappedCommand.CanExecuteChanged -= value; } } diff --git a/ILSpy/Commands/CopyFullyQualifiedNameContextMenuEntry.cs b/ILSpy/Commands/CopyFullyQualifiedNameContextMenuEntry.cs index 3afc9fd14..020fc76b3 100644 --- a/ILSpy/Commands/CopyFullyQualifiedNameContextMenuEntry.cs +++ b/ILSpy/Commands/CopyFullyQualifiedNameContextMenuEntry.cs @@ -1,5 +1,6 @@ using System; using System.Windows; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -21,7 +22,8 @@ namespace ICSharpCode.ILSpy public void Execute(TextViewContext context) { var member = GetMemberNodeFromContext(context)?.Member; - if (member == null) return; + if (member == null) + return; Clipboard.SetText(member.ReflectionName); } diff --git a/ILSpy/Commands/DecompileAllCommand.cs b/ILSpy/Commands/DecompileAllCommand.cs index 56a698e33..db4b24c87 100644 --- a/ILSpy/Commands/DecompileAllCommand.cs +++ b/ILSpy/Commands/DecompileAllCommand.cs @@ -23,6 +23,7 @@ using System.Collections.Concurrent; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; + using ICSharpCode.Decompiler; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; @@ -42,24 +43,30 @@ namespace ICSharpCode.ILSpy Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task.Factory.StartNew(() => { AvalonEditTextOutput output = new AvalonEditTextOutput(); Parallel.ForEach( - Partitioner.Create( MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), loadBalance: true), - new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, - delegate(LoadedAssembly asm) { - if (!asm.HasLoadError) { + Partitioner.Create(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), loadBalance: true), + new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, + delegate (LoadedAssembly asm) { + if (!asm.HasLoadError) + { Stopwatch w = Stopwatch.StartNew(); Exception exception = null; - using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs")) { - try { + using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs")) + { + try + { new CSharpLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions() { FullDecompilation = true, CancellationToken = ct }); } - catch (Exception ex) { + catch (Exception ex) + { writer.WriteLine(ex.ToString()); exception = ex; } } - lock (output) { + lock (output) + { output.Write(asm.ShortName + " - " + w.Elapsed); - if (exception != null) { + if (exception != null) + { output.Write(" - "); output.Write(exception.GetType().Name); } @@ -72,7 +79,7 @@ namespace ICSharpCode.ILSpy } } - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile100x), MenuCategory = nameof(Resources.Open), MenuOrder = 2.6)] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile100x), MenuCategory = nameof(Resources.Open), MenuOrder = 2.6)] sealed class Decompile100TimesCommand : SimpleCommand { public override void Execute(object parameter) @@ -84,8 +91,10 @@ namespace ICSharpCode.ILSpy Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task.Factory.StartNew(() => { options.CancellationToken = ct; Stopwatch w = Stopwatch.StartNew(); - for (int i = 0; i < numRuns; ++i) { - foreach (var node in nodes) { + for (int i = 0; i < numRuns; ++i) + { + foreach (var node in nodes) + { node.Decompile(language, new PlainTextOutput(), options); } } diff --git a/ILSpy/Commands/DecompileCommand.cs b/ILSpy/Commands/DecompileCommand.cs index d9485e512..0902c03e9 100644 --- a/ILSpy/Commands/DecompileCommand.cs +++ b/ILSpy/Commands/DecompileCommand.cs @@ -21,6 +21,7 @@ using System.Linq; using System.Reflection; using System.Reflection.Metadata.Ecma335; using System.Windows.Controls; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Metadata; @@ -43,7 +44,8 @@ namespace ICSharpCode.ILSpy.Commands { if (context.SelectedTreeNodes == null) return context.Reference?.Reference is IEntity; - foreach (IMemberTreeNode node in context.SelectedTreeNodes) { + foreach (IMemberTreeNode node in context.SelectedTreeNodes) + { if (!IsValidReference(node.Member)) return false; } @@ -59,9 +61,12 @@ namespace ICSharpCode.ILSpy.Commands public void Execute(TextViewContext context) { IEntity selection = null; - if (context.SelectedTreeNodes?[0] is IMemberTreeNode node) { + if (context.SelectedTreeNodes?[0] is IMemberTreeNode node) + { selection = node.Member; - } else if (context.Reference?.Reference is IEntity entity) { + } + else if (context.Reference?.Reference is IEntity entity) + { selection = entity; } if (selection != null) diff --git a/ILSpy/Commands/DecompileInNewViewCommand.cs b/ILSpy/Commands/DecompileInNewViewCommand.cs index 152d0f8dd..744c1ecc9 100644 --- a/ILSpy/Commands/DecompileInNewViewCommand.cs +++ b/ILSpy/Commands/DecompileInNewViewCommand.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Windows.Threading; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Docking; using ICSharpCode.ILSpy.Properties; @@ -48,14 +49,21 @@ namespace ICSharpCode.ILSpy.Commands IEnumerable GetNodes(TextViewContext context) { - if (context.SelectedTreeNodes != null) { - if (context.TreeView != MainWindow.Instance.AssemblyTreeView) { + if (context.SelectedTreeNodes != null) + { + if (context.TreeView != MainWindow.Instance.AssemblyTreeView) + { return context.SelectedTreeNodes.OfType().Select(FindTreeNode).Where(n => n != null); - } else { + } + else + { return context.SelectedTreeNodes.OfType().Where(n => n != null); } - } else if (context.Reference?.Reference is IEntity entity) { - if (MainWindow.Instance.FindTreeNode(entity) is ILSpyTreeNode node) { + } + else if (context.Reference?.Reference is IEntity entity) + { + if (MainWindow.Instance.FindTreeNode(entity) is ILSpyTreeNode node) + { return new[] { node }; } } diff --git a/ILSpy/Commands/DisassembleAllCommand.cs b/ILSpy/Commands/DisassembleAllCommand.cs index e220ead0c..c34bea449 100644 --- a/ILSpy/Commands/DisassembleAllCommand.cs +++ b/ILSpy/Commands/DisassembleAllCommand.cs @@ -19,15 +19,16 @@ #if DEBUG using System; +using System.Collections.Concurrent; using System.Diagnostics; using System.Threading.Tasks; -using ICSharpCode.ILSpy.TextView; + using ICSharpCode.ILSpy.Properties; -using System.Collections.Concurrent; +using ICSharpCode.ILSpy.TextView; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.DEBUGDisassemble), MenuCategory = nameof(Resources.Open), MenuOrder = 2.5)] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.DEBUGDisassemble), MenuCategory = nameof(Resources.Open), MenuOrder = 2.5)] sealed class DisassembleAllCommand : SimpleCommand { public override bool CanExecute(object parameter) @@ -43,28 +44,34 @@ namespace ICSharpCode.ILSpy Partitioner.Create(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), loadBalance: true), new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, delegate (LoadedAssembly asm) { - if (!asm.HasLoadError) { - Stopwatch w = Stopwatch.StartNew(); - Exception exception = null; - using (var writer = new System.IO.StreamWriter("c:\\temp\\disassembled\\" + asm.Text.Replace("(", "").Replace(")", "").Replace(' ', '_') + ".il")) { - try { - new ILLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions { FullDecompilation = true, CancellationToken = ct }); - } - catch (Exception ex) { - writer.WriteLine(ex.ToString()); - exception = ex; + if (!asm.HasLoadError) + { + Stopwatch w = Stopwatch.StartNew(); + Exception exception = null; + using (var writer = new System.IO.StreamWriter("c:\\temp\\disassembled\\" + asm.Text.Replace("(", "").Replace(")", "").Replace(' ', '_') + ".il")) + { + try + { + new ILLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions { FullDecompilation = true, CancellationToken = ct }); + } + catch (Exception ex) + { + writer.WriteLine(ex.ToString()); + exception = ex; + } } - } - lock (output) { - output.Write(asm.ShortName + " - " + w.Elapsed); - if (exception != null) { - output.Write(" - "); - output.Write(exception.GetType().Name); + lock (output) + { + output.Write(asm.ShortName + " - " + w.Elapsed); + if (exception != null) + { + output.Write(" - "); + output.Write(exception.GetType().Name); + } + output.WriteLine(); } - output.WriteLine(); } - } - }); + }); return output; }, ct)).Then(output => Docking.DockWorkspace.Instance.ShowText(output)).HandleExceptions(); } diff --git a/ILSpy/Commands/ExitCommand.cs b/ILSpy/Commands/ExitCommand.cs index a3be28e72..34ad7f93f 100644 --- a/ILSpy/Commands/ExitCommand.cs +++ b/ILSpy/Commands/ExitCommand.cs @@ -19,7 +19,7 @@ using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.E_xit), MenuOrder = 99999, MenuCategory = nameof(Resources.Exit))] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.E_xit), MenuOrder = 99999, MenuCategory = nameof(Resources.Exit))] sealed class ExitCommand : SimpleCommand { public override void Execute(object parameter) diff --git a/ILSpy/Commands/ExportCommandAttribute.cs b/ILSpy/Commands/ExportCommandAttribute.cs index eaa296682..f8db38bbc 100644 --- a/ILSpy/Commands/ExportCommandAttribute.cs +++ b/ILSpy/Commands/ExportCommandAttribute.cs @@ -31,16 +31,16 @@ namespace ICSharpCode.ILSpy object Tag { get; } double ToolbarOrder { get; } } - + [MetadataAttribute] - [AttributeUsage(AttributeTargets.Class, AllowMultiple=false)] + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class ExportToolbarCommandAttribute : ExportAttribute, IToolbarCommandMetadata { public ExportToolbarCommandAttribute() : base("ToolbarCommand", typeof(ICommand)) { } - + public string ToolTip { get; set; } public string ToolbarIcon { get; set; } public string ToolbarCategory { get; set; } @@ -48,7 +48,7 @@ namespace ICSharpCode.ILSpy public object Tag { get; set; } } #endregion - + #region Main Menu public interface IMainMenuCommandMetadata { @@ -60,18 +60,18 @@ namespace ICSharpCode.ILSpy bool IsEnabled { get; } double MenuOrder { get; } } - + [MetadataAttribute] - [AttributeUsage(AttributeTargets.Class, AllowMultiple=false)] + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class ExportMainMenuCommandAttribute : ExportAttribute, IMainMenuCommandMetadata { bool isEnabled = true; - + public ExportMainMenuCommandAttribute() : base("MainMenuCommand", typeof(ICommand)) { } - + public string MenuIcon { get; set; } public string Header { get; set; } public string Menu { get; set; } diff --git a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs index a9b2631f6..4f803f66f 100644 --- a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs +++ b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs @@ -22,13 +22,15 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.DebugInfo; +using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; + using Microsoft.Win32; -using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy { @@ -38,7 +40,8 @@ namespace ICSharpCode.ILSpy public void Execute(TextViewContext context) { var assembly = (context.SelectedTreeNodes?.FirstOrDefault() as AssemblyTreeNode)?.LoadedAssembly; - if (assembly == null) return; + if (assembly == null) + return; GeneratePdbForAssembly(assembly); } @@ -54,7 +57,8 @@ namespace ICSharpCode.ILSpy internal static void GeneratePdbForAssembly(LoadedAssembly assembly) { var file = assembly.GetPEFileOrNull(); - if (!PortablePdbWriter.HasCodeViewDebugDirectoryEntry(file)) { + if (!PortablePdbWriter.HasCodeViewDebugDirectoryEntry(file)) + { MessageBox.Show(string.Format(Resources.CannotCreatePDBFile, Path.GetFileName(assembly.FileName))); return; } @@ -62,17 +66,22 @@ namespace ICSharpCode.ILSpy dlg.FileName = DecompilerTextView.CleanUpName(assembly.ShortName) + ".pdb"; dlg.Filter = Resources.PortablePDBPdbAllFiles; dlg.InitialDirectory = Path.GetDirectoryName(assembly.FileName); - if (dlg.ShowDialog() != true) return; + if (dlg.ShowDialog() != true) + return; DecompilationOptions options = new DecompilationOptions(); string fileName = dlg.FileName; Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task.Factory.StartNew(() => { AvalonEditTextOutput output = new AvalonEditTextOutput(); Stopwatch stopwatch = Stopwatch.StartNew(); - using (FileStream stream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write)) { - try { + using (FileStream stream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write)) + { + try + { var decompiler = new CSharpDecompiler(file, assembly.GetAssemblyResolver(), options.DecompilerSettings); PortablePdbWriter.WritePdb(file, decompiler, options.DecompilerSettings, stream); - } catch (OperationCanceledException) { + } + catch (OperationCanceledException) + { output.WriteLine(); output.WriteLine(Resources.GenerationWasCancelled); throw; @@ -88,7 +97,7 @@ namespace ICSharpCode.ILSpy } } - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.GeneratePortable), MenuCategory = nameof(Resources.Save))] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.GeneratePortable), MenuCategory = nameof(Resources.Save))] class GeneratePdbMainMenuEntry : SimpleCommand { public override bool CanExecute(object parameter) @@ -101,7 +110,8 @@ namespace ICSharpCode.ILSpy public override void Execute(object parameter) { var assembly = (MainWindow.Instance.SelectedNodes?.FirstOrDefault() as AssemblyTreeNode)?.LoadedAssembly; - if (assembly == null) return; + if (assembly == null) + return; GeneratePdbContextMenuEntry.GeneratePdbForAssembly(assembly); } } diff --git a/ILSpy/Commands/ILSpyCommands.cs b/ILSpy/Commands/ILSpyCommands.cs index 379432b7f..aab6d6f0b 100644 --- a/ILSpy/Commands/ILSpyCommands.cs +++ b/ILSpy/Commands/ILSpyCommands.cs @@ -22,6 +22,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; + using ICSharpCode.ILSpy.Analyzers; namespace ICSharpCode.ILSpy diff --git a/ILSpy/Commands/IProtocolHandler.cs b/ILSpy/Commands/IProtocolHandler.cs index 3ab28d7f1..251b6b5f5 100644 --- a/ILSpy/Commands/IProtocolHandler.cs +++ b/ILSpy/Commands/IProtocolHandler.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Reflection.Metadata; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.TreeView; diff --git a/ILSpy/Commands/OpenCommand.cs b/ILSpy/Commands/OpenCommand.cs index 88a632610..9e4030cc8 100644 --- a/ILSpy/Commands/OpenCommand.cs +++ b/ILSpy/Commands/OpenCommand.cs @@ -17,12 +17,13 @@ // DEALINGS IN THE SOFTWARE. using System.Windows.Input; + using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy { - [ExportToolbarCommand(ToolTip = nameof(Resources.Open), ToolbarIcon = "Images/Open", ToolbarCategory = nameof(Resources.Open), ToolbarOrder = 0)] - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources._Open), MenuIcon = "Images/Open", MenuCategory = nameof(Resources.Open), MenuOrder = 0)] + [ExportToolbarCommand(ToolTip = nameof(Resources.Open), ToolbarIcon = "Images/Open", ToolbarCategory = nameof(Resources.Open), ToolbarOrder = 0)] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources._Open), MenuIcon = "Images/Open", MenuCategory = nameof(Resources.Open), MenuOrder = 0)] sealed class OpenCommand : CommandWrapper { public OpenCommand() diff --git a/ILSpy/Commands/OpenFromGacCommand.cs b/ILSpy/Commands/OpenFromGacCommand.cs index bcac992ce..e9d72811a 100644 --- a/ILSpy/Commands/OpenFromGacCommand.cs +++ b/ILSpy/Commands/OpenFromGacCommand.cs @@ -19,7 +19,7 @@ using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.OpenFrom_GAC), MenuIcon = "Images/AssemblyListGAC", MenuCategory = nameof(Resources.Open), MenuOrder = 1)] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.OpenFrom_GAC), MenuIcon = "Images/AssemblyListGAC", MenuCategory = nameof(Resources.Open), MenuOrder = 1)] sealed class OpenFromGacCommand : SimpleCommand { public override void Execute(object parameter) diff --git a/ILSpy/Commands/Pdb2XmlCommand.cs b/ILSpy/Commands/Pdb2XmlCommand.cs index 13856e8b0..b261651cc 100644 --- a/ILSpy/Commands/Pdb2XmlCommand.cs +++ b/ILSpy/Commands/Pdb2XmlCommand.cs @@ -22,16 +22,18 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; + using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; + using Microsoft.DiaSymReader.Tools; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = nameof(Resources._File) , Header = nameof(Resources.DEBUGDumpPDBAsXML), MenuCategory = nameof(Resources.Open), MenuOrder = 2.6)] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources.DEBUGDumpPDBAsXML), MenuCategory = nameof(Resources.Open), MenuOrder = 2.6)] sealed class Pdb2XmlCommand : SimpleCommand { public override bool CanExecute(object parameter) @@ -53,9 +55,11 @@ namespace ICSharpCode.ILSpy Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task.Factory.StartNew(() => { AvalonEditTextOutput output = new AvalonEditTextOutput(); var writer = new TextOutputWriter(output); - foreach (var node in nodes) { + foreach (var node in nodes) + { string pdbFileName = Path.ChangeExtension(node.LoadedAssembly.FileName, ".pdb"); - if (!File.Exists(pdbFileName)) continue; + if (!File.Exists(pdbFileName)) + continue; using (var pdbStream = File.OpenRead(pdbFileName)) using (var peStream = File.OpenRead(node.LoadedAssembly.FileName)) PdbToXmlConverter.ToXml(writer, pdbStream, peStream, options); diff --git a/ILSpy/Commands/RefreshCommand.cs b/ILSpy/Commands/RefreshCommand.cs index bf92dc491..b81c2260e 100644 --- a/ILSpy/Commands/RefreshCommand.cs +++ b/ILSpy/Commands/RefreshCommand.cs @@ -17,12 +17,13 @@ // DEALINGS IN THE SOFTWARE. using System.Windows.Input; + using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy { - [ExportToolbarCommand(ToolTip = nameof(Resources.RefreshCommand_ReloadAssemblies), ToolbarIcon = "Images/Refresh", ToolbarCategory = nameof(Resources.Open), ToolbarOrder = 2)] - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources._Reload), MenuIcon = "Images/Refresh", MenuCategory = nameof(Resources.Open), MenuOrder = 2)] + [ExportToolbarCommand(ToolTip = nameof(Resources.RefreshCommand_ReloadAssemblies), ToolbarIcon = "Images/Refresh", ToolbarCategory = nameof(Resources.Open), ToolbarOrder = 2)] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources._Reload), MenuIcon = "Images/Refresh", MenuCategory = nameof(Resources.Open), MenuOrder = 2)] sealed class RefreshCommand : CommandWrapper { public RefreshCommand() diff --git a/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs b/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs index e67515444..c368a8179 100644 --- a/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs +++ b/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs @@ -19,11 +19,12 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources._RemoveAssembliesWithLoadErrors), MenuCategory = nameof(Resources.Remove), MenuOrder = 2.6)] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources._RemoveAssembliesWithLoadErrors), MenuCategory = nameof(Resources.Remove), MenuOrder = 2.6)] class RemoveAssembliesWithLoadErrors : SimpleCommand { public override bool CanExecute(object parameter) @@ -33,8 +34,10 @@ namespace ICSharpCode.ILSpy public override void Execute(object parameter) { - foreach (var asm in MainWindow.Instance.CurrentAssemblyList.GetAssemblies()) { - if (!asm.HasLoadError) continue; + foreach (var asm in MainWindow.Instance.CurrentAssemblyList.GetAssemblies()) + { + if (!asm.HasLoadError) + continue; var node = MainWindow.Instance.AssemblyListTreeNode.FindAssemblyNode(asm); if (node != null && node.CanDelete()) node.Delete(); diff --git a/ILSpy/Commands/SaveCodeContextMenuEntry.cs b/ILSpy/Commands/SaveCodeContextMenuEntry.cs index c54a2ba7b..088ab9da5 100644 --- a/ILSpy/Commands/SaveCodeContextMenuEntry.cs +++ b/ILSpy/Commands/SaveCodeContextMenuEntry.cs @@ -22,10 +22,12 @@ using System.IO; using System.Linq; using System.Windows; using System.Windows.Input; + using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.TreeView; + using Microsoft.Win32; namespace ICSharpCode.ILSpy.TextView @@ -58,15 +60,19 @@ namespace ICSharpCode.ILSpy.TextView var currentLanguage = MainWindow.Instance.CurrentLanguage; var tabPage = Docking.DockWorkspace.Instance.ActiveTabPage; tabPage.ShowTextView(textView => { - if (selectedNodes.Count == 1 && selectedNodes[0] is ILSpyTreeNode singleSelection) { + if (selectedNodes.Count == 1 && selectedNodes[0] is ILSpyTreeNode singleSelection) + { // if there's only one treenode selected // we will invoke the custom Save logic if (singleSelection.Save(tabPage)) return; - } else if (selectedNodes.Count > 1 && selectedNodes.All(n => n is AssemblyTreeNode)) { + } + else if (selectedNodes.Count > 1 && selectedNodes.All(n => n is AssemblyTreeNode)) + { var selectedPath = SelectSolutionFile(); - if (!string.IsNullOrEmpty(selectedPath)) { + if (!string.IsNullOrEmpty(selectedPath)) + { var assemblies = selectedNodes.OfType() .Select(n => n.LoadedAssembly) .Where(a => !a.HasLoadError).ToArray(); @@ -95,15 +101,19 @@ namespace ICSharpCode.ILSpy.TextView dlg.FileName = "Solution.sln"; dlg.Filter = Resources.VisualStudioSolutionFileSlnAllFiles; - if (dlg.ShowDialog() != true) { + if (dlg.ShowDialog() != true) + { return null; } string selectedPath = Path.GetDirectoryName(dlg.FileName); bool directoryNotEmpty; - try { + try + { directoryNotEmpty = Directory.EnumerateFileSystemEntries(selectedPath).Any(); - } catch (Exception e) when (e is IOException || e is UnauthorizedAccessException || e is System.Security.SecurityException) { + } + catch (Exception e) when (e is IOException || e is UnauthorizedAccessException || e is System.Security.SecurityException) + { MessageBox.Show( "The directory cannot be accessed. Please ensure it exists and you have sufficient rights to access it.", "Solution directory not accessible", @@ -111,7 +121,8 @@ namespace ICSharpCode.ILSpy.TextView return null; } - if (directoryNotEmpty) { + if (directoryNotEmpty) + { var result = MessageBox.Show( Resources.AssemblySaveCodeDirectoryNotEmpty, Resources.AssemblySaveCodeDirectoryNotEmptyTitle, diff --git a/ILSpy/Commands/SaveCommand.cs b/ILSpy/Commands/SaveCommand.cs index fe18990ce..b8ca82bb1 100644 --- a/ILSpy/Commands/SaveCommand.cs +++ b/ILSpy/Commands/SaveCommand.cs @@ -17,11 +17,12 @@ // DEALINGS IN THE SOFTWARE. using System.Windows.Input; + using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources._SaveCode), MenuIcon = "Images/Save", MenuCategory = nameof(Resources.Save), MenuOrder = 0)] + [ExportMainMenuCommand(Menu = nameof(Resources._File), Header = nameof(Resources._SaveCode), MenuIcon = "Images/Save", MenuCategory = nameof(Resources.Save), MenuOrder = 0)] sealed class SaveCommand : CommandWrapper { public SaveCommand() diff --git a/ILSpy/Commands/SearchMsdnContextMenuEntry.cs b/ILSpy/Commands/SearchMsdnContextMenuEntry.cs index 986f9db25..1e5e9d73d 100644 --- a/ILSpy/Commands/SearchMsdnContextMenuEntry.cs +++ b/ILSpy/Commands/SearchMsdnContextMenuEntry.cs @@ -17,10 +17,11 @@ // DEALINGS IN THE SOFTWARE. using System.Linq; +using System.Threading; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TreeNodes; -using System.Threading; namespace ICSharpCode.ILSpy { [ExportContextMenuEntry(Header = nameof(Resources.SearchMSDN), Icon = "images/SearchMsdn", Order = 9999)] @@ -75,7 +76,8 @@ namespace ICSharpCode.ILSpy { if (entity.DeclaringTypeDefinition == null) return false; - switch (entity.DeclaringTypeDefinition.Accessibility) { + switch (entity.DeclaringTypeDefinition.Accessibility) + { case Accessibility.Public: case Accessibility.Protected: case Accessibility.ProtectedOrInternal: @@ -87,8 +89,10 @@ namespace ICSharpCode.ILSpy public void Execute(TextViewContext context) { - if (context.SelectedTreeNodes != null) { - foreach (ILSpyTreeNode node in context.SelectedTreeNodes) { + if (context.SelectedTreeNodes != null) + { + foreach (ILSpyTreeNode node in context.SelectedTreeNodes) + { SearchMsdn(node); } } @@ -102,7 +106,8 @@ namespace ICSharpCode.ILSpy if (namespaceNode != null) address = string.Format(msdnAddress, namespaceNode.Name); - if (node is IMemberTreeNode memberNode) { + if (node is IMemberTreeNode memberNode) + { var member = memberNode.Member; var memberName = string.Empty; diff --git a/ILSpy/Commands/SelectPdbContextMenuEntry.cs b/ILSpy/Commands/SelectPdbContextMenuEntry.cs index b538ad708..c6977eb51 100644 --- a/ILSpy/Commands/SelectPdbContextMenuEntry.cs +++ b/ILSpy/Commands/SelectPdbContextMenuEntry.cs @@ -18,9 +18,11 @@ using System.IO; using System.Linq; + using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; + using Microsoft.Win32; namespace ICSharpCode.ILSpy { @@ -30,14 +32,17 @@ namespace ICSharpCode.ILSpy public void Execute(TextViewContext context) { var assembly = (context.SelectedTreeNodes?.FirstOrDefault() as AssemblyTreeNode)?.LoadedAssembly; - if (assembly == null) return; + if (assembly == null) + return; OpenFileDialog dlg = new OpenFileDialog(); dlg.FileName = DecompilerTextView.CleanUpName(assembly.ShortName) + ".pdb"; dlg.Filter = Resources.PortablePDBPdbAllFiles; dlg.InitialDirectory = Path.GetDirectoryName(assembly.FileName); - if (dlg.ShowDialog() != true) return; + if (dlg.ShowDialog() != true) + return; - using (context.TreeView.LockUpdates()) { + using (context.TreeView.LockUpdates()) + { assembly.PdbFileOverride = dlg.FileName; assembly.AssemblyList.ReloadAssembly(assembly); } diff --git a/ILSpy/Commands/ShowCFGContextMenuEntry.cs b/ILSpy/Commands/ShowCFGContextMenuEntry.cs index d1d2e4c51..217240e95 100644 --- a/ILSpy/Commands/ShowCFGContextMenuEntry.cs +++ b/ILSpy/Commands/ShowCFGContextMenuEntry.cs @@ -1,5 +1,6 @@ using System; using System.Windows; + using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.ControlFlow; @@ -12,11 +13,14 @@ namespace ICSharpCode.ILSpy.Commands { public void Execute(TextViewContext context) { - try { + try + { var container = (BlockContainer)context.Reference.Reference; var cfg = new ControlFlowGraph(container); ControlFlowNode.ExportGraph(cfg.cfg).Show(); - } catch (Exception ex) { + } + catch (Exception ex) + { MessageBox.Show("Error generating CFG - requires GraphViz dot.exe in PATH" + Environment.NewLine + Environment.NewLine + ex.ToString()); } } diff --git a/ILSpy/Commands/ShowDebugSteps.cs b/ILSpy/Commands/ShowDebugSteps.cs index bb2ead201..21f1c069e 100644 --- a/ILSpy/Commands/ShowDebugSteps.cs +++ b/ILSpy/Commands/ShowDebugSteps.cs @@ -6,7 +6,7 @@ using ICSharpCode.ILSpy.ViewModels; namespace ICSharpCode.ILSpy.Commands { - [ExportMainMenuCommand(Menu = nameof(Resources._View), Header = nameof(Resources._ShowDebugSteps), MenuOrder = 5000)] + [ExportMainMenuCommand(Menu = nameof(Resources._View), Header = nameof(Resources._ShowDebugSteps), MenuOrder = 5000)] class ShowDebugSteps : SimpleCommand { public override void Execute(object parameter) diff --git a/ILSpy/Commands/SimpleCommand.cs b/ILSpy/Commands/SimpleCommand.cs index d8490a1a6..8822482e7 100644 --- a/ILSpy/Commands/SimpleCommand.cs +++ b/ILSpy/Commands/SimpleCommand.cs @@ -23,8 +23,7 @@ namespace ICSharpCode.ILSpy { public abstract class SimpleCommand : ICommand { - public event EventHandler CanExecuteChanged - { + public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } diff --git a/ILSpy/Commands/SortAssemblyListCommand.cs b/ILSpy/Commands/SortAssemblyListCommand.cs index 2222518a6..a9e09226a 100644 --- a/ILSpy/Commands/SortAssemblyListCommand.cs +++ b/ILSpy/Commands/SortAssemblyListCommand.cs @@ -18,13 +18,14 @@ using System; using System.Collections.Generic; + using ICSharpCode.ILSpy.Properties; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy { - [ExportMainMenuCommand(Menu = nameof(Resources._View), Header = nameof(Resources.SortAssembly_listName), MenuIcon = "Images/Sort", MenuCategory = nameof(Resources.View))] - [ExportToolbarCommand(ToolTip = nameof(Resources.SortAssemblyListName), ToolbarIcon = "Images/Sort", ToolbarCategory = nameof(Resources.View))] + [ExportMainMenuCommand(Menu = nameof(Resources._View), Header = nameof(Resources.SortAssembly_listName), MenuIcon = "Images/Sort", MenuCategory = nameof(Resources.View))] + [ExportToolbarCommand(ToolTip = nameof(Resources.SortAssemblyListName), ToolbarIcon = "Images/Sort", ToolbarCategory = nameof(Resources.View))] sealed class SortAssemblyListCommand : SimpleCommand, IComparer { public override void Execute(object parameter) @@ -39,8 +40,8 @@ namespace ICSharpCode.ILSpy } } - [ExportMainMenuCommand(Menu = nameof(Resources._View), Header = nameof(Resources._CollapseTreeNodes), MenuIcon = "Images/CollapseAll", MenuCategory = nameof(Resources.View))] - [ExportToolbarCommand(ToolTip = nameof(Resources.CollapseTreeNodes), ToolbarIcon = "Images/CollapseAll", ToolbarCategory = nameof(Resources.View))] + [ExportMainMenuCommand(Menu = nameof(Resources._View), Header = nameof(Resources._CollapseTreeNodes), MenuIcon = "Images/CollapseAll", MenuCategory = nameof(Resources.View))] + [ExportToolbarCommand(ToolTip = nameof(Resources.CollapseTreeNodes), ToolbarIcon = "Images/CollapseAll", ToolbarCategory = nameof(Resources.View))] sealed class CollapseAllCommand : SimpleCommand { public override void Execute(object parameter) @@ -50,7 +51,8 @@ namespace ICSharpCode.ILSpy void CollapseChildren(SharpTreeNode node) { - foreach (var child in node.Children) { + foreach (var child in node.Children) + { if (!child.IsExpanded) continue; CollapseChildren(child); diff --git a/ILSpy/ContextMenuEntry.cs b/ILSpy/ContextMenuEntry.cs index 2edb04c99..d7b10617b 100644 --- a/ILSpy/ContextMenuEntry.cs +++ b/ILSpy/ContextMenuEntry.cs @@ -23,6 +23,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; + using ICSharpCode.AvalonEdit; using ICSharpCode.ILSpy.TextView; using ICSharpCode.TreeView; @@ -35,7 +36,7 @@ namespace ICSharpCode.ILSpy bool IsEnabled(TextViewContext context); void Execute(TextViewContext context); } - + public class TextViewContext { /// @@ -43,13 +44,13 @@ namespace ICSharpCode.ILSpy /// Returns null, if context menu does not belong to a tree view. /// public SharpTreeNode[] SelectedTreeNodes { get; private set; } - + /// /// Returns the tree view the context menu is assigned to. /// Returns null, if context menu is not assigned to a tree view. /// public SharpTreeView TreeView { get; private set; } - + /// /// Returns the text view the context menu is assigned to. /// Returns null, if context menu is not assigned to a text view. @@ -73,7 +74,7 @@ namespace ICSharpCode.ILSpy /// Returns null, if there was no reference found. /// public ReferenceSegment Reference { get; private set; } - + /// /// Returns the position in TextView the mouse cursor is currently hovering above. /// Returns null, if TextView returns null; @@ -113,7 +114,7 @@ namespace ICSharpCode.ILSpy }; } } - + public interface IContextMenuEntryMetadata { string Icon { get; } @@ -123,9 +124,9 @@ namespace ICSharpCode.ILSpy double Order { get; } } - + [MetadataAttribute] - [AttributeUsage(AttributeTargets.Class, AllowMultiple=false)] + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class ExportContextMenuEntryAttribute : ExportAttribute, IContextMenuEntryMetadata { public ExportContextMenuEntryAttribute() @@ -134,14 +135,14 @@ namespace ICSharpCode.ILSpy // entries default to end of menu unless given specific order position Order = double.MaxValue; } - + public string Icon { get; set; } public string Header { get; set; } public string Category { get; set; } public string InputGestureText { get; set; } public double Order { get; set; } } - + internal class ContextMenuProvider { /// @@ -184,7 +185,7 @@ namespace ICSharpCode.ILSpy readonly ListBox listBox; readonly DataGrid dataGrid; readonly Lazy[] entries; - + private ContextMenuProvider() { entries = App.ExportProvider.GetExports().ToArray(); @@ -195,7 +196,7 @@ namespace ICSharpCode.ILSpy { this.textView = textView ?? throw new ArgumentNullException(nameof(textView)); } - + ContextMenuProvider(SharpTreeView treeView) : this() { @@ -217,7 +218,8 @@ namespace ICSharpCode.ILSpy void treeView_ContextMenuOpening(object sender, ContextMenuEventArgs e) { TextViewContext context = TextViewContext.Create(treeView); - if (context.SelectedTreeNodes.Length == 0) { + if (context.SelectedTreeNodes.Length == 0) + { e.Handled = true; // don't show the menu return; } @@ -228,7 +230,7 @@ namespace ICSharpCode.ILSpy // hide the context menu. e.Handled = true; } - + void textView_ContextMenuOpening(object sender, ContextMenuEventArgs e) { TextViewContext context = TextViewContext.Create(textView: textView); @@ -265,28 +267,35 @@ namespace ICSharpCode.ILSpy bool ShowContextMenu(TextViewContext context, out ContextMenu menu) { menu = new ContextMenu(); - foreach (var category in entries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.Category)) { + foreach (var category in entries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.Category)) + { bool needSeparatorForCategory = menu.Items.Count > 0; - foreach (var entryPair in category) { + foreach (var entryPair in category) + { IContextMenuEntry entry = entryPair.Value; - if (entry.IsVisible(context)) { - if (needSeparatorForCategory) { + if (entry.IsVisible(context)) + { + if (needSeparatorForCategory) + { menu.Items.Add(new Separator()); needSeparatorForCategory = false; } MenuItem menuItem = new MenuItem(); menuItem.Header = MainWindow.GetResourceString(entryPair.Metadata.Header); menuItem.InputGestureText = entryPair.Metadata.InputGestureText; - if (!string.IsNullOrEmpty(entryPair.Metadata.Icon)) { + if (!string.IsNullOrEmpty(entryPair.Metadata.Icon)) + { menuItem.Icon = new Image { Width = 16, Height = 16, Source = Images.Load(entryPair.Value, entryPair.Metadata.Icon) }; } - if (entryPair.Value.IsEnabled(context)) { + if (entryPair.Value.IsEnabled(context)) + { menuItem.Click += delegate { entry.Execute(context); }; - } else + } + else menuItem.IsEnabled = false; menu.Items.Add(menuItem); } diff --git a/ILSpy/Controls/BoolToVisibilityConverter.cs b/ILSpy/Controls/BoolToVisibilityConverter.cs index eb0d6f8ec..31211050c 100644 --- a/ILSpy/Controls/BoolToVisibilityConverter.cs +++ b/ILSpy/Controls/BoolToVisibilityConverter.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpy.Controls notVisible = Visibility.Collapsed; if (!(value is bool b)) return notVisible; - return b ? Visibility.Visible : notVisible; + return b ? Visibility.Visible : notVisible; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) diff --git a/ILSpy/Controls/CustomDialog.cs b/ILSpy/Controls/CustomDialog.cs index 6150d2e69..994bedffc 100644 --- a/ILSpy/Controls/CustomDialog.cs +++ b/ILSpy/Controls/CustomDialog.cs @@ -33,8 +33,7 @@ namespace ICSharpCode.ILSpy.Controls /// /// Gets the index of the button pressed. /// - public int Result - { + public int Result { get { return result; } @@ -50,14 +49,16 @@ namespace ICSharpCode.ILSpy.Controls this.cancelButton = cancelButton; this.Text = caption; - using (Graphics g = this.CreateGraphics()) { + using (Graphics g = this.CreateGraphics()) + { Rectangle screen = Screen.PrimaryScreen.WorkingArea; SizeF size = g.MeasureString(message, label.Font, screen.Width - 20); Size clientSize = size.ToSize(); Button[] buttons = new Button[buttonLabels.Length]; int[] positions = new int[buttonLabels.Length]; int pos = 0; - for (int i = 0; i < buttons.Length; i++) { + for (int i = 0; i < buttons.Length; i++) + { Button newButton = new Button(); newButton.FlatStyle = FlatStyle.System; newButton.Tag = i; @@ -70,37 +71,44 @@ namespace ICSharpCode.ILSpy.Controls buttons[i] = newButton; pos += newButton.Width + 4; } - if (acceptButton >= 0) { + if (acceptButton >= 0) + { AcceptButton = buttons[acceptButton]; } - if (cancelButton >= 0) { + if (cancelButton >= 0) + { CancelButton = buttons[cancelButton]; } pos += 4; // add space before first button // (we don't start with pos=4 because this space doesn't belong to the button panel) - if (pos > clientSize.Width) { + if (pos > clientSize.Width) + { clientSize.Width = pos; } clientSize.Height += panel.Height + 6; this.ClientSize = clientSize; int start = (clientSize.Width - pos) / 2; - for (int i = 0; i < buttons.Length; i++) { + for (int i = 0; i < buttons.Length; i++) + { buttons[i].Location = new Point(start + positions[i], 4); } panel.Controls.AddRange(buttons); } label.Text = message; - + this.ResumeLayout(false); } protected override void OnKeyDown(KeyEventArgs e) { - if (cancelButton == -1 && e.KeyCode == Keys.Escape) { + if (cancelButton == -1 && e.KeyCode == Keys.Escape) + { this.Close(); - } else if (e.KeyCode == Keys.C && e.Control) { + } + else if (e.KeyCode == Keys.C && e.Control) + { Clipboard.SetText(this.Text + Environment.NewLine + label.Text); } } diff --git a/ILSpy/Controls/ExtensionMethods.cs b/ILSpy/Controls/ExtensionMethods.cs index 095ddc41e..15e40eb7b 100644 --- a/ILSpy/Controls/ExtensionMethods.cs +++ b/ILSpy/Controls/ExtensionMethods.cs @@ -35,31 +35,31 @@ namespace ICSharpCode.ILSpy.Controls public static void SetValueToExtension(this DependencyObject targetObject, DependencyProperty property, MarkupExtension markupExtension) { // This method was copied from ICSharpCode.Core.Presentation (with permission to switch license to X11) - + if (targetObject == null) throw new ArgumentNullException(nameof(targetObject)); if (property == null) throw new ArgumentNullException(nameof(property)); if (markupExtension == null) throw new ArgumentNullException(nameof(markupExtension)); - + var serviceProvider = new SetValueToExtensionServiceProvider(targetObject, property); targetObject.SetValue(property, markupExtension.ProvideValue(serviceProvider)); } - + sealed class SetValueToExtensionServiceProvider : IServiceProvider, IProvideValueTarget { // This class was copied from ICSharpCode.Core.Presentation (with permission to switch license to X11) - + readonly DependencyObject targetObject; readonly DependencyProperty targetProperty; - + public SetValueToExtensionServiceProvider(DependencyObject targetObject, DependencyProperty property) { this.targetObject = targetObject; this.targetProperty = property; } - + public object GetService(Type serviceType) { if (serviceType == typeof(IProvideValueTarget)) @@ -67,11 +67,11 @@ namespace ICSharpCode.ILSpy.Controls else return null; } - + public object TargetObject { get { return targetObject; } } - + public object TargetProperty { get { return targetProperty; } } diff --git a/ILSpy/Controls/GridViewColumnAutoSize.cs b/ILSpy/Controls/GridViewColumnAutoSize.cs index 8b010ebce..5c833b1cf 100644 --- a/ILSpy/Controls/GridViewColumnAutoSize.cs +++ b/ILSpy/Controls/GridViewColumnAutoSize.cs @@ -38,58 +38,68 @@ namespace ICSharpCode.ILSpy.Controls public static readonly DependencyProperty AutoWidthProperty = DependencyProperty.RegisterAttached("AutoWidth", typeof(string), typeof(GridViewColumnAutoSize), - new FrameworkPropertyMetadata(null, AutoWidthPropertyChanged)); - + new FrameworkPropertyMetadata(null, AutoWidthPropertyChanged)); + public static string GetAutoWidth(DependencyObject obj) { return (string)obj.GetValue(AutoWidthProperty); } - + public static void SetAutoWidth(DependencyObject obj, string value) { obj.SetValue(AutoWidthProperty, value); } - + static void AutoWidthPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { ListView grid = sender as ListView; - if (grid == null) return; - grid.SizeChanged += delegate(object listView, SizeChangedEventArgs e) { + if (grid == null) + return; + grid.SizeChanged += delegate (object listView, SizeChangedEventArgs e) { ListView lv = listView as ListView; - if (lv == null) return; + if (lv == null) + return; GridView v = lv.View as GridView; - if (v == null) return; + if (v == null) + return; CalculateSizes(v, GetAutoWidth(lv), e.NewSize.Width); }; GridView view = grid.View as GridView; - if (view == null) return; + if (view == null) + return; CalculateSizes(view, args.NewValue as string, grid.ActualWidth); } - + static void CalculateSizes(GridView view, string sizeValue, double fullWidth) { string[] sizes = (sizeValue ?? "").Split(';'); - + if (sizes.Length != view.Columns.Count) return; Dictionary> percentages = new Dictionary>(); double remainingWidth = fullWidth - 30; // 30 is a good offset for the scrollbar - - for (int i = 0; i < view.Columns.Count; i++) { + + for (int i = 0; i < view.Columns.Count; i++) + { var column = view.Columns[i]; double size; bool isPercentage = !double.TryParse(sizes[i], out size); - if (isPercentage) { + if (isPercentage) + { size = double.Parse(sizes[i].TrimEnd('%', ' ')); percentages.Add(i, w => w * size / 100.0); - } else { + } + else + { column.Width = size; remainingWidth -= size; } } - - if (remainingWidth < 0) return; - foreach (var p in percentages) { + + if (remainingWidth < 0) + return; + foreach (var p in percentages) + { var column = view.Columns[p.Key]; column.Width = p.Value(remainingWidth); } diff --git a/ILSpy/Controls/MarkupExtensions.cs b/ILSpy/Controls/MarkupExtensions.cs index 54d5a863b..c3383270c 100644 --- a/ILSpy/Controls/MarkupExtensions.cs +++ b/ILSpy/Controls/MarkupExtensions.cs @@ -27,12 +27,12 @@ namespace ICSharpCode.ILSpy.Controls class ControlColor : MarkupExtension { readonly float val; - + /// /// Amount of highlight (0..1) /// public float Highlight { get; set; } - + /// /// val: Color value in the range 105..255. /// @@ -42,18 +42,23 @@ namespace ICSharpCode.ILSpy.Controls throw new ArgumentOutOfRangeException(nameof(val)); this.val = val; } - + public override object ProvideValue(IServiceProvider serviceProvider) { - if (val > 227) { + if (val > 227) + { return Interpolate(227, SystemColors.ControlLightColor, 255, SystemColors.ControlLightLightColor); - } else if (val > 160) { + } + else if (val > 160) + { return Interpolate(160, SystemColors.ControlDarkColor, 227, SystemColors.ControlLightColor); - } else { + } + else + { return Interpolate(105, SystemColors.ControlDarkDarkColor, 160, SystemColors.ControlDarkColor); } } - + Color Interpolate(float v1, Color c1, float v2, Color c2) { float v = (val - v1) / (v2 - v1); diff --git a/ILSpy/Controls/ResourceObjectTable.xaml.cs b/ILSpy/Controls/ResourceObjectTable.xaml.cs index a226a7c56..2a836d44a 100644 --- a/ILSpy/Controls/ResourceObjectTable.xaml.cs +++ b/ILSpy/Controls/ResourceObjectTable.xaml.cs @@ -48,7 +48,7 @@ namespace ICSharpCode.ILSpy.Controls if (e.HeightChanged) MaxHeight = e.NewSize.Height; } - + void ExecuteCopy(object sender, ExecutedRoutedEventArgs args) { StringBuilder sb = new StringBuilder(); @@ -58,7 +58,7 @@ namespace ICSharpCode.ILSpy.Controls } Clipboard.SetText(sb.ToString()); } - + void CanExecuteCopy(object sender, CanExecuteRoutedEventArgs args) { args.CanExecute = true; diff --git a/ILSpy/Controls/ResourceStringTable.xaml.cs b/ILSpy/Controls/ResourceStringTable.xaml.cs index 0a0ec2c06..5db68e561 100644 --- a/ILSpy/Controls/ResourceStringTable.xaml.cs +++ b/ILSpy/Controls/ResourceStringTable.xaml.cs @@ -48,7 +48,7 @@ namespace ICSharpCode.ILSpy.Controls if (e.HeightChanged) MaxHeight = e.NewSize.Height; } - + void ExecuteCopy(object sender, ExecutedRoutedEventArgs args) { StringBuilder sb = new StringBuilder(); @@ -58,7 +58,7 @@ namespace ICSharpCode.ILSpy.Controls } Clipboard.SetText(sb.ToString()); } - + void CanExecuteCopy(object sender, CanExecuteRoutedEventArgs args) { args.CanExecute = true; diff --git a/ILSpy/Controls/SearchBox.cs b/ILSpy/Controls/SearchBox.cs index d6e7cbf4d..b36640e1c 100644 --- a/ILSpy/Controls/SearchBox.cs +++ b/ILSpy/Controls/SearchBox.cs @@ -27,28 +27,29 @@ namespace ICSharpCode.ILSpy.Controls { public class SearchBox : TextBox { - static SearchBox() { + static SearchBox() + { DefaultStyleKeyProperty.OverrideMetadata( typeof(SearchBox), new FrameworkPropertyMetadata(typeof(SearchBox))); } - + #region Dependency properties - + public static DependencyProperty WatermarkTextProperty = DependencyProperty.Register("WatermarkText", typeof(string), typeof(SearchBox)); - + public static DependencyProperty WatermarkColorProperty = DependencyProperty.Register("WatermarkColor", typeof(Brush), typeof(SearchBox)); - + public static DependencyProperty HasTextProperty = DependencyProperty.Register("HasText", typeof(bool), typeof(SearchBox)); - + public static readonly DependencyProperty UpdateDelayProperty = DependencyProperty.Register("UpdateDelay", typeof(TimeSpan), typeof(SearchBox), - new FrameworkPropertyMetadata(TimeSpan.FromMilliseconds(200))); - + new FrameworkPropertyMetadata(TimeSpan.FromMilliseconds(200))); + #endregion - + #region Public Properties - + public string WatermarkText { get { return (string)GetValue(WatermarkTextProperty); } set { SetValue(WatermarkTextProperty, value); } @@ -58,7 +59,7 @@ namespace ICSharpCode.ILSpy.Controls get { return (Brush)GetValue(WatermarkColorProperty); } set { SetValue(WatermarkColorProperty, value); } } - + public bool HasText { get { return (bool)GetValue(HasTextProperty); } private set { SetValue(HasTextProperty, value); } @@ -68,27 +69,30 @@ namespace ICSharpCode.ILSpy.Controls get { return (TimeSpan)GetValue(UpdateDelayProperty); } set { SetValue(UpdateDelayProperty, value); } } - + #endregion - + #region Handlers - private void IconBorder_MouseLeftButtonUp(object obj, MouseButtonEventArgs e) { + private void IconBorder_MouseLeftButtonUp(object obj, MouseButtonEventArgs e) + { if (this.HasText) this.Text = string.Empty; } #endregion - + #region Overrides - + DispatcherTimer timer; - - protected override void OnTextChanged(TextChangedEventArgs e) { + + protected override void OnTextChanged(TextChangedEventArgs e) + { base.OnTextChanged(e); - + HasText = this.Text.Length > 0; - if (timer == null) { + if (timer == null) + { timer = new DispatcherTimer(); timer.Tick += timer_Tick; } @@ -102,48 +106,56 @@ namespace ICSharpCode.ILSpy.Controls timer.Stop(); timer = null; var textBinding = GetBindingExpression(TextProperty); - if (textBinding != null) { + if (textBinding != null) + { textBinding.UpdateSource(); } } - + protected override void OnLostFocus(RoutedEventArgs e) { - if (!HasText) { + if (!HasText) + { Label wl = (Label)GetTemplateChild("WatermarkLabel"); if (wl != null) wl.Visibility = Visibility.Visible; } - + base.OnLostFocus(e); } - + protected override void OnGotFocus(RoutedEventArgs e) { - if (!HasText) { + if (!HasText) + { Label wl = (Label)GetTemplateChild("WatermarkLabel"); if (wl != null) wl.Visibility = Visibility.Hidden; } - + base.OnGotFocus(e); } - public override void OnApplyTemplate() { + public override void OnApplyTemplate() + { base.OnApplyTemplate(); Border iconBorder = GetTemplateChild("PART_IconBorder") as Border; - if (iconBorder != null) { + if (iconBorder != null) + { iconBorder.MouseLeftButtonUp += IconBorder_MouseLeftButtonUp; } } - + protected override void OnKeyDown(KeyEventArgs e) { - if (e.Key == Key.Escape && this.Text.Length > 0) { + if (e.Key == Key.Escape && this.Text.Length > 0) + { this.Text = string.Empty; e.Handled = true; - } else { + } + else + { base.OnKeyDown(e); } } diff --git a/ILSpy/Controls/SortableGridViewColumn.cs b/ILSpy/Controls/SortableGridViewColumn.cs index 94a0ca031..336f5442c 100644 --- a/ILSpy/Controls/SortableGridViewColumn.cs +++ b/ILSpy/Controls/SortableGridViewColumn.cs @@ -30,50 +30,52 @@ namespace ICSharpCode.ILSpy.Controls public class SortableGridViewColumn : GridViewColumn { // This class was copied from ICSharpCode.Core.Presentation. - + static readonly ComponentResourceKey headerTemplateKey = new ComponentResourceKey(typeof(SortableGridViewColumn), "ColumnHeaderTemplate"); - + public SortableGridViewColumn() { this.SetValueToExtension(HeaderTemplateProperty, new DynamicResourceExtension(headerTemplateKey)); } - + string sortBy; - + public string SortBy { get { return sortBy; } set { - if (sortBy != value) { + if (sortBy != value) + { sortBy = value; OnPropertyChanged(new PropertyChangedEventArgs("SortBy")); } } } - + #region SortDirection property public static readonly DependencyProperty SortDirectionProperty = DependencyProperty.RegisterAttached("SortDirection", typeof(ColumnSortDirection), typeof(SortableGridViewColumn), - new FrameworkPropertyMetadata(ColumnSortDirection.None, OnSortDirectionChanged)); - + new FrameworkPropertyMetadata(ColumnSortDirection.None, OnSortDirectionChanged)); + public ColumnSortDirection SortDirection { get { return (ColumnSortDirection)GetValue(SortDirectionProperty); } set { SetValue(SortDirectionProperty, value); } } - + public static ColumnSortDirection GetSortDirection(ListView listView) { return (ColumnSortDirection)listView.GetValue(SortDirectionProperty); } - + public static void SetSortDirection(ListView listView, ColumnSortDirection value) { listView.SetValue(SortDirectionProperty, value); } - + static void OnSortDirectionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { ListView grid = sender as ListView; - if (grid != null) { + if (grid != null) + { SortableGridViewColumn col = GetCurrentSortColumn(grid); if (col != null) col.SortDirection = (ColumnSortDirection)args.NewValue; @@ -81,71 +83,77 @@ namespace ICSharpCode.ILSpy.Controls } } #endregion - + #region CurrentSortColumn property public static readonly DependencyProperty CurrentSortColumnProperty = DependencyProperty.RegisterAttached("CurrentSortColumn", typeof(SortableGridViewColumn), typeof(SortableGridViewColumn), - new FrameworkPropertyMetadata(OnCurrentSortColumnChanged)); - + new FrameworkPropertyMetadata(OnCurrentSortColumnChanged)); + public static SortableGridViewColumn GetCurrentSortColumn(ListView listView) { return (SortableGridViewColumn)listView.GetValue(CurrentSortColumnProperty); } - + public static void SetCurrentSortColumn(ListView listView, SortableGridViewColumn value) { listView.SetValue(CurrentSortColumnProperty, value); } - + static void OnCurrentSortColumnChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { ListView grid = sender as ListView; - if (grid != null) { + if (grid != null) + { SortableGridViewColumn oldColumn = (SortableGridViewColumn)args.OldValue; if (oldColumn != null) oldColumn.SortDirection = ColumnSortDirection.None; SortableGridViewColumn newColumn = (SortableGridViewColumn)args.NewValue; - if (newColumn != null) { + if (newColumn != null) + { newColumn.SortDirection = GetSortDirection(grid); } Sort(grid); } } #endregion - + #region SortMode property public static readonly DependencyProperty SortModeProperty = DependencyProperty.RegisterAttached("SortMode", typeof(ListViewSortMode), typeof(SortableGridViewColumn), - new FrameworkPropertyMetadata(ListViewSortMode.None, OnSortModeChanged)); - + new FrameworkPropertyMetadata(ListViewSortMode.None, OnSortModeChanged)); + public static ListViewSortMode GetSortMode(ListView listView) { return (ListViewSortMode)listView.GetValue(SortModeProperty); } - + public static void SetSortMode(ListView listView, ListViewSortMode value) { listView.SetValue(SortModeProperty, value); } - + static void OnSortModeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { ListView grid = sender as ListView; - if (grid != null) { + if (grid != null) + { if ((ListViewSortMode)args.NewValue != ListViewSortMode.None) grid.AddHandler(GridViewColumnHeader.ClickEvent, new RoutedEventHandler(GridViewColumnHeaderClickHandler)); else grid.RemoveHandler(GridViewColumnHeader.ClickEvent, new RoutedEventHandler(GridViewColumnHeaderClickHandler)); } } - + static void GridViewColumnHeaderClickHandler(object sender, RoutedEventArgs e) { ListView grid = sender as ListView; GridViewColumnHeader headerClicked = e.OriginalSource as GridViewColumnHeader; - if (grid != null && headerClicked != null && headerClicked.Role != GridViewColumnHeaderRole.Padding) { - if (headerClicked.Column == GetCurrentSortColumn(grid)) { - switch (GetSortDirection(grid)) { + if (grid != null && headerClicked != null && headerClicked.Role != GridViewColumnHeaderRole.Padding) + { + if (headerClicked.Column == GetCurrentSortColumn(grid)) + { + switch (GetSortDirection(grid)) + { case ColumnSortDirection.None: SetSortDirection(grid, ColumnSortDirection.Ascending); break; @@ -156,33 +164,40 @@ namespace ICSharpCode.ILSpy.Controls SetSortDirection(grid, ColumnSortDirection.None); break; } - } else { + } + else + { SetSortDirection(grid, ColumnSortDirection.Ascending); SetCurrentSortColumn(grid, headerClicked.Column as SortableGridViewColumn); } } } #endregion - + static void Sort(ListView grid) { ColumnSortDirection currentDirection = GetSortDirection(grid); SortableGridViewColumn column = GetCurrentSortColumn(grid); ICollectionView dataView = CollectionViewSource.GetDefaultView(grid.ItemsSource); - if (dataView == null) return; + if (dataView == null) + return; - if (column != null && GetSortMode(grid) == ListViewSortMode.Automatic && currentDirection != ColumnSortDirection.None) { + if (column != null && GetSortMode(grid) == ListViewSortMode.Automatic && currentDirection != ColumnSortDirection.None) + { string sortBy = column.SortBy; - if (sortBy == null) { + if (sortBy == null) + { Binding binding = column.DisplayMemberBinding as Binding; - if (binding != null && binding.Path != null) { + if (binding != null && binding.Path != null) + { sortBy = binding.Path.Path; } } dataView.SortDescriptions.Clear(); - if (sortBy != null) { + if (sortBy != null) + { ListSortDirection direction; if (currentDirection == ColumnSortDirection.Descending) direction = ListSortDirection.Descending; @@ -190,21 +205,23 @@ namespace ICSharpCode.ILSpy.Controls direction = ListSortDirection.Ascending; dataView.SortDescriptions.Add(new SortDescription(sortBy, direction)); } - } else { + } + else + { dataView.SortDescriptions.Clear(); } dataView.Refresh(); } } - + public enum ColumnSortDirection { None, Ascending, Descending } - + public enum ListViewSortMode { /// @@ -221,14 +238,14 @@ namespace ICSharpCode.ILSpy.Controls /// HalfAutomatic } - + sealed class ColumnSortDirectionToVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return Equals(value, parameter) ? Visibility.Visible : Visibility.Collapsed; } - + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotSupportedException(); diff --git a/ILSpy/DebugInfo/DebugInfoUtils.cs b/ILSpy/DebugInfo/DebugInfoUtils.cs index 652db992e..fff7ed5c3 100644 --- a/ILSpy/DebugInfo/DebugInfoUtils.cs +++ b/ILSpy/DebugInfo/DebugInfoUtils.cs @@ -22,6 +22,7 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Runtime.InteropServices; + using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Metadata; @@ -31,18 +32,25 @@ namespace ICSharpCode.Decompiler.PdbProvider { public static IDebugInfoProvider LoadSymbols(PEFile module) { - try { + try + { // try to open portable pdb file/embedded pdb info: - if (TryOpenPortablePdb(module, out var provider, out var pdbFileName)) { + if (TryOpenPortablePdb(module, out var provider, out var pdbFileName)) + { return new PortableDebugInfoProvider(pdbFileName, provider); - } else { + } + else + { // search for pdb in same directory as dll pdbFileName = Path.Combine(Path.GetDirectoryName(module.FileName), Path.GetFileNameWithoutExtension(module.FileName) + ".pdb"); - if (File.Exists(pdbFileName)) { + if (File.Exists(pdbFileName)) + { return new MonoCecilDebugInfoProvider(module, pdbFileName); } } - } catch (Exception ex) when (ex is BadImageFormatException || ex is COMException) { + } + catch (Exception ex) when (ex is BadImageFormatException || ex is COMException) + { // Ignore PDB load errors } return null; @@ -58,10 +66,13 @@ namespace ICSharpCode.Decompiler.PdbProvider return null; if (stream.Read(buffer, 0, buffer.Length) == LegacyPDBPrefix.Length - && System.Text.Encoding.ASCII.GetString(buffer) == LegacyPDBPrefix) { + && System.Text.Encoding.ASCII.GetString(buffer) == LegacyPDBPrefix) + { stream.Position = 0; return new MonoCecilDebugInfoProvider(module, pdbFileName); - } else { + } + else + { stream.Position = 0; var provider = MetadataReaderProvider.FromPortablePdbStream(stream); return new PortableDebugInfoProvider(pdbFileName, provider); @@ -76,17 +87,22 @@ namespace ICSharpCode.Decompiler.PdbProvider provider = null; pdbFileName = null; var reader = module.Reader; - foreach (var entry in reader.ReadDebugDirectory()) { - if (entry.IsPortableCodeView) { + foreach (var entry in reader.ReadDebugDirectory()) + { + if (entry.IsPortableCodeView) + { return reader.TryOpenAssociatedPortablePdb(module.FileName, OpenStream, out provider, out pdbFileName); } - if (entry.Type == DebugDirectoryEntryType.CodeView) { + if (entry.Type == DebugDirectoryEntryType.CodeView) + { string pdbDirectory = Path.GetDirectoryName(module.FileName); pdbFileName = Path.Combine(pdbDirectory, Path.GetFileNameWithoutExtension(module.FileName) + ".pdb"); - if (File.Exists(pdbFileName)) { + if (File.Exists(pdbFileName)) + { Stream stream = OpenStream(pdbFileName); if (stream.Read(buffer, 0, buffer.Length) == LegacyPDBPrefix.Length - && System.Text.Encoding.ASCII.GetString(buffer) == LegacyPDBPrefix) { + && System.Text.Encoding.ASCII.GetString(buffer) == LegacyPDBPrefix) + { return false; } stream.Position = 0; diff --git a/ILSpy/DebugInfo/PortableDebugInfoProvider.cs b/ILSpy/DebugInfo/PortableDebugInfoProvider.cs index 7ed280919..58a1ca125 100644 --- a/ILSpy/DebugInfo/PortableDebugInfoProvider.cs +++ b/ILSpy/DebugInfo/PortableDebugInfoProvider.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.DebugInfo; namespace ICSharpCode.Decompiler.PdbProvider @@ -45,13 +46,17 @@ namespace ICSharpCode.Decompiler.PdbProvider var debugInfo = metadata.GetMethodDebugInformation(method); var sequencePoints = new List(); - foreach (var point in debugInfo.GetSequencePoints()) { + foreach (var point in debugInfo.GetSequencePoints()) + { string documentFileName; - if (!point.Document.IsNil) { + if (!point.Document.IsNil) + { var document = metadata.GetDocument(point.Document); documentFileName = metadata.GetString(document.Name); - } else { + } + else + { documentFileName = ""; } @@ -73,9 +78,11 @@ namespace ICSharpCode.Decompiler.PdbProvider var metadata = Provider.GetMetadataReader(); var variables = new List(); - foreach (var h in metadata.GetLocalScopes(method)) { + foreach (var h in metadata.GetLocalScopes(method)) + { var scope = metadata.GetLocalScope(h); - foreach (var v in scope.GetLocalVariables()) { + foreach (var v in scope.GetLocalVariables()) + { var var = metadata.GetLocalVariable(v); variables.Add(new Variable(var.Index, metadata.GetString(var.Name))); } @@ -89,11 +96,14 @@ namespace ICSharpCode.Decompiler.PdbProvider var metadata = Provider.GetMetadataReader(); name = null; - foreach (var h in metadata.GetLocalScopes(method)) { + foreach (var h in metadata.GetLocalScopes(method)) + { var scope = metadata.GetLocalScope(h); - foreach (var v in scope.GetLocalVariables()) { + foreach (var v in scope.GetLocalVariables()) + { var var = metadata.GetLocalVariable(v); - if (var.Index == index) { + if (var.Index == index) + { name = metadata.GetString(var.Name); return true; } diff --git a/ILSpy/DecompilationOptions.cs b/ILSpy/DecompilationOptions.cs index b73bb8530..1218b20f6 100644 --- a/ILSpy/DecompilationOptions.cs +++ b/ILSpy/DecompilationOptions.cs @@ -18,6 +18,7 @@ using System; using System.Threading; + using ICSharpCode.ILSpy.Options; namespace ICSharpCode.ILSpy @@ -32,7 +33,7 @@ namespace ICSharpCode.ILSpy /// If this option is false, language bindings are allowed to show the only headers of the decompiled element's children. /// public bool FullDecompilation { get; set; } - + /// /// Gets/Sets the directory into which the project is saved. /// @@ -43,7 +44,7 @@ namespace ICSharpCode.ILSpy /// This setting is ignored in case is set. /// public bool EscapeInvalidIdentifiers { get; set; } - + /// /// Gets the cancellation token that is used to abort the decompiler. /// @@ -52,7 +53,7 @@ namespace ICSharpCode.ILSpy /// to allow for cooperative cancellation of the decompilation task. /// public CancellationToken CancellationToken { get; set; } - + /// /// Gets the settings for the decompiler. /// @@ -84,7 +85,7 @@ namespace ICSharpCode.ILSpy public DecompilationOptions(LanguageVersion version, Decompiler.DecompilerSettings settings, Options.DisplaySettings displaySettings) { - if (!Enum.TryParse(version?.Version, out Decompiler.CSharp.LanguageVersion languageVersion)) + if (!Enum.TryParse(version?.Version, out Decompiler.CSharp.LanguageVersion languageVersion)) languageVersion = Decompiler.CSharp.LanguageVersion.Latest; var newSettings = this.DecompilerSettings = settings.Clone(); newSettings.SetLanguageVersion(languageVersion); @@ -97,7 +98,8 @@ namespace ICSharpCode.ILSpy private string GetIndentationString(DisplaySettings displaySettings) { - if (displaySettings.IndentationUseTabs) { + if (displaySettings.IndentationUseTabs) + { int numberOfTabs = displaySettings.IndentationSize / displaySettings.IndentationTabSize; int numberOfSpaces = displaySettings.IndentationSize % displaySettings.IndentationTabSize; return new string('\t', numberOfTabs) + new string(' ', numberOfSpaces); diff --git a/ILSpy/Docking/ActiveTabPageConverter.cs b/ILSpy/Docking/ActiveTabPageConverter.cs index f80c9ebbf..191a7088a 100644 --- a/ILSpy/Docking/ActiveTabPageConverter.cs +++ b/ILSpy/Docking/ActiveTabPageConverter.cs @@ -18,6 +18,7 @@ using System; using System.Windows.Data; + using ICSharpCode.ILSpy.ViewModels; namespace ICSharpCode.ILSpy.Docking diff --git a/ILSpy/Docking/CloseAllDocumentsCommand.cs b/ILSpy/Docking/CloseAllDocumentsCommand.cs index db4c64ab2..d08af41e8 100644 --- a/ILSpy/Docking/CloseAllDocumentsCommand.cs +++ b/ILSpy/Docking/CloseAllDocumentsCommand.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; + using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy.Docking diff --git a/ILSpy/Docking/DockLayoutSettings.cs b/ILSpy/Docking/DockLayoutSettings.cs index 6ccf5868e..132e5390d 100644 --- a/ILSpy/Docking/DockLayoutSettings.cs +++ b/ILSpy/Docking/DockLayoutSettings.cs @@ -21,6 +21,7 @@ using System.IO; using System.Linq; using System.Xml; using System.Xml.Linq; + using Xceed.Wpf.AvalonDock.Layout.Serialization; namespace ICSharpCode.ILSpy.Docking @@ -70,16 +71,20 @@ namespace ICSharpCode.ILSpy.Docking public DockLayoutSettings(XElement element) { - if ((element != null) && element.HasElements) { + if ((element != null) && element.HasElements) + { rawSettings = element.Elements().FirstOrDefault()?.ToString(); } } public XElement SaveAsXml() { - try { + try + { return XElement.Parse(rawSettings); - } catch (Exception) { + } + catch (Exception) + { return null; } } @@ -88,15 +93,19 @@ namespace ICSharpCode.ILSpy.Docking { if (!Valid) rawSettings = DefaultLayout; - try { + try + { Deserialize(rawSettings); - } catch (Exception) { + } + catch (Exception) + { Deserialize(DefaultLayout); } void Deserialize(string settings) { - using (StringReader reader = new StringReader(settings)) { + using (StringReader reader = new StringReader(settings)) + { serializer.Deserialize(reader); } } @@ -104,7 +113,8 @@ namespace ICSharpCode.ILSpy.Docking public void Serialize(XmlLayoutSerializer serializer) { - using (StringWriter fs = new StringWriter()) { + using (StringWriter fs = new StringWriter()) + { serializer.Serialize(fs); rawSettings = fs.ToString(); } diff --git a/ILSpy/Docking/DockWorkspace.cs b/ILSpy/Docking/DockWorkspace.cs index f94ad7eff..a123f1ad4 100644 --- a/ILSpy/Docking/DockWorkspace.cs +++ b/ILSpy/Docking/DockWorkspace.cs @@ -27,9 +27,11 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using System.Windows.Threading; + using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.ViewModels; + using Xceed.Wpf.AvalonDock.Layout; using Xceed.Wpf.AvalonDock.Layout.Serialization; @@ -52,7 +54,8 @@ namespace ICSharpCode.ILSpy.Docking { var collection = (PaneCollection)sender; bool canClose = collection.Count > 1; - foreach (var item in collection) { + foreach (var item in collection) + { item.IsCloseable = canClose; } } @@ -64,7 +67,8 @@ namespace ICSharpCode.ILSpy.Docking public bool ShowToolPane(string contentId) { var pane = ToolPanes.FirstOrDefault(p => p.ContentId == contentId); - if (pane != null) { + if (pane != null) + { pane.Show(); return true; } @@ -85,7 +89,8 @@ namespace ICSharpCode.ILSpy.Docking return _activeTabPage; } set { - if (_activeTabPage != value) { + if (_activeTabPage != value) + { _activeTabPage = value; this.sessionSettings.FilterSettings.Language = value.Language; this.sessionSettings.FilterSettings.LanguageVersion = value.LanguageVersion; @@ -102,21 +107,26 @@ namespace ICSharpCode.ILSpy.Docking manager.LayoutUpdateStrategy = this; XmlLayoutSerializer serializer = new XmlLayoutSerializer(manager); serializer.LayoutSerializationCallback += LayoutSerializationCallback; - try { + try + { sessionSettings.DockLayout.Deserialize(serializer); - } finally { + } + finally + { serializer.LayoutSerializationCallback -= LayoutSerializationCallback; } } void LayoutSerializationCallback(object sender, LayoutSerializationCallbackEventArgs e) { - switch (e.Model) { + switch (e.Model) + { case LayoutAnchorable la: e.Content = ToolPanes.FirstOrDefault(p => p.ContentId == la.ContentId); e.Cancel = e.Content == null; la.CanDockAsTabbedDocument = false; - if (!e.Cancel) { + if (!e.Cancel) + { e.Cancel = ((ToolPaneModel)e.Content).IsVisible; ((ToolPaneModel)e.Content).IsVisible = true; } @@ -155,19 +165,24 @@ namespace ICSharpCode.ILSpy.Docking private void FilterSettings_PropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == "Language") { + if (e.PropertyName == "Language") + { ActiveTabPage.Language = sessionSettings.FilterSettings.Language; - if (sessionSettings.FilterSettings.Language.HasLanguageVersions) { + if (sessionSettings.FilterSettings.Language.HasLanguageVersions) + { sessionSettings.FilterSettings.LanguageVersion = ActiveTabPage.LanguageVersion; } - } else if (e.PropertyName == "LanguageVersion") { + } + else if (e.PropertyName == "LanguageVersion") + { ActiveTabPage.LanguageVersion = sessionSettings.FilterSettings.LanguageVersion; } } internal void CloseAllTabs() { - foreach (var doc in TabPages.ToArray()) { + foreach (var doc in TabPages.ToArray()) + { if (doc.IsCloseable) TabPages.Remove(doc); } @@ -175,7 +190,8 @@ namespace ICSharpCode.ILSpy.Docking internal void ResetLayout() { - foreach (var pane in ToolPanes) { + foreach (var pane in ToolPanes) + { pane.IsVisible = false; } CloseAllTabs(); @@ -193,7 +209,8 @@ namespace ICSharpCode.ILSpy.Docking anchorableToShow.CanDockAsTabbedDocument = false; LayoutAnchorablePane previousContainer; - switch (legacyContent.Location) { + switch (legacyContent.Location) + { case LegacyToolPaneLocation.Top: previousContainer = GetContainer(); previousContainer.Children.Add(anchorableToShow); diff --git a/ILSpy/Docking/PaneCollection.cs b/ILSpy/Docking/PaneCollection.cs index 5189865b9..5b5861062 100644 --- a/ILSpy/Docking/PaneCollection.cs +++ b/ILSpy/Docking/PaneCollection.cs @@ -22,6 +22,7 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Linq; + using ICSharpCode.ILSpy.ViewModels; namespace ICSharpCode.ILSpy.Docking diff --git a/ILSpy/Docking/PaneStyleSelector.cs b/ILSpy/Docking/PaneStyleSelector.cs index f36fe9b8d..887b72da7 100644 --- a/ILSpy/Docking/PaneStyleSelector.cs +++ b/ILSpy/Docking/PaneStyleSelector.cs @@ -1,5 +1,6 @@ using System.Windows; using System.Windows.Controls; + using ICSharpCode.ILSpy.ViewModels; // Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team // diff --git a/ILSpy/Docking/PaneTemplateSelector.cs b/ILSpy/Docking/PaneTemplateSelector.cs index 0bfecd642..7890a1dde 100644 --- a/ILSpy/Docking/PaneTemplateSelector.cs +++ b/ILSpy/Docking/PaneTemplateSelector.cs @@ -36,7 +36,8 @@ namespace ICSharpCode.ILSpy.Docking public override DataTemplate SelectTemplate(object item, DependencyObject container) { - if (item == null) { + if (item == null) + { return base.SelectTemplate(item, container); } diff --git a/ILSpy/EntityReference.cs b/ILSpy/EntityReference.cs index a4ef94704..af410476b 100644 --- a/ILSpy/EntityReference.cs +++ b/ILSpy/EntityReference.cs @@ -19,6 +19,7 @@ using System; using System.Diagnostics; using System.Reflection.Metadata; + using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy diff --git a/ILSpy/ExtensionMethods.cs b/ILSpy/ExtensionMethods.cs index 315814167..5ebe7ecef 100644 --- a/ILSpy/ExtensionMethods.cs +++ b/ILSpy/ExtensionMethods.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Media; + using ICSharpCode.ILSpy.Options; namespace ICSharpCode.ILSpy @@ -53,7 +54,8 @@ namespace ICSharpCode.ILSpy if (count < 0 || count > list.Count - start) throw new ArgumentOutOfRangeException(nameof(count), count, "Value must be between 0 and " + (list.Count - start)); int end = start + count - 1; - while (start <= end) { + while (start <= end) + { int pivot = (start + end) / 2; int result = comparer.Compare(item, list[pivot]); if (result == 0) @@ -77,7 +79,8 @@ namespace ICSharpCode.ILSpy int start = 0; int end = instance.Count - 1; - while (start <= end) { + while (start <= end) + { int m = (start + end) / 2; TKey key = keySelector(instance[m]); int result = key.CompareTo(itemKey); @@ -159,7 +162,8 @@ namespace ICSharpCode.ILSpy { U[] result = new U[collection.Count]; int index = 0; - foreach (var element in collection) { + foreach (var element in collection) + { result[index++] = func(element); } return result; @@ -205,15 +209,19 @@ namespace ICSharpCode.ILSpy public static T FindVisualChild(this DependencyObject depObj) where T : DependencyObject { - if (depObj != null) { - for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) { + if (depObj != null) + { + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) + { DependencyObject child = VisualTreeHelper.GetChild(depObj, i); - if (child != null && child is T) { + if (child != null && child is T) + { return (T)child; } T childItem = FindVisualChild(child); - if (childItem != null) return childItem; + if (childItem != null) + return childItem; } } return null; @@ -223,7 +231,8 @@ namespace ICSharpCode.ILSpy { if (depObj == null) return null; - while (!(depObj is T)) { + while (!(depObj is T)) + { var parent = VisualTreeHelper.GetParent(depObj); if (parent == null) return null; diff --git a/ILSpy/FilterSettings.cs b/ILSpy/FilterSettings.cs index f1898b26c..e1e11269c 100644 --- a/ILSpy/FilterSettings.cs +++ b/ILSpy/FilterSettings.cs @@ -42,7 +42,7 @@ namespace ICSharpCode.ILSpy if (this.LanguageVersion == default(LanguageVersion)) this.LanguageVersion = language.LanguageVersions.LastOrDefault(); } - + public XElement SaveAsXml() { return new XElement( @@ -52,9 +52,9 @@ namespace ICSharpCode.ILSpy new XElement("LanguageVersion", this.LanguageVersion?.Version) ); } - + string searchTerm; - + /// /// Gets/Sets the search term. /// Only tree nodes containing the search term will be shown. @@ -62,13 +62,14 @@ namespace ICSharpCode.ILSpy public string SearchTerm { get { return searchTerm; } set { - if (searchTerm != value) { + if (searchTerm != value) + { searchTerm = value; OnPropertyChanged(nameof(SearchTerm)); } } } - + /// /// Gets whether a node with the specified text is matched by the current search term. /// @@ -87,7 +88,8 @@ namespace ICSharpCode.ILSpy public ApiVisibility ShowApiLevel { get { return showApiLevel; } set { - if (showApiLevel != value) { + if (showApiLevel != value) + { showApiLevel = value; OnPropertyChanged(nameof(ShowApiLevel)); } @@ -97,7 +99,8 @@ namespace ICSharpCode.ILSpy public bool ApiVisPublicOnly { get { return showApiLevel == ApiVisibility.PublicOnly; } set { - if (value == (showApiLevel == ApiVisibility.PublicOnly)) return; + if (value == (showApiLevel == ApiVisibility.PublicOnly)) + return; ShowApiLevel = ApiVisibility.PublicOnly; OnPropertyChanged(nameof(ApiVisPublicOnly)); OnPropertyChanged(nameof(ApiVisPublicAndInternal)); @@ -108,7 +111,8 @@ namespace ICSharpCode.ILSpy public bool ApiVisPublicAndInternal { get { return showApiLevel == ApiVisibility.PublicAndInternal; } set { - if (value == (showApiLevel == ApiVisibility.PublicAndInternal)) return; + if (value == (showApiLevel == ApiVisibility.PublicAndInternal)) + return; ShowApiLevel = ApiVisibility.PublicAndInternal; OnPropertyChanged(nameof(ApiVisPublicOnly)); OnPropertyChanged(nameof(ApiVisPublicAndInternal)); @@ -119,7 +123,8 @@ namespace ICSharpCode.ILSpy public bool ApiVisAll { get { return showApiLevel == ApiVisibility.All; } set { - if (value == (showApiLevel == ApiVisibility.All)) return; + if (value == (showApiLevel == ApiVisibility.All)) + return; ShowApiLevel = ApiVisibility.All; OnPropertyChanged(nameof(ApiVisPublicOnly)); OnPropertyChanged(nameof(ApiVisPublicAndInternal)); @@ -128,7 +133,7 @@ namespace ICSharpCode.ILSpy } Language language; - + /// /// Gets/Sets the current language. /// @@ -139,7 +144,8 @@ namespace ICSharpCode.ILSpy public Language Language { get { return language; } set { - if (language != value) { + if (language != value) + { language = value; OnPropertyChanged(); } @@ -158,7 +164,8 @@ namespace ICSharpCode.ILSpy public LanguageVersion LanguageVersion { get { return languageVersion; } set { - if (languageVersion != value) { + if (languageVersion != value) + { languageVersion = value; OnPropertyChanged(); } @@ -166,14 +173,15 @@ namespace ICSharpCode.ILSpy } public event PropertyChangedEventHandler PropertyChanged; - + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { - if (PropertyChanged != null) { + if (PropertyChanged != null) + { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } - + public FilterSettings Clone() { FilterSettings f = (FilterSettings)MemberwiseClone(); diff --git a/ILSpy/GuessFileType.cs b/ILSpy/GuessFileType.cs index 2d1467861..8835e1123 100644 --- a/ILSpy/GuessFileType.cs +++ b/ILSpy/GuessFileType.cs @@ -31,100 +31,141 @@ namespace ICSharpCode.ILSpy public static FileType DetectFileType(Stream stream) { StreamReader reader; - if (stream.Length >= 2) { + if (stream.Length >= 2) + { int firstByte = stream.ReadByte(); int secondByte = stream.ReadByte(); - switch ((firstByte << 8) | secondByte) { + switch ((firstByte << 8) | secondByte) + { case 0xfffe: // UTF-16 LE BOM / UTF-32 LE BOM case 0xfeff: // UTF-16 BE BOM stream.Position -= 2; reader = new StreamReader(stream, detectEncodingFromByteOrderMarks: true); break; case 0xefbb: // start of UTF-8 BOM - if (stream.ReadByte() == 0xbf) { + if (stream.ReadByte() == 0xbf) + { reader = new StreamReader(stream, Encoding.UTF8); break; - } else { + } + else + { return FileType.Binary; } default: - if (IsUTF8(stream, (byte)firstByte, (byte)secondByte)) { + if (IsUTF8(stream, (byte)firstByte, (byte)secondByte)) + { stream.Position = 0; reader = new StreamReader(stream, Encoding.UTF8); break; - } else { + } + else + { return FileType.Binary; } } - } else { + } + else + { return FileType.Binary; } // Now we got a StreamReader with the correct encoding // Check for XML now - try { + try + { XmlTextReader xmlReader = new XmlTextReader(reader); xmlReader.XmlResolver = null; xmlReader.MoveToContent(); return FileType.Xml; - } catch (XmlException) { + } + catch (XmlException) + { return FileType.Text; } } - + static bool IsUTF8(Stream fs, byte firstByte, byte secondByte) { int max = (int)Math.Min(fs.Length, 500000); // look at max. 500 KB const int ASCII = 0; const int Error = 1; - const int UTF8 = 2; + const int UTF8 = 2; const int UTF8Sequence = 3; int state = ASCII; int sequenceLength = 0; byte b; - for (int i = 0; i < max; i++) { - if (i == 0) { + for (int i = 0; i < max; i++) + { + if (i == 0) + { b = firstByte; - } else if (i == 1) { + } + else if (i == 1) + { b = secondByte; - } else { + } + else + { b = (byte)fs.ReadByte(); } - if (b < 0x80) { + if (b < 0x80) + { // normal ASCII character - if (state == UTF8Sequence) { + if (state == UTF8Sequence) + { state = Error; break; } - } else if (b < 0xc0) { + } + else if (b < 0xc0) + { // 10xxxxxx : continues UTF8 byte sequence - if (state == UTF8Sequence) { + if (state == UTF8Sequence) + { --sequenceLength; - if (sequenceLength < 0) { + if (sequenceLength < 0) + { state = Error; break; - } else if (sequenceLength == 0) { + } + else if (sequenceLength == 0) + { state = UTF8; } - } else { + } + else + { state = Error; break; } - } else if (b >= 0xc2 && b < 0xf5) { + } + else if (b >= 0xc2 && b < 0xf5) + { // beginning of byte sequence - if (state == UTF8 || state == ASCII) { + if (state == UTF8 || state == ASCII) + { state = UTF8Sequence; - if (b < 0xe0) { + if (b < 0xe0) + { sequenceLength = 1; // one more byte following - } else if (b < 0xf0) { + } + else if (b < 0xf0) + { sequenceLength = 2; // two more bytes following - } else { + } + else + { sequenceLength = 3; // three more bytes following } - } else { + } + else + { state = Error; break; } - } else { + } + else + { // 0xc0, 0xc1, 0xf5 to 0xff are invalid in UTF-8 (see RFC 3629) state = Error; break; @@ -133,7 +174,7 @@ namespace ICSharpCode.ILSpy return state != Error; } } - + enum FileType { Binary, diff --git a/ILSpy/ILSpySettings.cs b/ILSpy/ILSpySettings.cs index 54382b132..84afc60bc 100644 --- a/ILSpy/ILSpySettings.cs +++ b/ILSpy/ILSpySettings.cs @@ -30,23 +30,23 @@ namespace ICSharpCode.ILSpy public class ILSpySettings { readonly XElement root; - + ILSpySettings() { this.root = new XElement("ILSpy"); } - + ILSpySettings(XElement root) { this.root = root; } - + public XElement this[XName section] { get { return root.Element(section) ?? new XElement(section); } } - + /// /// Loads the settings file from disk. /// @@ -55,23 +55,29 @@ namespace ICSharpCode.ILSpy /// public static ILSpySettings Load() { - using (new MutexProtector(ConfigFileMutex)) { - try { + using (new MutexProtector(ConfigFileMutex)) + { + try + { XDocument doc = LoadWithoutCheckingCharacters(GetConfigFile()); return new ILSpySettings(doc.Root); - } catch (IOException) { + } + catch (IOException) + { return new ILSpySettings(); - } catch (XmlException) { + } + catch (XmlException) + { return new ILSpySettings(); } } } - + static XDocument LoadWithoutCheckingCharacters(string fileName) { return XDocument.Load(fileName, LoadOptions.None); } - + /// /// Saves a setting section. /// @@ -86,7 +92,7 @@ namespace ICSharpCode.ILSpy root.Add(section); }); } - + /// /// Updates the saved settings. /// We always reload the file on updates to ensure we aren't overwriting unrelated changes performed @@ -94,16 +100,22 @@ namespace ICSharpCode.ILSpy /// public static void Update(Action action) { - using (new MutexProtector(ConfigFileMutex)) { + using (new MutexProtector(ConfigFileMutex)) + { string config = GetConfigFile(); XDocument doc; - try { + try + { doc = LoadWithoutCheckingCharacters(config); - } catch (IOException) { + } + catch (IOException) + { // ensure the directory exists Directory.CreateDirectory(Path.GetDirectoryName(config)); doc = new XDocument(new XElement("ILSpy")); - } catch (XmlException) { + } + catch (XmlException) + { doc = new XDocument(new XElement("ILSpy")); } doc.Root.SetAttributeValue("version", RevisionClass.Major + "." + RevisionClass.Minor + "." + RevisionClass.Build + "." + RevisionClass.Revision); @@ -111,7 +123,7 @@ namespace ICSharpCode.ILSpy doc.Save(config, SaveOptions.None); } } - + static string GetConfigFile() { if (App.CommandLineArguments.ConfigFile != null) @@ -121,28 +133,32 @@ namespace ICSharpCode.ILSpy return localPath; return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ICSharpCode\\ILSpy.xml"); } - + const string ConfigFileMutex = "01A91708-49D1-410D-B8EB-4DE2662B3971"; - + /// /// Helper class for serializing access to the config file when multiple ILSpy instances are running. /// sealed class MutexProtector : IDisposable { readonly Mutex mutex; - + public MutexProtector(string name) { bool createdNew; this.mutex = new Mutex(true, name, out createdNew); - if (!createdNew) { - try { + if (!createdNew) + { + try + { mutex.WaitOne(); - } catch (AbandonedMutexException) { + } + catch (AbandonedMutexException) + { } } } - + public void Dispose() { mutex.ReleaseMutex(); diff --git a/ILSpy/ILSpyTraceListener.cs b/ILSpy/ILSpyTraceListener.cs index 726c5187d..ec9c5be07 100644 --- a/ILSpy/ILSpyTraceListener.cs +++ b/ILSpy/ILSpyTraceListener.cs @@ -19,9 +19,10 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; + using ICSharpCode.ILSpy.Controls; -using System.Linq; namespace ICSharpCode.ILSpy { @@ -52,7 +53,8 @@ namespace ICSharpCode.ILSpy base.Fail(message, detailMessage); // let base class write the assert to the debug console string topFrame = ""; string stackTrace = ""; - try { + try + { stackTrace = new StackTrace(true).ToString(); var frames = stackTrace.Split('\r', '\n') .Where(f => f.Length > 0) @@ -60,8 +62,10 @@ namespace ICSharpCode.ILSpy .ToList(); topFrame = frames[0]; stackTrace = string.Join(Environment.NewLine, frames); - } catch { } - lock (ignoredStacks) { + } + catch { } + lock (ignoredStacks) + { if (ignoredStacks.Contains(topFrame)) return; if (dialogIsOpen) @@ -77,13 +81,21 @@ namespace ICSharpCode.ILSpy thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(); - if (result == 0) { // throw + if (result == 0) + { // throw throw new AssertionFailedException(message); - } else if (result == 1) { // debug + } + else if (result == 1) + { // debug Debugger.Break(); - } else if (result == 2) { // ignore - } else if (result == 3) { - lock (ignoredStacks) { + } + else if (result == 2) + { // ignore + } + else if (result == 3) + { + lock (ignoredStacks) + { ignoredStacks.Add(topFrame); } } @@ -96,10 +108,13 @@ namespace ICSharpCode.ILSpy CustomDialog inputBox = new CustomDialog("Assertion Failed", message.TakeStartEllipsis(750), -1, 2, buttonTexts); inputBox.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; inputBox.ShowInTaskbar = true; // make this window more visible, because it effectively interrupts the decompilation process. - try { + try + { inputBox.ShowDialog(); return inputBox.Result; - } finally { + } + finally + { dialogIsOpen = false; inputBox.Dispose(); } diff --git a/ILSpy/ISmartTextOutput.cs b/ILSpy/ISmartTextOutput.cs index 62098956e..be15a929a 100644 --- a/ILSpy/ISmartTextOutput.cs +++ b/ILSpy/ISmartTextOutput.cs @@ -21,6 +21,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; + using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; @@ -59,7 +60,8 @@ namespace ICSharpCode.ILSpy button.Margin = new Thickness(2); button.Padding = new Thickness(9, 1, 9, 1); button.MinWidth = 73; - if (icon != null) { + if (icon != null) + { button.Content = new StackPanel { Orientation = Orientation.Horizontal, Children = { @@ -67,7 +69,9 @@ namespace ICSharpCode.ILSpy new TextBlock { Text = text } } }; - } else { + } + else + { button.Content = text; } button.Click += click; diff --git a/ILSpy/Images/Images.cs b/ILSpy/Images/Images.cs index e0a1e4b18..c542172a0 100644 --- a/ILSpy/Images/Images.cs +++ b/ILSpy/Images/Images.cs @@ -17,13 +17,13 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Windows.Media.Imaging; -using System.Windows.Media; -using System.Windows; using System.Collections.Generic; +using System.IO; +using System.Windows; using System.Windows.Controls; using System.Windows.Markup; -using System.IO; +using System.Windows.Media; +using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace ICSharpCode.ILSpy @@ -101,7 +101,8 @@ namespace ICSharpCode.ILSpy if (icon.EndsWith(".png", StringComparison.OrdinalIgnoreCase)) return LoadImage(part, icon); Uri uri = GetUri(part, icon + ".xaml"); - if (ResourceExists(uri)) { + if (ResourceExists(uri)) + { return new DrawingImage(LoadDrawingGroup(part, icon)); } return LoadImage(part, icon + ".png"); @@ -126,16 +127,22 @@ namespace ICSharpCode.ILSpy var assembly = part?.GetType().Assembly; string prefix; UriKind kind; - if (absolute) { + if (absolute) + { prefix = "pack://application:,,,/"; kind = UriKind.Absolute; - } else { + } + else + { prefix = "/"; kind = UriKind.Relative; } - if (part == null || assembly == typeof(Images).Assembly) { + if (part == null || assembly == typeof(Images).Assembly) + { uri = new Uri(prefix + icon, kind); - } else { + } + else + { var name = assembly.GetName(); uri = new Uri(prefix + name.Name + ";v" + name.Version + ";component/" + icon, kind); } @@ -145,10 +152,13 @@ namespace ICSharpCode.ILSpy private static bool ResourceExists(Uri uri) { - try { + try + { Application.GetResourceStream(uri); return true; - } catch (IOException) { + } + catch (IOException) + { return false; } } @@ -184,7 +194,8 @@ namespace ICSharpCode.ILSpy protected override ImageSource GetBaseImage(TypeIcon icon) { ImageSource baseImage; - switch (icon) { + switch (icon) + { case TypeIcon.Class: baseImage = Images.Class; break; @@ -230,7 +241,8 @@ namespace ICSharpCode.ILSpy protected override ImageSource GetBaseImage(MemberIcon icon) { ImageSource baseImage; - switch (icon) { + switch (icon) + { case MemberIcon.Field: baseImage = Images.Field; break; @@ -291,9 +303,12 @@ namespace ICSharpCode.ILSpy public ImageSource GetIcon(T icon, AccessOverlayIcon overlay, bool isStatic) { var iconKey = (icon, overlay, isStatic); - if (cache.ContainsKey(iconKey)) { + if (cache.ContainsKey(iconKey)) + { return cache[iconKey]; - } else { + } + else + { ImageSource result = BuildMemberIcon(icon, overlay, isStatic); cache.Add(iconKey, result); return result; @@ -313,7 +328,8 @@ namespace ICSharpCode.ILSpy private static ImageSource GetOverlayImage(AccessOverlayIcon overlay) { ImageSource overlayImage; - switch (overlay) { + switch (overlay) + { case AccessOverlayIcon.Public: overlayImage = null; break; @@ -349,16 +365,20 @@ namespace ICSharpCode.ILSpy Drawing baseDrawing = new ImageDrawing(baseImage, iconRect); - if (overlay != null) { + if (overlay != null) + { var nestedGroup = new DrawingGroup { Transform = new ScaleTransform(0.8, 0.8) }; nestedGroup.Children.Add(baseDrawing); group.Children.Add(nestedGroup); group.Children.Add(new ImageDrawing(overlay, iconRect)); - } else { + } + else + { group.Children.Add(baseDrawing); } - if (isStatic) { + if (isStatic) + { group.Children.Add(new ImageDrawing(Images.OverlayStatic, iconRect)); } diff --git a/ILSpy/Languages/CSharpBracketSearcher.cs b/ILSpy/Languages/CSharpBracketSearcher.cs index bc12dd7f5..28a7a4fd2 100644 --- a/ILSpy/Languages/CSharpBracketSearcher.cs +++ b/ILSpy/Languages/CSharpBracketSearcher.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; + using ICSharpCode.AvalonEdit.Document; using ICSharpCode.ILSpy.TextView; @@ -34,7 +35,8 @@ namespace ICSharpCode.ILSpy public BracketSearchResult SearchBracket(IDocument document, int offset) { - if (offset > 0) { + if (offset > 0) + { char c = document.GetCharAt(offset - 1); int index = openingBrackets.IndexOf(c); int otherOffset = -1; @@ -45,7 +47,8 @@ namespace ICSharpCode.ILSpy if (index > -1) otherOffset = SearchBracketBackward(document, offset - 2, openingBrackets[index], closingBrackets[index]); - if (otherOffset > -1) { + if (otherOffset > -1) + { var result = new BracketSearchResult(Math.Min(offset - 1, otherOffset), 1, Math.Max(offset - 1, otherOffset), 1); return result; @@ -58,7 +61,8 @@ namespace ICSharpCode.ILSpy #region SearchBracket helper functions static int ScanLineStart(IDocument document, int offset) { - for (int i = offset - 1; i > 0; --i) { + for (int i = offset - 1; i > 0; --i) + { if (document.GetCharAt(i) == '\n') return i + 1; } @@ -78,32 +82,44 @@ namespace ICSharpCode.ILSpy bool inChar = false; bool verbatim = false; int result = 0; - for (int i = linestart; i < offset; i++) { - switch (document.GetCharAt(i)) { + for (int i = linestart; i < offset; i++) + { + switch (document.GetCharAt(i)) + { case '/': - if (!inString && !inChar && i + 1 < document.TextLength) { - if (document.GetCharAt(i + 1) == '/') { + if (!inString && !inChar && i + 1 < document.TextLength) + { + if (document.GetCharAt(i + 1) == '/') + { result = 1; } } break; case '"': - if (!inChar) { - if (inString && verbatim) { - if (i + 1 < document.TextLength && document.GetCharAt(i + 1) == '"') { + if (!inChar) + { + if (inString && verbatim) + { + if (i + 1 < document.TextLength && document.GetCharAt(i + 1) == '"') + { ++i; // skip escaped quote inString = false; // let the string go on - } else { + } + else + { verbatim = false; } - } else if (!inString && i > 0 && document.GetCharAt(i - 1) == '@') { + } + else if (!inString && i > 0 && document.GetCharAt(i - 1) == '@') + { verbatim = true; } inString = !inString; } break; case '\'': - if (!inString) inChar = !inChar; + if (!inString) + inChar = !inChar; break; case '\\': if ((inString && !verbatim) || inChar) @@ -119,12 +135,14 @@ namespace ICSharpCode.ILSpy #region SearchBracketBackward int SearchBracketBackward(IDocument document, int offset, char openBracket, char closingBracket) { - if (offset + 1 >= document.TextLength) return -1; + if (offset + 1 >= document.TextLength) + return -1; // this method parses a c# document backwards to find the matching bracket // first try "quick find" - find the matching bracket if there is no string/comment in the way int quickResult = QuickSearchBracketBackward(document, offset, openBracket, closingBracket); - if (quickResult >= 0) return quickResult; + if (quickResult >= 0) + return quickResult; // we need to parse the line from the beginning, so get the line start position int linestart = ScanLineStart(document, offset + 1); @@ -132,7 +150,8 @@ namespace ICSharpCode.ILSpy // we need to know where offset is - in a string/comment or in normal code? // ignore cases where offset is in a block comment int starttype = GetStartType(document, linestart, offset + 1); - if (starttype == 1) { + if (starttype == 1) + { return -1; // start position is in a comment } @@ -145,48 +164,64 @@ namespace ICSharpCode.ILSpy bool inString = false; bool verbatim = false; - for (int i = 0; i <= offset; ++i) { + for (int i = 0; i <= offset; ++i) + { char ch = document.GetCharAt(i); - switch (ch) { + switch (ch) + { case '\r': case '\n': lineComment = false; inChar = false; - if (!verbatim) inString = false; + if (!verbatim) + inString = false; break; case '/': - if (blockComment) { + if (blockComment) + { Debug.Assert(i > 0); - if (document.GetCharAt(i - 1) == '*') { + if (document.GetCharAt(i - 1) == '*') + { blockComment = false; } } - if (!inString && !inChar && i + 1 < document.TextLength) { - if (!blockComment && document.GetCharAt(i + 1) == '/') { + if (!inString && !inChar && i + 1 < document.TextLength) + { + if (!blockComment && document.GetCharAt(i + 1) == '/') + { lineComment = true; } - if (!lineComment && document.GetCharAt(i + 1) == '*') { + if (!lineComment && document.GetCharAt(i + 1) == '*') + { blockComment = true; } } break; case '"': - if (!(inChar || lineComment || blockComment)) { - if (inString && verbatim) { - if (i + 1 < document.TextLength && document.GetCharAt(i + 1) == '"') { + if (!(inChar || lineComment || blockComment)) + { + if (inString && verbatim) + { + if (i + 1 < document.TextLength && document.GetCharAt(i + 1) == '"') + { ++i; // skip escaped quote inString = false; // let the string go - } else { + } + else + { verbatim = false; } - } else if (!inString && offset > 0 && document.GetCharAt(i - 1) == '@') { + } + else if (!inString && offset > 0 && document.GetCharAt(i - 1) == '@') + { verbatim = true; } inString = !inString; } break; case '\'': - if (!(inString || lineComment || blockComment)) { + if (!(inString || lineComment || blockComment)) + { inChar = !inChar; } break; @@ -195,12 +230,17 @@ namespace ICSharpCode.ILSpy ++i; // skip next character break; default: - if (ch == openBracket) { - if (!(inString || inChar || lineComment || blockComment)) { + if (ch == openBracket) + { + if (!(inString || inChar || lineComment || blockComment)) + { bracketStack.Push(i); } - } else if (ch == closingBracket) { - if (!(inString || inChar || lineComment || blockComment)) { + } + else if (ch == closingBracket) + { + if (!(inString || inChar || lineComment || blockComment)) + { if (bracketStack.Count > 0) bracketStack.Pop(); } @@ -208,7 +248,8 @@ namespace ICSharpCode.ILSpy break; } } - if (bracketStack.Count > 0) return (int)bracketStack.Pop(); + if (bracketStack.Count > 0) + return (int)bracketStack.Pop(); return -1; } #endregion @@ -223,11 +264,13 @@ namespace ICSharpCode.ILSpy bool lineComment = false; bool blockComment = false; - if (offset < 0) return -1; + if (offset < 0) + return -1; // first try "quick find" - find the matching bracket if there is no string/comment in the way int quickResult = QuickSearchBracketForward(document, offset, openBracket, closingBracket); - if (quickResult >= 0) return quickResult; + if (quickResult >= 0) + return quickResult; // we need to parse the line from the beginning, so get the line start position int linestart = ScanLineStart(document, offset); @@ -235,52 +278,69 @@ namespace ICSharpCode.ILSpy // we need to know where offset is - in a string/comment or in normal code? // ignore cases where offset is in a block comment int starttype = GetStartType(document, linestart, offset); - if (starttype != 0) return -1; // start position is in a comment/string + if (starttype != 0) + return -1; // start position is in a comment/string int brackets = 1; - while (offset < document.TextLength) { + while (offset < document.TextLength) + { char ch = document.GetCharAt(offset); - switch (ch) { + switch (ch) + { case '\r': case '\n': lineComment = false; inChar = false; - if (!verbatim) inString = false; + if (!verbatim) + inString = false; break; case '/': - if (blockComment) { + if (blockComment) + { Debug.Assert(offset > 0); - if (document.GetCharAt(offset - 1) == '*') { + if (document.GetCharAt(offset - 1) == '*') + { blockComment = false; } } - if (!inString && !inChar && offset + 1 < document.TextLength) { - if (!blockComment && document.GetCharAt(offset + 1) == '/') { + if (!inString && !inChar && offset + 1 < document.TextLength) + { + if (!blockComment && document.GetCharAt(offset + 1) == '/') + { lineComment = true; } - if (!lineComment && document.GetCharAt(offset + 1) == '*') { + if (!lineComment && document.GetCharAt(offset + 1) == '*') + { blockComment = true; } } break; case '"': - if (!(inChar || lineComment || blockComment)) { - if (inString && verbatim) { - if (offset + 1 < document.TextLength && document.GetCharAt(offset + 1) == '"') { + if (!(inChar || lineComment || blockComment)) + { + if (inString && verbatim) + { + if (offset + 1 < document.TextLength && document.GetCharAt(offset + 1) == '"') + { ++offset; // skip escaped quote inString = false; // let the string go - } else { + } + else + { verbatim = false; } - } else if (!inString && offset > 0 && document.GetCharAt(offset - 1) == '@') { + } + else if (!inString && offset > 0 && document.GetCharAt(offset - 1) == '@') + { verbatim = true; } inString = !inString; } break; case '\'': - if (!(inString || lineComment || blockComment)) { + if (!(inString || lineComment || blockComment)) + { inChar = !inChar; } break; @@ -289,14 +349,20 @@ namespace ICSharpCode.ILSpy ++offset; // skip next character break; default: - if (ch == openBracket) { - if (!(inString || inChar || lineComment || blockComment)) { + if (ch == openBracket) + { + if (!(inString || inChar || lineComment || blockComment)) + { ++brackets; } - } else if (ch == closingBracket) { - if (!(inString || inChar || lineComment || blockComment)) { + } + else if (ch == closingBracket) + { + if (!(inString || inChar || lineComment || blockComment)) + { --brackets; - if (brackets == 0) { + if (brackets == 0) + { return offset; } } @@ -313,20 +379,33 @@ namespace ICSharpCode.ILSpy { int brackets = -1; // first try "quick find" - find the matching bracket if there is no string/comment in the way - for (int i = offset; i >= 0; --i) { + for (int i = offset; i >= 0; --i) + { char ch = document.GetCharAt(i); - if (ch == openBracket) { + if (ch == openBracket) + { ++brackets; - if (brackets == 0) return i; - } else if (ch == closingBracket) { + if (brackets == 0) + return i; + } + else if (ch == closingBracket) + { --brackets; - } else if (ch == '"') { + } + else if (ch == '"') + { break; - } else if (ch == '\'') { + } + else if (ch == '\'') + { break; - } else if (ch == '/' && i > 0) { - if (document.GetCharAt(i - 1) == '/') break; - if (document.GetCharAt(i - 1) == '*') break; + } + else if (ch == '/' && i > 0) + { + if (document.GetCharAt(i - 1) == '/') + break; + if (document.GetCharAt(i - 1) == '*') + break; } } return -1; @@ -336,21 +415,36 @@ namespace ICSharpCode.ILSpy { int brackets = 1; // try "quick find" - find the matching bracket if there is no string/comment in the way - for (int i = offset; i < document.TextLength; ++i) { + for (int i = offset; i < document.TextLength; ++i) + { char ch = document.GetCharAt(i); - if (ch == openBracket) { + if (ch == openBracket) + { ++brackets; - } else if (ch == closingBracket) { + } + else if (ch == closingBracket) + { --brackets; - if (brackets == 0) return i; - } else if (ch == '"') { + if (brackets == 0) + return i; + } + else if (ch == '"') + { break; - } else if (ch == '\'') { + } + else if (ch == '\'') + { break; - } else if (ch == '/' && i > 0) { - if (document.GetCharAt(i - 1) == '/') break; - } else if (ch == '*' && i > 0) { - if (document.GetCharAt(i - 1) == '/') break; + } + else if (ch == '/' && i > 0) + { + if (document.GetCharAt(i - 1) == '/') + break; + } + else if (ch == '*' && i > 0) + { + if (document.GetCharAt(i - 1) == '/') + break; } } return -1; diff --git a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs index f588cd153..20a480da8 100644 --- a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs +++ b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; + using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; @@ -111,7 +112,8 @@ namespace ICSharpCode.ILSpy public override void WriteKeyword(Role role, string keyword) { HighlightingColor color = null; - switch (keyword) { + switch (keyword) + { case "namespace": case "using": if (role == UsingStatement.UsingKeywordRole) @@ -266,11 +268,13 @@ namespace ICSharpCode.ILSpy } if (nodeStack.PeekOrDefault() is AttributeSection) color = attributeKeywordsColor; - if (color != null) { + if (color != null) + { BeginSpan(color); } base.WriteKeyword(role, keyword); - if (color != null) { + if (color != null) + { EndSpan(); } } @@ -278,7 +282,8 @@ namespace ICSharpCode.ILSpy public override void WritePrimitiveType(string type) { HighlightingColor color = null; - switch (type) { + switch (type) + { case "new": case "notnull": // Not sure if reference type or value type @@ -312,11 +317,13 @@ namespace ICSharpCode.ILSpy color = referenceTypeKeywordsColor; break; } - if (color != null) { + if (color != null) + { BeginSpan(color); } base.WritePrimitiveType(type); - if (color != null) { + if (color != null) + { EndSpan(); } } @@ -334,9 +341,11 @@ namespace ICSharpCode.ILSpy } if (identifier.Name == "var" && identifier.Parent is AstType) color = queryKeywordsColor; - switch (GetCurrentDefinition()) { + switch (GetCurrentDefinition()) + { case ITypeDefinition t: - switch (t.Kind) { + switch (t.Kind) + { case TypeKind.Delegate: color = delegateTypeColor; break; @@ -361,9 +370,11 @@ namespace ICSharpCode.ILSpy color = fieldDeclarationColor; break; } - switch (GetCurrentMemberReference()) { + switch (GetCurrentMemberReference()) + { case IType t: - switch (t.Kind) { + switch (t.Kind) + { case TypeKind.Delegate: color = delegateTypeColor; break; @@ -388,11 +399,13 @@ namespace ICSharpCode.ILSpy color = fieldAccessColor; break; } - if (color != null) { + if (color != null) + { BeginSpan(color); } base.WriteIdentifier(identifier); - if (color != null) { + if (color != null) + { EndSpan(); } } @@ -400,17 +413,21 @@ namespace ICSharpCode.ILSpy public override void WritePrimitiveValue(object value, Decompiler.CSharp.Syntax.LiteralFormat format) { HighlightingColor color = null; - if (value is null) { + if (value is null) + { color = valueKeywordColor; } - if (value is true || value is false) { + if (value is true || value is false) + { color = trueKeywordColor; } - if (color != null) { + if (color != null) + { BeginSpan(color); } base.WritePrimitiveValue(value, format); - if (color != null) { + if (color != null) + { EndSpan(); } } @@ -436,13 +453,16 @@ namespace ICSharpCode.ILSpy AstNode node = nodeStack.Peek(); var symbol = node.GetSymbol(); - if (symbol == null && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) { + if (symbol == null && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) + { symbol = node.Parent.GetSymbol(); } - if (symbol != null && node.Parent is ObjectCreateExpression) { + if (symbol != null && node.Parent is ObjectCreateExpression) + { symbol = node.Parent.GetSymbol(); } - if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) { + if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) + { var declaringType = member.DeclaringType; if (declaringType != null && declaringType.Kind == TypeKind.Delegate) return null; @@ -472,7 +492,8 @@ namespace ICSharpCode.ILSpy private void BeginSpan(HighlightingColor highlightingColor) { - if (textOutput != null) { + if (textOutput != null) + { textOutput.BeginSpan(highlightingColor); return; } @@ -488,7 +509,8 @@ namespace ICSharpCode.ILSpy private void EndSpan() { - if (textOutput != null) { + if (textOutput != null) + { textOutput.EndSpan(); return; } diff --git a/ILSpy/Languages/CSharpILMixedLanguage.cs b/ILSpy/Languages/CSharpILMixedLanguage.cs index 6e986512a..5bea5a8a3 100644 --- a/ILSpy/Languages/CSharpILMixedLanguage.cs +++ b/ILSpy/Languages/CSharpILMixedLanguage.cs @@ -26,6 +26,7 @@ using System.Reflection.Metadata; using System.Threading; using System.Windows; using System.Windows.Media; + using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; @@ -52,8 +53,7 @@ namespace ICSharpCode.ILSpy DetectControlStructure = detectControlStructure, ShowSequencePoints = options.DecompilerSettings.ShowDebugInfo }, - options.CancellationToken) - { + options.CancellationToken) { ShowMetadataTokens = Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens, ShowMetadataTokensInBase10 = Options.DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokensInBase10, ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions @@ -74,7 +74,7 @@ namespace ICSharpCode.ILSpy tokenWriter = TokenWriter.WrapInWriterThatSetsLocationsInAST(tokenWriter); syntaxTree.AcceptVisitor(new CSharpOutputVisitor(tokenWriter, settings.CSharpFormattingOptions)); } - + class MixedMethodBodyDisassembler : MethodBodyDisassembler { readonly DecompilationOptions options; @@ -91,7 +91,8 @@ namespace ICSharpCode.ILSpy public override void Disassemble(PEFile module, MethodDefinitionHandle handle) { - try { + try + { var csharpOutput = new StringWriter(); CSharpDecompiler decompiler = CreateDecompiler(module, options); var st = decompiler.Decompile(handle); @@ -100,7 +101,9 @@ namespace ICSharpCode.ILSpy this.sequencePoints = mapping.Value ?? (IList)EmptyList.Instance; this.codeLines = csharpOutput.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None); base.Disassemble(module, handle); - } finally { + } + finally + { this.sequencePoints = null; this.codeLines = null; } @@ -109,12 +112,16 @@ namespace ICSharpCode.ILSpy protected override void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodDefinition, ref BlobReader blob) { int index = sequencePoints.BinarySearch(blob.Offset, seq => seq.Offset); - if (index >= 0) { + if (index >= 0) + { var info = sequencePoints[index]; var highlightingOutput = output as ISmartTextOutput; - if (!info.IsHidden) { - for (int line = info.StartLine; line <= info.EndLine; line++) { - if (highlightingOutput != null) { + if (!info.IsHidden) + { + for (int line = info.StartLine; line <= info.EndLine; line++) + { + if (highlightingOutput != null) + { string text = codeLines[line - 1]; int startColumn = 1; int endColumn = text.Length + 1; @@ -123,10 +130,13 @@ namespace ICSharpCode.ILSpy if (line == info.EndLine) endColumn = info.EndColumn; WriteHighlightedCommentLine(highlightingOutput, text, startColumn - 1, endColumn - 1, info.StartLine == info.EndLine); - } else + } + else WriteCommentLine(output, codeLines[line - 1]); } - } else { + } + else + { output.Write("// "); highlightingOutput?.BeginSpan(gray); output.WriteLine("(no C# code)"); @@ -140,11 +150,13 @@ namespace ICSharpCode.ILSpy void WriteHighlightedCommentLine(ISmartTextOutput output, string text, int startColumn, int endColumn, bool isSingleLine) { - if (startColumn > text.Length) { + if (startColumn > text.Length) + { Debug.Fail("startColumn is invalid"); startColumn = text.Length; } - if (endColumn > text.Length) { + if (endColumn > text.Length) + { Debug.Fail("endColumn is invalid"); endColumn = text.Length; } diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs index 96c22ce91..13b938e30 100644 --- a/ILSpy/Languages/CSharpLanguage.cs +++ b/ILSpy/Languages/CSharpLanguage.cs @@ -26,6 +26,7 @@ using System.Reflection.Metadata; using System.Text; using System.Windows; using System.Windows.Controls; + using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Utils; @@ -62,7 +63,8 @@ namespace ICSharpCode.ILSpy { string lastTransformName = "no transforms"; int transformCount = 0; - foreach (var transform in CSharpDecompiler.GetAstTransforms()) { + foreach (var transform in CSharpDecompiler.GetAstTransforms()) + { yield return new CSharpLanguage { transformCount = transformCount, name = "C# - " + lastTransformName, @@ -94,7 +96,8 @@ namespace ICSharpCode.ILSpy public override IReadOnlyList LanguageVersions { get { - if (versions == null) { + if (versions == null) + { versions = new List() { new LanguageVersion(Decompiler.CSharp.LanguageVersion.CSharp1.ToString(), "C# 1.0 / VS .NET"), new LanguageVersion(Decompiler.CSharp.LanguageVersion.CSharp2.ToString(), "C# 2.0 / VS 2005"), @@ -121,7 +124,8 @@ namespace ICSharpCode.ILSpy decompiler.DebugInfoProvider = module.GetDebugInfoOrNull(); while (decompiler.AstTransforms.Count > transformCount) decompiler.AstTransforms.RemoveAt(decompiler.AstTransforms.Count - 1); - if (options.EscapeInvalidIdentifiers) { + if (options.EscapeInvalidIdentifiers) + { decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()); } return decompiler; @@ -132,7 +136,8 @@ namespace ICSharpCode.ILSpy syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }); output.IndentationString = settings.CSharpFormattingOptions.IndentationString; TokenWriter tokenWriter = new TextTokenWriter(output, settings, typeSystem); - if (output is ISmartTextOutput highlightingOutput) { + if (output is ISmartTextOutput highlightingOutput) + { tokenWriter = new CSharpHighlightingTokenWriter(tokenWriter, highlightingOutput); } syntaxTree.AcceptVisitor(new CSharpOutputVisitor(tokenWriter, settings.CSharpFormattingOptions)); @@ -146,11 +151,14 @@ namespace ICSharpCode.ILSpy AddReferenceWarningMessage(assembly, output); WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true)); var methodDefinition = decompiler.TypeSystem.MainModule.ResolveEntity(method.MetadataToken) as IMethod; - if (methodDefinition.IsConstructor && methodDefinition.DeclaringType.IsReferenceType != false) { + if (methodDefinition.IsConstructor && methodDefinition.DeclaringType.IsReferenceType != false) + { var members = CollectFieldsAndCtors(methodDefinition.DeclaringTypeDefinition, methodDefinition.IsStatic); decompiler.AstTransforms.Add(new SelectCtorTransform(methodDefinition)); WriteCode(output, options.DecompilerSettings, decompiler.Decompile(members), decompiler.TypeSystem); - } else { + } + else + { WriteCode(output, options.DecompilerSettings, decompiler.Decompile(method.MetadataToken), decompiler.TypeSystem); } } @@ -168,12 +176,17 @@ namespace ICSharpCode.ILSpy public void Run(AstNode rootNode, TransformContext context) { ConstructorDeclaration ctorDecl = null; - foreach (var node in rootNode.Children) { - switch (node) { + foreach (var node in rootNode.Children) + { + switch (node) + { case ConstructorDeclaration ctor: - if (ctor.GetSymbol() == this.ctor) { + if (ctor.GetSymbol() == this.ctor) + { ctorDecl = ctor; - } else { + } + else + { // remove other ctors ctor.Remove(); removedSymbols.Add(ctor.GetSymbol()); @@ -181,17 +194,21 @@ namespace ICSharpCode.ILSpy break; case FieldDeclaration fd: // Remove any fields without initializers - if (fd.Variables.All(v => v.Initializer.IsNull)) { + if (fd.Variables.All(v => v.Initializer.IsNull)) + { fd.Remove(); removedSymbols.Add(fd.GetSymbol()); } break; } } - if (ctorDecl?.Initializer.ConstructorInitializerType == ConstructorInitializerType.This) { + if (ctorDecl?.Initializer.ConstructorInitializerType == ConstructorInitializerType.This) + { // remove all fields - foreach (var node in rootNode.Children) { - switch (node) { + foreach (var node in rootNode.Children) + { + switch (node) + { case FieldDeclaration fd: fd.Remove(); removedSymbols.Add(fd.GetSymbol()); @@ -199,7 +216,8 @@ namespace ICSharpCode.ILSpy } } } - foreach (var node in rootNode.Children) { + foreach (var node in rootNode.Children) + { if (node is Comment && removedSymbols.Contains(node.GetSymbol())) node.Remove(); } @@ -223,9 +241,12 @@ namespace ICSharpCode.ILSpy AddReferenceAssemblyWarningMessage(assembly, output); AddReferenceWarningMessage(assembly, output); WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true)); - if (field.IsConst) { + if (field.IsConst) + { WriteCode(output, options.DecompilerSettings, decompiler.Decompile(field.MetadataToken), decompiler.TypeSystem); - } else { + } + else + { var members = CollectFieldsAndCtors(field.DeclaringTypeDefinition, field.IsStatic); var resolvedField = decompiler.TypeSystem.MainModule.GetDefinition((FieldDefinitionHandle)field.MetadataToken); decompiler.AstTransforms.Add(new SelectFieldTransform(resolvedField)); @@ -236,11 +257,13 @@ namespace ICSharpCode.ILSpy static List CollectFieldsAndCtors(ITypeDefinition type, bool isStatic) { var members = new List(); - foreach (var field in type.Fields) { + foreach (var field in type.Fields) + { if (!field.MetadataToken.IsNil && field.IsStatic == isStatic) members.Add(field.MetadataToken); } - foreach (var ctor in type.Methods) { + foreach (var ctor in type.Methods) + { if (!ctor.MetadataToken.IsNil && ctor.IsConstructor && ctor.IsStatic == isStatic) members.Add(ctor.MetadataToken); } @@ -262,8 +285,10 @@ namespace ICSharpCode.ILSpy public void Run(AstNode rootNode, TransformContext context) { - foreach (var node in rootNode.Children) { - switch (node) { + foreach (var node in rootNode.Children) + { + switch (node) + { case EntityDeclaration ed: if (node.GetSymbol() != field) node.Remove(); @@ -323,7 +348,8 @@ namespace ICSharpCode.ILSpy void AddWarningMessage(PEFile module, ITextOutput output, string line1, string line2 = null, string buttonText = null, System.Windows.Media.ImageSource buttonImage = null, RoutedEventHandler buttonClickHandler = null) { - if (output is ISmartTextOutput fancyOutput) { + if (output is ISmartTextOutput fancyOutput) + { string text = line1; if (!string.IsNullOrEmpty(line2)) text += Environment.NewLine + line2; @@ -343,11 +369,14 @@ namespace ICSharpCode.ILSpy } }); fancyOutput.WriteLine(); - if (buttonText != null && buttonClickHandler != null) { + if (buttonText != null && buttonClickHandler != null) + { fancyOutput.AddButton(buttonImage, buttonText, buttonClickHandler); fancyOutput.WriteLine(); } - } else { + } + else + { WriteCommentLine(output, line1); if (!string.IsNullOrEmpty(line2)) WriteCommentLine(output, line2); @@ -357,21 +386,26 @@ namespace ICSharpCode.ILSpy public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { var module = assembly.GetPEFileOrNull(); - if (options.FullDecompilation && options.SaveAsProjectDirectory != null) { + if (options.FullDecompilation && options.SaveAsProjectDirectory != null) + { var decompiler = new ILSpyWholeProjectDecompiler(assembly, options); return decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken); - } else { + } + else + { AddReferenceAssemblyWarningMessage(module, output); AddReferenceWarningMessage(module, output); output.WriteLine(); base.DecompileAssembly(assembly, output, options); // don't automatically load additional assemblies when an assembly node is selected in the tree view - using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad(assembly.AssemblyList)) { + using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad(assembly.AssemblyList)) + { IAssemblyResolver assemblyResolver = assembly.GetAssemblyResolver(); var typeSystem = new DecompilerTypeSystem(module, assemblyResolver, options.DecompilerSettings); var globalType = typeSystem.MainModule.TypeDefinitions.FirstOrDefault(); - if (globalType != null) { + if (globalType != null) + { output.Write("// Global type: "); output.WriteReference(globalType, globalType.FullName); output.WriteLine(); @@ -379,30 +413,37 @@ namespace ICSharpCode.ILSpy var metadata = module.Metadata; var corHeader = module.Reader.PEHeaders.CorHeader; var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress); - if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition) { + if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition) + { var entrypoint = typeSystem.MainModule.ResolveMethod(entrypointHandle, new Decompiler.TypeSystem.GenericContext()); - if (entrypoint != null) { + if (entrypoint != null) + { output.Write("// Entry point: "); output.WriteReference(entrypoint, entrypoint.DeclaringType.FullName + "." + entrypoint.Name); output.WriteLine(); } } output.WriteLine("// Architecture: " + GetPlatformDisplayName(module)); - if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0) { + if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0) + { output.WriteLine("// This assembly contains unmanaged code."); } string runtimeName = GetRuntimeDisplayName(module); - if (runtimeName != null) { + if (runtimeName != null) + { output.WriteLine("// Runtime: " + runtimeName); } - if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.StrongNameSigned) != 0) { + if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.StrongNameSigned) != 0) + { output.WriteLine("// This assembly is signed with a strong name key."); } - if (metadata.IsAssembly) { + if (metadata.IsAssembly) + { var asm = metadata.GetAssemblyDefinition(); if (asm.HashAlgorithm != AssemblyHashAlgorithm.None) output.WriteLine("// Hash algorithm: " + asm.HashAlgorithm.ToString().ToUpper()); - if (!asm.PublicKey.IsNil) { + if (!asm.PublicKey.IsNil) + { output.Write("// Public key: "); var reader = metadata.GetBlobReader(asm.PublicKey); while (reader.RemainingBytes > 0) @@ -411,20 +452,25 @@ namespace ICSharpCode.ILSpy } } var debugInfo = assembly.GetDebugInfoOrNull(); - if (debugInfo != null) { + if (debugInfo != null) + { output.WriteLine("// Debug info: " + debugInfo.Description); } output.WriteLine(); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, options.DecompilerSettings); decompiler.CancellationToken = options.CancellationToken; - if (options.EscapeInvalidIdentifiers) { + if (options.EscapeInvalidIdentifiers) + { decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()); } SyntaxTree st; - if (options.FullDecompilation) { + if (options.FullDecompilation) + { st = decompiler.DecompileWholeModuleAsSingleFile(); - } else { + } + else + { st = decompiler.DecompileModuleAndAssemblyAttributes(); } WriteCode(output, options.DecompilerSettings, st, decompiler.TypeSystem); @@ -447,8 +493,10 @@ namespace ICSharpCode.ILSpy protected override IEnumerable<(string itemType, string fileName)> WriteResourceToFile(string fileName, string resourceName, Stream entryStream) { - foreach (var handler in App.ExportProvider.GetExportedValues()) { - if (handler.CanHandle(fileName, options)) { + foreach (var handler in App.ExportProvider.GetExportedValues()) + { + if (handler.CanHandle(fileName, options)) + { entryStream.Position = 0; fileName = handler.WriteResourceToFile(assembly, fileName, entryStream, options); return new[] { (handler.EntryType, fileName) }; @@ -463,7 +511,8 @@ namespace ICSharpCode.ILSpy CSharpAmbience ambience = new CSharpAmbience(); // Do not forget to update CSharpAmbienceTests.ILSpyMainTreeViewTypeFlags, if this ever changes. ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.PlaceReturnTypeAfterParameterList; - if (new DecompilationOptions().DecompilerSettings.LiftNullables) { + if (new DecompilationOptions().DecompilerSettings.LiftNullables) + { ambience.ConversionFlags |= ConversionFlags.UseNullableSpecifierForValueTypes; } return ambience; @@ -489,17 +538,23 @@ namespace ICSharpCode.ILSpy throw new ArgumentNullException(nameof(type)); var ambience = CreateAmbience(); // Do not forget to update CSharpAmbienceTests.ILSpyMainTreeViewFlags, if this ever changes. - if (includeNamespace) { + if (includeNamespace) + { ambience.ConversionFlags |= ConversionFlags.UseFullyQualifiedTypeNames; ambience.ConversionFlags |= ConversionFlags.UseFullyQualifiedEntityNames; } - if (type is ITypeDefinition definition) { + if (type is ITypeDefinition definition) + { return ambience.ConvertSymbol(definition); // HACK : UnknownType is not supported by CSharpAmbience. - } else if (type.Kind == TypeKind.Unknown) { + } + else if (type.Kind == TypeKind.Unknown) + { return (includeNamespace ? type.FullName : type.Name) + (type.TypeParameterCount > 0 ? "<" + string.Join(", ", type.TypeArguments.Select(t => t.Name)) + ">" : ""); - } else { + } + else + { return ambience.ConvertType(type); } } @@ -538,26 +593,31 @@ namespace ICSharpCode.ILSpy var currentTypeDefHandle = handle; var typeDef = metadata.GetTypeDefinition(currentTypeDefHandle); - while (!currentTypeDefHandle.IsNil) { + while (!currentTypeDefHandle.IsNil) + { if (builder.Length > 0) builder.Insert(0, '.'); typeDef = metadata.GetTypeDefinition(currentTypeDefHandle); var part = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(typeDef.Name), out int typeParamCount); var genericParams = typeDef.GetGenericParameters(); - if (!omitGenerics && genericParams.Count > 0) { + if (!omitGenerics && genericParams.Count > 0) + { builder.Insert(0, '>'); int firstIndex = genericParams.Count - typeParamCount; - for (int i = genericParams.Count - 1; i >= genericParams.Count - typeParamCount; i--) { + for (int i = genericParams.Count - 1; i >= genericParams.Count - typeParamCount; i--) + { builder.Insert(0, metadata.GetString(metadata.GetGenericParameter(genericParams[i]).Name)); builder.Insert(0, i == firstIndex ? '<' : ','); } } builder.Insert(0, part); currentTypeDefHandle = typeDef.GetDeclaringType(); - if (!fullName) break; + if (!fullName) + break; } - if (fullName && !typeDef.Namespace.IsNil) { + if (fullName && !typeDef.Namespace.IsNil) + { builder.Insert(0, '.'); builder.Insert(0, metadata.GetString(typeDef.Namespace)); } @@ -568,7 +628,8 @@ namespace ICSharpCode.ILSpy public override string GetEntityName(PEFile module, EntityHandle handle, bool fullName, bool omitGenerics) { MetadataReader metadata = module.Metadata; - switch (handle.Kind) { + switch (handle.Kind) + { case HandleKind.TypeDefinition: return ToCSharpString(metadata, (TypeDefinitionHandle)handle, fullName, omitGenerics); case HandleKind.FieldDefinition: @@ -581,7 +642,8 @@ namespace ICSharpCode.ILSpy var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle); declaringType = md.GetDeclaringType(); string methodName = metadata.GetString(md.Name); - switch (methodName) { + switch (methodName) + { case ".ctor": case ".cctor": var td = metadata.GetTypeDefinition(declaringType); @@ -599,10 +661,12 @@ namespace ICSharpCode.ILSpy break; default: var genericParams = md.GetGenericParameters(); - if (!omitGenerics && genericParams.Count > 0) { + if (!omitGenerics && genericParams.Count > 0) + { methodName += "<"; int i = 0; - foreach (var h in genericParams) { + foreach (var h in genericParams) + { if (i > 0) methodName += ","; var gp = metadata.GetGenericParameter(h); @@ -645,10 +709,12 @@ namespace ICSharpCode.ILSpy var decoratedWriter = new TextWriterTokenWriter(output); var writer = new CSharpHighlightingTokenWriter(TokenWriter.InsertRequiredSpaces(decoratedWriter), locatable: decoratedWriter); var settings = new DecompilationOptions().DecompilerSettings; - if (!settings.LiftNullables) { + if (!settings.LiftNullables) + { flags &= ~ConversionFlags.UseNullableSpecifierForValueTypes; } - if (entity is IMethod m && m.IsLocalFunction) { + if (entity is IMethod m && m.IsLocalFunction) + { writer.WriteIdentifier(Identifier.Create("(local)")); } new CSharpAmbience() { diff --git a/ILSpy/Languages/CSharpLexer.cs b/ILSpy/Languages/CSharpLexer.cs index e8e3a29ee..56d4f5e10 100644 --- a/ILSpy/Languages/CSharpLexer.cs +++ b/ILSpy/Languages/CSharpLexer.cs @@ -49,7 +49,8 @@ namespace ICSharpCode.ILSpy public int Peek(int step) { - while (step >= buffer.Count) { + while (step >= buffer.Count) + { buffer.Add(reader.Read()); } @@ -120,7 +121,7 @@ namespace ICSharpCode.ILSpy // used for the original value of strings (with escape sequences). protected StringBuilder originalValue = new StringBuilder(); - + protected int Line { get { return line; @@ -140,11 +141,14 @@ namespace ICSharpCode.ILSpy int val = reader.Read(); if (recordRead && val >= 0) recordedText.Append((char)val); - if ((val == '\r' && reader.Peek() != '\n') || val == '\n') { + if ((val == '\r' && reader.Peek() != '\n') || val == '\n') + { ++line; col = 1; LineBreak(); - } else if (val >= 0) { + } + else if (val >= 0) + { col++; } return val; @@ -162,7 +166,8 @@ namespace ICSharpCode.ILSpy protected void ReaderSkip(int steps) { - for (int i = 0; i < steps; i++) { + for (int i = 0; i < steps; i++) + { ReaderRead(); } } @@ -171,7 +176,8 @@ namespace ICSharpCode.ILSpy { StringBuilder builder = new StringBuilder(); - for (int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) + { int peek = ReaderPeek(i); if (peek != -1) builder.Append((char)peek); @@ -231,7 +237,8 @@ namespace ICSharpCode.ILSpy public Literal Peek() { // Console.WriteLine("Call to Peek"); - if (peekToken.next == null) { + if (peekToken.next == null) + { peekToken.next = Next(); } peekToken = peekToken.next; @@ -244,7 +251,8 @@ namespace ICSharpCode.ILSpy /// An object. public virtual Literal NextToken() { - if (curToken == null) { + if (curToken == null) + { curToken = Next(); //Console.WriteLine(ICSharpCode.NRefactory.Parser.CSharp.Tokens.GetTokenString(curToken.kind) + " -- " + curToken.val + "(" + curToken.kind + ")"); return curToken; @@ -252,7 +260,8 @@ namespace ICSharpCode.ILSpy lastToken = curToken; - if (curToken.next == null) { + if (curToken.next == null) + { curToken.next = Next(); } @@ -265,8 +274,10 @@ namespace ICSharpCode.ILSpy protected static bool IsIdentifierPart(int ch) { - if (ch == 95) return true; // 95 = '_' - if (ch == -1) return false; + if (ch == 95) + return true; // 95 = '_' + if (ch == -1) + return false; return char.IsLetterOrDigit((char)ch); // accept unicode letters } @@ -277,13 +288,16 @@ namespace ICSharpCode.ILSpy protected int GetHexNumber(char digit) { - if (Char.IsDigit(digit)) { + if (Char.IsDigit(digit)) + { return digit - '0'; } - if ('A' <= digit && digit <= 'F') { + if ('A' <= digit && digit <= 'F') + { return digit - 'A' + 0xA; } - if ('a' <= digit && digit <= 'f') { + if ('a' <= digit && digit <= 'f') + { return digit - 'a' + 0xA; } return 0; @@ -294,16 +308,21 @@ namespace ICSharpCode.ILSpy protected bool HandleLineEnd(char ch) { // Handle MS-DOS or MacOS line ends. - if (ch == '\r') { - if (reader.Peek() == '\n') { // MS-DOS line end '\r\n' + if (ch == '\r') + { + if (reader.Peek() == '\n') + { // MS-DOS line end '\r\n' ReaderRead(); // LineBreak (); called by ReaderRead (); return true; - } else { // assume MacOS line end which is '\r' + } + else + { // assume MacOS line end which is '\r' LineBreak(); return true; } } - if (ch == '\n') { + if (ch == '\n') + { LineBreak(); return true; } @@ -313,13 +332,16 @@ namespace ICSharpCode.ILSpy protected void SkipToEndOfLine() { int nextChar; - while ((nextChar = reader.Read()) != -1) { - if (nextChar == '\r') { + while ((nextChar = reader.Read()) != -1) + { + if (nextChar == '\r') + { if (reader.Peek() == '\n') reader.Read(); nextChar = '\n'; } - if (nextChar == '\n') { + if (nextChar == '\n') + { ++line; col = 1; break; @@ -331,16 +353,19 @@ namespace ICSharpCode.ILSpy { sb.Length = 0; int nextChar; - while ((nextChar = reader.Read()) != -1) { + while ((nextChar = reader.Read()) != -1) + { char ch = (char)nextChar; - if (nextChar == '\r') { + if (nextChar == '\r') + { if (reader.Peek() == '\n') reader.Read(); nextChar = '\n'; } // Return read string, if EOL is reached - if (nextChar == '\n') { + if (nextChar == '\n') + { ++line; col = 1; return sb.ToString(); @@ -365,14 +390,16 @@ namespace ICSharpCode.ILSpy protected override Literal Next() { char ch; - while (true) { + while (true) + { int nextChar = ReaderRead(); if (nextChar == -1) break; Literal token = null; - switch (nextChar) { + switch (nextChar) + { case ' ': case '\t': continue; @@ -388,20 +415,28 @@ namespace ICSharpCode.ILSpy break; case '@': int next = ReaderRead(); - if (next == -1) { + if (next == -1) + { Error(Line, Col, String.Format("EOF after @")); continue; - } else { + } + else + { int x = Col - 1; int y = Line; ch = (char)next; - if (ch == '"') { + if (ch == '"') + { token = ReadVerbatimString(); - } else if (Char.IsLetterOrDigit(ch) || ch == '_') { + } + else if (Char.IsLetterOrDigit(ch) || ch == '_') + { bool canBeKeyword; string s = ReadIdent(ch, out canBeKeyword); return new Literal(null, null, LiteralFormat.None); - } else { + } + else + { HandleLineEnd(ch); Error(y, x, String.Format("Unexpected char in Lexer.Next() : {0}", ch)); continue; @@ -410,20 +445,24 @@ namespace ICSharpCode.ILSpy break; default: // non-ws chars are handled here ch = (char)nextChar; - if (Char.IsLetter(ch) || ch == '_' || ch == '\\') { + if (Char.IsLetter(ch) || ch == '_' || ch == '\\') + { int x = Col - 1; // Col was incremented above, but we want the start of the identifier int y = Line; bool canBeKeyword; string s = ReadIdent(ch, out canBeKeyword); return new Literal(null, null, LiteralFormat.None); - } else if (Char.IsDigit(ch)) { + } + else if (Char.IsDigit(ch)) + { token = ReadDigit(ch, Col - 1); } break; } // try error recovery (token = null -> continue with next char) - if (token != null) { + if (token != null) + { return token; } } @@ -441,47 +480,64 @@ namespace ICSharpCode.ILSpy int peek; int curPos = 0; canBeKeyword = true; - while (true) { - if (ch == '\\') { + while (true) + { + if (ch == '\\') + { peek = ReaderPeek(); - if (peek != 'u' && peek != 'U') { + if (peek != 'u' && peek != 'U') + { Error(Line, Col, "Identifiers can only contain unicode escape sequences"); } canBeKeyword = false; string surrogatePair; ReadEscapeSequence(out ch, out surrogatePair); - if (surrogatePair != null) { - if (!char.IsLetterOrDigit(surrogatePair, 0)) { + if (surrogatePair != null) + { + if (!char.IsLetterOrDigit(surrogatePair, 0)) + { Error(Line, Col, "Unicode escape sequences in identifiers cannot be used to represent characters that are invalid in identifiers"); } - for (int i = 0; i < surrogatePair.Length - 1; i++) { - if (curPos < MAX_IDENTIFIER_LENGTH) { + for (int i = 0; i < surrogatePair.Length - 1; i++) + { + if (curPos < MAX_IDENTIFIER_LENGTH) + { identBuffer[curPos++] = surrogatePair[i]; } } ch = surrogatePair[surrogatePair.Length - 1]; - } else { - if (!IsIdentifierPart(ch)) { + } + else + { + if (!IsIdentifierPart(ch)) + { Error(Line, Col, "Unicode escape sequences in identifiers cannot be used to represent characters that are invalid in identifiers"); } } } - if (curPos < MAX_IDENTIFIER_LENGTH) { + if (curPos < MAX_IDENTIFIER_LENGTH) + { if (ch != '\0') // only add character, if it is valid // prevents \ from being added identBuffer[curPos++] = ch; - } else { + } + else + { Error(Line, Col, String.Format("Identifier too long")); - while (IsIdentifierPart(ReaderPeek())) { + while (IsIdentifierPart(ReaderPeek())) + { ReaderRead(); } break; } peek = ReaderPeek(); - if (IsIdentifierPart(peek) || peek == '\\') { + if (IsIdentifierPart(peek) || peek == '\\') + { ch = (char)ReaderRead(); - } else { + } + else + { break; } } @@ -490,7 +546,8 @@ namespace ICSharpCode.ILSpy Literal ReadDigit(char ch, int x) { - unchecked { // prevent exception when ReaderPeek() = -1 is cast to char + unchecked + { // prevent exception when ReaderPeek() = -1 is cast to char int y = Line; sb.Length = 0; sb.Append(ch); @@ -506,97 +563,127 @@ namespace ICSharpCode.ILSpy char peek = (char)ReaderPeek(); - if (ch == '.') { + if (ch == '.') + { isdouble = true; - while (Char.IsDigit((char)ReaderPeek())) { // read decimal digits beyond the dot + while (Char.IsDigit((char)ReaderPeek())) + { // read decimal digits beyond the dot sb.Append((char)ReaderRead()); } peek = (char)ReaderPeek(); - } else if (ch == '0' && (peek == 'x' || peek == 'X')) { + } + else if (ch == '0' && (peek == 'x' || peek == 'X')) + { ReaderRead(); // skip 'x' sb.Length = 0; // Remove '0' from 0x prefix from the stringvalue - while (IsHex((char)ReaderPeek())) { + while (IsHex((char)ReaderPeek())) + { sb.Append((char)ReaderRead()); } - if (sb.Length == 0) { + if (sb.Length == 0) + { sb.Append('0'); // dummy value to prevent exception Error(y, x, "Invalid hexadecimal integer literal"); } ishex = true; prefix = "0x"; peek = (char)ReaderPeek(); - } else { - while (Char.IsDigit((char)ReaderPeek())) { + } + else + { + while (Char.IsDigit((char)ReaderPeek())) + { sb.Append((char)ReaderRead()); } peek = (char)ReaderPeek(); } Literal nextToken = null; // if we accidently read a 'dot' - if (peek == '.') { // read floating point number + if (peek == '.') + { // read floating point number ReaderRead(); peek = (char)ReaderPeek(); - if (!Char.IsDigit(peek)) { + if (!Char.IsDigit(peek)) + { nextToken = new Literal(null, null, LiteralFormat.None); peek = '.'; - } else { + } + else + { isdouble = true; // double is default - if (ishex) { + if (ishex) + { Error(y, x, "No hexadecimal floating point values allowed"); } sb.Append('.'); - while (Char.IsDigit((char)ReaderPeek())) { // read decimal digits beyond the dot + while (Char.IsDigit((char)ReaderPeek())) + { // read decimal digits beyond the dot sb.Append((char)ReaderRead()); } peek = (char)ReaderPeek(); } } - if (peek == 'e' || peek == 'E') { // read exponent + if (peek == 'e' || peek == 'E') + { // read exponent isdouble = true; sb.Append((char)ReaderRead()); peek = (char)ReaderPeek(); - if (peek == '-' || peek == '+') { + if (peek == '-' || peek == '+') + { sb.Append((char)ReaderRead()); } - while (Char.IsDigit((char)ReaderPeek())) { // read exponent value + while (Char.IsDigit((char)ReaderPeek())) + { // read exponent value sb.Append((char)ReaderRead()); } isunsigned = true; peek = (char)ReaderPeek(); } - if (peek == 'f' || peek == 'F') { // float value + if (peek == 'f' || peek == 'F') + { // float value ReaderRead(); suffix = "f"; isfloat = true; - } else if (peek == 'd' || peek == 'D') { // double type suffix (obsolete, double is default) + } + else if (peek == 'd' || peek == 'D') + { // double type suffix (obsolete, double is default) ReaderRead(); suffix = "d"; isdouble = true; - } else if (peek == 'm' || peek == 'M') { // decimal value + } + else if (peek == 'm' || peek == 'M') + { // decimal value ReaderRead(); suffix = "m"; isdecimal = true; - } else if (!isdouble) { - if (peek == 'u' || peek == 'U') { + } + else if (!isdouble) + { + if (peek == 'u' || peek == 'U') + { ReaderRead(); suffix = "u"; isunsigned = true; peek = (char)ReaderPeek(); } - if (peek == 'l' || peek == 'L') { + if (peek == 'l' || peek == 'L') + { ReaderRead(); peek = (char)ReaderPeek(); islong = true; - if (!isunsigned && (peek == 'u' || peek == 'U')) { + if (!isunsigned && (peek == 'u' || peek == 'U')) + { ReaderRead(); suffix = "Lu"; isunsigned = true; - } else { + } + else + { suffix = isunsigned ? "uL" : "L"; } } @@ -605,29 +692,41 @@ namespace ICSharpCode.ILSpy string digit = sb.ToString(); string stringValue = prefix + digit + suffix; - if (isfloat) { + if (isfloat) + { float num; - if (float.TryParse(digit, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { + if (float.TryParse(digit, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) + { return new Literal(stringValue, num, LiteralFormat.DecimalNumber); - } else { + } + else + { Error(y, x, String.Format("Can't parse float {0}", digit)); return new Literal(stringValue, 0f, LiteralFormat.DecimalNumber); } } - if (isdecimal) { + if (isdecimal) + { decimal num; - if (decimal.TryParse(digit, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { + if (decimal.TryParse(digit, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) + { return new Literal(stringValue, num, LiteralFormat.DecimalNumber); - } else { + } + else + { Error(y, x, String.Format("Can't parse decimal {0}", digit)); return new Literal(stringValue, 0m, LiteralFormat.DecimalNumber); } } - if (isdouble) { + if (isdouble) + { double num; - if (double.TryParse(digit, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) { + if (double.TryParse(digit, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) + { return new Literal(stringValue, num, LiteralFormat.DecimalNumber); - } else { + } + else + { Error(y, x, String.Format("Can't parse double {0}", digit)); return new Literal(stringValue, 0d, LiteralFormat.DecimalNumber); } @@ -635,62 +734,93 @@ namespace ICSharpCode.ILSpy // Try to determine a parsable value using ranges. ulong result; - if (ishex) { - if (!ulong.TryParse(digit, NumberStyles.HexNumber, null, out result)) { + if (ishex) + { + if (!ulong.TryParse(digit, NumberStyles.HexNumber, null, out result)) + { Error(y, x, String.Format("Can't parse hexadecimal constant {0}", digit)); return new Literal(stringValue.ToString(), 0, LiteralFormat.HexadecimalNumber); } - } else { - if (!ulong.TryParse(digit, NumberStyles.Integer, null, out result)) { + } + else + { + if (!ulong.TryParse(digit, NumberStyles.Integer, null, out result)) + { Error(y, x, String.Format("Can't parse integral constant {0}", digit)); return new Literal(stringValue.ToString(), 0, LiteralFormat.DecimalNumber); } } - if (result > long.MaxValue) { + if (result > long.MaxValue) + { islong = true; isunsigned = true; - } else if (result > uint.MaxValue) { + } + else if (result > uint.MaxValue) + { islong = true; - } else if (islong == false && result > int.MaxValue) { + } + else if (islong == false && result > int.MaxValue) + { isunsigned = true; } Literal token; LiteralFormat literalFormat = ishex ? LiteralFormat.HexadecimalNumber : LiteralFormat.DecimalNumber; - if (islong) { - if (isunsigned) { + if (islong) + { + if (isunsigned) + { ulong num; - if (ulong.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) { + if (ulong.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) + { token = new Literal(stringValue, num, literalFormat); - } else { + } + else + { Error(y, x, String.Format("Can't parse unsigned long {0}", digit)); token = new Literal(stringValue, 0UL, literalFormat); } - } else { + } + else + { long num; - if (long.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) { + if (long.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) + { token = new Literal(stringValue, num, literalFormat); - } else { + } + else + { Error(y, x, String.Format("Can't parse long {0}", digit)); token = new Literal(stringValue, 0L, literalFormat); } } - } else { - if (isunsigned) { + } + else + { + if (isunsigned) + { uint num; - if (uint.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) { + if (uint.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) + { token = new Literal(stringValue, num, literalFormat); - } else { + } + else + { Error(y, x, String.Format("Can't parse unsigned int {0}", digit)); token = new Literal(stringValue, (uint)0, literalFormat); } - } else { + } + else + { int num; - if (int.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) { + if (int.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) + { token = new Literal(stringValue, num, literalFormat); - } else { + } + else + { Error(y, x, String.Format("Can't parse int {0}", digit)); token = new Literal(stringValue, 0, literalFormat); } @@ -711,35 +841,46 @@ namespace ICSharpCode.ILSpy originalValue.Append('"'); bool doneNormally = false; int nextChar; - while ((nextChar = ReaderRead()) != -1) { + while ((nextChar = ReaderRead()) != -1) + { char ch = (char)nextChar; - if (ch == '"') { + if (ch == '"') + { doneNormally = true; originalValue.Append('"'); break; } - if (ch == '\\') { + if (ch == '\\') + { originalValue.Append('\\'); string surrogatePair; originalValue.Append(ReadEscapeSequence(out ch, out surrogatePair)); - if (surrogatePair != null) { + if (surrogatePair != null) + { sb.Append(surrogatePair); - } else { + } + else + { sb.Append(ch); } - } else if (HandleLineEnd(ch)) { + } + else if (HandleLineEnd(ch)) + { // call HandleLineEnd to ensure line numbers are still correct after the error Error(y, x, "No new line is allowed inside a string literal"); break; - } else { + } + else + { originalValue.Append(ch); sb.Append(ch); } } - if (!doneNormally) { + if (!doneNormally) + { Error(y, x, "End of file reached inside string literal"); } @@ -752,27 +893,35 @@ namespace ICSharpCode.ILSpy originalValue.Length = 0; originalValue.Append("@\""); int nextChar; - while ((nextChar = ReaderRead()) != -1) { + while ((nextChar = ReaderRead()) != -1) + { char ch = (char)nextChar; - if (ch == '"') { - if (ReaderPeek() != '"') { + if (ch == '"') + { + if (ReaderPeek() != '"') + { originalValue.Append('"'); break; } originalValue.Append("\"\""); sb.Append('"'); ReaderRead(); - } else if (HandleLineEnd(ch)) { + } + else if (HandleLineEnd(ch)) + { sb.Append("\r\n"); originalValue.Append("\r\n"); - } else { + } + else + { sb.Append(ch); originalValue.Append(ch); } } - if (nextChar == -1) { + if (nextChar == -1) + { Error(Line, Col, "End of file reached inside verbatim string literal"); } @@ -796,7 +945,8 @@ namespace ICSharpCode.ILSpy surrogatePair = null; int nextChar = ReaderRead(); - if (nextChar == -1) { + if (nextChar == -1) + { Error(Line, Col, "End of file reached inside escape sequence"); ch = '\0'; return String.Empty; @@ -805,7 +955,8 @@ namespace ICSharpCode.ILSpy char c = (char)nextChar; int curPos = 1; escapeSequenceBuffer[0] = c; - switch (c) { + switch (c) + { case '\'': ch = '\''; break; @@ -846,16 +997,21 @@ namespace ICSharpCode.ILSpy number = GetHexNumber(c); escapeSequenceBuffer[curPos++] = c; - if (number < 0) { + if (number < 0) + { Error(Line, Col - 1, String.Format("Invalid char in literal : {0}", c)); } - for (int i = 0; i < 3; ++i) { - if (IsHex((char)ReaderPeek())) { + for (int i = 0; i < 3; ++i) + { + if (IsHex((char)ReaderPeek())) + { c = (char)ReaderRead(); int idx = GetHexNumber(c); escapeSequenceBuffer[curPos++] = c; number = 16 * number + idx; - } else { + } + else + { break; } } @@ -864,21 +1020,28 @@ namespace ICSharpCode.ILSpy case 'U': // 32 bit unicode character number = 0; - for (int i = 0; i < 8; ++i) { - if (IsHex((char)ReaderPeek())) { + for (int i = 0; i < 8; ++i) + { + if (IsHex((char)ReaderPeek())) + { c = (char)ReaderRead(); int idx = GetHexNumber(c); escapeSequenceBuffer[curPos++] = c; number = 16 * number + idx; - } else { + } + else + { Error(Line, Col - 1, String.Format("Invalid char in literal : {0}", (char)ReaderPeek())); break; } } - if (number > 0xffff) { + if (number > 0xffff) + { ch = '\0'; surrogatePair = char.ConvertFromUtf32(number); - } else { + } + else + { ch = (char)number; } break; @@ -895,22 +1058,27 @@ namespace ICSharpCode.ILSpy int x = Col - 1; int y = Line; int nextChar = ReaderRead(); - if (nextChar == -1 || HandleLineEnd((char)nextChar)) { + if (nextChar == -1 || HandleLineEnd((char)nextChar)) + { return null; } char ch = (char)nextChar; char chValue = ch; string escapeSequence = String.Empty; - if (ch == '\\') { + if (ch == '\\') + { string surrogatePair; escapeSequence = ReadEscapeSequence(out chValue, out surrogatePair); - if (surrogatePair != null) { + if (surrogatePair != null) + { Error(y, x, "The unicode character must be represented by a surrogate pair and does not fit into a System.Char"); } } - unchecked { - if ((char)ReaderRead() != '\'') { + unchecked + { + if ((char)ReaderRead() != '\'') + { Error(y, x, "Char not terminated"); } } diff --git a/ILSpy/Languages/ILAstLanguage.cs b/ILSpy/Languages/ILAstLanguage.cs index 5c3917294..7d4156168 100644 --- a/ILSpy/Languages/ILAstLanguage.cs +++ b/ILSpy/Languages/ILAstLanguage.cs @@ -24,14 +24,15 @@ using System.Linq; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.Disassembler; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpy.ViewModels; -using SRM = System.Reflection.Metadata; using static System.Reflection.Metadata.PEReaderExtensions; -using ICSharpCode.ILSpy.ViewModels; + +using SRM = System.Reflection.Metadata; namespace ICSharpCode.ILSpy { @@ -51,12 +52,12 @@ namespace ICSharpCode.ILSpy public Stepper Stepper { get; set; } = new Stepper(); readonly string name; - + protected ILAstLanguage(string name) { this.name = name; } - + public override string Name { get { return name; } } internal static IEnumerable GetDebugLanguages() @@ -64,7 +65,7 @@ namespace ICSharpCode.ILSpy yield return new TypedIL(); yield return new BlockIL(CSharpDecompiler.GetILTransforms()); } - + public override string FileExtension { get { return ".il"; @@ -82,8 +83,8 @@ namespace ICSharpCode.ILSpy class TypedIL : ILAstLanguage { - public TypedIL() : base("Typed IL") {} - + public TypedIL() : base("Typed IL") { } + public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options) { base.DecompileMethod(method, output, options); @@ -125,16 +126,24 @@ namespace ICSharpCode.ILSpy ILTransformContext context = decompiler.CreateILTransformContext(il); context.Stepper.StepLimit = options.StepLimit; context.Stepper.IsDebug = options.IsDebug; - try { + try + { il.RunTransforms(transforms, context); - } catch (StepLimitReachedException) { - } catch (Exception ex) { + } + catch (StepLimitReachedException) + { + } + catch (Exception ex) + { output.WriteLine(ex.ToString()); output.WriteLine(); output.WriteLine("ILAst after the crash:"); - } finally { + } + finally + { // update stepper even if a transform crashed unexpectedly - if (options.StepLimit == int.MaxValue) { + if (options.StepLimit == int.MaxValue) + { Stepper = context.Stepper; OnStepperUpdated(new EventArgs()); } @@ -147,5 +156,5 @@ namespace ICSharpCode.ILSpy } } } - #endif +#endif } diff --git a/ILSpy/Languages/ILLanguage.cs b/ILSpy/Languages/ILLanguage.cs index 7e8365a7d..d88085699 100644 --- a/ILSpy/Languages/ILLanguage.cs +++ b/ILSpy/Languages/ILLanguage.cs @@ -17,16 +17,17 @@ // DEALINGS IN THE SOFTWARE. using System.Collections.Generic; -using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; using System.ComponentModel.Composition; -using System.Reflection.Metadata; using System.Linq; +using System.Reflection.Metadata; + +using ICSharpCode.AvalonEdit.Highlighting; +using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; -using ICSharpCode.Decompiler.Solution; -using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.ILSpy.TextView; namespace ICSharpCode.ILSpy @@ -42,15 +43,15 @@ namespace ICSharpCode.ILSpy public class ILLanguage : Language { protected bool detectControlStructure = true; - + public override string Name { get { return "IL"; } } - + public override string FileExtension { get { return ".il"; } } - + protected virtual ReflectionDisassembler CreateDisassembler(ITextOutput output, DecompilationOptions options) { output.IndentationString = options.DecompilerSettings.CSharpFormattingOptions.IndentationString; @@ -71,7 +72,7 @@ namespace ICSharpCode.ILSpy dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleMethod(module, (MethodDefinitionHandle)method.MetadataToken); } - + public override void DecompileField(IField field, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); @@ -80,7 +81,7 @@ namespace ICSharpCode.ILSpy dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleField(module, (FieldDefinitionHandle)field.MetadataToken); } - + public override void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); @@ -91,11 +92,13 @@ namespace ICSharpCode.ILSpy var pd = module.Metadata.GetPropertyDefinition((PropertyDefinitionHandle)property.MetadataToken); var accessors = pd.GetAccessors(); - if (!accessors.Getter.IsNil) { + if (!accessors.Getter.IsNil) + { output.WriteLine(); dis.DisassembleMethod(module, accessors.Getter); } - if (!accessors.Setter.IsNil) { + if (!accessors.Setter.IsNil) + { output.WriteLine(); dis.DisassembleMethod(module, accessors.Setter); } @@ -104,7 +107,7 @@ namespace ICSharpCode.ILSpy dis.DisassembleMethod(m); }*/ } - + public override void DecompileEvent(IEvent ev, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); @@ -115,15 +118,18 @@ namespace ICSharpCode.ILSpy var ed = ((MetadataReader)module.Metadata).GetEventDefinition((EventDefinitionHandle)ev.MetadataToken); var accessors = ed.GetAccessors(); - if (!accessors.Adder.IsNil) { + if (!accessors.Adder.IsNil) + { output.WriteLine(); dis.DisassembleMethod(module, accessors.Adder); } - if (!accessors.Remover.IsNil) { + if (!accessors.Remover.IsNil) + { output.WriteLine(); dis.DisassembleMethod(module, accessors.Remover); } - if (!accessors.Raiser.IsNil) { + if (!accessors.Raiser.IsNil) + { output.WriteLine(); dis.DisassembleMethod(module, accessors.Raiser); } @@ -132,7 +138,7 @@ namespace ICSharpCode.ILSpy dis.DisassembleMethod(m); }*/ } - + public override void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options) { var dis = CreateDisassembler(output, options); @@ -150,7 +156,7 @@ namespace ICSharpCode.ILSpy dis.DebugInfo = module.GetDebugInfoOrNull(); dis.DisassembleNamespace(nameSpace, module, types.Select(t => (TypeDefinitionHandle)t.MetadataToken)); } - + public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { output.WriteLine("// " + assembly.FileName); @@ -160,7 +166,8 @@ namespace ICSharpCode.ILSpy var dis = CreateDisassembler(output, options); // don't automatically load additional assemblies when an assembly node is selected in the tree view - using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad(assembly.AssemblyList)) { + using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad(assembly.AssemblyList)) + { dis.AssemblyResolver = module.GetAssemblyResolver(); dis.DebugInfo = module.GetDebugInfoOrNull(); if (options.FullDecompilation) @@ -169,7 +176,8 @@ namespace ICSharpCode.ILSpy dis.WriteAssemblyHeader(module); output.WriteLine(); dis.WriteModuleHeader(module); - if (options.FullDecompilation) { + if (options.FullDecompilation) + { output.WriteLine(); output.WriteLine(); dis.WriteModuleContents(module); @@ -182,7 +190,8 @@ namespace ICSharpCode.ILSpy { var output = new AvalonEditTextOutput() { IgnoreNewLineAndIndent = true }; var disasm = CreateDisassembler(output, new DecompilationOptions()); - switch (entity.SymbolKind) { + switch (entity.SymbolKind) + { case SymbolKind.TypeDefinition: disasm.DisassembleTypeHeader(entity.ParentModule.PEFile, (TypeDefinitionHandle)entity.MetadataToken); break; diff --git a/ILSpy/Languages/Language.cs b/ILSpy/Languages/Language.cs index 98d6b40db..25fa64e85 100644 --- a/ILSpy/Languages/Language.cs +++ b/ILSpy/Languages/Language.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Text; + using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; @@ -68,8 +69,7 @@ namespace ICSharpCode.ILSpy /// public abstract string FileExtension { get; } - public virtual string ProjectFileExtension - { + public virtual string ProjectFileExtension { get { return null; } } @@ -82,10 +82,8 @@ namespace ICSharpCode.ILSpy /// /// Gets the syntax highlighting used for this language. /// - public virtual ICSharpCode.AvalonEdit.Highlighting.IHighlightingDefinition SyntaxHighlighting - { - get - { + public virtual ICSharpCode.AvalonEdit.Highlighting.IHighlightingDefinition SyntaxHighlighting { + get { return ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance.GetDefinitionByExtension(this.FileExtension); } } @@ -130,16 +128,23 @@ namespace ICSharpCode.ILSpy { WriteCommentLine(output, assembly.FileName); var asm = assembly.GetPEFileOrNull(); - if (asm == null) return null; + if (asm == null) + return null; var metadata = asm.Metadata; - if (metadata.IsAssembly) { + if (metadata.IsAssembly) + { var name = metadata.GetAssemblyDefinition(); - if ((name.Flags & System.Reflection.AssemblyFlags.WindowsRuntime) != 0) { + if ((name.Flags & System.Reflection.AssemblyFlags.WindowsRuntime) != 0) + { WriteCommentLine(output, metadata.GetString(name.Name) + " [WinRT]"); - } else { + } + else + { WriteCommentLine(output, metadata.GetFullAssemblyName()); } - } else { + } + else + { WriteCommentLine(output, metadata.GetString(metadata.GetModuleDefinition().Name)); } return null; @@ -229,7 +234,8 @@ namespace ICSharpCode.ILSpy { type.GenericType.AcceptVisitor(this); builder.Append('<'); - for (int i = 0; i < type.TypeArguments.Count; i++) { + for (int i = 0; i < type.TypeArguments.Count; i++) + { if (i > 0) builder.Append(','); type.TypeArguments[i].AcceptVisitor(this); @@ -256,7 +262,8 @@ namespace ICSharpCode.ILSpy EscapeName(builder, type.FullName); else EscapeName(builder, type.Name); - if (type.TypeParameterCount > 0) { + if (type.TypeParameterCount > 0) + { builder.Append('`'); builder.Append(type.TypeParameterCount); } @@ -264,7 +271,8 @@ namespace ICSharpCode.ILSpy public override IType VisitTypeDefinition(ITypeDefinition type) { - switch (type.KnownTypeCode) { + switch (type.KnownTypeCode) + { case KnownTypeCode.Object: builder.Append("object"); break; @@ -369,11 +377,13 @@ namespace ICSharpCode.ILSpy var buffer = new StringBuilder(); buffer.Append(GetDisplayName(method, includeDeclaringTypeName, includeNamespace, includeNamespaceOfDeclaringTypeName)); var typeParameters = method.TypeParameters; - if (typeParameters.Count > 0) { + if (typeParameters.Count > 0) + { buffer.Append("``"); buffer.Append(typeParameters.Count); buffer.Append('<'); - foreach (var tp in typeParameters) { + foreach (var tp in typeParameters) + { if (i > 0) buffer.Append(", "); buffer.Append(tp.Name); @@ -385,14 +395,16 @@ namespace ICSharpCode.ILSpy i = 0; var parameters = method.Parameters; - foreach (var param in parameters) { + foreach (var param in parameters) + { if (i > 0) buffer.Append(", "); buffer.Append(TypeToString(param.Type, includeNamespace)); i++; } buffer.Append(')'); - if (!method.IsConstructor) { + if (!method.IsConstructor) + { buffer.Append(" : "); buffer.Append(TypeToString(method.ReturnType, includeNamespace)); } @@ -413,18 +425,24 @@ namespace ICSharpCode.ILSpy protected string GetDisplayName(IEntity entity, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName) { string entityName; - if (entity is ITypeDefinition t && !t.MetadataToken.IsNil) { + if (entity is ITypeDefinition t && !t.MetadataToken.IsNil) + { MetadataReader metadata = t.ParentModule.PEFile.Metadata; var typeDef = metadata.GetTypeDefinition((TypeDefinitionHandle)t.MetadataToken); entityName = EscapeName(metadata.GetString(typeDef.Name)); - } else { + } + else + { entityName = EscapeName(entity.Name); } - if (includeNamespace || includeDeclaringTypeName) { + if (includeNamespace || includeDeclaringTypeName) + { if (entity.DeclaringTypeDefinition != null) return TypeToString(entity.DeclaringTypeDefinition, includeNamespaceOfDeclaringTypeName) + "." + entityName; return EscapeName(entity.Namespace) + "." + entityName; - } else { + } + else + { return entityName; } } @@ -448,7 +466,8 @@ namespace ICSharpCode.ILSpy public virtual string GetEntityName(PEFile module, EntityHandle handle, bool fullName, bool omitGenerics) { MetadataReader metadata = module.Metadata; - switch (handle.Kind) { + switch (handle.Kind) + { case HandleKind.TypeDefinition: if (fullName) return EscapeName(((TypeDefinitionHandle)handle).GetFullTypeName(metadata).ToILNameString(omitGenerics)); @@ -462,10 +481,11 @@ namespace ICSharpCode.ILSpy case HandleKind.MethodDefinition: var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle); string methodName = metadata.GetString(md.Name); - if (!omitGenerics) { + if (!omitGenerics) + { int genericParamCount = md.GetGenericParameters().Count; if (genericParamCount > 0) - methodName += "``" + genericParamCount; + methodName += "``" + genericParamCount; } if (fullName) return EscapeName(md.GetDeclaringType().GetFullTypeName(metadata).ToILNameString(omitGenerics) + "." + methodName); @@ -491,7 +511,8 @@ namespace ICSharpCode.ILSpy { var declaringType = member.GetDeclaringType(module.Metadata); - if (declaringType.IsNil && member.Kind == SRM.HandleKind.TypeDefinition) { + if (declaringType.IsNil && member.Kind == SRM.HandleKind.TypeDefinition) + { declaringType = (SRM.TypeDefinitionHandle)member; } @@ -504,7 +525,8 @@ namespace ICSharpCode.ILSpy var architecture = headers.CoffHeader.Machine; var characteristics = headers.CoffHeader.Characteristics; var corflags = headers.CorHeader.Flags; - switch (architecture) { + switch (architecture) + { case Machine.I386: if ((corflags & CorFlags.Prefers32Bit) != 0) return "AnyCPU (32-bit preferred)"; @@ -534,7 +556,8 @@ namespace ICSharpCode.ILSpy /// public static StringBuilder EscapeName(StringBuilder sb, string name) { - foreach (char ch in name) { + foreach (char ch in name) + { if (char.IsWhiteSpace(ch) || char.IsControl(ch) || char.IsSurrogate(ch)) sb.AppendFormat("\\u{0:x4}", (int)ch); else diff --git a/ILSpy/Languages/Languages.cs b/ILSpy/Languages/Languages.cs index f8c70f46a..5721f0e72 100644 --- a/ILSpy/Languages/Languages.cs +++ b/ILSpy/Languages/Languages.cs @@ -35,8 +35,7 @@ namespace ICSharpCode.ILSpy /// /// A list of all languages. /// - public static ReadOnlyCollection AllLanguages - { + public static ReadOnlyCollection AllLanguages { get { return allLanguages; } } @@ -45,10 +44,10 @@ namespace ICSharpCode.ILSpy List languages = new List(); languages.AddRange(ep.GetExportedValues()); languages.Sort((a, b) => a.Name.CompareTo(b.Name)); - #if DEBUG +#if DEBUG languages.AddRange(ILAstLanguage.GetDebugLanguages()); languages.AddRange(CSharpLanguage.GetDebugLanguages()); - #endif +#endif allLanguages = languages.AsReadOnly(); } @@ -64,7 +63,8 @@ namespace ICSharpCode.ILSpy static ILLanguage ilLanguage; public static ILLanguage ILLanguage { get { - if (ilLanguage == null) { + if (ilLanguage == null) + { ilLanguage = (ILLanguage)GetLanguage("IL"); } return ilLanguage; diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs index 60c37eefe..6f65d8483 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ILSpy/LoadedAssembly.cs @@ -90,9 +90,12 @@ namespace ICSharpCode.ILSpy /// public PEFile GetPEFileOrNull() { - try { + try + { return GetPEFileAsync().GetAwaiter().GetResult(); - } catch (Exception ex) { + } + catch (Exception ex) + { System.Diagnostics.Trace.TraceError(ex.ToString()); return null; } @@ -143,24 +146,31 @@ namespace ICSharpCode.ILSpy public string Text { get { - if (IsLoaded && !HasLoadError) { + if (IsLoaded && !HasLoadError) + { PEFile module = GetPEFileOrNull(); var metadata = module?.Metadata; string versionOrInfo = null; - if (metadata != null) { - if (metadata.IsAssembly) { + if (metadata != null) + { + if (metadata.IsAssembly) + { versionOrInfo = metadata.GetAssemblyDefinition().Version?.ToString(); var tfId = GetTargetFrameworkIdAsync().Result; if (!string.IsNullOrEmpty(tfId)) versionOrInfo += ", " + tfId.Replace("Version=", " "); - } else { + } + else + { versionOrInfo = ".netmodule"; } } if (versionOrInfo == null) return ShortName; return string.Format("{0} ({1})", ShortName, versionOrInfo); - } else { + } + else + { return ShortName; } } @@ -177,36 +187,51 @@ namespace ICSharpCode.ILSpy PEFile LoadAssembly(object state) { MetadataReaderOptions options; - if (DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections) { + if (DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections) + { options = MetadataReaderOptions.ApplyWindowsRuntimeProjections; - } else { + } + else + { options = MetadataReaderOptions.None; } PEFile module; // runs on background thread - if (state is Stream stream) { + if (state is Stream stream) + { // Read the module from a precrafted stream var streamOptions = stream is MemoryStream ? PEStreamOptions.PrefetchEntireImage : PEStreamOptions.Default; module = new PEFile(fileName, stream, streamOptions, metadataOptions: options); - } else { + } + else + { // Read the module from disk (by default) stream = new FileStream(fileName, FileMode.Open, FileAccess.Read); module = new PEFile(fileName, stream, PEStreamOptions.PrefetchEntireImage, metadataOptions: options); } - if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) { - try { + if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) + { + try + { debugInfoProvider = DebugInfoUtils.FromFile(module, PdbFileOverride) ?? DebugInfoUtils.LoadSymbols(module); - } catch (IOException) { - } catch (UnauthorizedAccessException) { - } catch (InvalidOperationException) { + } + catch (IOException) + { + } + catch (UnauthorizedAccessException) + { + } + catch (InvalidOperationException) + { // ignore any errors during symbol loading } } - lock (loadedAssemblies) { + lock (loadedAssemblies) + { loadedAssemblies.Add(module, this); } return module; @@ -239,7 +264,8 @@ namespace ICSharpCode.ILSpy public void Dispose() { - if (!disposed) { + if (!disposed) + { disposed = true; assemblyLoadDisableCount--; // clear the lookup cache since we might have stored the lookups failed due to DisableAssemblyLoad() @@ -295,9 +321,12 @@ namespace ICSharpCode.ILSpy if (reference == null) throw new ArgumentNullException(nameof(reference)); var tfm = GetTargetFrameworkIdAsync().Result; - if (reference.IsWindowsRuntime) { + if (reference.IsWindowsRuntime) + { return assemblyList.assemblyLookupCache.GetOrAdd((reference.Name, true, tfm), key => LookupReferencedAssemblyInternal(reference, true, tfm)); - } else { + } + else + { return assemblyList.assemblyLookupCache.GetOrAdd((reference.FullName, false, tfm), key => LookupReferencedAssemblyInternal(reference, false, tfm)); } } @@ -339,27 +368,34 @@ namespace ICSharpCode.ILSpy string file; LoadedAssembly asm; - lock (loadingAssemblies) { - foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) { + lock (loadingAssemblies) + { + foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) + { var module = loaded.GetPEFileOrNull(); var reader = module?.Metadata; - if (reader == null || !reader.IsAssembly) continue; + if (reader == null || !reader.IsAssembly) + continue; var asmDef = reader.GetAssemblyDefinition(); var asmDefName = loaded.GetTargetFrameworkIdAsync().Result + ";" + (isWinRT ? reader.GetString(asmDef.Name) : reader.GetFullAssemblyName()); - if (key.Equals(asmDefName, StringComparison.OrdinalIgnoreCase)) { + if (key.Equals(asmDefName, StringComparison.OrdinalIgnoreCase)) + { LoadedAssemblyReferencesInfo.AddMessageOnce(fullName.FullName, MessageKind.Info, "Success - Found in Assembly List"); return loaded; } } - if (universalResolver == null) { + if (universalResolver == null) + { universalResolver = new MyUniversalResolver(this); } file = universalResolver.FindAssemblyFile(fullName); - foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) { - if (loaded.FileName.Equals(file, StringComparison.OrdinalIgnoreCase)) { + foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) + { + if (loaded.FileName.Equals(file, StringComparison.OrdinalIgnoreCase)) + { return loaded; } } @@ -370,24 +406,31 @@ namespace ICSharpCode.ILSpy if (assemblyLoadDisableCount > 0) return null; - if (file != null) { + if (file != null) + { LoadedAssemblyReferencesInfo.AddMessage(fullName.ToString(), MessageKind.Info, "Success - Loading from: " + file); asm = new LoadedAssembly(assemblyList, file) { IsAutoLoaded = true }; - } else { + } + else + { var candidates = new List<(LoadedAssembly assembly, Version version)>(); - foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) { + foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) + { var module = loaded.GetPEFileOrNull(); var reader = module?.Metadata; - if (reader == null || !reader.IsAssembly) continue; + if (reader == null || !reader.IsAssembly) + continue; var asmDef = reader.GetAssemblyDefinition(); var asmDefName = reader.GetString(asmDef.Name); - if (fullName.Name.Equals(asmDefName, StringComparison.OrdinalIgnoreCase)) { + if (fullName.Name.Equals(asmDefName, StringComparison.OrdinalIgnoreCase)) + { candidates.Add((loaded, asmDef.Version)); } } - if (candidates.Count == 0) { + if (candidates.Count == 0) + { LoadedAssemblyReferencesInfo.AddMessageOnce(fullName.ToString(), MessageKind.Error, "Could not find reference: " + fullName); return null; } @@ -401,10 +444,12 @@ namespace ICSharpCode.ILSpy loadingAssemblies.Add(file, asm); } App.Current.Dispatcher.BeginInvoke((Action)delegate () { - lock (assemblyList.assemblies) { + lock (assemblyList.assemblies) + { assemblyList.assemblies.Add(asm); } - lock (loadingAssemblies) { + lock (loadingAssemblies) + { loadingAssemblies.Remove(file); } }, DispatcherPriority.Normal); @@ -415,12 +460,16 @@ namespace ICSharpCode.ILSpy { string file; LoadedAssembly asm; - lock (loadingAssemblies) { - foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) { + lock (loadingAssemblies) + { + foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) + { var reader = loaded.GetPEFileOrNull()?.Metadata; - if (reader == null || reader.IsAssembly) continue; + if (reader == null || reader.IsAssembly) + continue; var moduleDef = reader.GetModuleDefinition(); - if (moduleName.Equals(reader.GetString(moduleDef.Name), StringComparison.OrdinalIgnoreCase)) { + if (moduleName.Equals(reader.GetString(moduleDef.Name), StringComparison.OrdinalIgnoreCase)) + { LoadedAssemblyReferencesInfo.AddMessageOnce(moduleName, MessageKind.Info, "Success - Found in Assembly List"); return loaded; } @@ -430,8 +479,10 @@ namespace ICSharpCode.ILSpy if (!File.Exists(file)) return null; - foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) { - if (loaded.FileName.Equals(file, StringComparison.OrdinalIgnoreCase)) { + foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) + { + if (loaded.FileName.Equals(file, StringComparison.OrdinalIgnoreCase)) + { return loaded; } } @@ -442,20 +493,25 @@ namespace ICSharpCode.ILSpy if (assemblyLoadDisableCount > 0) return null; - if (file != null) { + if (file != null) + { LoadedAssemblyReferencesInfo.AddMessage(moduleName, MessageKind.Info, "Success - Loading from: " + file); asm = new LoadedAssembly(assemblyList, file) { IsAutoLoaded = true }; - } else { + } + else + { LoadedAssemblyReferencesInfo.AddMessageOnce(moduleName, MessageKind.Error, "Could not find reference: " + moduleName); return null; } loadingAssemblies.Add(file, asm); } App.Current.Dispatcher.BeginInvoke((Action)delegate () { - lock (assemblyList.assemblies) { + lock (assemblyList.assemblies) + { assemblyList.assemblies.Add(asm); } - lock (loadingAssemblies) { + lock (loadingAssemblies) + { loadingAssemblies.Remove(file); } }); diff --git a/ILSpy/LoadedAssemblyExtensions.cs b/ILSpy/LoadedAssemblyExtensions.cs index f2b9c15ed..0e11707c7 100644 --- a/ILSpy/LoadedAssemblyExtensions.cs +++ b/ILSpy/LoadedAssemblyExtensions.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -55,7 +56,8 @@ namespace ICSharpCode.ILSpy if (file == null) throw new ArgumentNullException(nameof(file)); LoadedAssembly loadedAssembly; - lock (LoadedAssembly.loadedAssemblies) { + lock (LoadedAssembly.loadedAssemblies) + { if (!LoadedAssembly.loadedAssemblies.TryGetValue(file, out loadedAssembly)) throw new ArgumentException("The specified file is not associated with a LoadedAssembly!"); } diff --git a/ILSpy/LoadedNugetPackage.cs b/ILSpy/LoadedNugetPackage.cs index c96469723..e685409b2 100644 --- a/ILSpy/LoadedNugetPackage.cs +++ b/ILSpy/LoadedNugetPackage.cs @@ -18,13 +18,13 @@ using System; using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.IO.Compression; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; -using System.IO.Compression; -using System.IO; -using System.ComponentModel; -using System.Runtime.CompilerServices; namespace ICSharpCode.ILSpy { @@ -35,9 +35,12 @@ namespace ICSharpCode.ILSpy public LoadedNugetPackage(string file) { - using (var archive = ZipFile.OpenRead(file)) { - foreach (var entry in archive.Entries) { - switch (Path.GetExtension(entry.FullName)) { + using (var archive = ZipFile.OpenRead(file)) + { + foreach (var entry in archive.Entries) + { + switch (Path.GetExtension(entry.FullName)) + { case ".dll": case ".exe": var memory = new MemoryStream(); @@ -54,7 +57,8 @@ namespace ICSharpCode.ILSpy void EntryPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == nameof(Entry.IsSelected)) { + if (e.PropertyName == nameof(Entry.IsSelected)) + { var entry = (Entry)sender; if (entry.IsSelected) SelectedEntries.Add(entry); @@ -84,7 +88,8 @@ namespace ICSharpCode.ILSpy public bool IsSelected { get { return isSelected; } set { - if (isSelected != value) { + if (isSelected != value) + { isSelected = value; OnPropertyChanged(); } diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 10bd97d47..fcb1624af 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -35,6 +35,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.Metadata; @@ -46,8 +47,11 @@ using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.TreeView; + using Microsoft.Win32; + using OSVersionHelper; + using Xceed.Wpf.AvalonDock.Layout.Serialization; namespace ICSharpCode.ILSpy @@ -135,7 +139,8 @@ namespace ICSharpCode.ILSpy private void SessionSettings_PropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == "ActiveAssemblyList") { + if (e.PropertyName == "ActiveAssemblyList") + { ShowAssemblyList(sessionSettings.ActiveAssemblyList); } } @@ -155,19 +160,28 @@ namespace ICSharpCode.ILSpy int navigationPos = 0; int openPos = 1; var toolbarCommands = App.ExportProvider.GetExports("ToolbarCommand"); - foreach (var commandGroup in toolbarCommands.OrderBy(c => c.Metadata.ToolbarOrder).GroupBy(c => Properties.Resources.ResourceManager.GetString(c.Metadata.ToolbarCategory))) { - if (commandGroup.Key == Properties.Resources.ResourceManager.GetString("Navigation")) { - foreach (var command in commandGroup) { + foreach (var commandGroup in toolbarCommands.OrderBy(c => c.Metadata.ToolbarOrder).GroupBy(c => Properties.Resources.ResourceManager.GetString(c.Metadata.ToolbarCategory))) + { + if (commandGroup.Key == Properties.Resources.ResourceManager.GetString("Navigation")) + { + foreach (var command in commandGroup) + { toolBar.Items.Insert(navigationPos++, MakeToolbarItem(command)); openPos++; } - } else if (commandGroup.Key == Properties.Resources.ResourceManager.GetString("Open")) { - foreach (var command in commandGroup) { + } + else if (commandGroup.Key == Properties.Resources.ResourceManager.GetString("Open")) + { + foreach (var command in commandGroup) + { toolBar.Items.Insert(openPos++, MakeToolbarItem(command)); } - } else { + } + else + { toolBar.Items.Add(new Separator()); - foreach (var command in commandGroup) { + foreach (var command in commandGroup) + { toolBar.Items.Add(MakeToolbarItem(command)); } } @@ -195,22 +209,29 @@ namespace ICSharpCode.ILSpy void InitMainMenu() { var mainMenuCommands = App.ExportProvider.GetExports("MainMenuCommand"); - foreach (var topLevelMenu in mainMenuCommands.OrderBy(c => c.Metadata.MenuOrder).GroupBy(c => GetResourceString(c.Metadata.Menu))) { + foreach (var topLevelMenu in mainMenuCommands.OrderBy(c => c.Metadata.MenuOrder).GroupBy(c => GetResourceString(c.Metadata.Menu))) + { var topLevelMenuItem = mainMenu.Items.OfType().FirstOrDefault(m => (GetResourceString(m.Header as string)) == topLevelMenu.Key); - foreach (var category in topLevelMenu.GroupBy(c => GetResourceString(c.Metadata.MenuCategory))) { - if (topLevelMenuItem == null) { + foreach (var category in topLevelMenu.GroupBy(c => GetResourceString(c.Metadata.MenuCategory))) + { + if (topLevelMenuItem == null) + { topLevelMenuItem = new MenuItem(); topLevelMenuItem.Header = GetResourceString(topLevelMenu.Key); mainMenu.Items.Add(topLevelMenuItem); - } else if (topLevelMenuItem.Items.Count > 0) { + } + else if (topLevelMenuItem.Items.Count > 0) + { topLevelMenuItem.Items.Add(new Separator()); } - foreach (var entry in category) { + foreach (var entry in category) + { MenuItem menuItem = new MenuItem(); menuItem.Command = CommandWrapper.Unwrap(entry.Value); if (!string.IsNullOrEmpty(GetResourceString(entry.Metadata.Header))) menuItem.Header = GetResourceString(entry.Metadata.Header); - if (!string.IsNullOrEmpty(entry.Metadata.MenuIcon)) { + if (!string.IsNullOrEmpty(entry.Metadata.MenuIcon)) + { menuItem.Icon = new Image { Width = 16, Height = 16, @@ -246,7 +267,8 @@ namespace ICSharpCode.ILSpy Type = typeof(LegacyToolPaneModel), Template = (DataTemplate)FindResource("DefaultContentTemplate") }); - foreach (var toolPane in toolPanes) { + foreach (var toolPane in toolPanes) + { ToolPaneModel model = toolPane.Value; templateSelector.Mappings.Add(new TemplateMapping { Type = model.GetType(), Template = model.Template }); DockWorkspace.Instance.ToolPanes.Add(model); @@ -257,7 +279,8 @@ namespace ICSharpCode.ILSpy public void ShowInTopPane(string title, object content) { var model = DockWorkspace.Instance.ToolPanes.OfType().FirstOrDefault(p => p.Content == content); - if (model == null) { + if (model == null) + { model = new LegacyToolPaneModel(title, content, LegacyToolPaneLocation.Top); DockWorkspace.Instance.ToolPanes.Add(model); } @@ -267,7 +290,8 @@ namespace ICSharpCode.ILSpy public void ShowInBottomPane(string title, object content) { var model = DockWorkspace.Instance.ToolPanes.OfType().FirstOrDefault(p => p.Content == content); - if (model == null) { + if (model == null) + { model = new LegacyToolPaneModel(title, content, LegacyToolPaneLocation.Bottom); DockWorkspace.Instance.ToolPanes.Add(model); } @@ -281,14 +305,16 @@ namespace ICSharpCode.ILSpy base.OnSourceInitialized(e); PresentationSource source = PresentationSource.FromVisual(this); HwndSource hwndSource = source as HwndSource; - if (hwndSource != null) { + if (hwndSource != null) + { hwndSource.AddHook(WndProc); } // Validate and Set Window Bounds Rect bounds = Rect.Transform(sessionSettings.WindowBounds, source.CompositionTarget.TransformToDevice); var boundsRect = new System.Drawing.Rectangle((int)bounds.Left, (int)bounds.Top, (int)bounds.Width, (int)bounds.Height); bool boundsOK = false; - foreach (var screen in System.Windows.Forms.Screen.AllScreens) { + foreach (var screen in System.Windows.Forms.Screen.AllScreens) + { var intersection = System.Drawing.Rectangle.Intersect(boundsRect, screen.WorkingArea); if (intersection.Width > 10 && intersection.Height > 10) boundsOK = true; @@ -303,21 +329,25 @@ namespace ICSharpCode.ILSpy unsafe IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { - if (msg == NativeMethods.WM_COPYDATA) { + if (msg == NativeMethods.WM_COPYDATA) + { CopyDataStruct* copyData = (CopyDataStruct*)lParam; string data = new string((char*)copyData->Buffer, 0, copyData->Size / sizeof(char)); - if (data.StartsWith("ILSpy:\r\n", StringComparison.Ordinal)) { + if (data.StartsWith("ILSpy:\r\n", StringComparison.Ordinal)) + { if (handlingNugetPackageSelection) return (IntPtr)1; data = data.Substring(8); List lines = new List(); - using (StringReader r = new StringReader(data)) { + using (StringReader r = new StringReader(data)) + { string line; while ((line = r.ReadLine()) != null) lines.Add(line); } var args = new CommandLineArguments(lines); - if (HandleCommandLineArguments(args)) { + if (HandleCommandLineArguments(args)) + { if (!args.NoActivate && WindowState == WindowState.Minimized) WindowState = WindowState.Normal; HandleCommandLineArgumentsAfterShowList(args); @@ -343,12 +373,16 @@ namespace ICSharpCode.ILSpy bool HandleCommandLineArguments(CommandLineArguments args) { int i = 0; - while (i < args.AssembliesToLoad.Count) { + while (i < args.AssembliesToLoad.Count) + { var asm = args.AssembliesToLoad[i]; - if (Path.GetExtension(asm) == ".nupkg") { + if (Path.GetExtension(asm) == ".nupkg") + { nugetPackagesToLoad.Add(asm); args.AssembliesToLoad.RemoveAt(i); - } else { + } + else + { i++; } } @@ -364,7 +398,8 @@ namespace ICSharpCode.ILSpy /// void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args, ILSpySettings spySettings = null) { - if (nugetPackagesToLoad.Count > 0) { + if (nugetPackagesToLoad.Count > 0) + { var relevantPackages = nugetPackagesToLoad.ToArray(); nugetPackagesToLoad.Clear(); // Show the nuget package open dialog after the command line/window message was processed. @@ -373,7 +408,8 @@ namespace ICSharpCode.ILSpy var relevantAssemblies = commandLineLoadedAssemblies.ToList(); commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies); - if (args.Search != null) { + if (args.Search != null) + { SearchPane.SearchTerm = args.Search; SearchPane.Show(); } @@ -382,59 +418,80 @@ namespace ICSharpCode.ILSpy async void NavigateOnLaunch(string navigateTo, string[] activeTreeViewPath, ILSpySettings spySettings, List relevantAssemblies) { var initialSelection = AssemblyTreeView.SelectedItem; - if (navigateTo != null) { + if (navigateTo != null) + { bool found = false; - if (navigateTo.StartsWith("N:", StringComparison.Ordinal)) { + if (navigateTo.StartsWith("N:", StringComparison.Ordinal)) + { string namespaceName = navigateTo.Substring(2); - foreach (LoadedAssembly asm in relevantAssemblies) { + foreach (LoadedAssembly asm in relevantAssemblies) + { AssemblyTreeNode asmNode = assemblyListTreeNode.FindAssemblyNode(asm); - if (asmNode != null) { + if (asmNode != null) + { // FindNamespaceNode() blocks the UI if the assembly is not yet loaded, // so use an async wait instead. await asm.GetPEFileAsync().Catch(ex => { }); NamespaceTreeNode nsNode = asmNode.FindNamespaceNode(namespaceName); - if (nsNode != null) { + if (nsNode != null) + { found = true; - if (AssemblyTreeView.SelectedItem == initialSelection) { + if (AssemblyTreeView.SelectedItem == initialSelection) + { SelectNode(nsNode); } break; } } } - } else if (navigateTo == "none") { + } + else if (navigateTo == "none") + { // Don't navigate anywhere; start empty. // Used by ILSpy VS addin, it'll send us the real location to navigate to via IPC. found = true; - } else { + } + else + { IEntity mr = await Task.Run(() => FindEntityInRelevantAssemblies(navigateTo, relevantAssemblies)); // Make sure we wait for assemblies being loaded... // BeginInvoke in LoadedAssembly.LookupReferencedAssemblyInternal await Dispatcher.InvokeAsync(delegate { }, DispatcherPriority.Normal); - if (mr != null && mr.ParentModule.PEFile != null) { + if (mr != null && mr.ParentModule.PEFile != null) + { found = true; - if (AssemblyTreeView.SelectedItem == initialSelection) { + if (AssemblyTreeView.SelectedItem == initialSelection) + { JumpToReference(mr); } } } - if (!found && AssemblyTreeView.SelectedItem == initialSelection) { + if (!found && AssemblyTreeView.SelectedItem == initialSelection) + { AvalonEditTextOutput output = new AvalonEditTextOutput(); output.Write(string.Format("Cannot find '{0}' in command line specified assemblies.", navigateTo)); DockWorkspace.Instance.ShowText(output); } - } else if (relevantAssemblies.Count == 1) { + } + else if (relevantAssemblies.Count == 1) + { // NavigateTo == null and an assembly was given on the command-line: // Select the newly loaded assembly AssemblyTreeNode asmNode = assemblyListTreeNode.FindAssemblyNode(relevantAssemblies[0]); - if (asmNode != null && AssemblyTreeView.SelectedItem == initialSelection) { + if (asmNode != null && AssemblyTreeView.SelectedItem == initialSelection) + { SelectNode(asmNode); } - } else if (spySettings != null) { + } + else if (spySettings != null) + { SharpTreeNode node = null; - if (activeTreeViewPath?.Length > 0) { - foreach (var asm in CurrentAssemblyList.GetAssemblies()) { - if (asm.FileName == activeTreeViewPath[0]) { + if (activeTreeViewPath?.Length > 0) + { + foreach (var asm in CurrentAssemblyList.GetAssemblies()) + { + if (asm.FileName == activeTreeViewPath[0]) + { // FindNodeByPath() blocks the UI if the assembly is not yet loaded, // so use an async wait instead. await asm.GetPEFileAsync().Catch(ex => { }); @@ -442,13 +499,17 @@ namespace ICSharpCode.ILSpy } node = FindNodeByPath(activeTreeViewPath, true); } - if (AssemblyTreeView.SelectedItem == initialSelection) { - if (node != null) { + if (AssemblyTreeView.SelectedItem == initialSelection) + { + if (node != null) + { SelectNode(node); // only if not showing the about page, perform the update check: await ShowMessageIfUpdatesAvailableAsync(spySettings); - } else { + } + else + { DockWorkspace.Instance.ActiveTabPage.ShowTextView(AboutPage.Display); } } @@ -459,15 +520,20 @@ namespace ICSharpCode.ILSpy { ITypeReference typeRef = null; IMemberReference memberRef = null; - if (navigateTo.StartsWith("T:", StringComparison.Ordinal)) { + if (navigateTo.StartsWith("T:", StringComparison.Ordinal)) + { typeRef = IdStringProvider.ParseTypeName(navigateTo); - } else { + } + else + { memberRef = IdStringProvider.ParseMemberIdString(navigateTo); typeRef = memberRef.DeclaringTypeReference; } - foreach (LoadedAssembly asm in relevantAssemblies.ToList()) { + foreach (LoadedAssembly asm in relevantAssemblies.ToList()) + { var module = asm.GetPEFileOrNull(); - if (CanResolveTypeInPEFile(module, typeRef, out var typeHandle)) { + if (CanResolveTypeInPEFile(module, typeRef, out var typeHandle)) + { ICompilation compilation = typeHandle.Kind == HandleKind.ExportedType ? new DecompilerTypeSystem(module, module.GetAssemblyResolver()) : new SimpleCompilation(module, MinimalCorlib.Instance); @@ -481,18 +547,21 @@ namespace ICSharpCode.ILSpy static bool CanResolveTypeInPEFile(PEFile module, ITypeReference typeRef, out EntityHandle typeHandle) { - if (module == null) { + if (module == null) + { typeHandle = default; return false; } // We intentionally ignore reference assemblies, so that the loop continues looking for another assembly that might have a usable definition. - if (module.IsReferenceAssembly()) { + if (module.IsReferenceAssembly()) + { typeHandle = default; return false; } - switch (typeRef) { + switch (typeRef) + { case GetPotentiallyNestedClassTypeReference topLevelType: typeHandle = topLevelType.ResolveInPEFile(module); return !typeHandle.IsNil; @@ -526,11 +595,14 @@ namespace ICSharpCode.ILSpy this.spySettingsForMainWindow_Loaded = null; var loadPreviousAssemblies = Options.MiscSettingsPanel.CurrentMiscSettings.LoadPreviousAssemblies; - if (loadPreviousAssemblies) { + if (loadPreviousAssemblies) + { // Load AssemblyList only in Loaded event so that WPF is initialized before we start the CPU-heavy stuff. // This makes the UI come up a bit faster. this.assemblyList = AssemblyListManager.LoadList(spySettings, sessionSettings.ActiveAssemblyList); - } else { + } + else + { this.assemblyList = new AssemblyList(AssemblyListManager.DefaultListName); AssemblyListManager.ClearAll(); } @@ -539,13 +611,15 @@ namespace ICSharpCode.ILSpy if (assemblyList.GetAssemblies().Length == 0 && assemblyList.ListName == AssemblyListManager.DefaultListName - && loadPreviousAssemblies) { + && loadPreviousAssemblies) + { LoadInitialAssemblies(); } ShowAssemblyList(this.assemblyList); - if (sessionSettings.ActiveAutoLoadedAssembly != null) { + if (sessionSettings.ActiveAutoLoadedAssembly != null) + { this.assemblyList.Open(sessionSettings.ActiveAutoLoadedAssembly, true); } @@ -565,7 +639,8 @@ namespace ICSharpCode.ILSpy { var stringBuilder = new StringBuilder(); var result = FormatExceptions(exceptions, stringBuilder); - if (result) { + if (result) + { output.Write(stringBuilder.ToString()); } return result; @@ -573,22 +648,27 @@ namespace ICSharpCode.ILSpy internal static bool FormatExceptions(App.ExceptionData[] exceptions, StringBuilder output) { - if (exceptions.Length == 0) return false; + if (exceptions.Length == 0) + return false; bool first = true; - foreach (var item in exceptions) { + foreach (var item in exceptions) + { if (first) first = false; else output.AppendLine("-------------------------------------------------"); output.AppendLine("Error(s) loading plugin: " + item.PluginName); - if (item.Exception is System.Reflection.ReflectionTypeLoadException) { + if (item.Exception is System.Reflection.ReflectionTypeLoadException) + { var e = (System.Reflection.ReflectionTypeLoadException)item.Exception; - foreach (var ex in e.LoaderExceptions) { + foreach (var ex in e.LoaderExceptions) + { output.AppendLine(ex.ToString()); output.AppendLine(); } - } else + } + else output.AppendLine(item.Exception.ToString()); } @@ -601,14 +681,18 @@ namespace ICSharpCode.ILSpy public async Task ShowMessageIfUpdatesAvailableAsync(ILSpySettings spySettings, bool forceCheck = false) { // Don't check for updates if we're in an MSIX since they work differently - if (WindowsVersionHelper.HasPackageIdentity) { + if (WindowsVersionHelper.HasPackageIdentity) + { return; } string downloadUrl; - if (forceCheck) { + if (forceCheck) + { downloadUrl = await AboutPage.CheckForUpdatesAsync(spySettings); - } else { + } + else + { downloadUrl = await AboutPage.CheckForUpdatesIfEnabledAsync(spySettings); } @@ -622,9 +706,12 @@ namespace ICSharpCode.ILSpy async void downloadOrCheckUpdateButtonClick(object sender, RoutedEventArgs e) { - if (updateAvailableDownloadUrl != null) { + if (updateAvailableDownloadUrl != null) + { MainWindow.OpenLink(updateAvailableDownloadUrl); - } else { + } + else + { updatePanel.Visibility = Visibility.Collapsed; string downloadUrl = await AboutPage.CheckForUpdatesAsync(ILSpySettings.Load()); AdjustUpdateUIAfterCheck(downloadUrl, true); @@ -635,10 +722,13 @@ namespace ICSharpCode.ILSpy { updateAvailableDownloadUrl = downloadUrl; updatePanel.Visibility = displayMessage ? Visibility.Visible : Visibility.Collapsed; - if (downloadUrl != null) { + if (downloadUrl != null) + { updatePanelMessage.Text = Properties.Resources.ILSpyVersionAvailable; downloadOrCheckUpdateButton.Content = Properties.Resources.Download; - } else { + } + else + { updatePanelMessage.Text = Properties.Resources.UpdateILSpyFound; downloadOrCheckUpdateButton.Content = Properties.Resources.CheckAgain; } @@ -649,7 +739,8 @@ namespace ICSharpCode.ILSpy { AssemblyList list = this.AssemblyListManager.LoadList(ILSpySettings.Load(), name); //Only load a new list when it is a different one - if (list.ListName != CurrentAssemblyList.ListName) { + if (list.ListName != CurrentAssemblyList.ListName) + { ShowAssemblyList(list); SelectNode(AssemblyTreeView.Root); } @@ -683,10 +774,12 @@ namespace ICSharpCode.ILSpy void assemblyList_Assemblies_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - if (e.Action == NotifyCollectionChangedAction.Reset) { + if (e.Action == NotifyCollectionChangedAction.Reset) + { history.RemoveAll(_ => true); } - if (e.OldItems != null) { + if (e.OldItems != null) + { var oldAssemblies = new HashSet(e.OldItems.Cast()); history.RemoveAll(n => n.TreeNodes.Any( nd => nd.AncestorsAndSelf().OfType().Any( @@ -718,7 +811,8 @@ namespace ICSharpCode.ILSpy { RefreshTreeView(); RefreshTreeViewFilter(); - if (e.PropertyName == "Language" || e.PropertyName == "LanguageVersion") { + if (e.PropertyName == "Language" || e.PropertyName == "LanguageVersion") + { DecompileSelectedNodes(recordHistory: false); } } @@ -750,9 +844,12 @@ namespace ICSharpCode.ILSpy public void SelectNode(SharpTreeNode obj, bool inNewTabPage, bool setFocus) { - if (obj != null) { - if (!obj.AncestorsAndSelf().Any(node => node.IsHidden)) { - if (inNewTabPage) { + if (obj != null) + { + if (!obj.AncestorsAndSelf().Any(node => node.IsHidden)) + { + if (inNewTabPage) + { DockWorkspace.Instance.TabPages.Add( new TabPageModel() { Language = CurrentLanguage, @@ -763,13 +860,18 @@ namespace ICSharpCode.ILSpy } // Set both the selection and focus to ensure that keyboard navigation works as expected. - if (setFocus) { + if (setFocus) + { AssemblyTreeView.FocusNode(obj); - } else { + } + else + { AssemblyTreeView.ScrollIntoView(obj); } AssemblyTreeView.SelectedItem = obj; - } else { + } + else + { MessageBox.Show(Properties.Resources.NavigationFailed, "ILSpy", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } @@ -787,8 +889,10 @@ namespace ICSharpCode.ILSpy public void SelectNodes(IEnumerable nodes, bool inNewTabPage, bool setFocus) { - if (nodes.Any() && nodes.All(n => !n.AncestorsAndSelf().Any(a => a.IsHidden))) { - if (inNewTabPage) { + if (nodes.Any() && nodes.All(n => !n.AncestorsAndSelf().Any(a => a.IsHidden))) + { + if (inNewTabPage) + { DockWorkspace.Instance.TabPages.Add( new TabPageModel() { Language = CurrentLanguage, @@ -797,9 +901,12 @@ namespace ICSharpCode.ILSpy DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last(); } - if (setFocus) { + if (setFocus) + { AssemblyTreeView.FocusNode(nodes.First()); - } else { + } + else + { AssemblyTreeView.ScrollIntoView(nodes.First()); } AssemblyTreeView.SetSelectedNodes(nodes); @@ -815,7 +922,8 @@ namespace ICSharpCode.ILSpy return null; SharpTreeNode node = AssemblyTreeView.Root; SharpTreeNode bestMatch = node; - foreach (var element in path) { + foreach (var element in path) + { if (node == null) break; bestMatch = node; @@ -839,7 +947,8 @@ namespace ICSharpCode.ILSpy if (node == null) return null; List path = new List(); - while (node.Parent != null) { + while (node.Parent != null) + { path.Add(node.ToString()); node = node.Parent; } @@ -849,7 +958,8 @@ namespace ICSharpCode.ILSpy public ILSpyTreeNode FindTreeNode(object reference) { - switch (reference) { + switch (reference) + { case LoadedAssembly lasm: return assemblyListTreeNode.FindAssemblyNode(lasm); case PEFile asm: @@ -900,25 +1010,30 @@ namespace ICSharpCode.ILSpy public Task JumpToReferenceAsync(object reference, bool inNewTabPage) { decompilationTask = TaskHelper.CompletedTask; - switch (reference) { + switch (reference) + { case Decompiler.Disassembler.OpCodeInfo opCode: OpenLink(opCode.Link); break; case EntityReference unresolvedEntity: string protocol = unresolvedEntity.Protocol ?? "decompile"; PEFile file = unresolvedEntity.Module; - if (protocol != "decompile") { + if (protocol != "decompile") + { var protocolHandlers = App.ExportProvider.GetExports(); - foreach (var handler in protocolHandlers) { + foreach (var handler in protocolHandlers) + { var node = handler.Value.Resolve(protocol, file, unresolvedEntity.Handle, out bool newTabPage); - if (node != null) { + if (node != null) + { SelectNode(node, newTabPage || inNewTabPage); return decompilationTask; } } } var possibleToken = MetadataTokenHelpers.TryAsEntityHandle(MetadataTokens.GetToken(unresolvedEntity.Handle)); - if (possibleToken != null) { + if (possibleToken != null) + { var typeSystem = new DecompilerTypeSystem(file, file.GetAssemblyResolver(), TypeSystemOptions.Default | TypeSystemOptions.Uncached); reference = typeSystem.MainModule.ResolveEntity(possibleToken.Value); goto default; @@ -935,10 +1050,13 @@ namespace ICSharpCode.ILSpy public static void OpenLink(string link) { - try { + try + { Process.Start(link); #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body - } catch (Exception) { + } + catch (Exception) + { #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body // Process.Start can throw several errors (not all of them documented), // just ignore all of them. @@ -947,10 +1065,13 @@ namespace ICSharpCode.ILSpy public static void ExecuteCommand(string fileName, string arguments) { - try { + try + { Process.Start(fileName, arguments); #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body - } catch (Exception) { + } + catch (Exception) + { #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body // Process.Start can throw several errors (not all of them documented), // just ignore all of them. @@ -966,7 +1087,8 @@ namespace ICSharpCode.ILSpy dlg.Filter = ".NET assemblies|*.dll;*.exe;*.winmd|Nuget Packages (*.nupkg)|*.nupkg|All files|*.*"; dlg.Multiselect = true; dlg.RestoreDirectory = true; - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { OpenFiles(dlg.FileNames); } } @@ -985,42 +1107,54 @@ namespace ICSharpCode.ILSpy void LoadAssemblies(IEnumerable fileNames, List loadedAssemblies = null, bool focusNode = true) { SharpTreeNode lastNode = null; - foreach (string file in fileNames) { - switch (Path.GetExtension(file)) { + foreach (string file in fileNames) + { + switch (Path.GetExtension(file)) + { case ".nupkg": this.handlingNugetPackageSelection = true; - try { + try + { LoadedNugetPackage package = new LoadedNugetPackage(file); var selectionDialog = new NugetPackageBrowserDialog(package); selectionDialog.Owner = this; if (selectionDialog.ShowDialog() != true) break; - foreach (var entry in selectionDialog.SelectedItems) { + foreach (var entry in selectionDialog.SelectedItems) + { var nugetAsm = assemblyList.OpenAssembly("nupkg://" + file + ";" + entry.Name, entry.Stream, true); - if (nugetAsm != null) { + if (nugetAsm != null) + { if (loadedAssemblies != null) loadedAssemblies.Add(nugetAsm); - else { + else + { var node = assemblyListTreeNode.FindAssemblyNode(nugetAsm); - if (node != null && focusNode) { + if (node != null && focusNode) + { AssemblyTreeView.SelectedItems.Add(node); lastNode = node; } } } } - } finally { + } + finally + { this.handlingNugetPackageSelection = false; } break; default: var asm = assemblyList.OpenAssembly(file); - if (asm != null) { + if (asm != null) + { if (loadedAssemblies != null) loadedAssemblies.Add(asm); - else { + else + { var node = assemblyListTreeNode.FindAssemblyNode(asm); - if (node != null && focusNode) { + if (node != null && focusNode) + { AssemblyTreeView.SelectedItems.Add(node); lastNode = node; } @@ -1041,12 +1175,15 @@ namespace ICSharpCode.ILSpy void RefreshTreeView() { - try { + try + { refreshInProgress = true; var path = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode); ShowAssemblyList(AssemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName)); SelectNode(FindNodeByPath(path, true), false, false); - } finally { + } + finally + { refreshInProgress = false; } } @@ -1076,7 +1213,8 @@ namespace ICSharpCode.ILSpy if (AssemblyTreeView.SelectedItems.Count == 0 && refreshInProgress) return; - if (recordHistory) { + if (recordHistory) + { var currentState = DockWorkspace.Instance.ActiveTabPage.GetState(); if (currentState != null) history.UpdateCurrent(new NavigationState(currentState)); @@ -1085,12 +1223,14 @@ namespace ICSharpCode.ILSpy DockWorkspace.Instance.ActiveTabPage.SupportsLanguageSwitching = true; - if (AssemblyTreeView.SelectedItems.Count == 1) { + if (AssemblyTreeView.SelectedItems.Count == 1) + { ILSpyTreeNode node = AssemblyTreeView.SelectedItem as ILSpyTreeNode; if (node != null && node.View(DockWorkspace.Instance.ActiveTabPage)) return; } - if (newState?.ViewedUri != null) { + if (newState?.ViewedUri != null) + { NavigateTo(new RequestNavigateEventArgs(newState.ViewedUri, null), recordHistory: false); return; } @@ -1110,10 +1250,13 @@ namespace ICSharpCode.ILSpy public void RefreshDecompiledView() { - try { + try + { refreshInProgress = true; DecompileSelectedNodes(); - } finally { + } + finally + { refreshInProgress = false; } } @@ -1139,7 +1282,8 @@ namespace ICSharpCode.ILSpy void BackCommandExecuted(object sender, ExecutedRoutedEventArgs e) { - if (history.CanNavigateBack) { + if (history.CanNavigateBack) + { e.Handled = true; NavigateHistory(false); } @@ -1153,7 +1297,8 @@ namespace ICSharpCode.ILSpy void ForwardCommandExecuted(object sender, ExecutedRoutedEventArgs e) { - if (history.CanNavigateForward) { + if (history.CanNavigateForward) + { e.Handled = true; NavigateHistory(true); } @@ -1168,7 +1313,8 @@ namespace ICSharpCode.ILSpy ignoreDecompilationRequests = true; AssemblyTreeView.SelectedItems.Clear(); - foreach (var node in newState.TreeNodes) { + foreach (var node in newState.TreeNodes) + { AssemblyTreeView.SelectedItems.Add(node); } if (newState.TreeNodes.Any()) @@ -1180,8 +1326,10 @@ namespace ICSharpCode.ILSpy internal void NavigateTo(RequestNavigateEventArgs e, bool recordHistory = true) { - if (e.Uri.Scheme == "resource") { - if (e.Uri.Host == "aboutpage") { + if (e.Uri.Scheme == "resource") + { + if (e.Uri.Host == "aboutpage") + { RecordHistory(); DockWorkspace.Instance.ActiveTabPage.ShowTextView(AboutPage.Display); e.Handled = true; @@ -1192,10 +1340,13 @@ namespace ICSharpCode.ILSpy Title = e.Uri.AbsolutePath, EnableHyperlinks = true }; - using (Stream s = typeof(App).Assembly.GetManifestResourceStream(typeof(App), e.Uri.AbsolutePath)) { - using (StreamReader r = new StreamReader(s)) { + using (Stream s = typeof(App).Assembly.GetManifestResourceStream(typeof(App), e.Uri.AbsolutePath)) + { + using (StreamReader r = new StreamReader(s)) + { string line; - while ((line = r.ReadLine()) != null) { + while ((line = r.ReadLine()) != null) + { output.Write(line); output.WriteLine(); } @@ -1243,7 +1394,8 @@ namespace ICSharpCode.ILSpy { if (node == null) return null; - while (!(node is TreeNodes.AssemblyTreeNode) && node.Parent != null) { + while (!(node is TreeNodes.AssemblyTreeNode) && node.Parent != null) + { node = node.Parent; } //this should be an assembly node diff --git a/ILSpy/Metadata/CoffHeaderTreeNode.cs b/ILSpy/Metadata/CoffHeaderTreeNode.cs index e9973a763..b48bec968 100644 --- a/ILSpy/Metadata/CoffHeaderTreeNode.cs +++ b/ILSpy/Metadata/CoffHeaderTreeNode.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Data; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TextView; diff --git a/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs index 485cb856d..af63009a9 100644 --- a/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs @@ -48,9 +48,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); AssemblyRefEntry scrollTargetEntry = default; - foreach (var row in metadata.AssemblyReferences) { + foreach (var row in metadata.AssemblyReferences) + { AssemblyRefEntry entry = new AssemblyRefEntry(module, row); - if (scrollTarget == MetadataTokens.GetRowNumber(row)) { + if (scrollTarget == MetadataTokens.GetRowNumber(row)) + { scrollTargetEntry = entry; } list.Add(entry); @@ -59,7 +61,8 @@ namespace ICSharpCode.ILSpy.Metadata view.ItemsSource = list; tabPage.Content = view; - if (scrollTargetEntry.RID > 1) { + if (scrollTargetEntry.RID > 1) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs index 70087a3d9..ecbd02c57 100644 --- a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs @@ -53,9 +53,11 @@ namespace ICSharpCode.ILSpy.Metadata int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; ClassLayoutEntry scrollTargetEntry = default; - for (int rid = 1; rid <= length; rid++) { + for (int rid = 1; rid <= length; rid++) + { ClassLayoutEntry entry = new ClassLayoutEntry(module, ptr, metadataOffset, rid); - if (scrollTarget == rid) { + if (scrollTarget == rid) + { scrollTargetEntry = entry; } list.Add(entry); @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata view.ItemsSource = list; tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -77,7 +80,7 @@ namespace ICSharpCode.ILSpy.Metadata public readonly EntityHandle Parent; public readonly uint ClassSize; - public unsafe ClassLayout(byte *ptr, int typeDefSize) + public unsafe ClassLayout(byte* ptr, int typeDefSize) { PackingSize = (ushort)Helpers.GetValue(ptr, 2); ClassSize = (uint)Helpers.GetValue(ptr + 2, 4); diff --git a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs index ed78c296e..c80c09b4d 100644 --- a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs @@ -50,9 +50,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); ConstantEntry scrollTargetEntry = default; - for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.Constant); row++) { + for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.Constant); row++) + { ConstantEntry entry = new ConstantEntry(module, MetadataTokens.ConstantHandle(row)); - if (scrollTarget == row) { + if (scrollTarget == row) + { scrollTargetEntry = entry; } list.Add(entry); @@ -61,7 +63,8 @@ namespace ICSharpCode.ILSpy.Metadata view.ItemsSource = list; tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs index d0bb7d122..bb4781a70 100644 --- a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs @@ -49,9 +49,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); CustomAttributeEntry scrollTargetEntry = default; - foreach (var row in metadata.CustomAttributes) { + foreach (var row in metadata.CustomAttributes) + { CustomAttributeEntry entry = new CustomAttributeEntry(module, row); - if (scrollTarget == MetadataTokens.GetRowNumber(row)) { + if (scrollTarget == MetadataTokens.GetRowNumber(row)) + { scrollTargetEntry = entry; } list.Add(entry); @@ -61,7 +63,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs index 582129842..519cb5cc0 100644 --- a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs @@ -50,9 +50,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); DeclSecurityEntry scrollTargetEntry = default; - foreach (var row in metadata.DeclarativeSecurityAttributes) { + foreach (var row in metadata.DeclarativeSecurityAttributes) + { var entry = new DeclSecurityEntry(module, row); - if (scrollTarget == MetadataTokens.GetRowNumber(row)) { + if (scrollTarget == MetadataTokens.GetRowNumber(row)) + { scrollTargetEntry = entry; } list.Add(entry); @@ -62,7 +64,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs index fb3980d59..d1790b684 100644 --- a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs @@ -52,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var length = metadata.GetTableRowCount(TableIndex.EventMap); byte* ptr = metadata.MetadataPointer; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - for (int rid = 1; rid <= length; rid++) { + for (int rid = 1; rid <= length; rid++) + { EventMapEntry entry = new EventMapEntry(module, ptr, metadataOffset, rid); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -76,7 +79,7 @@ namespace ICSharpCode.ILSpy.Metadata public readonly TypeDefinitionHandle Parent; public readonly EventDefinitionHandle EventList; - public unsafe EventMap(byte *ptr, int typeDefSize, int eventDefSize) + public unsafe EventMap(byte* ptr, int typeDefSize, int eventDefSize) { Parent = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr, typeDefSize)); EventList = MetadataTokens.EventDefinitionHandle(Helpers.GetValue(ptr + typeDefSize, eventDefSize)); diff --git a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs index 40504dccd..7b50c3249 100644 --- a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs @@ -52,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); EventDefEntry scrollTargetEntry = default; - foreach (var row in metadata.EventDefinitions) { + foreach (var row in metadata.EventDefinitions) + { EventDefEntry entry = new EventDefEntry(module, row); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs index ba7b70444..56a9fa835 100644 --- a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs @@ -48,9 +48,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); ExportedTypeEntry scrollTargetEntry = default; - foreach (var row in metadata.ExportedTypes) { + foreach (var row in metadata.ExportedTypes) + { ExportedTypeEntry entry = new ExportedTypeEntry(module.Reader.PEHeaders.MetadataStartOffset, module, row, metadata.GetExportedType(row)); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -60,7 +62,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -81,7 +84,7 @@ namespace ICSharpCode.ILSpy.Metadata public int Offset => metadataOffset + metadata.GetTableMetadataOffset(TableIndex.ExportedType) - + metadata.GetTableRowSize(TableIndex.ExportedType) * (RID-1); + + metadata.GetTableRowSize(TableIndex.ExportedType) * (RID - 1); [StringFormat("X8")] public TypeAttributes Attributes => type.Attributes; diff --git a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs index 5673131f8..10cad63b5 100644 --- a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs @@ -52,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var length = metadata.GetTableRowCount(TableIndex.FieldLayout); byte* ptr = metadata.MetadataPointer; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - for (int rid = 1; rid <= length; rid++) { + for (int rid = 1; rid <= length; rid++) + { FieldLayoutEntry entry = new FieldLayoutEntry(module, ptr, metadataOffset, rid); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs index 8a0c10d49..ad4fd4e3d 100644 --- a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs @@ -52,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var length = metadata.GetTableRowCount(TableIndex.FieldMarshal); byte* ptr = metadata.MetadataPointer; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - for (int rid = 1; rid <= length; rid++) { + for (int rid = 1; rid <= length; rid++) + { FieldMarshalEntry entry = new FieldMarshalEntry(module, ptr, metadataOffset, rid); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs index 7e6431528..64fb06600 100644 --- a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs @@ -52,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var length = metadata.GetTableRowCount(TableIndex.FieldRva); byte* ptr = metadata.MetadataPointer; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - for (int rid = 1; rid <= length; rid++) { + for (int rid = 1; rid <= length; rid++) + { FieldRVAEntry entry = new FieldRVAEntry(module, ptr, metadataOffset, rid); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs index 7e2b89de6..6d5beb3ed 100644 --- a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs @@ -24,6 +24,7 @@ using System.Reflection.Metadata.Ecma335; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.IL; @@ -55,9 +56,11 @@ namespace ICSharpCode.ILSpy.Metadata FieldDefEntry scrollTargetEntry = default; - foreach (var row in metadata.FieldDefinitions) { + foreach (var row in metadata.FieldDefinitions) + { var entry = new FieldDefEntry(module, row); - if (scrollTarget == entry.RID) { + if (scrollTarget == entry.RID) + { scrollTargetEntry = entry; } list.Add(entry); @@ -67,7 +70,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs index a959c2db5..c48b8890b 100644 --- a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs @@ -47,9 +47,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); FileEntry scrollTargetEntry = default; - foreach (var row in metadata.AssemblyFiles) { + foreach (var row in metadata.AssemblyFiles) + { FileEntry entry = new FileEntry(module, row); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -59,7 +61,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs index 60e75dc4e..ec05906ea 100644 --- a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs @@ -45,13 +45,15 @@ namespace ICSharpCode.ILSpy.Metadata var view = Helpers.PrepareDataGrid(tabPage, this); var metadata = module.Metadata; - + var list = new List(); GenericParamConstraintEntry scrollTargetEntry = default; - for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.GenericParamConstraint); row++) { + for (int row = 1; row <= metadata.GetTableRowCount(TableIndex.GenericParamConstraint); row++) + { GenericParamConstraintEntry entry = new GenericParamConstraintEntry(module, MetadataTokens.GenericParameterConstraintHandle(row)); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -60,7 +62,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -81,7 +84,7 @@ namespace ICSharpCode.ILSpy.Metadata public int Offset => metadataOffset + metadata.GetTableMetadataOffset(TableIndex.GenericParamConstraint) - + metadata.GetTableRowSize(TableIndex.GenericParamConstraint) * (RID-1); + + metadata.GetTableRowSize(TableIndex.GenericParamConstraint) * (RID - 1); [StringFormat("X8")] public int Owner => MetadataTokens.GetToken(genericParamConstraint.Parameter); @@ -90,7 +93,8 @@ namespace ICSharpCode.ILSpy.Metadata public string OwnerTooltip { get { - if (ownerTooltip == null) { + if (ownerTooltip == null) + { ITextOutput output = new PlainTextOutput(); var p = metadata.GetGenericParameter(genericParamConstraint.Parameter); output.Write("parameter " + p.Index + (p.Name.IsNil ? "" : " (" + metadata.GetString(p.Name) + ")") + " of "); diff --git a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs index 4d387d989..bcf350386 100644 --- a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs @@ -45,13 +45,15 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - + var list = new List(); GenericParamEntry scrollTargetEntry = default; - for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.GenericParam); row++) { + for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.GenericParam); row++) + { GenericParamEntry entry = new GenericParamEntry(module, MetadataTokens.GenericParameterHandle(row)); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -60,7 +62,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -81,7 +84,7 @@ namespace ICSharpCode.ILSpy.Metadata public int Offset => metadataOffset + metadata.GetTableMetadataOffset(TableIndex.GenericParam) - + metadata.GetTableRowSize(TableIndex.GenericParam) * (RID-1); + + metadata.GetTableRowSize(TableIndex.GenericParam) * (RID - 1); public int Number => genericParam.Index; diff --git a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs index 683866e79..95167c6a0 100644 --- a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs @@ -54,9 +54,11 @@ namespace ICSharpCode.ILSpy.Metadata var length = metadata.GetTableRowCount(TableIndex.ImplMap); byte* ptr = metadata.MetadataPointer; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - for (int rid = 1; rid <= length; rid++) { + for (int rid = 1; rid <= length; rid++) + { ImplMapEntry entry = new ImplMapEntry(module, ptr, metadataOffset, rid); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -66,7 +68,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -80,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata public readonly StringHandle ImportName; public readonly ModuleReferenceHandle ImportScope; - public unsafe ImplMap(byte *ptr, int moduleRefSize, int memberForwardedTagRefSize, int stringHandleSize) + public unsafe ImplMap(byte* ptr, int moduleRefSize, int memberForwardedTagRefSize, int stringHandleSize) { MappingFlags = (PInvokeAttributes)Helpers.GetValue(ptr, 2); MemberForwarded = Helpers.FromMemberForwardedTag((uint)Helpers.GetValue(ptr + 2, memberForwardedTagRefSize)); diff --git a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs index 44841637e..45f68b941 100644 --- a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs @@ -52,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var length = metadata.GetTableRowCount(TableIndex.InterfaceImpl); byte* ptr = metadata.MetadataPointer; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - for (int rid = 1; rid <= length; rid++) { + for (int rid = 1; rid <= length; rid++) + { InterfaceImplEntry entry = new InterfaceImplEntry(module, ptr, metadataOffset, rid); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -76,7 +79,7 @@ namespace ICSharpCode.ILSpy.Metadata public readonly EntityHandle Class; public readonly EntityHandle Interface; - public unsafe InterfaceImpl(byte *ptr, int classSize, int interfaceSize) + public unsafe InterfaceImpl(byte* ptr, int classSize, int interfaceSize) { Class = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr, classSize)); Interface = Helpers.FromTypeDefOrRefTag((uint)Helpers.GetValue(ptr + classSize, interfaceSize)); diff --git a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs index 01d37c2fb..75440f5d5 100644 --- a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs @@ -50,9 +50,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); ManifestResourceEntry scrollTargetEntry = default; - foreach (var row in metadata.ManifestResources) { + foreach (var row in metadata.ManifestResources) + { ManifestResourceEntry entry = new ManifestResourceEntry(module, row); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -62,7 +64,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs index 0bc8c5019..3f1738408 100644 --- a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs @@ -49,9 +49,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); MemberRefEntry scrollTargetEntry = default; - foreach (var row in metadata.MemberReferences) { + foreach (var row in metadata.MemberReferences) + { MemberRefEntry entry = new MemberRefEntry(module, row); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -61,7 +63,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs index e07ad1a7d..6c37c90b8 100644 --- a/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs @@ -48,9 +48,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); MethodImplEntry scrollTargetEntry = default; - for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.MethodImpl); row++) { + for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.MethodImpl); row++) + { MethodImplEntry entry = new MethodImplEntry(module, MetadataTokens.MethodImplementationHandle(row)); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -60,7 +62,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs index d973644e3..34b785440 100644 --- a/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs @@ -50,9 +50,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); MethodSemanticsEntry scrollTargetEntry = default; - foreach (var row in metadata.GetMethodSemantics()) { + foreach (var row in metadata.GetMethodSemantics()) + { MethodSemanticsEntry entry = new MethodSemanticsEntry(module, row.Handle, row.Semantics, row.Method, row.Association); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -62,7 +64,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs index f1adc2863..19bf278b8 100644 --- a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs @@ -45,23 +45,26 @@ namespace ICSharpCode.ILSpy.Metadata var view = Helpers.PrepareDataGrid(tabPage, this); var metadata = module.Metadata; - + var list = new List(); MethodSpecEntry scrollTargetEntry = default; - foreach (var row in metadata.GetMethodSpecifications()) { + foreach (var row in metadata.GetMethodSpecifications()) + { MethodSpecEntry entry = new MethodSpecEntry(module, row); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); } view.ItemsSource = list; - + tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -82,7 +85,7 @@ namespace ICSharpCode.ILSpy.Metadata public int Offset => metadataOffset + metadata.GetTableMetadataOffset(TableIndex.MethodSpec) - + metadata.GetTableRowSize(TableIndex.MethodSpec) * (RID-1); + + metadata.GetTableRowSize(TableIndex.MethodSpec) * (RID - 1); [StringFormat("X8")] public int Method => MetadataTokens.GetToken(methodSpec.Method); @@ -103,7 +106,8 @@ namespace ICSharpCode.ILSpy.Metadata ITextOutput output = new PlainTextOutput(); var signature = methodSpec.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), GenericContext.Empty); bool first = true; - foreach (var type in signature) { + foreach (var type in signature) + { if (first) first = false; else diff --git a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs index 590662382..498daa401 100644 --- a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs @@ -23,6 +23,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Windows.Controls; using System.Windows.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.IL; @@ -53,9 +54,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); MethodDefEntry scrollTargetEntry = default; - foreach (var row in metadata.MethodDefinitions) { + foreach (var row in metadata.MethodDefinitions) + { MethodDefEntry entry = new MethodDefEntry(module, row); - if (entry.RID == scrollTarget) { + if (entry.RID == scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -65,7 +68,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 1) { + if (scrollTargetEntry.RID > 1) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -120,7 +124,8 @@ namespace ICSharpCode.ILSpy.Metadata public string SignatureTooltip { get { - if (signatureTooltip == null) { + if (signatureTooltip == null) + { ITextOutput output = new PlainTextOutput(); var context = new Decompiler.Metadata.GenericContext(default(TypeDefinitionHandle), module); ((EntityHandle)handle).WriteTo(module, output, context); diff --git a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs index 171f36585..987471e85 100644 --- a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs @@ -43,23 +43,26 @@ namespace ICSharpCode.ILSpy.Metadata var view = Helpers.PrepareDataGrid(tabPage, this); var metadata = module.Metadata; - + var list = new List(); ModuleRefEntry scrollTargetEntry = default; - foreach (var row in metadata.GetModuleReferences()) { + foreach (var row in metadata.GetModuleReferences()) + { ModuleRefEntry entry = new ModuleRefEntry(module, row); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); } view.ItemsSource = list; - + tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -80,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata public int Offset => metadataOffset + metadata.GetTableMetadataOffset(TableIndex.ModuleRef) - + metadata.GetTableRowSize(TableIndex.ModuleRef) * (RID-1); + + metadata.GetTableRowSize(TableIndex.ModuleRef) * (RID - 1); public string Name => metadata.GetString(moduleRef.Name); diff --git a/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs index bec566739..b86387ecd 100644 --- a/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs @@ -42,17 +42,18 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - + var list = new List(); ModuleEntry scrollTargetEntry = default; list.Add(new ModuleEntry(module, EntityHandle.ModuleDefinition)); view.ItemsSource = list; - + tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -73,7 +74,7 @@ namespace ICSharpCode.ILSpy.Metadata public int Offset => metadataOffset + metadata.GetTableMetadataOffset(TableIndex.Module) - + metadata.GetTableRowSize(TableIndex.Module) * (RID-1); + + metadata.GetTableRowSize(TableIndex.Module) * (RID - 1); public int Generation => moduleDef.Generation; diff --git a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs index c93ad5760..2699af243 100644 --- a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs @@ -52,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var length = metadata.GetTableRowCount(TableIndex.NestedClass); byte* ptr = metadata.MetadataPointer; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - for (int rid = 1; rid <= length; rid++) { + for (int rid = 1; rid <= length; rid++) + { NestedClassEntry entry = new NestedClassEntry(module, ptr, metadataOffset, rid); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -76,7 +79,7 @@ namespace ICSharpCode.ILSpy.Metadata public readonly TypeDefinitionHandle Nested; public readonly TypeDefinitionHandle Enclosing; - public unsafe NestedClass(byte *ptr, int typeDefSize) + public unsafe NestedClass(byte* ptr, int typeDefSize) { Nested = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr, typeDefSize)); Enclosing = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr + typeDefSize, typeDefSize)); diff --git a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs index 37d82a930..5aea6118d 100644 --- a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs @@ -43,23 +43,26 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.SupportsLanguageSwitching = false; var view = Helpers.PrepareDataGrid(tabPage, this); - + var list = new List(); ParamEntry scrollTargetEntry = default; - for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.Param); row++) { + for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.Param); row++) + { ParamEntry entry = new ParamEntry(module, MetadataTokens.ParameterHandle(row)); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); } view.ItemsSource = list; - + tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -80,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata public int Offset => metadataOffset + metadata.GetTableMetadataOffset(TableIndex.Param) - + metadata.GetTableRowSize(TableIndex.Param) * (RID-1); + + metadata.GetTableRowSize(TableIndex.Param) * (RID - 1); [StringFormat("X8")] public ParameterAttributes Attributes => param.Attributes; diff --git a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs index 657f11571..1a3e6c715 100644 --- a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs @@ -52,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var length = metadata.GetTableRowCount(TableIndex.PropertyMap); byte* ptr = metadata.MetadataPointer; int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; - for (int rid = 1; rid <= length; rid++) { + for (int rid = 1; rid <= length; rid++) + { PropertyMapEntry entry = new PropertyMapEntry(module, ptr, metadataOffset, rid); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -76,7 +79,7 @@ namespace ICSharpCode.ILSpy.Metadata public readonly TypeDefinitionHandle Parent; public readonly PropertyDefinitionHandle PropertyList; - public unsafe PropertyMap(byte *ptr, int typeDefSize, int propertyDefSize) + public unsafe PropertyMap(byte* ptr, int typeDefSize, int propertyDefSize) { Parent = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr, typeDefSize)); PropertyList = MetadataTokens.PropertyDefinitionHandle(Helpers.GetValue(ptr + typeDefSize, propertyDefSize)); diff --git a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs index 1877b7ae7..dad13c218 100644 --- a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs @@ -52,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); PropertyDefEntry scrollTargetEntry = default; - foreach (var row in metadata.PropertyDefinitions) { + foreach (var row in metadata.PropertyDefinitions) + { PropertyDefEntry entry = new PropertyDefEntry(module, row); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs index 1bb0cfa2e..02ba8159b 100644 --- a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs @@ -48,9 +48,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); StandAloneSigEntry scrollTargetEntry = default; - for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.StandAloneSig); row++) { + for (int row = 1; row <= module.Metadata.GetTableRowCount(TableIndex.StandAloneSig); row++) + { StandAloneSigEntry entry = new StandAloneSigEntry(module, MetadataTokens.StandaloneSignatureHandle(row)); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -60,7 +62,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs index 4d5e605c4..82bd2e6a4 100644 --- a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs @@ -53,9 +53,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); TypeDefEntry scrollTargetEntry = default; - foreach (var row in metadata.TypeDefinitions) { + foreach (var row in metadata.TypeDefinitions) + { TypeDefEntry entry = new TypeDefEntry(module, row); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -65,7 +67,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -86,7 +89,7 @@ namespace ICSharpCode.ILSpy.Metadata public int Offset => metadataOffset + metadata.GetTableMetadataOffset(TableIndex.TypeDef) - + metadata.GetTableRowSize(TableIndex.TypeDef) * (RID-1); + + metadata.GetTableRowSize(TableIndex.TypeDef) * (RID - 1); [StringFormat("X8")] public TypeAttributes Attributes => typeDef.Attributes; @@ -119,7 +122,8 @@ namespace ICSharpCode.ILSpy.Metadata var provider = new DisassemblerSignatureTypeProvider(module, output); if (typeDef.BaseType.IsNil) return null; - switch (typeDef.BaseType.Kind) { + switch (typeDef.BaseType.Kind) + { case HandleKind.TypeDefinition: provider.GetTypeFromDefinition(module.Metadata, (TypeDefinitionHandle)typeDef.BaseType, 0)(ILNameSyntax.Signature); return output.ToString(); diff --git a/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs index 909662b80..26e0ea498 100644 --- a/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs @@ -44,23 +44,26 @@ namespace ICSharpCode.ILSpy.Metadata var view = Helpers.PrepareDataGrid(tabPage, this); var metadata = module.Metadata; - + var list = new List(); TypeRefEntry scrollTargetEntry = default; - foreach (var row in metadata.TypeReferences) { + foreach (var row in metadata.TypeReferences) + { TypeRefEntry entry = new TypeRefEntry(module, row); - if (entry.RID == this.scrollTarget) { + if (entry.RID == this.scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); } view.ItemsSource = list; - + tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -81,7 +84,7 @@ namespace ICSharpCode.ILSpy.Metadata public int Offset => metadataOffset + metadata.GetTableMetadataOffset(TableIndex.TypeRef) - + metadata.GetTableRowSize(TableIndex.TypeRef) * (RID-1); + + metadata.GetTableRowSize(TableIndex.TypeRef) * (RID - 1); [StringFormat("X8")] public int ResolutionScope => MetadataTokens.GetToken(typeRef.ResolutionScope); @@ -91,7 +94,8 @@ namespace ICSharpCode.ILSpy.Metadata if (typeRef.ResolutionScope.IsNil) return null; var output = new PlainTextOutput(); - switch (typeRef.ResolutionScope.Kind) { + switch (typeRef.ResolutionScope.Kind) + { case HandleKind.ModuleDefinition: output.Write(metadata.GetString(metadata.GetModuleDefinition().Name)); break; diff --git a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs index 3433bba60..f99c64e57 100644 --- a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs @@ -44,23 +44,26 @@ namespace ICSharpCode.ILSpy.Metadata var view = Helpers.PrepareDataGrid(tabPage, this); var metadata = module.Metadata; - + var list = new List(); TypeSpecEntry scrollTargetEntry = default; - - foreach (var row in metadata.GetTypeSpecifications()) { + + foreach (var row in metadata.GetTypeSpecifications()) + { TypeSpecEntry entry = new TypeSpecEntry(module, row); - if (scrollTarget.Equals(row)) { + if (scrollTarget.Equals(row)) + { scrollTargetEntry = entry; } list.Add(entry); } view.ItemsSource = list; - + tabPage.Content = view; - if (scrollTargetEntry.RID > 0) { + if (scrollTargetEntry.RID > 0) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -81,7 +84,7 @@ namespace ICSharpCode.ILSpy.Metadata public int Offset => metadataOffset + metadata.GetTableMetadataOffset(TableIndex.TypeSpec) - + metadata.GetTableRowSize(TableIndex.TypeSpec) * (RID-1); + + metadata.GetTableRowSize(TableIndex.TypeSpec) * (RID - 1); [StringFormat("X")] public int Signature => MetadataTokens.GetHeapOffset(typeSpec.Signature); diff --git a/ILSpy/Metadata/DataDirectoriesTreeNode.cs b/ILSpy/Metadata/DataDirectoriesTreeNode.cs index f7b429d4e..879389674 100644 --- a/ILSpy/Metadata/DataDirectoriesTreeNode.cs +++ b/ILSpy/Metadata/DataDirectoriesTreeNode.cs @@ -19,6 +19,7 @@ using System.Reflection.PortableExecutable; using System.Windows.Controls; using System.Windows.Data; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TextView; diff --git a/ILSpy/Metadata/DataGridCustomTextColumn.cs b/ILSpy/Metadata/DataGridCustomTextColumn.cs index 238f85e2b..b16dade3e 100644 --- a/ILSpy/Metadata/DataGridCustomTextColumn.cs +++ b/ILSpy/Metadata/DataGridCustomTextColumn.cs @@ -32,7 +32,8 @@ namespace ICSharpCode.ILSpy.Metadata { TextBox textBox = new TextBox() { Style = (Style)MetadataTableViews.Instance["DataGridCustomTextColumnTextBoxStyle"] }; BindingOperations.SetBinding(textBox, TextBox.TextProperty, Binding); - if (ToolTipBinding != null) { + if (ToolTipBinding != null) + { textBox.MouseMove += TextBox_MouseMove; } textBox.GotFocus += TextBox_GotFocus; diff --git a/ILSpy/Metadata/DebugMetadataTreeNode.cs b/ILSpy/Metadata/DebugMetadataTreeNode.cs index 92c4ab1bf..d14556511 100644 --- a/ILSpy/Metadata/DebugMetadataTreeNode.cs +++ b/ILSpy/Metadata/DebugMetadataTreeNode.cs @@ -19,6 +19,7 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Options; diff --git a/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs b/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs index bbe0b966b..9a73b53d1 100644 --- a/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs @@ -22,6 +22,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Disassembler; @@ -53,9 +54,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); CustomDebugInformationEntry scrollTargetEntry = default; - foreach (var row in metadata.CustomDebugInformation) { + foreach (var row in metadata.CustomDebugInformation) + { CustomDebugInformationEntry entry = new CustomDebugInformationEntry(module, metadata, isEmbedded, row); - if (entry.RID == scrollTarget) { + if (entry.RID == scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -65,7 +68,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 1) { + if (scrollTargetEntry.RID > 1) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -104,28 +108,36 @@ namespace ICSharpCode.ILSpy.Metadata if (debugInfo.Kind.IsNil) return null; var guid = metadata.GetGuid(debugInfo.Kind); - if (KnownGuids.StateMachineHoistedLocalScopes == guid) { + if (KnownGuids.StateMachineHoistedLocalScopes == guid) + { return "State Machine Hoisted Local Scopes (C# / VB) [" + guid + "]"; } - if (KnownGuids.DynamicLocalVariables == guid) { + if (KnownGuids.DynamicLocalVariables == guid) + { return "Dynamic Local Variables (C#) [" + guid + "]"; } - if (KnownGuids.DefaultNamespaces == guid) { + if (KnownGuids.DefaultNamespaces == guid) + { return "Default Namespaces (VB) [" + guid + "]"; } - if (KnownGuids.EditAndContinueLocalSlotMap == guid) { + if (KnownGuids.EditAndContinueLocalSlotMap == guid) + { return "Edit And Continue Local Slot Map (C# / VB) [" + guid + "]"; } - if (KnownGuids.EditAndContinueLambdaAndClosureMap == guid) { + if (KnownGuids.EditAndContinueLambdaAndClosureMap == guid) + { return "Edit And Continue Lambda And Closure Map (C# / VB) [" + guid + "]"; } - if (KnownGuids.EmbeddedSource == guid) { + if (KnownGuids.EmbeddedSource == guid) + { return "Embedded Source (C# / VB) [" + guid + "]"; } - if (KnownGuids.SourceLink == guid) { + if (KnownGuids.SourceLink == guid) + { return "Source Link (C# / VB) [" + guid + "]"; } - if (KnownGuids.MethodSteppingInformation == guid) { + if (KnownGuids.MethodSteppingInformation == guid) + { return "Method Stepping Information (C# / VB) [" + guid + "]"; } diff --git a/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs b/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs index 6b690c7df..4f5ba625f 100644 --- a/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs @@ -51,9 +51,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); DocumentEntry scrollTargetEntry = default; - foreach (var row in metadata.Documents) { + foreach (var row in metadata.Documents) + { DocumentEntry entry = new DocumentEntry(metadata, isEmbedded, row); - if (entry.RID == scrollTarget) { + if (entry.RID == scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -63,7 +65,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 1) { + if (scrollTargetEntry.RID > 1) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs b/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs index 289cbabc9..5762e6290 100644 --- a/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs @@ -18,15 +18,16 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; + using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Disassembler; +using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; -using System.Linq; namespace ICSharpCode.ILSpy.Metadata { @@ -53,9 +54,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); ImportScopeEntry scrollTargetEntry = default; - foreach (var row in metadata.ImportScopes) { + foreach (var row in metadata.ImportScopes) + { ImportScopeEntry entry = new ImportScopeEntry(module, metadata, isEmbedded, row); - if (entry.RID == scrollTarget) { + if (entry.RID == scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -65,7 +68,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 1) { + if (scrollTargetEntry.RID > 1) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs index 35b80317f..16918b0c9 100644 --- a/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs @@ -22,6 +22,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; @@ -51,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); LocalConstantEntry scrollTargetEntry = default; - foreach (var row in metadata.LocalConstants) { + foreach (var row in metadata.LocalConstants) + { LocalConstantEntry entry = new LocalConstantEntry(module, metadata, isEmbedded, row); - if (entry.RID == scrollTarget) { + if (entry.RID == scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -63,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 1) { + if (scrollTargetEntry.RID > 1) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs index e30b45245..6e0258e32 100644 --- a/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs @@ -18,15 +18,16 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; + using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Disassembler; +using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; -using System.Linq; namespace ICSharpCode.ILSpy.Metadata { @@ -53,9 +54,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); LocalScopeEntry scrollTargetEntry = default; - foreach (var row in metadata.LocalScopes) { + foreach (var row in metadata.LocalScopes) + { LocalScopeEntry entry = new LocalScopeEntry(module, metadata, isEmbedded, row); - if (entry.RID == scrollTarget) { + if (entry.RID == scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -65,7 +68,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 1) { + if (scrollTargetEntry.RID > 1) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs index 165e1f37c..3ee0767c1 100644 --- a/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; @@ -47,9 +48,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); LocalVariableEntry scrollTargetEntry = default; - foreach (var row in metadata.LocalVariables) { + foreach (var row in metadata.LocalVariables) + { LocalVariableEntry entry = new LocalVariableEntry(module, metadata, isEmbedded, row); - if (entry.RID == scrollTarget) { + if (entry.RID == scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -59,7 +62,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 1) { + if (scrollTargetEntry.RID > 1) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs b/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs index 718e4cad9..dd2da3905 100644 --- a/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs @@ -22,6 +22,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; @@ -51,9 +52,11 @@ namespace ICSharpCode.ILSpy.Metadata var list = new List(); MethodDebugInformationEntry scrollTargetEntry = default; - foreach (var row in metadata.MethodDebugInformation) { + foreach (var row in metadata.MethodDebugInformation) + { MethodDebugInformationEntry entry = new MethodDebugInformationEntry(module, metadata, isEmbedded, row); - if (entry.RID == scrollTarget) { + if (entry.RID == scrollTarget) + { scrollTargetEntry = entry; } list.Add(entry); @@ -63,7 +66,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 1) { + if (scrollTargetEntry.RID > 1) + { ScrollItemIntoView(view, scrollTargetEntry); } @@ -102,7 +106,8 @@ namespace ICSharpCode.ILSpy.Metadata if (debugInfo.SequencePointsBlob.IsNil) return null; StringBuilder sb = new StringBuilder(); - foreach (var p in debugInfo.GetSequencePoints()) { + foreach (var p in debugInfo.GetSequencePoints()) + { sb.AppendLine($"document='{MetadataTokens.GetToken(p.Document):X8}', offset={p.Offset}, start={p.StartLine};{p.StartColumn}, end={p.EndLine};{p.EndColumn}, hidden={p.IsHidden}"); } return sb.ToString().TrimEnd(); @@ -121,8 +126,10 @@ namespace ICSharpCode.ILSpy.Metadata StandaloneSignature localSignature = module.Metadata.GetStandaloneSignature(debugInfo.LocalSignature); var signatureDecoder = new DisassemblerSignatureTypeProvider(module, output); int index = 0; - foreach (var item in localSignature.DecodeLocalSignature(signatureDecoder, context)) { - if (index > 0) output.WriteLine(); + foreach (var item in localSignature.DecodeLocalSignature(signatureDecoder, context)) + { + if (index > 0) + output.WriteLine(); output.Write("[{0}] ", index); item(ILNameSyntax.Signature); index++; diff --git a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs index 318637141..76b826e3e 100644 --- a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs @@ -22,9 +22,10 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; + using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Disassembler; +using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.ILSpy.Metadata @@ -55,9 +56,11 @@ namespace ICSharpCode.ILSpy.Metadata var reader = new BlobReader(metadata.MetadataPointer, metadata.MetadataLength); reader.Offset = +metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod); - for (int rid = 1; rid <= length; rid++) { + for (int rid = 1; rid <= length; rid++) + { StateMachineMethodEntry entry = new StateMachineMethodEntry(module, ref reader, isEmbedded, rid); - if (scrollTarget == rid) { + if (scrollTarget == rid) + { scrollTargetEntry = entry; } list.Add(entry); @@ -67,7 +70,8 @@ namespace ICSharpCode.ILSpy.Metadata tabPage.Content = view; - if (scrollTargetEntry.RID > 1) { + if (scrollTargetEntry.RID > 1) + { ScrollItemIntoView(view, scrollTargetEntry); } diff --git a/ILSpy/Metadata/DosHeaderTreeNode.cs b/ILSpy/Metadata/DosHeaderTreeNode.cs index 347a91fbf..ad62e6fff 100644 --- a/ILSpy/Metadata/DosHeaderTreeNode.cs +++ b/ILSpy/Metadata/DosHeaderTreeNode.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Windows.Controls; using System.Windows.Data; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TreeNodes; diff --git a/ILSpy/Metadata/FlagsFilterControl.xaml.cs b/ILSpy/Metadata/FlagsFilterControl.xaml.cs index f75c686c0..18ab15620 100644 --- a/ILSpy/Metadata/FlagsFilterControl.xaml.cs +++ b/ILSpy/Metadata/FlagsFilterControl.xaml.cs @@ -4,7 +4,9 @@ using System.Linq; using System.Reflection; using System.Windows; using System.Windows.Controls; + using DataGridExtensions; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.ILSpy.Metadata @@ -45,7 +47,8 @@ namespace ICSharpCode.ILSpy.Metadata var filter = Filter; - if (filter == null || filter.Mask == -1) { + if (filter == null || filter.Mask == -1) + { listBox?.SelectAll(); } } @@ -54,7 +57,8 @@ namespace ICSharpCode.ILSpy.Metadata { var filter = Filter; - if (filter == null || filter.Mask == -1) { + if (filter == null || filter.Mask == -1) + { listBox?.SelectAll(); return; } @@ -62,8 +66,10 @@ namespace ICSharpCode.ILSpy.Metadata if (listBox?.SelectedItems.Count != 0) return; - foreach (var item in listBox.Items.Cast()) { - if ((item.Value & filter.Mask) != 0 || item.Value == 0) { + foreach (var item in listBox.Items.Cast()) + { + if ((item.Value & filter.Mask) != 0 || item.Value == 0) + { listBox.SelectedItems.Add(item); } } @@ -71,12 +77,14 @@ namespace ICSharpCode.ILSpy.Metadata private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { - if (e.RemovedItems?.OfType().Any(f => f.Value == -1) == true) { + if (e.RemovedItems?.OfType().Any(f => f.Value == -1) == true) + { Filter = new FlagsContentFilter(0); listBox.UnselectAll(); return; } - if (e.AddedItems?.OfType().Any(f => f.Value == -1) == true) { + if (e.AddedItems?.OfType().Any(f => f.Value == -1) == true) + { Filter = new FlagsContentFilter(-1); listBox.SelectAll(); return; @@ -85,7 +93,8 @@ namespace ICSharpCode.ILSpy.Metadata bool deselectAny = e.RemovedItems?.OfType().Any(f => f.Value != -1) == true; int mask = 0; - foreach (var item in listBox.SelectedItems.Cast()) { + foreach (var item in listBox.SelectedItems.Cast()) + { if (deselectAny && item.Value == -1) continue; mask |= item.Value; diff --git a/ILSpy/Metadata/FlagsTooltip.xaml.cs b/ILSpy/Metadata/FlagsTooltip.xaml.cs index d0a7d096f..8e670fca3 100644 --- a/ILSpy/Metadata/FlagsTooltip.xaml.cs +++ b/ILSpy/Metadata/FlagsTooltip.xaml.cs @@ -24,6 +24,7 @@ using System.Linq; using System.Reflection; using System.Windows; using System.Windows.Data; + using ICSharpCode.Decompiler.Util; namespace ICSharpCode.ILSpy.Metadata @@ -106,7 +107,8 @@ namespace ICSharpCode.ILSpy.Metadata var group = new SingleChoiceGroup(GetFlags(flagsType, mask, selectedValue, includeAny ? "" : null)); group.Header = header; group.SelectedFlag = group.Flags.SingleOrDefault(f => f.Value == selectedValue); - if (group.SelectedFlag.Name == null) { + if (group.SelectedFlag.Name == null) + { group.SelectedFlag = defaultFlag; } return group; @@ -117,7 +119,8 @@ namespace ICSharpCode.ILSpy.Metadata if (neutralItem != null) yield return new Flag(neutralItem, -1, false); - foreach (var item in flagsType.GetFields(BindingFlags.Static | BindingFlags.Public)) { + foreach (var item in flagsType.GetFields(BindingFlags.Static | BindingFlags.Public)) + { if (item.Name.EndsWith("Mask", StringComparison.Ordinal)) continue; int value = (int)CSharpPrimitiveCast.Cast(TypeCode.Int32, item.GetRawConstantValue(), false); diff --git a/ILSpy/Metadata/Helpers.cs b/ILSpy/Metadata/Helpers.cs index 6321f8ee3..cc60901db 100644 --- a/ILSpy/Metadata/Helpers.cs +++ b/ILSpy/Metadata/Helpers.cs @@ -31,7 +31,9 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; + using DataGridExtensions; + using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpy.Controls; using ICSharpCode.ILSpy.TextView; @@ -44,7 +46,8 @@ namespace ICSharpCode.ILSpy.Metadata { public static DataGrid PrepareDataGrid(TabPageModel tabPage, ILSpyTreeNode selectedNode) { - if (!(tabPage.Content is DataGrid view && view.Name == "MetadataView")) { + if (!(tabPage.Content is DataGrid view && view.Name == "MetadataView")) + { view = new MetaDataGrid() { Name = "MetadataView", GridLinesVisibility = DataGridGridLinesVisibility.None, @@ -111,7 +114,8 @@ namespace ICSharpCode.ILSpy.Metadata Binding = binding, ToolTipBinding = new Binding(e.PropertyName + "Tooltip") { Mode = BindingMode.OneWay } }; - switch (e.PropertyName) { + switch (e.PropertyName) + { case "RID": case "Meaning": e.Column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["DefaultFilter"]); @@ -126,26 +130,31 @@ namespace ICSharpCode.ILSpy.Metadata break; default: e.Cancel = e.PropertyName.Contains("Tooltip"); - if (!e.Cancel) { + if (!e.Cancel) + { e.Column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["DefaultFilter"]); } break; } - if (!e.Cancel) { + if (!e.Cancel) + { ApplyAttributes((PropertyDescriptor)e.PropertyDescriptor, binding, e.Column); } } static void ApplyAttributes(PropertyDescriptor descriptor, Binding binding, DataGridColumn column) { - if (descriptor.PropertyType.IsEnum) { + if (descriptor.PropertyType.IsEnum) + { binding.Converter = new UnderlyingEnumValueConverter(); column.SetTemplate((ControlTemplate)MetadataTableViews.Instance[descriptor.PropertyType.Name + "Filter"]); } var stringFormat = descriptor.Attributes.OfType().FirstOrDefault(); - if (stringFormat != null) { + if (stringFormat != null) + { binding.StringFormat = stringFormat.Format; - if (!descriptor.PropertyType.IsEnum && stringFormat.Format.StartsWith("X", StringComparison.OrdinalIgnoreCase)) { + if (!descriptor.PropertyType.IsEnum && stringFormat.Format.StartsWith("X", StringComparison.OrdinalIgnoreCase)) + { column.SetTemplate((ControlTemplate)MetadataTableViews.Instance["HexFilter"]); } } @@ -155,7 +164,8 @@ namespace ICSharpCode.ILSpy.Metadata public static unsafe int GetValue(byte* ptr, int size) { int result = 0; - for (int i = 0; i < size; i += 2) { + for (int i = 0; i < size; i += 2) + { result |= ptr[i] << 8 * i; result |= ptr[i + 1] << 8 * (i + 1); } @@ -210,7 +220,8 @@ namespace ICSharpCode.ILSpy.Metadata public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var t = value.GetType(); - if (t.IsEnum) { + if (t.IsEnum) + { return (int)CSharpPrimitiveCast.Cast(TypeCode.Int32, value, false); } return value; diff --git a/ILSpy/Metadata/HexFilterControl.xaml.cs b/ILSpy/Metadata/HexFilterControl.xaml.cs index b4ae0167b..9a50e0bed 100644 --- a/ILSpy/Metadata/HexFilterControl.xaml.cs +++ b/ILSpy/Metadata/HexFilterControl.xaml.cs @@ -12,6 +12,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; + using DataGridExtensions; namespace ICSharpCode.ILSpy.Metadata diff --git a/ILSpy/Metadata/MetadataProtocolHandler.cs b/ILSpy/Metadata/MetadataProtocolHandler.cs index 41d9ea749..ced6a7497 100644 --- a/ILSpy/Metadata/MetadataProtocolHandler.cs +++ b/ILSpy/Metadata/MetadataProtocolHandler.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Reflection.Metadata; using System.Text; using System.Threading.Tasks; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TreeNodes; @@ -22,7 +23,8 @@ namespace ICSharpCode.ILSpy.Metadata if (assemblyTreeNode == null) return null; var mxNode = assemblyTreeNode.Children.OfType().FirstOrDefault(); - if (mxNode != null) { + if (mxNode != null) + { mxNode.EnsureLazyChildren(); var node = mxNode.FindNodeByHandleKind(handle.Kind); node?.ScrollTo(handle); diff --git a/ILSpy/Metadata/MetadataTableTreeNode.cs b/ILSpy/Metadata/MetadataTableTreeNode.cs index 8daea15c9..a2644484b 100644 --- a/ILSpy/Metadata/MetadataTableTreeNode.cs +++ b/ILSpy/Metadata/MetadataTableTreeNode.cs @@ -21,6 +21,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Windows.Controls; using System.Windows.Threading; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; diff --git a/ILSpy/Metadata/MetadataTableViews.xaml.cs b/ILSpy/Metadata/MetadataTableViews.xaml.cs index 2c86e552a..025c8041b 100644 --- a/ILSpy/Metadata/MetadataTableViews.xaml.cs +++ b/ILSpy/Metadata/MetadataTableViews.xaml.cs @@ -29,7 +29,8 @@ namespace ICSharpCode.ILSpy.Metadata public static MetadataTableViews Instance { get { - if (instance == null) { + if (instance == null) + { instance = new MetadataTableViews(); } return instance; diff --git a/ILSpy/Metadata/MetadataTreeNode.cs b/ILSpy/Metadata/MetadataTreeNode.cs index 6a6f9d4f4..34995d7f3 100644 --- a/ILSpy/Metadata/MetadataTreeNode.cs +++ b/ILSpy/Metadata/MetadataTreeNode.cs @@ -27,6 +27,7 @@ using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Data; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Options; diff --git a/ILSpy/Metadata/OptionalHeaderTreeNode.cs b/ILSpy/Metadata/OptionalHeaderTreeNode.cs index 28c939771..cc7c6db30 100644 --- a/ILSpy/Metadata/OptionalHeaderTreeNode.cs +++ b/ILSpy/Metadata/OptionalHeaderTreeNode.cs @@ -21,6 +21,7 @@ using System.Reflection.PortableExecutable; using System.Windows; using System.Windows.Controls; using System.Windows.Data; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TextView; diff --git a/ILSpy/NativeMethods.cs b/ILSpy/NativeMethods.cs index 3805f3a23..87f087a68 100644 --- a/ILSpy/NativeMethods.cs +++ b/ILSpy/NativeMethods.cs @@ -17,10 +17,10 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Text; -using System.Runtime.InteropServices; using System.ComponentModel; using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Text; namespace ICSharpCode.ILSpy { @@ -82,13 +82,17 @@ namespace ICSharpCode.ILSpy char** arr = CommandLineToArgvW(commandLine, out numberOfArgs); if (arr == null) throw new Win32Exception(); - try { + try + { string[] result = new string[numberOfArgs]; - for (int i = 0; i < numberOfArgs; i++) { + for (int i = 0; i < numberOfArgs; i++) + { result[i] = new string(arr[i]); } return result; - } finally { + } + finally + { // Free memory obtained by CommandLineToArgW. LocalFree(new IntPtr(arr)); } @@ -110,7 +114,8 @@ namespace ICSharpCode.ILSpy if (arguments == null) return null; StringBuilder b = new StringBuilder(); - for (int i = 0; i < arguments.Length; i++) { + for (int i = 0; i < arguments.Length; i++) + { if (i > 0) b.Append(' '); AppendArgument(b, arguments[i]); @@ -120,27 +125,38 @@ namespace ICSharpCode.ILSpy static void AppendArgument(StringBuilder b, string arg) { - if (arg == null) { + if (arg == null) + { return; } - if (arg.Length > 0 && arg.IndexOfAny(charsNeedingQuoting) < 0) { + if (arg.Length > 0 && arg.IndexOfAny(charsNeedingQuoting) < 0) + { b.Append(arg); - } else { + } + else + { b.Append('"'); - for (int j = 0; ; j++) { + for (int j = 0; ; j++) + { int backslashCount = 0; - while (j < arg.Length && arg[j] == '\\') { + while (j < arg.Length && arg[j] == '\\') + { backslashCount++; j++; } - if (j == arg.Length) { + if (j == arg.Length) + { b.Append('\\', backslashCount * 2); break; - } else if (arg[j] == '"') { + } + else if (arg[j] == '"') + { b.Append('\\', backslashCount * 2 + 1); b.Append('"'); - } else { + } + else + { b.Append('\\', backslashCount); b.Append(arg[j]); } @@ -154,17 +170,25 @@ namespace ICSharpCode.ILSpy { int processId; GetWindowThreadProcessId(hWnd, &processId); - try { - using (var p = Process.GetProcessById(processId)) { + try + { + using (var p = Process.GetProcessById(processId)) + { return p.ProcessName; } - } catch (ArgumentException ex) { + } + catch (ArgumentException ex) + { Debug.WriteLine(ex.Message); return null; - } catch (InvalidOperationException ex) { + } + catch (InvalidOperationException ex) + { Debug.WriteLine(ex.Message); return null; - } catch (Win32Exception ex) { + } + catch (Win32Exception ex) + { Debug.WriteLine(ex.Message); return null; } diff --git a/ILSpy/NavigationHistory.cs b/ILSpy/NavigationHistory.cs index 976324e15..a17ab9d78 100644 --- a/ILSpy/NavigationHistory.cs +++ b/ILSpy/NavigationHistory.cs @@ -33,15 +33,15 @@ namespace ICSharpCode.ILSpy T current; List back = new List(); List forward = new List(); - + public bool CanNavigateBack { get { return back.Count > 0; } } - + public bool CanNavigateForward { get { return forward.Count > 0; } } - + public T GoBack() { forward.Add(current); @@ -49,7 +49,7 @@ namespace ICSharpCode.ILSpy back.RemoveAt(back.Count - 1); return current; } - + public T GoForward() { back.Add(current); @@ -63,7 +63,7 @@ namespace ICSharpCode.ILSpy back.RemoveAll(predicate); forward.RemoveAll(predicate); } - + public void Clear() { back.Clear(); @@ -74,15 +74,18 @@ namespace ICSharpCode.ILSpy { current = node; } - + public void Record(T node) { var navigationTime = DateTime.Now; var period = navigationTime - lastNavigationTime; - if (period.TotalSeconds < NavigationSecondsBeforeNewEntry) { + if (period.TotalSeconds < NavigationSecondsBeforeNewEntry) + { current = node; - } else { + } + else + { if (current != null) back.Add(current); diff --git a/ILSpy/NavigationState.cs b/ILSpy/NavigationState.cs index 008ad9f4a..0b9eceafd 100644 --- a/ILSpy/NavigationState.cs +++ b/ILSpy/NavigationState.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; + using ICSharpCode.ILSpy.TextView; using ICSharpCode.TreeView; diff --git a/ILSpy/Options/DecompilerSettingsPanel.xaml.cs b/ILSpy/Options/DecompilerSettingsPanel.xaml.cs index a9d87b515..665b5e081 100644 --- a/ILSpy/Options/DecompilerSettingsPanel.xaml.cs +++ b/ILSpy/Options/DecompilerSettingsPanel.xaml.cs @@ -24,6 +24,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Xml.Linq; + using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy.Options @@ -58,7 +59,8 @@ namespace ICSharpCode.ILSpy.Options var newSettings = new Decompiler.DecompilerSettings(); var properties = typeof(Decompiler.DecompilerSettings).GetProperties() .Where(p => p.GetCustomAttribute()?.Browsable != false); - foreach (var p in properties) { + foreach (var p in properties) + { var value = (bool?)e.Attribute(p.Name); if (value.HasValue) p.SetValue(newSettings, value.Value); @@ -77,7 +79,8 @@ namespace ICSharpCode.ILSpy.Options var newSettings = ((DecompilerSettings)this.DataContext).ToDecompilerSettings(); var properties = typeof(Decompiler.DecompilerSettings).GetProperties() .Where(p => p.GetCustomAttribute()?.Browsable != false); - foreach (var p in properties) { + foreach (var p in properties) + { section.SetAttributeValue(p.Name, p.GetValue(newSettings)); } XElement existingElement = root.Element("DecompilerSettings"); @@ -100,8 +103,10 @@ namespace ICSharpCode.ILSpy.Options void CheckGroup(CollectionViewGroup group, bool value) { - foreach (var item in group.Items) { - switch (item) { + foreach (var item in group.Items) + { + switch (item) + { case CollectionViewGroup subGroup: CheckGroup(subGroup, value); break; @@ -115,8 +120,10 @@ namespace ICSharpCode.ILSpy.Options bool IsGroupChecked(CollectionViewGroup group) { bool value = true; - foreach (var item in group.Items) { - switch (item) { + foreach (var item in group.Items) + { + switch (item) + { case CollectionViewGroup subGroup: value = value && IsGroupChecked(subGroup); break; @@ -165,7 +172,8 @@ namespace ICSharpCode.ILSpy.Options public Decompiler.DecompilerSettings ToDecompilerSettings() { var settings = new Decompiler.DecompilerSettings(); - foreach (var item in Settings) { + foreach (var item in Settings) + { item.Property.SetValue(settings, item.IsEnabled); } return settings; @@ -179,8 +187,8 @@ namespace ICSharpCode.ILSpy.Options public CSharpDecompilerSetting(PropertyInfo p) { this.Property = p; - this.Category = GetResourceString(p.GetCustomAttribute()?.Category ?? Resources.Other); - this.Description = GetResourceString(p.GetCustomAttribute()?.Description ?? p.Name); + this.Category = GetResourceString(p.GetCustomAttribute()?.Category ?? Resources.Other); + this.Description = GetResourceString(p.GetCustomAttribute()?.Description ?? p.Name); } public PropertyInfo Property { get; } @@ -188,7 +196,8 @@ namespace ICSharpCode.ILSpy.Options public bool IsEnabled { get => isEnabled; set { - if (value != isEnabled) { + if (value != isEnabled) + { isEnabled = value; OnPropertyChanged(); } diff --git a/ILSpy/Options/DisplaySettings.cs b/ILSpy/Options/DisplaySettings.cs index 301bcd694..deaba047f 100644 --- a/ILSpy/Options/DisplaySettings.cs +++ b/ILSpy/Options/DisplaySettings.cs @@ -37,51 +37,54 @@ namespace ICSharpCode.ILSpy.Options this.indentationTabSize = 4; this.highlightMatchingBraces = true; } - + #region INotifyPropertyChanged implementation public event PropertyChangedEventHandler PropertyChanged; - + protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { PropertyChanged?.Invoke(this, e); } - + protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); } #endregion - + FontFamily selectedFont; - + public FontFamily SelectedFont { get { return selectedFont; } set { - if (selectedFont != value) { + if (selectedFont != value) + { selectedFont = value; OnPropertyChanged(); } } } - + double selectedFontSize; - + public double SelectedFontSize { get { return selectedFontSize; } set { - if (selectedFontSize != value) { + if (selectedFontSize != value) + { selectedFontSize = value; OnPropertyChanged(); } } } - + bool showLineNumbers; - + public bool ShowLineNumbers { get { return showLineNumbers; } set { - if (showLineNumbers != value) { + if (showLineNumbers != value) + { showLineNumbers = value; OnPropertyChanged(); } @@ -93,7 +96,8 @@ namespace ICSharpCode.ILSpy.Options public bool ShowMetadataTokens { get { return showMetadataTokens; } set { - if (showMetadataTokens != value) { + if (showMetadataTokens != value) + { showMetadataTokens = value; OnPropertyChanged(); } @@ -105,7 +109,8 @@ namespace ICSharpCode.ILSpy.Options public bool ShowMetadataTokensInBase10 { get { return showMetadataTokensInBase10; } set { - if (showMetadataTokensInBase10 != value) { + if (showMetadataTokensInBase10 != value) + { showMetadataTokensInBase10 = value; OnPropertyChanged(); } @@ -114,12 +119,11 @@ namespace ICSharpCode.ILSpy.Options bool enableWordWrap; - public bool EnableWordWrap - { + public bool EnableWordWrap { get { return enableWordWrap; } - set - { - if (enableWordWrap != value) { + set { + if (enableWordWrap != value) + { enableWordWrap = value; OnPropertyChanged(); } @@ -131,7 +135,8 @@ namespace ICSharpCode.ILSpy.Options public bool SortResults { get { return sortResults; } set { - if (sortResults != value) { + if (sortResults != value) + { sortResults = value; OnPropertyChanged(); } @@ -143,7 +148,8 @@ namespace ICSharpCode.ILSpy.Options public bool FoldBraces { get { return foldBraces; } set { - if (foldBraces != value) { + if (foldBraces != value) + { foldBraces = value; OnPropertyChanged(); } @@ -155,7 +161,8 @@ namespace ICSharpCode.ILSpy.Options public bool ExpandMemberDefinitions { get { return expandMemberDefinitions; } set { - if (expandMemberDefinitions != value) { + if (expandMemberDefinitions != value) + { expandMemberDefinitions = value; OnPropertyChanged(); } @@ -167,7 +174,8 @@ namespace ICSharpCode.ILSpy.Options public bool ExpandUsingDeclarations { get { return expandUsingDeclarations; } set { - if (expandUsingDeclarations != value) { + if (expandUsingDeclarations != value) + { expandUsingDeclarations = value; OnPropertyChanged(); } @@ -179,7 +187,8 @@ namespace ICSharpCode.ILSpy.Options public bool ShowDebugInfo { get { return showDebugInfo; } set { - if (showDebugInfo != value) { + if (showDebugInfo != value) + { showDebugInfo = value; OnPropertyChanged(); } @@ -191,7 +200,8 @@ namespace ICSharpCode.ILSpy.Options public bool IndentationUseTabs { get { return indentationUseTabs; } set { - if (indentationUseTabs != value) { + if (indentationUseTabs != value) + { indentationUseTabs = value; OnPropertyChanged(); } @@ -203,7 +213,8 @@ namespace ICSharpCode.ILSpy.Options public int IndentationTabSize { get { return indentationTabSize; } set { - if (indentationTabSize != value) { + if (indentationTabSize != value) + { indentationTabSize = value; OnPropertyChanged(); } @@ -215,7 +226,8 @@ namespace ICSharpCode.ILSpy.Options public int IndentationSize { get { return indentationSize; } set { - if (indentationSize != value) { + if (indentationSize != value) + { indentationSize = value; OnPropertyChanged(); } @@ -227,7 +239,8 @@ namespace ICSharpCode.ILSpy.Options public bool HighlightMatchingBraces { get { return highlightMatchingBraces; } set { - if (highlightMatchingBraces != value) { + if (highlightMatchingBraces != value) + { highlightMatchingBraces = value; OnPropertyChanged(); } @@ -239,7 +252,8 @@ namespace ICSharpCode.ILSpy.Options public bool HideEmptyMetadataTables { get { return hideEmptyMetadataTables; } set { - if (hideEmptyMetadataTables != value) { + if (hideEmptyMetadataTables != value) + { hideEmptyMetadataTables = value; OnPropertyChanged(); } diff --git a/ILSpy/Options/DisplaySettingsPanel.xaml.cs b/ILSpy/Options/DisplaySettingsPanel.xaml.cs index f64b45718..720fd6bd2 100644 --- a/ILSpy/Options/DisplaySettingsPanel.xaml.cs +++ b/ILSpy/Options/DisplaySettingsPanel.xaml.cs @@ -44,14 +44,16 @@ namespace ICSharpCode.ILSpy.Options Task task = new Task(FontLoader); task.Start(); task.ContinueWith( - delegate(Task continuation) { + delegate (Task continuation) { App.Current.Dispatcher.Invoke( DispatcherPriority.Normal, (Action)( () => { fontSelector.ItemsSource = task.Result; - if (continuation.Exception != null) { - foreach (var ex in continuation.Exception.InnerExceptions) { + if (continuation.Exception != null) + { + foreach (var ex in continuation.Exception.InnerExceptions) + { MessageBox.Show(ex.ToString()); } } @@ -65,29 +67,33 @@ namespace ICSharpCode.ILSpy.Options { this.DataContext = LoadDisplaySettings(settings); } - + static DisplaySettings currentDisplaySettings; - + public static DisplaySettings CurrentDisplaySettings { get { return currentDisplaySettings ?? (currentDisplaySettings = LoadDisplaySettings(ILSpySettings.Load())); } } - + static bool IsSymbolFont(FontFamily fontFamily) { - foreach (var tf in fontFamily.GetTypefaces()) { + foreach (var tf in fontFamily.GetTypefaces()) + { GlyphTypeface glyph; - try { + try + { if (tf.TryGetGlyphTypeface(out glyph)) return glyph.Symbol; - } catch (Exception) { + } + catch (Exception) + { return true; } } return false; } - + static FontFamily[] FontLoader() { return (from ff in Fonts.SystemFontFamilies @@ -95,7 +101,7 @@ namespace ICSharpCode.ILSpy.Options orderby ff.Source select ff).ToArray(); } - + public static DisplaySettings LoadDisplaySettings(ILSpySettings settings) { XElement e = settings["DisplaySettings"]; @@ -119,11 +125,11 @@ namespace ICSharpCode.ILSpy.Options return s; } - + public void Save(XElement root) { var s = (DisplaySettings)this.DataContext; - + var section = new XElement("DisplaySettings"); section.SetAttributeValue("Font", s.SelectedFont.Source); section.SetAttributeValue("FontSize", s.SelectedFontSize); @@ -178,21 +184,23 @@ namespace ICSharpCode.ILSpy.Options { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { - if (value is double d) { + if (value is double d) + { return Math.Round(d / 4 * 3); } - + throw new NotImplementedException(); } - + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { - if (value is string s) { + if (value is string s) + { if (double.TryParse(s, out double d)) return d * 4 / 3; return 11.0 * 4 / 3; } - + throw new NotImplementedException(); } } diff --git a/ILSpy/Options/MiscSettings.cs b/ILSpy/Options/MiscSettings.cs index 4802b9d3a..b111508fc 100644 --- a/ILSpy/Options/MiscSettings.cs +++ b/ILSpy/Options/MiscSettings.cs @@ -23,7 +23,9 @@ using System.Runtime.CompilerServices; using System.Security.Principal; using System.Windows; using System.Windows.Input; + using ICSharpCode.ILSpy.Commands; + using Microsoft.Win32; namespace ICSharpCode.ILSpy.Options @@ -41,11 +43,11 @@ namespace ICSharpCode.ILSpy.Options /// /// Allow multiple instances. /// - public bool AllowMultipleInstances - { + public bool AllowMultipleInstances { get { return allowMultipleInstances; } set { - if (allowMultipleInstances != value) { + if (allowMultipleInstances != value) + { allowMultipleInstances = value; OnPropertyChanged(); } @@ -58,7 +60,8 @@ namespace ICSharpCode.ILSpy.Options public bool LoadPreviousAssemblies { get { return loadPreviousAssemblies; } set { - if (loadPreviousAssemblies != value) { + if (loadPreviousAssemblies != value) + { loadPreviousAssemblies = value; OnPropertyChanged(); } @@ -73,13 +76,18 @@ namespace ICSharpCode.ILSpy.Options private void AddRemoveShellIntegration(object obj) { string commandLine = NativeMethods.ArgumentArrayToCommandLine(Assembly.GetEntryAssembly().Location) + " \"%L\""; - if (RegistryEntriesExist()) { - if (MessageBox.Show(string.Format(Properties.Resources.RemoveShellIntegrationMessage, commandLine), "ILSpy", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) { + if (RegistryEntriesExist()) + { + if (MessageBox.Show(string.Format(Properties.Resources.RemoveShellIntegrationMessage, commandLine), "ILSpy", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) + { Registry.CurrentUser.CreateSubKey(string.Format(rootPath, "dllfile")).DeleteSubKeyTree("Open with ILSpy"); Registry.CurrentUser.CreateSubKey(string.Format(rootPath, "exefile")).DeleteSubKeyTree("Open with ILSpy"); } - } else { - if (MessageBox.Show(string.Format(Properties.Resources.AddShellIntegrationMessage, commandLine), "ILSpy", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) { + } + else + { + if (MessageBox.Show(string.Format(Properties.Resources.AddShellIntegrationMessage, commandLine), "ILSpy", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) + { Registry.CurrentUser.CreateSubKey(string.Format(fullPath, "dllfile"))? .SetValue("", commandLine); Registry.CurrentUser.CreateSubKey(string.Format(fullPath, "exefile"))? diff --git a/ILSpy/Options/MiscSettingsPanel.xaml.cs b/ILSpy/Options/MiscSettingsPanel.xaml.cs index 866efcf0a..1297ed74c 100644 --- a/ILSpy/Options/MiscSettingsPanel.xaml.cs +++ b/ILSpy/Options/MiscSettingsPanel.xaml.cs @@ -24,7 +24,7 @@ namespace ICSharpCode.ILSpy.Options /// /// Interaction logic for MiscSettingsPanel.xaml /// - [ExportOptionPage(Title =nameof(Properties.Resources.Misc), Order = 30)] + [ExportOptionPage(Title = nameof(Properties.Resources.Misc), Order = 30)] public partial class MiscSettingsPanel : UserControl, IOptionPage { public MiscSettingsPanel() diff --git a/ILSpy/Options/OptionsDialog.xaml.cs b/ILSpy/Options/OptionsDialog.xaml.cs index b6f2161da..7e3d20277 100644 --- a/ILSpy/Options/OptionsDialog.xaml.cs +++ b/ILSpy/Options/OptionsDialog.xaml.cs @@ -22,6 +22,7 @@ using System.Linq; using System.Windows; using System.Windows.Controls; using System.Xml.Linq; + using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy.Options @@ -31,9 +32,9 @@ namespace ICSharpCode.ILSpy.Options /// public partial class OptionsDialog : Window { - + readonly Lazy[] optionPages; - + public OptionsDialog() { InitializeComponent(); @@ -43,23 +44,25 @@ namespace ICSharpCode.ILSpy.Options var ep = App.ExportProviderFactory.CreateExportProvider(); this.optionPages = ep.GetExports("OptionPages").ToArray(); ILSpySettings settings = ILSpySettings.Load(); - foreach (var optionPage in optionPages.OrderBy(p => p.Metadata.Order)) { + foreach (var optionPage in optionPages.OrderBy(p => p.Metadata.Order)) + { TabItem tabItem = new TabItem(); - tabItem.Header = MainWindow.GetResourceString( optionPage.Metadata.Title); + tabItem.Header = MainWindow.GetResourceString(optionPage.Metadata.Title); tabItem.Content = optionPage.Value; tabControl.Items.Add(tabItem); - + IOptionPage page = optionPage.Value as IOptionPage; if (page != null) page.Load(settings); } } - + void OKButton_Click(object sender, RoutedEventArgs e) { ILSpySettings.Update( delegate (XElement root) { - foreach (var optionPage in optionPages) { + foreach (var optionPage in optionPages) + { IOptionPage page = optionPage.Value as IOptionPage; if (page != null) page.Save(root); @@ -71,7 +74,8 @@ namespace ICSharpCode.ILSpy.Options private void DefaultsButton_Click(object sender, RoutedEventArgs e) { - if (MessageBox.Show(Properties.Resources.ResetToDefaultsConfirmationMessage, "ILSpy", MessageBoxButton.YesNo) == MessageBoxResult.Yes) { + if (MessageBox.Show(Properties.Resources.ResetToDefaultsConfirmationMessage, "ILSpy", MessageBoxButton.YesNo) == MessageBoxResult.Yes) + { var page = ((TabItem)tabControl.SelectedItem).Content as IOptionPage; if (page != null) page.LoadDefaults(); @@ -84,34 +88,35 @@ namespace ICSharpCode.ILSpy.Options string Title { get; } int Order { get; } } - + public interface IOptionPage { void Load(ILSpySettings settings); void Save(XElement root); void LoadDefaults(); } - + [MetadataAttribute] - [AttributeUsage(AttributeTargets.Class, AllowMultiple=false)] + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class ExportOptionPageAttribute : ExportAttribute { public ExportOptionPageAttribute() : base("OptionPages", typeof(UIElement)) { } - + public string Title { get; set; } - + public int Order { get; set; } } - - [ExportMainMenuCommand(Menu = nameof(Resources._View), Header = nameof(Resources._Options), MenuCategory = nameof(Resources.Options) ,MenuOrder = 999)] + + [ExportMainMenuCommand(Menu = nameof(Resources._View), Header = nameof(Resources._Options), MenuCategory = nameof(Resources.Options), MenuOrder = 999)] sealed class ShowOptionsCommand : SimpleCommand { public override void Execute(object parameter) { OptionsDialog dlg = new OptionsDialog(); dlg.Owner = MainWindow.Instance; - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { new RefreshCommand().Execute(parameter); } } diff --git a/ILSpy/Properties/AssemblyInfo.template.cs b/ILSpy/Properties/AssemblyInfo.template.cs index 6dd541349..6ca79f2d3 100644 --- a/ILSpy/Properties/AssemblyInfo.template.cs +++ b/ILSpy/Properties/AssemblyInfo.template.cs @@ -1,11 +1,11 @@ #region Using directives using System; -using System.Resources; +using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Diagnostics.CodeAnalysis; #endregion @@ -41,6 +41,6 @@ internal static class RevisionClass public const string Build = "0"; public const string Revision = "$INSERTREVISION$"; public const string VersionName = "preview1"; - + public const string FullVersion = Major + "." + Minor + "." + Build + ".$INSERTREVISION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$"; } diff --git a/ILSpy/Search/AbstractEntitySearchStrategy.cs b/ILSpy/Search/AbstractEntitySearchStrategy.cs index e969c69c3..9e711c084 100644 --- a/ILSpy/Search/AbstractEntitySearchStrategy.cs +++ b/ILSpy/Search/AbstractEntitySearchStrategy.cs @@ -3,13 +3,14 @@ using System.Collections.Concurrent; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Media; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; namespace ICSharpCode.ILSpy.Search { - abstract class AbstractEntitySearchStrategy : AbstractSearchStrategy + abstract class AbstractEntitySearchStrategy : AbstractSearchStrategy { protected readonly Language language; protected readonly ApiVisibility apiVisibility; @@ -26,13 +27,17 @@ namespace ICSharpCode.ILSpy.Search if (apiVisibility == ApiVisibility.All) return true; - do { - if (apiVisibility == ApiVisibility.PublicOnly) { + do + { + if (apiVisibility == ApiVisibility.PublicOnly) + { if (!(entity.Accessibility == Accessibility.Public || entity.Accessibility == Accessibility.Protected || entity.Accessibility == Accessibility.ProtectedOrInternal)) return false; - } else if (apiVisibility == ApiVisibility.PublicAndInternal) { + } + else if (apiVisibility == ApiVisibility.PublicAndInternal) + { if (!language.ShowMember(entity)) return false; } @@ -67,13 +72,15 @@ namespace ICSharpCode.ILSpy.Search string text = member.Name; // Probably compiler generated types without meaningful names, show them last - if (text.StartsWith("<")) { + if (text.StartsWith("<")) + { return 0; } // Constructors always have the same name in IL: // Use type name instead - if (text == ".cctor" || text == ".ctor") { + if (text == ".cctor" || text == ".ctor") + { text = member.DeclaringType.Name; } @@ -85,7 +92,8 @@ namespace ICSharpCode.ILSpy.Search string GetLanguageSpecificName(IEntity member) { - switch (member) { + switch (member) + { case ITypeDefinition t: return language.TypeToString(t, false); case IField f: @@ -103,7 +111,8 @@ namespace ICSharpCode.ILSpy.Search static internal ImageSource GetIcon(IEntity member) { - switch (member) { + switch (member) + { case ITypeDefinition t: return TypeTreeNode.GetIcon(t); case IField f: diff --git a/ILSpy/Search/AbstractSearchStrategy.cs b/ILSpy/Search/AbstractSearchStrategy.cs index 7af565262..74e6cd2c3 100644 --- a/ILSpy/Search/AbstractSearchStrategy.cs +++ b/ILSpy/Search/AbstractSearchStrategy.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Media; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; @@ -21,16 +22,20 @@ namespace ICSharpCode.ILSpy.Search { this.resultQueue = resultQueue; - if (terms.Length == 1 && terms[0].Length > 2) { + if (terms.Length == 1 && terms[0].Length > 2) + { string search = terms[0]; - if (search.StartsWith("/", StringComparison.Ordinal) && search.Length > 4) { + if (search.StartsWith("/", StringComparison.Ordinal) && search.Length > 4) + { var regexString = search.Substring(1, search.Length - 1); fullNameSearch = search.Contains("\\."); omitGenerics = !search.Contains("<"); if (regexString.EndsWith("/", StringComparison.Ordinal)) regexString = regexString.Substring(0, regexString.Length - 1); regex = SafeNewRegex(regexString); - } else { + } + else + { fullNameSearch = search.Contains("."); omitGenerics = !search.Contains("<"); } @@ -42,16 +47,20 @@ namespace ICSharpCode.ILSpy.Search protected virtual bool IsMatch(string name) { - if (regex != null) { + if (regex != null) + { return regex.IsMatch(name); } - for (int i = 0; i < searchTerm.Length; ++i) { + for (int i = 0; i < searchTerm.Length; ++i) + { // How to handle overlapping matches? var term = searchTerm[i]; - if (string.IsNullOrEmpty(term)) continue; + if (string.IsNullOrEmpty(term)) + continue; string text = name; - switch (term[0]) { + switch (term[0]) + { case '+': // must contain term = term.Substring(1); goto default; @@ -60,16 +69,16 @@ namespace ICSharpCode.ILSpy.Search return false; break; case '=': // exact match - { - var equalCompareLength = text.IndexOf('`'); - if (equalCompareLength == -1) - equalCompareLength = text.Length; + { + var equalCompareLength = text.IndexOf('`'); + if (equalCompareLength == -1) + equalCompareLength = text.Length; - if (term.Length > 1 && String.Compare(term, 1, text, 0, Math.Max(term.Length, equalCompareLength), - StringComparison.OrdinalIgnoreCase) != 0) - return false; - } - break; + if (term.Length > 1 && String.Compare(term, 1, text, 0, Math.Max(term.Length, equalCompareLength), + StringComparison.OrdinalIgnoreCase) != 0) + return false; + } + break; case '~': if (term.Length > 1 && !IsNoncontiguousMatch(text.ToLower(), term.Substring(1).ToLower())) return false; @@ -85,17 +94,22 @@ namespace ICSharpCode.ILSpy.Search bool IsNoncontiguousMatch(string text, string searchTerm) { - if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(searchTerm)) { + if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(searchTerm)) + { return false; } var textLength = text.Length; - if (searchTerm.Length > textLength) { + if (searchTerm.Length > textLength) + { return false; } var i = 0; - for (int searchIndex = 0; searchIndex < searchTerm.Length;) { - while (i != textLength) { - if (text[i] == searchTerm[searchIndex]) { + for (int searchIndex = 0; searchIndex < searchTerm.Length;) + { + while (i != textLength) + { + if (text[i] == searchTerm[searchIndex]) + { // Check if all characters in searchTerm have been matched if (searchTerm.Length == ++searchIndex) return true; @@ -117,9 +131,12 @@ namespace ICSharpCode.ILSpy.Search Regex SafeNewRegex(string unsafePattern) { - try { + try + { return new Regex(unsafePattern, RegexOptions.Compiled); - } catch (ArgumentException) { + } + catch (ArgumentException) + { return null; } } diff --git a/ILSpy/Search/AssemblySearchStrategy.cs b/ILSpy/Search/AssemblySearchStrategy.cs index 30859b3a2..d13d658ba 100644 --- a/ILSpy/Search/AssemblySearchStrategy.cs +++ b/ILSpy/Search/AssemblySearchStrategy.cs @@ -7,6 +7,7 @@ using System.Reflection.Metadata; using System.Threading; using System.Windows.Media; using System.Windows.Media.Imaging; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -34,7 +35,8 @@ namespace ICSharpCode.ILSpy.Search { cancellationToken.ThrowIfCancellationRequested(); - if (searchKind == AssemblySearchKind.NameOrFileName) { + if (searchKind == AssemblySearchKind.NameOrFileName) + { string localName = GetNameToMatch(module, AssemblySearchKind.Name); string fileName = Path.GetFileName(GetNameToMatch(module, AssemblySearchKind.FilePath)); if (IsMatch(localName) || IsMatch(fileName)) @@ -49,7 +51,8 @@ namespace ICSharpCode.ILSpy.Search string GetNameToMatch(PEFile module, AssemblySearchKind kind) { - switch (kind) { + switch (kind) + { case AssemblySearchKind.FullName: return module.FullName; case AssemblySearchKind.Name: @@ -64,7 +67,8 @@ namespace ICSharpCode.ILSpy.Search var metadata = module.Metadata; var definition = module.Metadata.GetAssemblyDefinition(); - switch (kind) { + switch (kind) + { case AssemblySearchKind.Culture: if (definition.Culture.IsNil) return "neutral"; diff --git a/ILSpy/Search/LiteralSearchStrategy.cs b/ILSpy/Search/LiteralSearchStrategy.cs index a20c5909c..78b51db33 100644 --- a/ILSpy/Search/LiteralSearchStrategy.cs +++ b/ILSpy/Search/LiteralSearchStrategy.cs @@ -1,17 +1,19 @@ using System; -using ICSharpCode.Decompiler.Util; -using ICSharpCode.Decompiler.Disassembler; -using SRM = System.Reflection.Metadata; -using ILOpCode = System.Reflection.Metadata.ILOpCode; -using ICSharpCode.Decompiler; - -using static System.Reflection.Metadata.PEReaderExtensions; -using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.Metadata; +using System.Collections.Concurrent; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Threading; -using System.Collections.Concurrent; + +using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.Disassembler; +using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Util; + +using static System.Reflection.Metadata.PEReaderExtensions; + +using ILOpCode = System.Reflection.Metadata.ILOpCode; +using SRM = System.Reflection.Metadata; namespace ICSharpCode.ILSpy.Search { @@ -23,13 +25,16 @@ namespace ICSharpCode.ILSpy.Search public LiteralSearchStrategy(Language language, ApiVisibility apiVisibility, IProducerConsumerCollection resultQueue, params string[] terms) : base(language, apiVisibility, resultQueue, terms) { - if (terms.Length == 1) { + if (terms.Length == 1) + { var lexer = new Lexer(new LATextReader(new System.IO.StringReader(terms[0]))); var value = lexer.NextToken(); - if (value != null && value.LiteralValue != null) { + if (value != null && value.LiteralValue != null) + { TypeCode valueType = Type.GetTypeCode(value.LiteralValue.GetType()); - switch (valueType) { + switch (valueType) + { case TypeCode.Byte: case TypeCode.SByte: case TypeCode.Int16: @@ -57,18 +62,23 @@ namespace ICSharpCode.ILSpy.Search cancellationToken.ThrowIfCancellationRequested(); var metadata = module.Metadata; var typeSystem = module.GetTypeSystemWithCurrentOptionsOrNull(); - if (typeSystem == null) return; + if (typeSystem == null) + return; - foreach (var handle in metadata.MethodDefinitions) { + foreach (var handle in metadata.MethodDefinitions) + { cancellationToken.ThrowIfCancellationRequested(); var md = metadata.GetMethodDefinition(handle); - if (!md.HasBody() || !MethodIsLiteralMatch(module, md)) continue; + if (!md.HasBody() || !MethodIsLiteralMatch(module, md)) + continue; var method = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle); - if (!CheckVisibility(method)) continue; + if (!CheckVisibility(method)) + continue; OnFoundResult(method); } - foreach (var handle in metadata.FieldDefinitions) { + foreach (var handle in metadata.FieldDefinitions) + { cancellationToken.ThrowIfCancellationRequested(); var fd = metadata.GetFieldDefinition(handle); if (!fd.HasFlag(System.Reflection.FieldAttributes.Literal)) @@ -81,7 +91,8 @@ namespace ICSharpCode.ILSpy.Search if (!IsLiteralMatch(metadata, blob.ReadConstant(constant.TypeCode))) continue; IField field = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle); - if (!CheckVisibility(field)) continue; + if (!CheckVisibility(field)) + continue; OnFoundResult(field); } } @@ -90,7 +101,8 @@ namespace ICSharpCode.ILSpy.Search { if (val == null) return false; - switch (searchTermLiteralType) { + switch (searchTermLiteralType) + { case TypeCode.Int64: TypeCode tc = Type.GetTypeCode(val.GetType()); if (tc >= TypeCode.SByte && tc <= TypeCode.UInt64) @@ -110,11 +122,14 @@ namespace ICSharpCode.ILSpy.Search bool MethodIsLiteralMatch(PEFile module, MethodDefinition methodDefinition) { var blob = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress).GetILReader(); - if (searchTermLiteralType == TypeCode.Int64) { + if (searchTermLiteralType == TypeCode.Int64) + { long val = (long)searchTermLiteralValue; - while (blob.RemainingBytes > 0) { + while (blob.RemainingBytes > 0) + { ILOpCode code; - switch (code = ILParser.DecodeOpCode(ref blob)) { + switch (code = ILParser.DecodeOpCode(ref blob)) + { case ILOpCode.Ldc_i8: if (val == blob.ReadInt64()) return true; @@ -172,9 +187,12 @@ namespace ICSharpCode.ILSpy.Search break; } } - } else if (searchTermLiteralType != TypeCode.Empty) { + } + else if (searchTermLiteralType != TypeCode.Empty) + { ILOpCode expectedCode; - switch (searchTermLiteralType) { + switch (searchTermLiteralType) + { case TypeCode.Single: expectedCode = ILOpCode.Ldc_r4; break; @@ -187,13 +205,16 @@ namespace ICSharpCode.ILSpy.Search default: throw new InvalidOperationException(); } - while (blob.RemainingBytes > 0) { + while (blob.RemainingBytes > 0) + { var code = ILParser.DecodeOpCode(ref blob); - if (code != expectedCode) { + if (code != expectedCode) + { ILParser.SkipOperand(ref blob, code); continue; } - switch (code) { + switch (code) + { case ILOpCode.Ldc_r4: if ((float)searchTermLiteralValue == blob.ReadSingle()) return true; @@ -208,10 +229,14 @@ namespace ICSharpCode.ILSpy.Search break; } } - } else { - while (blob.RemainingBytes > 0) { + } + else + { + while (blob.RemainingBytes > 0) + { var code = ILParser.DecodeOpCode(ref blob); - if (code != ILOpCode.Ldstr) { + if (code != ILOpCode.Ldstr) + { ILParser.SkipOperand(ref blob, code); continue; } diff --git a/ILSpy/Search/MemberSearchStrategy.cs b/ILSpy/Search/MemberSearchStrategy.cs index cbeae69e4..65e7ca374 100644 --- a/ILSpy/Search/MemberSearchStrategy.cs +++ b/ILSpy/Search/MemberSearchStrategy.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Threading; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -26,64 +27,80 @@ namespace ICSharpCode.ILSpy.Search cancellationToken.ThrowIfCancellationRequested(); var metadata = module.Metadata; var typeSystem = module.GetTypeSystemWithCurrentOptionsOrNull(); - if (typeSystem == null) return; + if (typeSystem == null) + return; - if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Type) { - foreach (var handle in metadata.TypeDefinitions) { + if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Type) + { + foreach (var handle in metadata.TypeDefinitions) + { cancellationToken.ThrowIfCancellationRequested(); string languageSpecificName = language.GetEntityName(module, handle, fullNameSearch, omitGenerics); if (languageSpecificName != null && !IsMatch(languageSpecificName)) continue; var type = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle); - if (!CheckVisibility(type)) continue; + if (!CheckVisibility(type)) + continue; OnFoundResult(type); } } - if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Method) { - foreach (var handle in metadata.MethodDefinitions) { + if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Method) + { + foreach (var handle in metadata.MethodDefinitions) + { cancellationToken.ThrowIfCancellationRequested(); string languageSpecificName = language.GetEntityName(module, handle, fullNameSearch, omitGenerics); if (languageSpecificName != null && !IsMatch(languageSpecificName)) continue; var method = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle); - if (!CheckVisibility(method)) continue; + if (!CheckVisibility(method)) + continue; OnFoundResult(method); } } - if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Field) { - foreach (var handle in metadata.FieldDefinitions) { + if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Field) + { + foreach (var handle in metadata.FieldDefinitions) + { cancellationToken.ThrowIfCancellationRequested(); string languageSpecificName = language.GetEntityName(module, handle, fullNameSearch, omitGenerics); if (languageSpecificName != null && !IsMatch(languageSpecificName)) continue; var field = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle); - if (!CheckVisibility(field)) continue; + if (!CheckVisibility(field)) + continue; OnFoundResult(field); } } - if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Property) { - foreach (var handle in metadata.PropertyDefinitions) { + if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Property) + { + foreach (var handle in metadata.PropertyDefinitions) + { cancellationToken.ThrowIfCancellationRequested(); string languageSpecificName = language.GetEntityName(module, handle, fullNameSearch, omitGenerics); if (languageSpecificName != null && !IsMatch(languageSpecificName)) continue; var property = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle); - if (!CheckVisibility(property)) continue; + if (!CheckVisibility(property)) + continue; OnFoundResult(property); } } - if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Event) { - foreach (var handle in metadata.EventDefinitions) { + if (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Member || searchKind == MemberSearchKind.Event) + { + foreach (var handle in metadata.EventDefinitions) + { cancellationToken.ThrowIfCancellationRequested(); string languageSpecificName = language.GetEntityName(module, handle, fullNameSearch, omitGenerics); if (!IsMatch(languageSpecificName)) continue; var @event = ((MetadataModule)typeSystem.MainModule).GetDefinition(handle); - if (!CheckVisibility(@event)) continue; + if (!CheckVisibility(@event)) + continue; OnFoundResult(@event); } } diff --git a/ILSpy/Search/MetadataTokenSearchStrategy.cs b/ILSpy/Search/MetadataTokenSearchStrategy.cs index 47f6fa070..ae1fa33e1 100644 --- a/ILSpy/Search/MetadataTokenSearchStrategy.cs +++ b/ILSpy/Search/MetadataTokenSearchStrategy.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Threading; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -16,7 +17,8 @@ namespace ICSharpCode.ILSpy.Search public MetadataTokenSearchStrategy(Language language, ApiVisibility apiVisibility, IProducerConsumerCollection resultQueue, params string[] terms) : base(language, apiVisibility, resultQueue, terms) { - if (terms.Length == 1) { + if (terms.Length == 1) + { int.TryParse(terms[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var token); searchTermToken = MetadataTokenHelpers.EntityHandleOrNil(token); } @@ -25,46 +27,54 @@ namespace ICSharpCode.ILSpy.Search public override void Search(PEFile module, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - if (searchTermToken.IsNil) return; + if (searchTermToken.IsNil) + return; var typeSystem = module.GetTypeSystemWithCurrentOptionsOrNull(); - if (typeSystem == null) return; + if (typeSystem == null) + return; var metadataModule = (MetadataModule)typeSystem.MainModule; int row = module.Metadata.GetRowNumber(searchTermToken); - switch (searchTermToken.Kind) { + switch (searchTermToken.Kind) + { case HandleKind.TypeDefinition: if (row < 1 || row > module.Metadata.TypeDefinitions.Count) break; var type = metadataModule.GetDefinition((TypeDefinitionHandle)searchTermToken); - if (!CheckVisibility(type)) break; + if (!CheckVisibility(type)) + break; OnFoundResult(type); break; case HandleKind.MethodDefinition: if (row < 1 || row > module.Metadata.MethodDefinitions.Count) break; var method = metadataModule.GetDefinition((MethodDefinitionHandle)searchTermToken); - if (!CheckVisibility(method)) break; + if (!CheckVisibility(method)) + break; OnFoundResult(method); break; case HandleKind.FieldDefinition: if (row < 1 || row > module.Metadata.FieldDefinitions.Count) break; var field = metadataModule.GetDefinition((FieldDefinitionHandle)searchTermToken); - if (!CheckVisibility(field)) break; + if (!CheckVisibility(field)) + break; OnFoundResult(field); break; case HandleKind.PropertyDefinition: if (row < 1 || row > module.Metadata.PropertyDefinitions.Count) break; var property = metadataModule.GetDefinition((PropertyDefinitionHandle)searchTermToken); - if (!CheckVisibility(property)) break; + if (!CheckVisibility(property)) + break; OnFoundResult(property); break; case HandleKind.EventDefinition: if (row < 1 || row > module.Metadata.EventDefinitions.Count) break; var @event = metadataModule.GetDefinition((EventDefinitionHandle)searchTermToken); - if (!CheckVisibility(@event)) break; + if (!CheckVisibility(@event)) + break; OnFoundResult(@event); break; } diff --git a/ILSpy/Search/NamespaceSearchStrategy.cs b/ILSpy/Search/NamespaceSearchStrategy.cs index ffd255139..d9ee18227 100644 --- a/ILSpy/Search/NamespaceSearchStrategy.cs +++ b/ILSpy/Search/NamespaceSearchStrategy.cs @@ -8,6 +8,7 @@ using System.Reflection.Metadata; using System.Threading; using System.Windows.Media; using System.Windows.Media.Imaging; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -30,7 +31,8 @@ namespace ICSharpCode.ILSpy.Search { cancellationToken.ThrowIfCancellationRequested(); var typeSystem = module.GetTypeSystemWithCurrentOptionsOrNull(); - if (typeSystem == null) return; + if (typeSystem == null) + return; var root = ((MetadataModule)typeSystem.MainModule).RootNamespace; Search(module, root); @@ -38,7 +40,8 @@ namespace ICSharpCode.ILSpy.Search private void Search(PEFile module, INamespace ns) { - if (ns.Types.Any()) { + if (ns.Types.Any()) + { if (IsMatch(ns.FullName.Length == 0 ? "-" : ns.FullName)) OnFoundResult(module, ns); } diff --git a/ILSpy/Search/ResourceSearchStrategy.cs b/ILSpy/Search/ResourceSearchStrategy.cs index 5824afd96..c42516a59 100644 --- a/ILSpy/Search/ResourceSearchStrategy.cs +++ b/ILSpy/Search/ResourceSearchStrategy.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.Threading; using System.Windows.Media; using System.Windows.Media.Imaging; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -55,7 +56,8 @@ namespace ICSharpCode.ILSpy.Search { cancellationToken.ThrowIfCancellationRequested(); - if (node is ResourceTreeNode treeNode) { + if (node is ResourceTreeNode treeNode) + { if (!CheckVisibility(treeNode.Resource)) return; resource = treeNode.Resource; diff --git a/ILSpy/Search/SearchPane.cs b/ILSpy/Search/SearchPane.cs index c74173c1c..263678ee6 100644 --- a/ILSpy/Search/SearchPane.cs +++ b/ILSpy/Search/SearchPane.cs @@ -31,6 +31,7 @@ using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; + using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Docking; using ICSharpCode.ILSpy.Search; @@ -49,7 +50,7 @@ namespace ICSharpCode.ILSpy bool runSearchOnNextShow; public static readonly DependencyProperty ResultsProperty = - DependencyProperty.Register("Results", typeof(ObservableCollection), typeof(SearchPane), + DependencyProperty.Register("Results", typeof(ObservableCollection), typeof(SearchPane), new PropertyMetadata(new ObservableCollection())); public ObservableCollection Results { get { return (ObservableCollection)GetValue(ResultsProperty); } @@ -82,9 +83,12 @@ namespace ICSharpCode.ILSpy void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e) { - if (IsVisible) { + if (IsVisible) + { StartSearch(this.SearchTerm); - } else { + } + else + { StartSearch(null); runSearchOnNextShow = true; } @@ -95,9 +99,12 @@ namespace ICSharpCode.ILSpy if (e.PropertyName != nameof(FilterSettings.ShowApiLevel)) return; - if (IsVisible) { + if (IsVisible) + { StartSearch(this.SearchTerm); - } else { + } + else + { StartSearch(null); runSearchOnNextShow = true; } @@ -105,9 +112,11 @@ namespace ICSharpCode.ILSpy public void Show() { - if (!IsVisible) { + if (!IsVisible) + { DockWorkspace.Instance.ToolPanes.Single(p => p.ContentId == SearchPaneModel.PaneContentId).IsVisible = true; - if (runSearchOnNextShow) { + if (runSearchOnNextShow) + { runSearchOnNextShow = false; StartSearch(this.SearchTerm); } @@ -140,19 +149,22 @@ namespace ICSharpCode.ILSpy MainWindow.Instance.SessionSettings.SelectedSearchMode = (SearchMode)searchModeComboBox.SelectedIndex; StartSearch(this.SearchTerm); } - + void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e) { JumpToSelectedItem(); e.Handled = true; } - + void ListBox_KeyDown(object sender, KeyEventArgs e) { - if (e.Key == Key.Return) { + if (e.Key == Key.Return) + { e.Handled = true; JumpToSelectedItem(); - } else if(e.Key == Key.Up && listBox.SelectedIndex == 0) { + } + else if (e.Key == Key.Up && listBox.SelectedIndex == 0) + { e.Handled = true; listBox.SelectedIndex = -1; searchBox.Focus(); @@ -162,13 +174,18 @@ namespace ICSharpCode.ILSpy protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); - if (e.Key == Key.T && e.KeyboardDevice.Modifiers == ModifierKeys.Control) { + if (e.Key == Key.T && e.KeyboardDevice.Modifiers == ModifierKeys.Control) + { searchModeComboBox.SelectedIndex = (int)SearchMode.Type; e.Handled = true; - } else if (e.Key == Key.M && e.KeyboardDevice.Modifiers == ModifierKeys.Control) { + } + else if (e.Key == Key.M && e.KeyboardDevice.Modifiers == ModifierKeys.Control) + { searchModeComboBox.SelectedIndex = (int)SearchMode.Member; e.Handled = true; - } else if (e.Key == Key.S && e.KeyboardDevice.Modifiers == ModifierKeys.Control) { + } + else if (e.Key == Key.S && e.KeyboardDevice.Modifiers == ModifierKeys.Control) + { searchModeComboBox.SelectedIndex = (int)SearchMode.Literal; e.Handled = true; } @@ -176,7 +193,8 @@ namespace ICSharpCode.ILSpy void SearchBox_PreviewKeyDown(object sender, KeyEventArgs e) { - if (e.Key == Key.Down && listBox.HasItems) { + if (e.Key == Key.Down && listBox.HasItems) + { e.Handled = true; listBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); listBox.SelectedIndex = 0; @@ -190,12 +208,14 @@ namespace ICSharpCode.ILSpy var timer = Stopwatch.StartNew(); int resultsAdded = 0; - while (Results.Count < MAX_RESULTS && timer.ElapsedMilliseconds < MAX_REFRESH_TIME_MS && currentSearch.resultQueue.TryTake(out var result)) { + while (Results.Count < MAX_RESULTS && timer.ElapsedMilliseconds < MAX_REFRESH_TIME_MS && currentSearch.resultQueue.TryTake(out var result)) + { InsertResult(Results, result); ++resultsAdded; } - if (resultsAdded > 0 && Results.Count == MAX_RESULTS) { + if (resultsAdded > 0 && Results.Count == MAX_RESULTS) + { Results.Add(new SearchResult { Name = Properties.Resources.SearchAbortedMoreThan1000ResultsFound }); currentSearch.Cancel(); } @@ -203,7 +223,8 @@ namespace ICSharpCode.ILSpy async void StartSearch(string searchTerm) { - if (currentSearch != null) { + if (currentSearch != null) + { currentSearch.Cancel(); currentSearch = null; } @@ -211,38 +232,47 @@ namespace ICSharpCode.ILSpy Results.Clear(); RunningSearch startedSearch = null; - if (!string.IsNullOrEmpty(searchTerm)) { + if (!string.IsNullOrEmpty(searchTerm)) + { MainWindow mainWindow = MainWindow.Instance; searchProgressBar.IsIndeterminate = true; startedSearch = new RunningSearch(mainWindow.CurrentAssemblyList.GetAssemblies(), searchTerm, - (SearchMode)searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage, + (SearchMode)searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage, mainWindow.SessionSettings.FilterSettings.ShowApiLevel); currentSearch = startedSearch; await startedSearch.Run(); } - if (currentSearch == startedSearch) { //are we still running the same search + if (currentSearch == startedSearch) + { //are we still running the same search searchProgressBar.IsIndeterminate = false; } } void InsertResult(IList results, SearchResult result) { - if (results.Count == 0) { + if (results.Count == 0) + { results.Add(result); - } else if (Options.DisplaySettingsPanel.CurrentDisplaySettings.SortResults) { + } + else if (Options.DisplaySettingsPanel.CurrentDisplaySettings.SortResults) + { // Keep results collection sorted by "Fitness" by inserting result into correct place // Inserts in the beginning shifts all elements, but there can be no more than 1000 items. - for (int i = 0; i < results.Count; i++) { - if (results[i].Fitness < result.Fitness) { + for (int i = 0; i < results.Count; i++) + { + if (results[i].Fitness < result.Fitness) + { results.Insert(i, result); return; } } results.Insert(results.Count - 1, result); - } else { + } + else + { // Original Code int index = results.BinarySearch(result, 0, results.Count - 1, SearchResult.Comparer); results.Insert(index < 0 ? ~index : index, result); @@ -251,11 +281,12 @@ namespace ICSharpCode.ILSpy void JumpToSelectedItem() { - if (listBox.SelectedItem is SearchResult result) { + if (listBox.SelectedItem is SearchResult result) + { MainWindow.Instance.JumpToReference(result.Reference); } } - + sealed class RunningSearch { readonly CancellationTokenSource cts = new CancellationTokenSource(); @@ -264,7 +295,7 @@ namespace ICSharpCode.ILSpy readonly SearchMode searchMode; readonly Language language; readonly ApiVisibility apiVisibility; - public readonly IProducerConsumerCollection resultQueue = new ConcurrentQueue(); + public readonly IProducerConsumerCollection resultQueue = new ConcurrentQueue(); public RunningSearch(LoadedAssembly[] assemblies, string searchTerm, SearchMode searchMode, Language language, ApiVisibility apiVisibility) { @@ -274,37 +305,45 @@ namespace ICSharpCode.ILSpy this.searchMode = searchMode; this.apiVisibility = apiVisibility; } - + public void Cancel() { cts.Cancel(); } - + public async Task Run() { - try { + try + { await Task.Factory.StartNew(() => { var searcher = GetSearchStrategy(); - try { - foreach (var loadedAssembly in assemblies) { + try + { + foreach (var loadedAssembly in assemblies) + { var module = loadedAssembly.GetPEFileOrNull(); if (module == null) continue; searcher.Search(module, cts.Token); } - } catch (OperationCanceledException) { + } + catch (OperationCanceledException) + { // ignore cancellation } }, cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false); - } catch (TaskCanceledException) { + } + catch (TaskCanceledException) + { // ignore cancellation } } AbstractSearchStrategy GetSearchStrategy() { - if (searchTerm.Length == 1) { + if (searchTerm.Length == 1) + { if (searchTerm[0].StartsWith("tm:", StringComparison.Ordinal)) return new MemberSearchStrategy(language, apiVisibility, searchTerm[0].Substring(3), resultQueue); @@ -381,7 +420,7 @@ namespace ICSharpCode.ILSpy } } - [ExportMainMenuCommand(Menu = nameof(Properties.Resources._View), Header =nameof(Properties.Resources.Search), MenuIcon = "Images/Search", MenuCategory = nameof(Properties.Resources.View), MenuOrder = 100)] + [ExportMainMenuCommand(Menu = nameof(Properties.Resources._View), Header = nameof(Properties.Resources.Search), MenuIcon = "Images/Search", MenuCategory = nameof(Properties.Resources.View), MenuOrder = 100)] [ExportToolbarCommand(ToolTip = nameof(Properties.Resources.SearchCtrlShiftFOrCtrlE), ToolbarIcon = "Images/Search", ToolbarCategory = nameof(Properties.Resources.View), ToolbarOrder = 100)] sealed class ShowSearchCommand : CommandWrapper { diff --git a/ILSpy/Search/SearchResult.cs b/ILSpy/Search/SearchResult.cs index 9d71adf59..5450a0b14 100644 --- a/ILSpy/Search/SearchResult.cs +++ b/ILSpy/Search/SearchResult.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Windows.Media; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Search; @@ -72,7 +73,8 @@ namespace ICSharpCode.ILSpy public override ImageSource Image { get { - if (base.Image == null) { + if (base.Image == null) + { base.Image = AbstractEntitySearchStrategy.GetIcon(Member); } return base.Image; @@ -81,7 +83,8 @@ namespace ICSharpCode.ILSpy public override ImageSource LocationImage { get { - if (base.LocationImage == null) { + if (base.LocationImage == null) + { base.LocationImage = Member.DeclaringTypeDefinition != null ? TypeTreeNode.GetIcon(Member.DeclaringTypeDefinition) : Images.Namespace; } return base.LocationImage; diff --git a/ILSpy/SessionSettings.cs b/ILSpy/SessionSettings.cs index adddb10bc..6a3fd4bdd 100644 --- a/ILSpy/SessionSettings.cs +++ b/ILSpy/SessionSettings.cs @@ -25,6 +25,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Windows; using System.Xml.Linq; + using ICSharpCode.ILSpy.Docking; namespace ICSharpCode.ILSpy @@ -40,14 +41,16 @@ namespace ICSharpCode.ILSpy XElement doc = spySettings["SessionSettings"]; XElement filterSettings = doc.Element("FilterSettings"); - if (filterSettings == null) filterSettings = new XElement("FilterSettings"); + if (filterSettings == null) + filterSettings = new XElement("FilterSettings"); this.FilterSettings = new FilterSettings(filterSettings); this.ActiveAssemblyList = (string)doc.Element("ActiveAssemblyList"); XElement activeTreeViewPath = doc.Element("ActiveTreeViewPath"); - if (activeTreeViewPath != null) { + if (activeTreeViewPath != null) + { this.ActiveTreeViewPath = activeTreeViewPath.Elements().Select(e => Unescape((string)e)).ToArray(); } this.ActiveAutoLoadedAssembly = (string)doc.Element("ActiveAutoLoadedAssembly"); @@ -78,7 +81,8 @@ namespace ICSharpCode.ILSpy public string ActiveAssemblyList { get => activeAssemblyList; set { - if (value != null && value != activeAssemblyList) { + if (value != null && value != activeAssemblyList) + { activeAssemblyList = value; OnPropertyChanged(); } @@ -100,13 +104,16 @@ namespace ICSharpCode.ILSpy { XElement doc = new XElement("SessionSettings"); doc.Add(this.FilterSettings.SaveAsXml()); - if (this.ActiveAssemblyList != null) { + if (this.ActiveAssemblyList != null) + { doc.Add(new XElement("ActiveAssemblyList", this.ActiveAssemblyList)); } - if (this.ActiveTreeViewPath != null) { + if (this.ActiveTreeViewPath != null) + { doc.Add(new XElement("ActiveTreeViewPath", ActiveTreeViewPath.Select(p => new XElement("Node", Escape(p))))); } - if (this.ActiveAutoLoadedAssembly != null) { + if (this.ActiveAutoLoadedAssembly != null) + { doc.Add(new XElement("ActiveAutoLoadedAssembly", this.ActiveAutoLoadedAssembly)); } doc.Add(new XElement("WindowState", ToString(this.WindowState))); @@ -117,7 +124,8 @@ namespace ICSharpCode.ILSpy doc.Add(new XElement("SelectedSearchMode", ToString(this.SelectedSearchMode))); var dockLayoutElement = new XElement("DockLayout"); - if (DockLayout.Valid) { + if (DockLayout.Valid) + { dockLayoutElement.Add(DockLayout.SaveAsXml()); } doc.Add(dockLayoutElement); @@ -131,7 +139,8 @@ namespace ICSharpCode.ILSpy static string Escape(string p) { StringBuilder sb = new StringBuilder(); - foreach (char ch in p) { + foreach (char ch in p) + { if (char.IsLetterOrDigit(ch)) sb.Append(ch); else @@ -149,10 +158,13 @@ namespace ICSharpCode.ILSpy { if (s == null) return defaultValue; - try { + try + { TypeConverter c = TypeDescriptor.GetConverter(typeof(T)); return (T)c.ConvertFromInvariantString(s); - } catch (FormatException) { + } + catch (FormatException) + { return defaultValue; } } diff --git a/ILSpy/SolutionWriter.cs b/ILSpy/SolutionWriter.cs index 614076206..2bdeac58d 100644 --- a/ILSpy/SolutionWriter.cs +++ b/ILSpy/SolutionWriter.cs @@ -24,6 +24,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.Util; @@ -53,15 +54,18 @@ namespace ICSharpCode.ILSpy /// is null. public static void CreateSolution(DecompilerTextView textView, string solutionFilePath, Language language, IEnumerable assemblies) { - if (textView == null) { + if (textView == null) + { throw new ArgumentNullException(nameof(textView)); } - if (string.IsNullOrWhiteSpace(solutionFilePath)) { + if (string.IsNullOrWhiteSpace(solutionFilePath)) + { throw new ArgumentException("The solution file path cannot be null or empty.", nameof(solutionFilePath)); } - if (assemblies == null) { + if (assemblies == null) + { throw new ArgumentNullException(nameof(assemblies)); } @@ -91,14 +95,16 @@ namespace ICSharpCode.ILSpy var result = new AvalonEditTextOutput(); var duplicates = new HashSet(); - if (assemblies.Any(asm => !duplicates.Add(asm.ShortName))) { + if (assemblies.Any(asm => !duplicates.Add(asm.ShortName))) + { result.WriteLine("Duplicate assembly names selected, cannot generate a solution."); return result; } Stopwatch stopwatch = Stopwatch.StartNew(); - try { + try + { // Explicitly create an enumerable partitioner here to avoid Parallel.ForEach's special cases for lists, // as those seem to use static partitioning which is inefficient if assemblies take differently // long to decompile. @@ -109,8 +115,11 @@ namespace ICSharpCode.ILSpy await Task.Run(() => SolutionCreator.WriteSolutionFile(solutionFilePath, projects)) .ConfigureAwait(false); - } catch (AggregateException ae) { - if (ae.Flatten().InnerExceptions.All(e => e is OperationCanceledException)) { + } + catch (AggregateException ae) + { + if (ae.Flatten().InnerExceptions.All(e => e is OperationCanceledException)) + { result.WriteLine(); result.WriteLine("Generation was cancelled."); return result; @@ -126,19 +135,23 @@ namespace ICSharpCode.ILSpy return result; } - foreach (var item in statusOutput) { + foreach (var item in statusOutput) + { result.WriteLine(item); } - if (statusOutput.Count == 0) { + if (statusOutput.Count == 0) + { result.WriteLine("Successfully decompiled the following assemblies into Visual Studio projects:"); - foreach (var item in assemblies.Select(n => n.Text.ToString())) { + foreach (var item in assemblies.Select(n => n.Text.ToString())) + { result.WriteLine(item); } result.WriteLine(); - if (assemblies.Count() == projects.Count) { + if (assemblies.Count() == projects.Count) + { result.WriteLine("Created the Visual Studio Solution file."); } @@ -156,17 +169,23 @@ namespace ICSharpCode.ILSpy targetDirectory = Path.Combine(targetDirectory, loadedAssembly.ShortName); string projectFileName = Path.Combine(targetDirectory, loadedAssembly.ShortName + language.ProjectFileExtension); - if (!Directory.Exists(targetDirectory)) { - try { + if (!Directory.Exists(targetDirectory)) + { + try + { Directory.CreateDirectory(targetDirectory); - } catch (Exception e) { + } + catch (Exception e) + { statusOutput.Add($"Failed to create a directory '{targetDirectory}':{Environment.NewLine}{e}"); return; } } - try { - using (var projectFileWriter = new StreamWriter(projectFileName)) { + try + { + using (var projectFileWriter = new StreamWriter(projectFileName)) + { var projectFileOutput = new PlainTextOutput(projectFileWriter); var options = new DecompilationOptions() { FullDecompilation = true, @@ -175,11 +194,14 @@ namespace ICSharpCode.ILSpy }; var projectInfo = language.DecompileAssembly(loadedAssembly, projectFileOutput, options); - if (projectInfo != null) { + if (projectInfo != null) + { projects.Add(new ProjectItem(projectFileName, projectInfo.PlatformName, projectInfo.Guid, projectInfo.TypeGuid)); } } - } catch (Exception e) when (!(e is OperationCanceledException)) { + } + catch (Exception e) when (!(e is OperationCanceledException)) + { statusOutput.Add($"Failed to decompile the assembly '{loadedAssembly.FileName}':{Environment.NewLine}{e}"); } } diff --git a/ILSpy/TaskHelper.cs b/ILSpy/TaskHelper.cs index bb76ffdbc..e26eaf062 100644 --- a/ILSpy/TaskHelper.cs +++ b/ILSpy/TaskHelper.cs @@ -19,6 +19,7 @@ using System; using System.Threading; using System.Threading.Tasks; + using ICSharpCode.ILSpy.TextView; namespace ICSharpCode.ILSpy @@ -26,14 +27,14 @@ namespace ICSharpCode.ILSpy public static class TaskHelper { public static readonly Task CompletedTask = FromResult(null); - + public static Task FromResult(T result) { TaskCompletionSource tcs = new TaskCompletionSource(); tcs.SetResult(result); return tcs.Task; } - + public static Task FromException(Exception ex) { var tcs = new TaskCompletionSource(); @@ -53,7 +54,8 @@ namespace ICSharpCode.ILSpy /// public static void SetFromTask(this TaskCompletionSource tcs, Task task) { - switch (task.Status) { + switch (task.Status) + { case TaskStatus.RanToCompletion: tcs.SetResult(task.Result); break; @@ -67,13 +69,14 @@ namespace ICSharpCode.ILSpy throw new InvalidOperationException("The input task must have already finished"); } } - + /// /// Sets the result of the TaskCompletionSource based on the result of the finished task. /// public static void SetFromTask(this TaskCompletionSource tcs, Task task) { - switch (task.Status) { + switch (task.Status) + { case TaskStatus.RanToCompletion: tcs.SetResult(null); break; @@ -87,7 +90,7 @@ namespace ICSharpCode.ILSpy throw new InvalidOperationException("The input task must have already finished"); } } - + public static Task Then(this Task task, Action action) { if (action == null) @@ -169,7 +172,8 @@ namespace ICSharpCode.ILSpy if (action == null) throw new ArgumentNullException(nameof(action)); return task.ContinueWith(t => { - if (t.IsFaulted) { + if (t.IsFaulted) + { Exception ex = t.Exception; while (ex is AggregateException) ex = ex.InnerException; @@ -180,14 +184,14 @@ namespace ICSharpCode.ILSpy } }, CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()); } - + /// /// Ignore exceptions thrown by the task. /// public static void IgnoreExceptions(this Task task) { } - + /// /// Handle exceptions by displaying the error message in the text view. /// diff --git a/ILSpy/TextView/AvalonEditTextOutput.cs b/ILSpy/TextView/AvalonEditTextOutput.cs index fdaa23f19..4ea8afa17 100644 --- a/ILSpy/TextView/AvalonEditTextOutput.cs +++ b/ILSpy/TextView/AvalonEditTextOutput.cs @@ -30,6 +30,7 @@ using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Rendering; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; + using TextLocation = ICSharpCode.Decompiler.CSharp.Syntax.TextLocation; namespace ICSharpCode.ILSpy.TextView @@ -43,14 +44,14 @@ namespace ICSharpCode.ILSpy.TextView public bool IsLocal; public bool IsDefinition; } - + /// /// Stores the positions of the definitions that were written to the text output. /// sealed class DefinitionLookup { internal Dictionary definitions = new Dictionary(); - + public int GetDefinitionPosition(object definition) { int val; @@ -59,13 +60,13 @@ namespace ICSharpCode.ILSpy.TextView else return -1; } - + public void AddDefinition(object definition, int offset) { definitions[definition] = offset; } } - + /// /// Text output implementation for AvalonEdit. /// @@ -74,7 +75,7 @@ namespace ICSharpCode.ILSpy.TextView int lastLineStart = 0; int lineNumber = 1; readonly StringBuilder b = new StringBuilder(); - + /// Current indentation level int indent; /// Whether indentation should be inserted on the next write @@ -91,63 +92,63 @@ namespace ICSharpCode.ILSpy.TextView /// Used to identify the AboutPage and other views built into ILSpy in the navigation history. /// public Uri Address { get; set; } - + internal readonly List elementGenerators = new List(); - + /// List of all references that were written to the output TextSegmentCollection references = new TextSegmentCollection(); - + /// Stack of the fold markers that are open but not closed yet Stack openFoldings = new Stack(); - + /// List of all foldings that were written to the output internal readonly List Foldings = new List(); - + internal readonly DefinitionLookup DefinitionLookup = new DefinitionLookup(); internal bool EnableHyperlinks { get; set; } - + /// Embedded UIElements, see . internal readonly List>> UIElements = new List>>(); public RichTextModel HighlightingModel { get; } = new RichTextModel(); - + public AvalonEditTextOutput() { } - + /// /// Gets the list of references (hyperlinks). /// internal TextSegmentCollection References { get { return references; } } - + public void AddVisualLineElementGenerator(VisualLineElementGenerator elementGenerator) { elementGenerators.Add(elementGenerator); } - + /// /// Controls the maximum length of the text. /// When this length is exceeded, an will be thrown, /// thus aborting the decompilation. /// public int LengthLimit = int.MaxValue; - + public int TextLength { get { return b.Length; } } - + public TextLocation Location { get { return new TextLocation(lineNumber, b.Length - lastLineStart + 1 + (needsIndent ? indent : 0)); } } - + #region Text Document TextDocument textDocument; - + /// /// Prepares the TextDocument. /// This method may be called by the background thread writing to the output. @@ -159,12 +160,13 @@ namespace ICSharpCode.ILSpy.TextView /// public void PrepareDocument() { - if (textDocument == null) { + if (textDocument == null) + { textDocument = new TextDocument(b.ToString()); textDocument.SetOwnerThread(null); // release ownership } } - + /// /// Retrieves the TextDocument. /// Once the document is retrieved, it can no longer be written to. @@ -176,58 +178,64 @@ namespace ICSharpCode.ILSpy.TextView return textDocument; } #endregion - + public void Indent() { if (IgnoreNewLineAndIndent) return; indent++; } - + public void Unindent() { if (IgnoreNewLineAndIndent) return; indent--; } - + void WriteIndent() { if (IgnoreNewLineAndIndent) return; Debug.Assert(textDocument == null); - if (needsIndent) { + if (needsIndent) + { needsIndent = false; - for (int i = 0; i < indent; i++) { + for (int i = 0; i < indent; i++) + { b.Append(IndentationString); } } } - + public void Write(char ch) { WriteIndent(); b.Append(ch); } - + public void Write(string text) { WriteIndent(); b.Append(text); } - + public void WriteLine() { Debug.Assert(textDocument == null); - if (IgnoreNewLineAndIndent) { + if (IgnoreNewLineAndIndent) + { b.Append(' '); - } else { + } + else + { b.AppendLine(); needsIndent = true; lastLineStart = b.Length; lineNumber++; } - if (this.TextLength > LengthLimit) { + if (this.TextLength > LengthLimit) + { throw new OutputLengthExceededException(); } } @@ -236,12 +244,16 @@ namespace ICSharpCode.ILSpy.TextView { WriteIndent(); int start = this.TextLength; - if (omitSuffix) { + if (omitSuffix) + { int lastDot = opCode.Name.LastIndexOf('.'); - if (lastDot > 0) { + if (lastDot > 0) + { b.Append(opCode.Name.Remove(lastDot + 1)); } - } else { + } + else + { b.Append(opCode.Name); } int end = this.TextLength - 1; @@ -254,7 +266,8 @@ namespace ICSharpCode.ILSpy.TextView int start = this.TextLength; b.Append(text); int end = this.TextLength; - if (isDefinition) { + if (isDefinition) + { this.DefinitionLookup.AddDefinition((module, handle), this.TextLength); } references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = new EntityReference(protocol, module, handle), IsDefinition = isDefinition }); @@ -266,7 +279,8 @@ namespace ICSharpCode.ILSpy.TextView int start = this.TextLength; b.Append(text); int end = this.TextLength; - if (isDefinition) { + if (isDefinition) + { this.DefinitionLookup.AddDefinition(type, this.TextLength); } references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = type, IsDefinition = isDefinition }); @@ -278,7 +292,8 @@ namespace ICSharpCode.ILSpy.TextView int start = this.TextLength; b.Append(text); int end = this.TextLength; - if (isDefinition) { + if (isDefinition) + { this.DefinitionLookup.AddDefinition(member, this.TextLength); } references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = member, IsDefinition = isDefinition }); @@ -290,7 +305,8 @@ namespace ICSharpCode.ILSpy.TextView int start = this.TextLength; b.Append(text); int end = this.TextLength; - if (isDefinition) { + if (isDefinition) + { this.DefinitionLookup.AddDefinition(reference, this.TextLength); } references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, IsLocal = true, IsDefinition = isDefinition }); @@ -306,17 +322,18 @@ namespace ICSharpCode.ILSpy.TextView DefaultClosed = defaultCollapsed }); } - + public void MarkFoldEnd() { NewFolding f = openFoldings.Pop(); f.EndOffset = this.TextLength; this.Foldings.Add(f); } - + public void AddUIElement(Func element) { - if (element != null) { + if (element != null) + { if (this.UIElements.Count > 0 && this.UIElements.Last().Key == this.TextLength) throw new InvalidOperationException("Only one UIElement is allowed for each position in the document"); this.UIElements.Add(new KeyValuePair>(this.TextLength, new Lazy(element))); diff --git a/ILSpy/TextView/BracketHighlightRenderer.cs b/ILSpy/TextView/BracketHighlightRenderer.cs index 97080dc9e..cdccc0e60 100644 --- a/ILSpy/TextView/BracketHighlightRenderer.cs +++ b/ILSpy/TextView/BracketHighlightRenderer.cs @@ -18,6 +18,7 @@ using System; using System.Windows.Media; + using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; @@ -77,7 +78,8 @@ namespace ICSharpCode.ILSpy.TextView public void SetHighlight(BracketSearchResult result) { - if (this.result != result) { + if (this.result != result) + { this.result = result; textView.InvalidateLayer(this.Layer); } @@ -119,7 +121,8 @@ namespace ICSharpCode.ILSpy.TextView builder.AddSegment(textView, new TextSegment() { StartOffset = result.ClosingBracketOffset, Length = result.ClosingBracketLength }); Geometry geometry = builder.CreateGeometry(); - if (geometry != null) { + if (geometry != null) + { drawingContext.DrawGeometry(backgroundBrush, borderPen, geometry); } } diff --git a/ILSpy/TextView/CaretHighlightAdorner.cs b/ILSpy/TextView/CaretHighlightAdorner.cs index 4701c79aa..1b85fc4a2 100644 --- a/ILSpy/TextView/CaretHighlightAdorner.cs +++ b/ILSpy/TextView/CaretHighlightAdorner.cs @@ -23,6 +23,7 @@ using System.Windows.Documents; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Threading; + using ICSharpCode.AvalonEdit.Editing; namespace ICSharpCode.ILSpy.TextView @@ -35,30 +36,30 @@ namespace ICSharpCode.ILSpy.TextView { readonly Pen pen; readonly RectangleGeometry geometry; - + public CaretHighlightAdorner(TextArea textArea) : base(textArea.TextView) { Rect min = textArea.Caret.CalculateCaretRectangle(); min.Offset(-textArea.TextView.ScrollOffset); - + Rect max = min; double size = Math.Max(min.Width, min.Height) * 0.25; max.Inflate(size, size); - + pen = new Pen(TextBlock.GetForeground(textArea.TextView).Clone(), 1); - + geometry = new RectangleGeometry(min, 2, 2); geometry.BeginAnimation(RectangleGeometry.RectProperty, new RectAnimation(min, max, new Duration(TimeSpan.FromMilliseconds(300))) { AutoReverse = true }); pen.Brush.BeginAnimation(Brush.OpacityProperty, new DoubleAnimation(1, 0, new Duration(TimeSpan.FromMilliseconds(200))) { BeginTime = TimeSpan.FromMilliseconds(450) }); } - + public static void DisplayCaretHighlightAnimation(TextArea textArea) { AdornerLayer layer = AdornerLayer.GetAdornerLayer(textArea.TextView); CaretHighlightAdorner adorner = new CaretHighlightAdorner(textArea); layer.Add(adorner); - + DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += delegate { @@ -67,7 +68,7 @@ namespace ICSharpCode.ILSpy.TextView }; timer.Start(); } - + protected override void OnRender(DrawingContext drawingContext) { drawingContext.DrawGeometry(null, pen, geometry); diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 39783221e..299e042d7 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -36,6 +36,7 @@ using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Threading; using System.Xml; + using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; @@ -55,6 +56,7 @@ using ICSharpCode.ILSpy.AvalonEdit; using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; + using Microsoft.Win32; namespace ICSharpCode.ILSpy.TextView @@ -73,22 +75,24 @@ namespace ICSharpCode.ILSpy.TextView FoldingManager foldingManager; ILSpyTreeNode[] decompiledNodes; Uri currentAddress; - + DefinitionLookup definitionLookup; TextSegmentCollection references; CancellationTokenSource currentCancellationTokenSource; - + readonly TextMarkerService textMarkerService; readonly List localReferenceMarks = new List(); - + #region Constructor public DecompilerTextView() { HighlightingManager.Instance.RegisterHighlighting( "ILAsm", new string[] { ".il" }, delegate { - using (Stream s = typeof(DecompilerTextView).Assembly.GetManifestResourceStream(typeof(DecompilerTextView), "ILAsm-Mode.xshd")) { - using (XmlTextReader reader = new XmlTextReader(s)) { + using (Stream s = typeof(DecompilerTextView).Assembly.GetManifestResourceStream(typeof(DecompilerTextView), "ILAsm-Mode.xshd")) + { + using (XmlTextReader reader = new XmlTextReader(s)) + { return HighlightingLoader.Load(reader, HighlightingManager.Instance); } } @@ -97,8 +101,10 @@ namespace ICSharpCode.ILSpy.TextView HighlightingManager.Instance.RegisterHighlighting( "C#", new string[] { ".cs" }, delegate { - using (Stream s = typeof(DecompilerTextView).Assembly.GetManifestResourceStream(typeof(DecompilerTextView), "CSharp-Mode.xshd")) { - using (XmlTextReader reader = new XmlTextReader(s)) { + using (Stream s = typeof(DecompilerTextView).Assembly.GetManifestResourceStream(typeof(DecompilerTextView), "CSharp-Mode.xshd")) + { + using (XmlTextReader reader = new XmlTextReader(s)) + { return HighlightingLoader.Load(reader, HighlightingManager.Instance); } } @@ -107,8 +113,10 @@ namespace ICSharpCode.ILSpy.TextView HighlightingManager.Instance.RegisterHighlighting( "Asm", new string[] { ".s", ".asm" }, delegate { - using (Stream s = typeof(DecompilerTextView).Assembly.GetManifestResourceStream(typeof(DecompilerTextView), "Asm-Mode.xshd")) { - using (XmlTextReader reader = new XmlTextReader(s)) { + using (Stream s = typeof(DecompilerTextView).Assembly.GetManifestResourceStream(typeof(DecompilerTextView), "Asm-Mode.xshd")) + { + using (XmlTextReader reader = new XmlTextReader(s)) + { return HighlightingLoader.Load(reader, HighlightingManager.Instance); } } @@ -136,7 +144,7 @@ namespace ICSharpCode.ILSpy.TextView // disable Tab editing command (useless for read-only editor); allow using tab for focus navigation instead RemoveEditCommand(EditingCommands.TabForward); RemoveEditCommand(EditingCommands.TabBackward); - + textMarkerService = new TextMarkerService(textEditor.TextArea.TextView); textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService); textEditor.TextArea.TextView.LineTransformers.Add(textMarkerService); @@ -146,9 +154,9 @@ namespace ICSharpCode.ILSpy.TextView // SearchPanel SearchPanel.Install(textEditor.TextArea) .RegisterCommands(Application.Current.MainWindow.CommandBindings); - + ShowLineMargin(); - + // add marker service & margin textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService); textEditor.TextArea.TextView.LineTransformers.Add(textMarkerService); @@ -167,20 +175,23 @@ namespace ICSharpCode.ILSpy.TextView handler.CommandBindings.Remove(commandBinding); } #endregion - + #region Line margin void CurrentDisplaySettings_PropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == "ShowLineNumbers") { + if (e.PropertyName == "ShowLineNumbers") + { ShowLineMargin(); } } - + void ShowLineMargin() { - foreach (var margin in this.textEditor.TextArea.LeftMargins) { - if (margin is LineNumberMargin || margin is System.Windows.Shapes.Line) { + foreach (var margin in this.textEditor.TextArea.LeftMargins) + { + if (margin is LineNumberMargin || margin is System.Windows.Shapes.Line) + { margin.Visibility = DisplaySettingsPanel.CurrentDisplaySettings.ShowLineNumbers ? Visibility.Visible : Visibility.Collapsed; } } @@ -194,7 +205,8 @@ namespace ICSharpCode.ILSpy.TextView void TextViewMouseHover(object sender, MouseEventArgs e) { - if (!TryCloseExistingPopup(false)) { + if (!TryCloseExistingPopup(false)) + { return; } TextViewPosition? position = GetPositionFromMousePosition(); @@ -207,11 +219,13 @@ namespace ICSharpCode.ILSpy.TextView if (seg == null) return; object content = GenerateTooltip(seg); - - if (content != null) { + + if (content != null) + { popupToolTip = content as Popup; - if (popupToolTip != null) { + if (popupToolTip != null) + { var popupPosition = GetPopupPosition(e); popupToolTip.Closed += ToolTipClosed; popupToolTip.HorizontalOffset = popupPosition.X; @@ -221,19 +235,24 @@ namespace ICSharpCode.ILSpy.TextView e.Handled = true; popupToolTip.IsOpen = true; distanceToPopupLimit = double.PositiveInfinity; // reset limit; we'll re-calculate it on the next mouse movement - } else { - if (toolTip == null) { + } + else + { + if (toolTip == null) + { toolTip = new ToolTip(); toolTip.Closed += ToolTipClosed; } toolTip.PlacementTarget = this; // required for property inheritance - if (content is string s) { + if (content is string s) + { toolTip.Content = new TextBlock { Text = s, TextWrapping = TextWrapping.Wrap }; - } else + } + else toolTip.Content = content; e.Handled = true; @@ -244,8 +263,10 @@ namespace ICSharpCode.ILSpy.TextView bool TryCloseExistingPopup(bool mouseClick) { - if (popupToolTip != null) { - if (popupToolTip.IsOpen && !mouseClick && popupToolTip is FlowDocumentTooltip t && !t.CloseWhenMouseMovesAway) { + if (popupToolTip != null) + { + if (popupToolTip.IsOpen && !mouseClick && popupToolTip is FlowDocumentTooltip t && !t.CloseWhenMouseMovesAway) + { return false; // Popup does not want to be closed yet } popupToolTip.IsOpen = false; @@ -261,13 +282,16 @@ namespace ICSharpCode.ILSpy.TextView Point positionInPixels; // align Popup with line bottom TextViewPosition? logicalPos = textEditor.GetPositionFromPoint(mousePos); - if (logicalPos.HasValue) { + if (logicalPos.HasValue) + { var textView = textEditor.TextArea.TextView; positionInPixels = textView.PointToScreen( textView.GetVisualPosition(logicalPos.Value, VisualYPosition.LineBottom) - textView.ScrollOffset); positionInPixels.X -= 4; - } else { + } + else + { positionInPixels = PointToScreen(mousePos + new Vector(-4, 6)); } // use device independent units, because Popup Left/Top are in independent units @@ -277,7 +301,8 @@ namespace ICSharpCode.ILSpy.TextView void TextViewMouseHoverStopped(object sender, MouseEventArgs e) { // Non-popup tooltips get closed as soon as the mouse starts moving again - if (toolTip != null) { + if (toolTip != null) + { toolTip.IsOpen = false; e.Handled = true; } @@ -288,12 +313,16 @@ namespace ICSharpCode.ILSpy.TextView void TextEditorMouseMove(object sender, MouseEventArgs e) { - if (popupToolTip != null) { + if (popupToolTip != null) + { double distanceToPopup = GetDistanceToPopup(e); - if (distanceToPopup > distanceToPopupLimit) { + if (distanceToPopup > distanceToPopupLimit) + { // Close popup if mouse moved away, exceeding the limit TryCloseExistingPopup(false); - } else { + } + else + { // reduce distanceToPopupLimit distanceToPopupLimit = Math.Min(distanceToPopupLimit, distanceToPopup + MaxMovementAwayFromPopup); } @@ -319,7 +348,8 @@ namespace ICSharpCode.ILSpy.TextView void TextEditorMouseLeave(object sender, MouseEventArgs e) { - if (popupToolTip != null && !popupToolTip.IsMouseOver) { + if (popupToolTip != null && !popupToolTip.IsMouseOver) + { // do not close popup if mouse moved from editor to popup TryCloseExistingPopup(false); } @@ -334,10 +364,12 @@ namespace ICSharpCode.ILSpy.TextView void ToolTipClosed(object sender, EventArgs e) { - if (toolTip == sender) { + if (toolTip == sender) + { toolTip = null; } - if (popupToolTip == sender) { + if (popupToolTip == sender) + { // Because popupToolTip instances are created by the tooltip provider, // they might be reused; so we should detach the event handler popupToolTip.Closed -= ToolTipClosed; @@ -347,25 +379,33 @@ namespace ICSharpCode.ILSpy.TextView object GenerateTooltip(ReferenceSegment segment) { - if (segment.Reference is ICSharpCode.Decompiler.Disassembler.OpCodeInfo code) { + if (segment.Reference is ICSharpCode.Decompiler.Disassembler.OpCodeInfo code) + { XmlDocumentationProvider docProvider = XmlDocLoader.MscorlibDocumentation; DocumentationUIBuilder renderer = new DocumentationUIBuilder(new CSharpAmbience(), MainWindow.Instance.CurrentLanguage.SyntaxHighlighting); renderer.AddSignatureBlock($"{code.Name} (0x{code.Code:x})"); - if (docProvider != null) { + if (docProvider != null) + { string documentation = docProvider.GetDocumentation("F:System.Reflection.Emit.OpCodes." + code.EncodedName); - if (documentation != null) { + if (documentation != null) + { renderer.AddXmlDocumentation(documentation, null, null); } } return new FlowDocumentTooltip(renderer.CreateDocument()); - } else if (segment.Reference is IEntity entity) { + } + else if (segment.Reference is IEntity entity) + { var document = CreateTooltipForEntity(entity); if (document == null) return null; return new FlowDocumentTooltip(document); - } else if (segment.Reference is EntityReference unresolvedEntity) { + } + else if (segment.Reference is EntityReference unresolvedEntity) + { var typeSystem = new DecompilerTypeSystem(unresolvedEntity.Module, unresolvedEntity.Module.GetAssemblyResolver(), TypeSystemOptions.Default | TypeSystemOptions.Uncached); - try { + try + { IEntity resolved = typeSystem.MainModule.ResolveEntity((EntityHandle)unresolvedEntity.Handle); if (resolved == null) return null; @@ -373,7 +413,9 @@ namespace ICSharpCode.ILSpy.TextView if (document == null) return null; return new FlowDocumentTooltip(document); - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { return null; } } @@ -386,17 +428,22 @@ namespace ICSharpCode.ILSpy.TextView DocumentationUIBuilder renderer = new DocumentationUIBuilder(new CSharpAmbience(), currentLanguage.SyntaxHighlighting); RichText richText = currentLanguage.GetRichTextTooltip(resolved); renderer.AddSignatureBlock(richText.Text, richText.ToRichTextModel()); - try { + try + { if (resolved.ParentModule == null || resolved.ParentModule.PEFile == null) return null; var docProvider = XmlDocLoader.LoadDocumentation(resolved.ParentModule.PEFile); - if (docProvider != null) { + if (docProvider != null) + { string documentation = docProvider.GetDocumentation(resolved.GetIdString()); - if (documentation != null) { + if (documentation != null) + { renderer.AddXmlDocumentation(documentation, resolved, ResolveReference); } } - } catch (XmlException) { + } + catch (XmlException) + { // ignore } return renderer.CreateDocument(); @@ -460,10 +507,13 @@ namespace ICSharpCode.ILSpy.TextView #region Highlight brackets void HighlightBrackets(object sender, EventArgs e) { - if (DisplaySettingsPanel.CurrentDisplaySettings.HighlightMatchingBraces) { + if (DisplaySettingsPanel.CurrentDisplaySettings.HighlightMatchingBraces) + { var result = MainWindow.Instance.CurrentLanguage.BracketSearcher.SearchBracket(textEditor.Document, textEditor.CaretOffset); bracketHighlightRenderer.SetHighlight(result); - } else { + } + else + { bracketHighlightRenderer.SetHighlight(null); } } @@ -483,7 +533,7 @@ namespace ICSharpCode.ILSpy.TextView { RunWithCancellation(taskCreation).ContinueWith(taskCompleted, CancellationToken.None, TaskContinuationOptions.NotOnCanceled, TaskScheduler.FromCurrentSynchronizationContext()); } - + /// /// Switches the GUI into "waiting" mode, then calls to create /// the task. @@ -491,14 +541,16 @@ namespace ICSharpCode.ILSpy.TextView /// public Task RunWithCancellation(Func> taskCreation) { - if (waitAdorner.Visibility != Visibility.Visible) { + if (waitAdorner.Visibility != Visibility.Visible) + { waitAdorner.Visibility = Visibility.Visible; // Work around a WPF bug by setting IsIndeterminate only while the progress bar is visible. // https://github.com/icsharpcode/ILSpy/issues/593 progressBar.IsIndeterminate = true; waitAdorner.BeginAnimation(OpacityProperty, new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(0.5)), FillBehavior.Stop)); var taskBar = MainWindow.Instance.TaskbarItemInfo; - if (taskBar != null) { + if (taskBar != null) + { taskBar.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Indeterminate; } } @@ -508,52 +560,66 @@ namespace ICSharpCode.ILSpy.TextView // cancel the previous only after current was set to the new one (avoid that the old one still finishes successfully) if (previousCancellationTokenSource != null) previousCancellationTokenSource.Cancel(); - + var tcs = new TaskCompletionSource(); Task task; - try { + try + { task = taskCreation(myCancellationTokenSource.Token); - } catch (OperationCanceledException) { + } + catch (OperationCanceledException) + { task = TaskHelper.FromCancellation(); - } catch (Exception ex) { + } + catch (Exception ex) + { task = TaskHelper.FromException(ex); } Action continuation = delegate { - try { - if (currentCancellationTokenSource == myCancellationTokenSource) { + try + { + if (currentCancellationTokenSource == myCancellationTokenSource) + { currentCancellationTokenSource = null; waitAdorner.Visibility = Visibility.Collapsed; progressBar.IsIndeterminate = false; var taskBar = MainWindow.Instance.TaskbarItemInfo; - if (taskBar != null) { + if (taskBar != null) + { taskBar.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None; } - if (task.IsCanceled) { + if (task.IsCanceled) + { AvalonEditTextOutput output = new AvalonEditTextOutput(); output.WriteLine("The operation was canceled."); ShowOutput(output); } tcs.SetFromTask(task); - } else { + } + else + { tcs.SetCanceled(); } - } finally { + } + finally + { myCancellationTokenSource.Dispose(); } }; task.ContinueWith(delegate { Dispatcher.BeginInvoke(DispatcherPriority.Normal, continuation); }); return tcs.Task; } - + void CancelButton_Click(object sender, RoutedEventArgs e) { - if (currentCancellationTokenSource != null) { + if (currentCancellationTokenSource != null) + { currentCancellationTokenSource.Cancel(); // Don't set to null: the task still needs to produce output and hide the wait adorner } } #endregion - + #region ShowOutput public void ShowText(AvalonEditTextOutput textOutput) { @@ -572,11 +638,13 @@ namespace ICSharpCode.ILSpy.TextView public void ShowNodes(AvalonEditTextOutput textOutput, ILSpyTreeNode[] nodes, IHighlightingDefinition highlighting = null) { // Cancel the decompilation task: - if (currentCancellationTokenSource != null) { + if (currentCancellationTokenSource != null) + { currentCancellationTokenSource.Cancel(); currentCancellationTokenSource = null; // prevent canceled task from producing output } - if (this.nextDecompilationRun != null) { + if (this.nextDecompilationRun != null) + { // remove scheduled decompilation run this.nextDecompilationRun.TaskCompletionSource.TrySetCanceled(); this.nextDecompilationRun = null; @@ -586,7 +654,7 @@ namespace ICSharpCode.ILSpy.TextView ShowOutput(textOutput, highlighting); decompiledNodes = nodes; } - + /// /// Shows the given output in the text view. /// @@ -597,7 +665,8 @@ namespace ICSharpCode.ILSpy.TextView ClearLocalReferenceMarks(); textEditor.ScrollToHome(); - if (foldingManager != null) { + if (foldingManager != null) + { FoldingManager.Uninstall(foldingManager); foldingManager = null; } @@ -611,63 +680,75 @@ namespace ICSharpCode.ILSpy.TextView textEditor.Options.EnableHyperlinks = textOutput.EnableHyperlinks; if (activeRichTextColorizer != null) textEditor.TextArea.TextView.LineTransformers.Remove(activeRichTextColorizer); - if (textOutput.HighlightingModel != null) { + if (textOutput.HighlightingModel != null) + { activeRichTextColorizer = new RichTextColorizer(textOutput.HighlightingModel); textEditor.TextArea.TextView.LineTransformers.Insert(highlighting == null ? 0 : 1, activeRichTextColorizer); } - + // Change the set of active element generators: - foreach (var elementGenerator in activeCustomElementGenerators) { + foreach (var elementGenerator in activeCustomElementGenerators) + { textEditor.TextArea.TextView.ElementGenerators.Remove(elementGenerator); } activeCustomElementGenerators.Clear(); - - foreach (var elementGenerator in textOutput.elementGenerators) { + + foreach (var elementGenerator in textOutput.elementGenerators) + { textEditor.TextArea.TextView.ElementGenerators.Add(elementGenerator); activeCustomElementGenerators.Add(elementGenerator); } - - Debug.WriteLine(" Set-up: {0}", w.Elapsed); w.Restart(); + + Debug.WriteLine(" Set-up: {0}", w.Elapsed); + w.Restart(); textEditor.Document = textOutput.GetDocument(); - Debug.WriteLine(" Assigning document: {0}", w.Elapsed); w.Restart(); - if (textOutput.Foldings.Count > 0) { - if (state != null) { + Debug.WriteLine(" Assigning document: {0}", w.Elapsed); + w.Restart(); + if (textOutput.Foldings.Count > 0) + { + if (state != null) + { state.RestoreFoldings(textOutput.Foldings); textEditor.ScrollToVerticalOffset(state.VerticalOffset); textEditor.ScrollToHorizontalOffset(state.HorizontalOffset); } foldingManager = FoldingManager.Install(textEditor.TextArea); foldingManager.UpdateFoldings(textOutput.Foldings.OrderBy(f => f.StartOffset), -1); - Debug.WriteLine(" Updating folding: {0}", w.Elapsed); w.Restart(); - } else if (highlighting?.Name == "XML") { + Debug.WriteLine(" Updating folding: {0}", w.Elapsed); + w.Restart(); + } + else if (highlighting?.Name == "XML") + { foldingManager = FoldingManager.Install(textEditor.TextArea); var foldingStrategy = new XmlFoldingStrategy(); foldingStrategy.UpdateFoldings(foldingManager, textEditor.Document); - Debug.WriteLine(" Updating folding: {0}", w.Elapsed); w.Restart(); + Debug.WriteLine(" Updating folding: {0}", w.Elapsed); + w.Restart(); } - if (this.DataContext is PaneModel model) { + if (this.DataContext is PaneModel model) + { model.Title = textOutput.Title; } currentAddress = textOutput.Address; } #endregion - + #region Decompile (for display) // more than 5M characters is too slow to output (when user browses treeview) - public const int DefaultOutputLengthLimit = 5000000; - + public const int DefaultOutputLengthLimit = 5000000; + // more than 75M characters can get us into trouble with memory usage public const int ExtendedOutputLengthLimit = 75000000; - + DecompilationContext nextDecompilationRun; - + [Obsolete("Use DecompileAsync() instead")] public void Decompile(ILSpy.Language language, IEnumerable treeNodes, DecompilationOptions options) { DecompileAsync(language, treeNodes, options).HandleExceptions(); } - + /// /// Starts the decompilation of the given nodes. /// The result is displayed in the text view. @@ -678,13 +759,14 @@ namespace ICSharpCode.ILSpy.TextView { // Some actions like loading an assembly list cause several selection changes in the tree view, // and each of those will start a decompilation action. - + bool isDecompilationScheduled = this.nextDecompilationRun != null; if (this.nextDecompilationRun != null) this.nextDecompilationRun.TaskCompletionSource.TrySetCanceled(); this.nextDecompilationRun = new DecompilationContext(language, treeNodes.ToArray(), options); var task = this.nextDecompilationRun.TaskCompletionSource.Task; - if (!isDecompilationScheduled) { + if (!isDecompilationScheduled) + { Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action( delegate { var context = this.nextDecompilationRun; @@ -697,14 +779,14 @@ namespace ICSharpCode.ILSpy.TextView } return task; } - + sealed class DecompilationContext { public readonly ILSpy.Language Language; public readonly ILSpyTreeNode[] TreeNodes; public readonly DecompilationOptions Options; public readonly TaskCompletionSource TaskCompletionSource = new TaskCompletionSource(); - + public DecompilationContext(ILSpy.Language language, ILSpyTreeNode[] treeNodes, DecompilationOptions options) { this.Language = language; @@ -712,7 +794,7 @@ namespace ICSharpCode.ILSpy.TextView this.Options = options; } } - + Task DoDecompile(DecompilationContext context, int outputLengthLimit) { return RunWithCancellation( @@ -726,65 +808,76 @@ namespace ICSharpCode.ILSpy.TextView decompiledNodes = context.TreeNodes; }) .Catch(exception => { - textEditor.SyntaxHighlighting = null; - Debug.WriteLine("Decompiler crashed: " + exception.ToString()); - AvalonEditTextOutput output = new AvalonEditTextOutput(); - if (exception is OutputLengthExceededException) { - WriteOutputLengthExceededMessage(output, context, outputLengthLimit == DefaultOutputLengthLimit); - } else { - output.WriteLine(exception.ToString()); - } - ShowOutput(output); - decompiledNodes = context.TreeNodes; - }); + textEditor.SyntaxHighlighting = null; + Debug.WriteLine("Decompiler crashed: " + exception.ToString()); + AvalonEditTextOutput output = new AvalonEditTextOutput(); + if (exception is OutputLengthExceededException) + { + WriteOutputLengthExceededMessage(output, context, outputLengthLimit == DefaultOutputLengthLimit); + } + else + { + output.WriteLine(exception.ToString()); + } + ShowOutput(output); + decompiledNodes = context.TreeNodes; + }); } - + Task DecompileAsync(DecompilationContext context, int outputLengthLimit) { Debug.WriteLine("Start decompilation of {0} tree nodes", context.TreeNodes.Length); - + TaskCompletionSource tcs = new TaskCompletionSource(); - if (context.TreeNodes.Length == 0) { + if (context.TreeNodes.Length == 0) + { // If there's nothing to be decompiled, don't bother starting up a thread. // (Improves perf in some cases since we don't have to wait for the thread-pool to accept our task) tcs.SetResult(new AvalonEditTextOutput()); return tcs.Task; } - + Thread thread = new Thread(new ThreadStart( delegate { - try { + try + { AvalonEditTextOutput textOutput = new AvalonEditTextOutput(); textOutput.LengthLimit = outputLengthLimit; DecompileNodes(context, textOutput); textOutput.PrepareDocument(); tcs.SetResult(textOutput); - } catch (OperationCanceledException) { + } + catch (OperationCanceledException) + { tcs.SetCanceled(); - } catch (Exception ex) { + } + catch (Exception ex) + { tcs.SetException(ex); } })); thread.Start(); return tcs.Task; } - + void DecompileNodes(DecompilationContext context, ITextOutput textOutput) { var nodes = context.TreeNodes; - if (textOutput is ISmartTextOutput smartTextOutput) { + if (textOutput is ISmartTextOutput smartTextOutput) + { smartTextOutput.Title = string.Join(", ", nodes.Select(n => n.Text)); } - for (int i = 0; i < nodes.Length; i++) { + for (int i = 0; i < nodes.Length; i++) + { if (i > 0) textOutput.WriteLine(); - + context.Options.CancellationToken.ThrowIfCancellationRequested(); nodes[i].Decompile(context.Language, textOutput, context.Options); } } #endregion - + #region WriteOutputLengthExceededMessage /// /// Creates a message that the decompiler output was too long. @@ -792,13 +885,17 @@ namespace ICSharpCode.ILSpy.TextView /// void WriteOutputLengthExceededMessage(ISmartTextOutput output, DecompilationContext context, bool wasNormalLimit) { - if (wasNormalLimit) { + if (wasNormalLimit) + { output.WriteLine("You have selected too much code for it to be displayed automatically."); - } else { + } + else + { output.WriteLine("You have selected too much code; it cannot be displayed here."); } output.WriteLine(); - if (wasNormalLimit) { + if (wasNormalLimit) + { output.AddButton( Images.ViewCode, Properties.Resources.DisplayCode, delegate { @@ -806,7 +903,7 @@ namespace ICSharpCode.ILSpy.TextView }); output.WriteLine(); } - + output.AddButton( Images.Save, Properties.Resources.SaveCode, delegate { @@ -823,11 +920,15 @@ namespace ICSharpCode.ILSpy.TextView internal void JumpToReference(ReferenceSegment referenceSegment, bool openInNewTab) { object reference = referenceSegment.Reference; - if (referenceSegment.IsLocal) { + if (referenceSegment.IsLocal) + { ClearLocalReferenceMarks(); - if (references != null) { - foreach (var r in references) { - if (reference.Equals(r.Reference)) { + if (references != null) + { + foreach (var r in references) + { + if (reference.Equals(r.Reference)) + { var mark = textMarkerService.Create(r.StartOffset, r.Length); mark.BackgroundColor = r.IsDefinition ? Colors.LightSeaGreen : Colors.GreenYellow; localReferenceMarks.Add(mark); @@ -836,9 +937,11 @@ namespace ICSharpCode.ILSpy.TextView } return; } - if (definitionLookup != null) { + if (definitionLookup != null) + { int pos = definitionLookup.GetDefinitionPosition(reference); - if (pos >= 0) { + if (pos >= 0) + { textEditor.TextArea.Focus(); textEditor.Select(pos, 0); textEditor.ScrollTo(textEditor.TextArea.Caret.Line, textEditor.TextArea.Caret.Column); @@ -858,7 +961,7 @@ namespace ICSharpCode.ILSpy.TextView { mouseDownPos = e.GetPosition(this); } - + void TextAreaMouseUp(object sender, MouseButtonEventArgs e) { if (mouseDownPos == null) @@ -870,9 +973,12 @@ namespace ICSharpCode.ILSpy.TextView { // click without moving mouse var referenceSegment = GetReferenceSegmentAtMousePosition(); - if (referenceSegment == null) { + if (referenceSegment == null) + { ClearLocalReferenceMarks(); - } else if (referenceSegment.IsLocal || !referenceSegment.IsDefinition) { + } + else if (referenceSegment.IsLocal || !referenceSegment.IsDefinition) + { textEditor.TextArea.ClearSelection(); // cancel mouse selection to avoid AvalonEdit selecting between the new // cursor position and the mouse position. @@ -882,15 +988,16 @@ namespace ICSharpCode.ILSpy.TextView } } } - + void ClearLocalReferenceMarks() { - foreach (var mark in localReferenceMarks) { + foreach (var mark in localReferenceMarks) + { textMarkerService.Remove(mark); } localReferenceMarks.Clear(); } - + /// /// Filters all ReferenceSegments that are no real links. /// @@ -899,7 +1006,7 @@ namespace ICSharpCode.ILSpy.TextView return referenceSegment.IsLocal || !referenceSegment.IsDefinition; } #endregion - + #region SaveToDisk /// /// Shows the 'save file dialog', prompting the user to save the decompiled nodes to disk. @@ -908,21 +1015,22 @@ namespace ICSharpCode.ILSpy.TextView { if (!treeNodes.Any()) return; - + SaveFileDialog dlg = new SaveFileDialog(); dlg.DefaultExt = language.FileExtension; dlg.Filter = language.Name + "|*" + language.FileExtension + Properties.Resources.AllFiles; dlg.FileName = CleanUpName(treeNodes.First().ToString()) + language.FileExtension; - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { SaveToDisk(new DecompilationContext(language, treeNodes.ToArray(), options), dlg.FileName); } } - + public void SaveToDisk(ILSpy.Language language, IEnumerable treeNodes, DecompilationOptions options, string fileName) { SaveToDisk(new DecompilationContext(language, treeNodes.ToArray(), options), fileName); } - + /// /// Starts the decompilation of the given nodes. /// The result will be saved to the given file name. @@ -951,14 +1059,19 @@ namespace ICSharpCode.ILSpy.TextView TaskCompletionSource tcs = new TaskCompletionSource(); Thread thread = new Thread(new ThreadStart( delegate { - try { + try + { context.Options.EscapeInvalidIdentifiers = true; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); - using (StreamWriter w = new StreamWriter(fileName)) { - try { + using (StreamWriter w = new StreamWriter(fileName)) + { + try + { DecompileNodes(context, new PlainTextOutput(w)); - } catch (OperationCanceledException) { + } + catch (OperationCanceledException) + { w.WriteLine(); w.WriteLine("Decompiled was cancelled."); throw; @@ -971,7 +1084,8 @@ namespace ICSharpCode.ILSpy.TextView }; output.WriteLine(Properties.Resources.DecompilationCompleteInF1Seconds, stopwatch.Elapsed.TotalSeconds); - if (context.Options.SaveAsProjectDirectory != null) { + if (context.Options.SaveAsProjectDirectory != null) + { output.WriteLine(); if (context.Options.DecompilerSettings.UseSdkStyleProjectFormat) output.WriteLine(Properties.Resources.ProjectExportFormatSDKHint); @@ -983,16 +1097,20 @@ namespace ICSharpCode.ILSpy.TextView output.AddButton(null, Properties.Resources.OpenExplorer, delegate { Process.Start("explorer", "/select,\"" + fileName + "\""); }); output.WriteLine(); tcs.SetResult(output); - } catch (OperationCanceledException) { + } + catch (OperationCanceledException) + { tcs.SetCanceled(); - } catch (Exception ex) { + } + catch (Exception ex) + { tcs.SetException(ex); } })); thread.Start(); return tcs.Task; } - + /// /// Cleans up a node name for use as a file name. /// @@ -1012,7 +1130,7 @@ namespace ICSharpCode.ILSpy.TextView int offset = textEditor.Document.GetOffset(position.Value.Location); return referenceElementGenerator.References.FindSegmentsContaining(offset).FirstOrDefault(); } - + internal TextViewPosition? GetPositionFromMousePosition() { var position = textEditor.TextArea.TextView.GetPosition(Mouse.GetPosition(textEditor.TextArea.TextView) + textEditor.TextArea.TextView.ScrollOffset); @@ -1023,7 +1141,7 @@ namespace ICSharpCode.ILSpy.TextView return null; return position; } - + public DecompilerTextViewState GetState() { if (decompiledNodes == null && currentAddress == null) @@ -1045,20 +1163,23 @@ namespace ICSharpCode.ILSpy.TextView { DisplaySettingsPanel.CurrentDisplaySettings.PropertyChanged -= CurrentDisplaySettings_PropertyChanged; } - + #region Unfold public void UnfoldAndScroll(int lineNumber) { if (lineNumber <= 0 || lineNumber > textEditor.Document.LineCount) return; - + var line = textEditor.Document.GetLineByNumber(lineNumber); - + // unfold var foldings = foldingManager.GetFoldingsContaining(line.Offset); - if (foldings != null) { - foreach (var folding in foldings) { - if (folding.IsFolded) { + if (foldings != null) + { + foreach (var folding in foldings) + { + if (folding.IsFolded) + { folding.IsFolded = false; } } @@ -1066,9 +1187,8 @@ namespace ICSharpCode.ILSpy.TextView // scroll to textEditor.ScrollTo(lineNumber, 0); } - - public FoldingManager FoldingManager - { + + public FoldingManager FoldingManager { get { return foldingManager; } @@ -1089,7 +1209,7 @@ namespace ICSharpCode.ILSpy.TextView && (DecompiledNodes == other.DecompiledNodes || DecompiledNodes?.SetEquals(other.DecompiledNodes) == true); } } - + public class DecompilerTextViewState : ViewState { private List> ExpandedFoldings; @@ -1113,7 +1233,8 @@ namespace ICSharpCode.ILSpy.TextView public override bool Equals(ViewState other) { - if (other is DecompilerTextViewState vs) { + if (other is DecompilerTextViewState vs) + { return base.Equals(vs) && FoldingsChecksum == vs.FoldingsChecksum && VerticalOffset == vs.VerticalOffset diff --git a/ILSpy/TextView/DocumentationUIBuilder.cs b/ILSpy/TextView/DocumentationUIBuilder.cs index 14cd8c421..10276289c 100644 --- a/ILSpy/TextView/DocumentationUIBuilder.cs +++ b/ILSpy/TextView/DocumentationUIBuilder.cs @@ -29,6 +29,7 @@ using System.Windows.Documents; using System.Windows.Media; using System.Xml; using System.Xml.Linq; + using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Utils; @@ -125,7 +126,7 @@ namespace ICSharpCode.ILSpy.TextView block.TextAlignment = TextAlignment.Left; AddBlock(block); } - + public void AddXmlDocumentation(string xmlDocumentation, IEntity declaringEntity, Func resolver) { if (xmlDocumentation == null) @@ -134,7 +135,7 @@ namespace ICSharpCode.ILSpy.TextView var xml = XElement.Parse("" + xmlDocumentation + ""); AddDocumentationElement(new XmlDocumentationElement(xml, declaringEntity, resolver)); } - + /// /// Gets/Sets the name of the parameter that should be shown. @@ -145,11 +146,13 @@ namespace ICSharpCode.ILSpy.TextView { if (element == null) throw new ArgumentNullException("element"); - if (element.IsTextNode) { + if (element.IsTextNode) + { AddText(element.TextContent); return; } - switch (element.Name) { + switch (element.Name) + { case "b": AddSpan(new Bold(), element.Children); break; @@ -254,20 +257,26 @@ namespace ICSharpCode.ILSpy.TextView else if (type == "bullet") list.MarkerStyle = TextMarkerStyle.Disc; var oldBlockCollection = blockCollection; - try { - foreach (var itemElement in items) { - if (itemElement.Name == "listheader" || itemElement.Name == "item") { + try + { + foreach (var itemElement in items) + { + if (itemElement.Name == "listheader" || itemElement.Name == "item") + { ListItem item = new ListItem(); blockCollection = item.Blocks; inlineCollection = null; - foreach (var prop in itemElement.Children) { + foreach (var prop in itemElement.Children) + { AddDocumentationElement(prop); } FlushAddedText(false); list.ListItems.Add(item); } } - } finally { + } + finally + { blockCollection = oldBlockCollection; } } @@ -316,7 +325,8 @@ namespace ICSharpCode.ILSpy.TextView { Span span = new Span(); span.Inlines.Add("Permission"); - if (referencedEntity != null) { + if (referencedEntity != null) + { span.Inlines.Add(" "); span.Inlines.Add(ConvertReference(referencedEntity)); } @@ -343,17 +353,21 @@ namespace ICSharpCode.ILSpy.TextView void AddParamRef(string name) { - if (name != null) { + if (name != null) + { AddInline(new Run(name) { FontStyle = FontStyles.Italic }); } } void AddPreliminary(IEnumerable children) { - if (children.Any()) { + if (children.Any()) + { foreach (var child in children) AddDocumentationElement(child); - } else { + } + else + { AddText("[This is preliminary documentation and subject to change.]"); } } @@ -361,28 +375,42 @@ namespace ICSharpCode.ILSpy.TextView void AddSee(XmlDocumentationElement element) { IEntity referencedEntity = element.ReferencedEntity; - if (referencedEntity != null) { - if (element.Children.Any()) { + if (referencedEntity != null) + { + if (element.Children.Any()) + { Hyperlink link = new Hyperlink(); link.Click += (sender, e) => { MainWindow.Instance.JumpToReference(referencedEntity); }; AddSpan(link, element.Children); - } else { + } + else + { AddInline(ConvertReference(referencedEntity)); } - } else if (element.GetAttribute("langword") != null) { + } + else if (element.GetAttribute("langword") != null) + { AddInline(new Run(element.GetAttribute("langword")) { FontFamily = GetCodeFont() }); - } else if (element.GetAttribute("href") != null) { + } + else if (element.GetAttribute("href") != null) + { Uri uri; - if (Uri.TryCreate(element.GetAttribute("href"), UriKind.Absolute, out uri)) { - if (element.Children.Any()) { + if (Uri.TryCreate(element.GetAttribute("href"), UriKind.Absolute, out uri)) + { + if (element.Children.Any()) + { AddSpan(new Hyperlink { NavigateUri = uri }, element.Children); - } else { + } + else + { AddInline(new Hyperlink(new Run(element.GetAttribute("href"))) { NavigateUri = uri }); } } - } else { + } + else + { // Invalid reference: print the cref value AddText(element.GetAttribute("cref")); } @@ -390,13 +418,16 @@ namespace ICSharpCode.ILSpy.TextView static string GetCref(string cref) { - if (cref == null || cref.Trim().Length==0) { + if (cref == null || cref.Trim().Length == 0) + { return ""; } - if (cref.Length < 2) { + if (cref.Length < 2) + { return cref; } - if (cref.Substring(1, 1) == ":") { + if (cref.Substring(1, 1) == ":") + { return cref.Substring(2, cref.Length - 2); } return cref; @@ -410,7 +441,8 @@ namespace ICSharpCode.ILSpy.TextView public void AddInline(Inline inline) { FlushAddedText(false); - if (inlineCollection == null) { + if (inlineCollection == null) + { var para = new Paragraph(); para.Margin = new Thickness(0, 0, 0, 5); inlineCollection = para.Inlines; @@ -439,7 +471,8 @@ namespace ICSharpCode.ILSpy.TextView var section = new Section(); AddBlock(section); var oldBlockCollection = blockCollection; - try { + try + { blockCollection = section.Blocks; inlineCollection = null; @@ -448,7 +481,9 @@ namespace ICSharpCode.ILSpy.TextView addChildren(); FlushAddedText(false); - } finally { + } + finally + { blockCollection = oldBlockCollection; inlineCollection = null; } @@ -457,13 +492,16 @@ namespace ICSharpCode.ILSpy.TextView void AddParagraph(Paragraph para, IEnumerable children) { AddBlock(para); - try { + try + { inlineCollection = para.Inlines; foreach (var child in children) AddDocumentationElement(child); FlushAddedText(false); - } finally { + } + finally + { inlineCollection = null; } } @@ -472,12 +510,15 @@ namespace ICSharpCode.ILSpy.TextView { AddInline(span); var oldInlineCollection = inlineCollection; - try { + try + { inlineCollection = span.Inlines; foreach (var child in children) AddDocumentationElement(child); FlushAddedText(false); - } finally { + } + finally + { inlineCollection = oldInlineCollection; } } @@ -502,17 +543,24 @@ namespace ICSharpCode.ILSpy.TextView { if (string.IsNullOrEmpty(textContent)) return; - for (int i = 0; i < textContent.Length; i++) { + for (int i = 0; i < textContent.Length; i++) + { char c = textContent[i]; - if (c == '\n' && IsEmptyLineBefore(textContent, i)) { + if (c == '\n' && IsEmptyLineBefore(textContent, i)) + { AddLineBreak(); // empty line -> line break - } else if (char.IsWhiteSpace(c)) { + } + else if (char.IsWhiteSpace(c)) + { // any whitespace sequence gets converted to a single space (like HTML) - if (!ignoreWhitespace) { + if (!ignoreWhitespace) + { addedText.Append(' '); ignoreWhitespace = true; } - } else { + } + else + { addedText.Append(c); ignoreWhitespace = false; } @@ -522,7 +570,8 @@ namespace ICSharpCode.ILSpy.TextView bool IsEmptyLineBefore(string text, int i) { // Skip previous whitespace - do { + do + { i--; } while (i >= 0 && (text[i] == ' ' || text[i] == '\r')); // Check if previous non-whitespace char is \n @@ -531,7 +580,8 @@ namespace ICSharpCode.ILSpy.TextView void TrimEndOfAddedText() { - while (addedText.Length > 0 && addedText[addedText.Length - 1] == ' ') { + while (addedText.Length > 0 && addedText[addedText.Length - 1] == ' ') + { addedText.Length--; } } diff --git a/ILSpy/TextView/FoldingCommands.cs b/ILSpy/TextView/FoldingCommands.cs index fa226f418..dc8051631 100644 --- a/ILSpy/TextView/FoldingCommands.cs +++ b/ILSpy/TextView/FoldingCommands.cs @@ -45,13 +45,16 @@ namespace ICSharpCode.ILSpy.TextView if (null == foldingManager) return; bool doFold = true; - foreach (FoldingSection fm in foldingManager.AllFoldings) { - if (fm.IsFolded) { + foreach (FoldingSection fm in foldingManager.AllFoldings) + { + if (fm.IsFolded) + { doFold = false; break; } } - foreach (FoldingSection fm in foldingManager.AllFoldings) { + foreach (FoldingSection fm in foldingManager.AllFoldings) + { fm.IsFolded = doFold; } } @@ -86,11 +89,13 @@ namespace ICSharpCode.ILSpy.TextView TextViewPosition pos = posBox.Value; // look for folding on this line: FoldingSection folding = foldingManager.GetNextFolding(editor.Document.GetOffset(pos.Line, 1)); - if (folding == null || editor.Document.GetLineByOffset(folding.StartOffset).LineNumber != pos.Line) { + if (folding == null || editor.Document.GetLineByOffset(folding.StartOffset).LineNumber != pos.Line) + { // no folding found on current line: find innermost folding containing the mouse position folding = foldingManager.GetFoldingsContaining(editor.Document.GetOffset(pos.Line, pos.Column)).LastOrDefault(); } - if (folding != null) { + if (folding != null) + { folding.IsFolded = !folding.IsFolded; } } diff --git a/ILSpy/TextView/OutputLengthExceededException.cs b/ILSpy/TextView/OutputLengthExceededException.cs index d097ae303..95fd26e38 100644 --- a/ILSpy/TextView/OutputLengthExceededException.cs +++ b/ILSpy/TextView/OutputLengthExceededException.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.ILSpy.TextView { } - public OutputLengthExceededException(string message) : base(message) + public OutputLengthExceededException(string message) : base(message) { } diff --git a/ILSpy/TextView/ReferenceElementGenerator.cs b/ILSpy/TextView/ReferenceElementGenerator.cs index 341dfcb04..f1255990a 100644 --- a/ILSpy/TextView/ReferenceElementGenerator.cs +++ b/ILSpy/TextView/ReferenceElementGenerator.cs @@ -18,6 +18,7 @@ using System; using System.Windows.Input; + using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; @@ -29,19 +30,19 @@ namespace ICSharpCode.ILSpy.TextView sealed class ReferenceElementGenerator : VisualLineElementGenerator { readonly Predicate isLink; - + /// /// The collection of references (hyperlinks). /// public TextSegmentCollection References { get; set; } - + public ReferenceElementGenerator(Predicate isLink) { if (isLink == null) throw new ArgumentNullException(nameof(isLink)); this.isLink = isLink; } - + public override int GetFirstInterestedOffset(int startOffset) { if (this.References == null) @@ -50,26 +51,28 @@ namespace ICSharpCode.ILSpy.TextView var segment = this.References.FindFirstSegmentWithStartAfter(startOffset); return segment != null ? segment.StartOffset : -1; } - + public override VisualLineElement ConstructElement(int offset) { if (this.References == null) return null; - foreach (var segment in this.References.FindSegmentsContaining(offset)) { + foreach (var segment in this.References.FindSegmentsContaining(offset)) + { // skip all non-links if (!isLink(segment)) continue; // ensure that hyperlinks don't span several lines (VisualLineElements can't contain line breaks) int endOffset = Math.Min(segment.EndOffset, CurrentContext.VisualLine.LastDocumentLine.EndOffset); // don't create hyperlinks with length 0 - if (offset < endOffset) { + if (offset < endOffset) + { return new VisualLineReferenceText(CurrentContext.VisualLine, endOffset - offset, this, segment); } } return null; } } - + /// /// VisualLineElement that represents a piece of text and is a clickable link. /// @@ -77,7 +80,7 @@ namespace ICSharpCode.ILSpy.TextView { readonly ReferenceElementGenerator parent; readonly ReferenceSegment referenceSegment; - + /// /// Creates a visual line text element with the specified length. /// It uses the and its @@ -88,14 +91,14 @@ namespace ICSharpCode.ILSpy.TextView this.parent = parent; this.referenceSegment = referenceSegment; } - + /// protected override void OnQueryCursor(QueryCursorEventArgs e) { e.Handled = true; e.Cursor = referenceSegment.IsLocal ? Cursors.Arrow : Cursors.Hand; } - + /// protected override VisualLineText CreateInstance(int length) { diff --git a/ILSpy/TextView/UIElementGenerator.cs b/ILSpy/TextView/UIElementGenerator.cs index 00e649adf..e0c254e61 100644 --- a/ILSpy/TextView/UIElementGenerator.cs +++ b/ILSpy/TextView/UIElementGenerator.cs @@ -25,7 +25,7 @@ using ICSharpCode.AvalonEdit.Rendering; namespace ICSharpCode.ILSpy.TextView { using Pair = KeyValuePair>; - + /// /// Embeds UIElements in the text output. /// @@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.TextView /// The "Lazy" part is used to create UIElements on demand (and thus on the UI thread, not on the decompiler thread). /// public List UIElements; - + public override int GetFirstInterestedOffset(int startOffset) { if (this.UIElements == null) @@ -52,7 +52,7 @@ namespace ICSharpCode.ILSpy.TextView else return -1; } - + public override VisualLineElement ConstructElement(int offset) { if (this.UIElements == null) @@ -63,7 +63,7 @@ namespace ICSharpCode.ILSpy.TextView else return null; } - + int IComparer.Compare(Pair x, Pair y) { // Compare (offset,Lazy) pairs by the offset. diff --git a/ILSpy/TreeNodes/AssemblyListTreeNode.cs b/ILSpy/TreeNodes/AssemblyListTreeNode.cs index 16df394cf..624a29f23 100644 --- a/ILSpy/TreeNodes/AssemblyListTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyListTreeNode.cs @@ -24,6 +24,7 @@ using System.IO; using System.Linq; using System.Reflection.PortableExecutable; using System.Windows; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -39,8 +40,7 @@ namespace ICSharpCode.ILSpy.TreeNodes { readonly AssemblyList assemblyList; - public AssemblyList AssemblyList - { + public AssemblyList AssemblyList { get { return assemblyList; } } @@ -50,8 +50,7 @@ namespace ICSharpCode.ILSpy.TreeNodes BindToObservableCollection(assemblyList.assemblies); } - public override object Text - { + public override object Text { get { return assemblyList.ListName; } } @@ -59,8 +58,9 @@ namespace ICSharpCode.ILSpy.TreeNodes { this.Children.Clear(); this.Children.AddRange(collection.Select(a => new AssemblyTreeNode(a))); - collection.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e) { - switch (e.Action) { + collection.CollectionChanged += delegate (object sender, NotifyCollectionChangedEventArgs e) { + switch (e.Action) + { case NotifyCollectionChangedAction.Add: this.Children.InsertRange(e.NewStartingIndex, e.NewItems.Cast().Select(a => new AssemblyTreeNode(a))); break; @@ -87,7 +87,8 @@ namespace ICSharpCode.ILSpy.TreeNodes return true; else if (e.Data.GetDataPresent(DataFormats.FileDrop)) return true; - else { + else + { e.Effects = DragDropEffects.None; return false; } @@ -98,22 +99,26 @@ namespace ICSharpCode.ILSpy.TreeNodes string[] files = e.Data.GetData(AssemblyTreeNode.DataFormat) as string[]; if (files == null) files = e.Data.GetData(DataFormats.FileDrop) as string[]; - if (files != null) { - lock (assemblyList.assemblies) { + if (files != null) + { + lock (assemblyList.assemblies) + { var assemblies = files .Where(file => file != null) .SelectMany(file => OpenAssembly(assemblyList, file)) .Where(asm => asm != null) .Distinct() .ToArray(); - foreach (LoadedAssembly asm in assemblies) { + foreach (LoadedAssembly asm in assemblies) + { int nodeIndex = assemblyList.assemblies.IndexOf(asm); if (nodeIndex < index) index--; assemblyList.assemblies.RemoveAt(nodeIndex); } Array.Reverse(assemblies); - foreach (LoadedAssembly asm in assemblies) { + foreach (LoadedAssembly asm in assemblies) + { assemblyList.assemblies.Insert(index, asm); } var nodes = assemblies.SelectArray(MainWindow.Instance.FindTreeNode); @@ -124,15 +129,18 @@ namespace ICSharpCode.ILSpy.TreeNodes private IEnumerable OpenAssembly(AssemblyList assemblyList, string file) { - if (file.EndsWith(".nupkg")) { + if (file.EndsWith(".nupkg")) + { LoadedNugetPackage package = new LoadedNugetPackage(file); var selectionDialog = new NugetPackageBrowserDialog(package); selectionDialog.Owner = Application.Current.MainWindow; if (selectionDialog.ShowDialog() != true) yield break; - foreach (var entry in selectionDialog.SelectedItems) { + foreach (var entry in selectionDialog.SelectedItems) + { var nugetAsm = assemblyList.OpenAssembly("nupkg://" + file + ";" + entry.Name, entry.Stream, true); - if (nugetAsm != null) { + if (nugetAsm != null) + { yield return nugetAsm; } } @@ -147,7 +155,8 @@ namespace ICSharpCode.ILSpy.TreeNodes { language.WriteCommentLine(output, "List: " + assemblyList.ListName); output.WriteLine(); - foreach (AssemblyTreeNode asm in this.Children) { + foreach (AssemblyTreeNode asm in this.Children) + { language.WriteCommentLine(output, new string('-', 60)); output.WriteLine(); asm.Decompile(language, output, options); @@ -199,7 +208,8 @@ namespace ICSharpCode.ILSpy.TreeNodes if (module == null) return null; App.Current.Dispatcher.VerifyAccess(); - foreach (AssemblyTreeNode node in this.Children) { + foreach (AssemblyTreeNode node in this.Children) + { if (node.LoadedAssembly.IsLoaded && node.LoadedAssembly.GetPEFileOrNull()?.FileName == module.FileName) return node; } @@ -211,7 +221,8 @@ namespace ICSharpCode.ILSpy.TreeNodes if (asm == null) return null; App.Current.Dispatcher.VerifyAccess(); - foreach (AssemblyTreeNode node in this.Children) { + foreach (AssemblyTreeNode node in this.Children) + { if (node.LoadedAssembly == asm) return node; } @@ -227,15 +238,20 @@ namespace ICSharpCode.ILSpy.TreeNodes if (def == null) return null; var declaringType = def.DeclaringTypeDefinition; - if (declaringType != null) { + if (declaringType != null) + { TypeTreeNode decl = FindTypeNode(declaringType); - if (decl != null) { + if (decl != null) + { decl.EnsureLazyChildren(); return decl.Children.OfType().FirstOrDefault(t => t.TypeDefinition.MetadataToken == def.MetadataToken && !t.IsHidden); } - } else { + } + else + { AssemblyTreeNode asm = FindAssemblyNode(def.ParentModule); - if (asm != null) { + if (asm != null) + { return asm.FindTypeNode(def); } } @@ -255,7 +271,8 @@ namespace ICSharpCode.ILSpy.TreeNodes ILSpyTreeNode parentNode = typeNode; MethodTreeNode methodNode; parentNode.EnsureLazyChildren(); - switch (def.AccessorOwner) { + switch (def.AccessorOwner) + { case IProperty p: parentNode = parentNode.Children.OfType().FirstOrDefault(m => m.PropertyDefinition.MetadataToken == p.MetadataToken && !m.IsHidden); if (parentNode == null) diff --git a/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs b/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs index 0a64b9ea7..eecf00c1f 100644 --- a/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; @@ -29,7 +30,7 @@ namespace ICSharpCode.ILSpy.TreeNodes { readonly AssemblyReference r; readonly AssemblyTreeNode parentAssembly; - + public AssemblyReferenceTreeNode(AssemblyReference r, AssemblyTreeNode parentAssembly) { this.r = r ?? throw new ArgumentNullException(nameof(r)); @@ -52,45 +53,54 @@ namespace ICSharpCode.ILSpy.TreeNodes return base.ShowExpander; } } - + public override void ActivateItem(System.Windows.RoutedEventArgs e) { var assemblyListNode = parentAssembly.Parent as AssemblyListTreeNode; - if (assemblyListNode != null) { + if (assemblyListNode != null) + { assemblyListNode.Select(assemblyListNode.FindAssemblyNode(parentAssembly.LoadedAssembly.LookupReferencedAssembly(r))); e.Handled = true; } } - + protected override void LoadChildren() { var assemblyListNode = parentAssembly.Parent as AssemblyListTreeNode; - if (assemblyListNode != null) { + if (assemblyListNode != null) + { var refNode = assemblyListNode.FindAssemblyNode(parentAssembly.LoadedAssembly.LookupReferencedAssembly(r)); - if (refNode != null) { + if (refNode != null) + { var module = refNode.LoadedAssembly.GetPEFileOrNull(); - if (module != null) { + if (module != null) + { foreach (var childRef in module.AssemblyReferences) this.Children.Add(new AssemblyReferenceTreeNode(childRef, refNode)); } } } } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { var loaded = parentAssembly.LoadedAssembly.LoadedAssemblyReferencesInfo.TryGetInfo(r.FullName, out var info); - if (r.IsWindowsRuntime) { + if (r.IsWindowsRuntime) + { language.WriteCommentLine(output, r.FullName + " [WinRT]" + (!loaded ? " (unresolved)" : "")); - } else { + } + else + { language.WriteCommentLine(output, r.FullName + (!loaded ? " (unresolved)" : "")); } - if (loaded) { + if (loaded) + { output.Indent(); language.WriteCommentLine(output, "Assembly reference loading information:"); if (info.HasErrors) language.WriteCommentLine(output, "There were some problems during assembly reference load, see below for more information!"); - foreach (var item in info.Messages) { + foreach (var item in info.Messages) + { language.WriteCommentLine(output, $"{item.Item1}: {item.Item2}"); } output.Unindent(); diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs index edbfb87ed..a53f4b084 100644 --- a/ILSpy/TreeNodes/AssemblyTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs @@ -24,15 +24,18 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; +using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.TreeView; + using Microsoft.Win32; -using ICSharpCode.Decompiler.TypeSystem; + using TypeDefinitionHandle = System.Reflection.Metadata.TypeDefinitionHandle; -using ICSharpCode.ILSpy.Properties; -using ICSharpCode.ILSpy.ViewModels; namespace ICSharpCode.ILSpy.TreeNodes { @@ -70,9 +73,12 @@ namespace ICSharpCode.ILSpy.TreeNodes public override object Icon { get { - if (LoadedAssembly.IsLoaded) { + if (LoadedAssembly.IsLoaded) + { return LoadedAssembly.HasLoadError ? Images.AssemblyWarning : Images.Assembly; - } else { + } + else + { return Images.FindAssembly; } } @@ -85,11 +91,13 @@ namespace ICSharpCode.ILSpy.TreeNodes if (LoadedAssembly.HasLoadError) return "Assembly could not be loaded. Click here for details."; - if (tooltip == null && LoadedAssembly.IsLoaded) { + if (tooltip == null && LoadedAssembly.IsLoaded) + { tooltip = new TextBlock(); var module = LoadedAssembly.GetPEFileOrNull(); var metadata = module?.Metadata; - if (metadata?.IsAssembly == true) { + if (metadata?.IsAssembly == true) + { tooltip.Inlines.Add(new Bold(new Run("Name: "))); tooltip.Inlines.Add(new Run(metadata.GetFullAssemblyName())); tooltip.Inlines.Add(new LineBreak()); @@ -100,7 +108,8 @@ namespace ICSharpCode.ILSpy.TreeNodes tooltip.Inlines.Add(new Bold(new Run("Architecture: "))); tooltip.Inlines.Add(new Run(Language.GetPlatformDisplayName(module))); string runtimeName = Language.GetRuntimeDisplayName(module); - if (runtimeName != null) { + if (runtimeName != null) + { tooltip.Inlines.Add(new LineBreak()); tooltip.Inlines.Add(new Bold(new Run("Runtime: "))); tooltip.Inlines.Add(new Run(runtimeName)); @@ -125,9 +134,12 @@ namespace ICSharpCode.ILSpy.TreeNodes RaisePropertyChanged(nameof(Icon)); RaisePropertyChanged(nameof(ExpandedIcon)); RaisePropertyChanged(nameof(ToolTip)); - if (moduleTask.IsFaulted) { + if (moduleTask.IsFaulted) + { RaisePropertyChanged(nameof(ShowExpander)); // cannot expand assemblies with load error - } else { + } + else + { RaisePropertyChanged(nameof(Text)); // shortname might have changed } } @@ -135,7 +147,8 @@ namespace ICSharpCode.ILSpy.TreeNodes protected override void LoadChildren() { var module = LoadedAssembly.GetPEFileOrNull(); - if (module == null) { + if (module == null) + { // if we crashed on loading, then we don't have any children return; } @@ -143,18 +156,22 @@ namespace ICSharpCode.ILSpy.TreeNodes var assembly = (MetadataModule)typeSystem.MainModule; this.Children.Add(new Metadata.MetadataTreeNode(module, this)); Decompiler.DebugInfo.IDebugInfoProvider debugInfo = LoadedAssembly.GetDebugInfoOrNull(); - if (debugInfo is Decompiler.PdbProvider.PortableDebugInfoProvider ppdb) { + if (debugInfo is Decompiler.PdbProvider.PortableDebugInfoProvider ppdb) + { this.Children.Add(new Metadata.DebugMetadataTreeNode(module, ppdb.IsEmbedded, ppdb.Provider.GetMetadataReader(), this)); } this.Children.Add(new ReferenceFolderTreeNode(module, this)); if (module.Resources.Any()) this.Children.Add(new ResourceListTreeNode(module)); - foreach (NamespaceTreeNode ns in namespaces.Values) { + foreach (NamespaceTreeNode ns in namespaces.Values) + { ns.Children.Clear(); } - foreach (var type in assembly.TopLevelTypeDefinitions.OrderBy(t => t.ReflectionName, NaturalStringComparer.Instance)) { + foreach (var type in assembly.TopLevelTypeDefinitions.OrderBy(t => t.ReflectionName, NaturalStringComparer.Instance)) + { var escapedNamespace = Language.EscapeName(type.Namespace); - if (!namespaces.TryGetValue(type.Namespace, out NamespaceTreeNode ns)) { + if (!namespaces.TryGetValue(type.Namespace, out NamespaceTreeNode ns)) + { ns = new NamespaceTreeNode(escapedNamespace); namespaces.Add(type.Namespace, ns); } @@ -162,7 +179,8 @@ namespace ICSharpCode.ILSpy.TreeNodes typeDict[(TypeDefinitionHandle)type.MetadataToken] = node; ns.Children.Add(node); } - foreach (NamespaceTreeNode ns in namespaces.Values.OrderBy(n => n.Name, NaturalStringComparer.Instance)) { + foreach (NamespaceTreeNode ns in namespaces.Values.OrderBy(n => n.Name, NaturalStringComparer.Instance)) + { if (ns.Children.Count > 0) this.Children.Add(ns); } @@ -254,11 +272,15 @@ namespace ICSharpCode.ILSpy.TreeNodes output.MarkFoldEnd(); } - try { + try + { LoadedAssembly.WaitUntilLoaded(); // necessary so that load errors are passed on to the caller - } catch (AggregateException ex) { + } + catch (AggregateException ex) + { language.WriteCommentLine(output, LoadedAssembly.FileName); - switch (ex.InnerException) { + switch (ex.InnerException) + { case BadImageFormatException badImage: HandleException(badImage, "This file does not contain a managed assembly."); return; @@ -286,13 +308,17 @@ namespace ICSharpCode.ILSpy.TreeNodes SaveFileDialog dlg = new SaveFileDialog(); dlg.FileName = DecompilerTextView.CleanUpName(LoadedAssembly.ShortName) + language.ProjectFileExtension; dlg.Filter = language.Name + " project|*" + language.ProjectFileExtension + "|" + language.Name + " single file|*" + language.FileExtension + "|All files|*.*"; - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { DecompilationOptions options = new DecompilationOptions(); options.FullDecompilation = true; - if (dlg.FilterIndex == 1) { + if (dlg.FilterIndex == 1) + { options.SaveAsProjectDirectory = Path.GetDirectoryName(dlg.FileName); - foreach (string entry in Directory.GetFileSystemEntries(options.SaveAsProjectDirectory)) { - if (!string.Equals(entry, dlg.FileName, StringComparison.OrdinalIgnoreCase)) { + foreach (string entry in Directory.GetFileSystemEntries(options.SaveAsProjectDirectory)) + { + if (!string.Equals(entry, dlg.FileName, StringComparison.OrdinalIgnoreCase)) + { var result = MessageBox.Show( Resources.AssemblySaveCodeDirectoryNotEmpty, Resources.AssemblySaveCodeDirectoryNotEmptyTitle, @@ -335,7 +361,8 @@ namespace ICSharpCode.ILSpy.TreeNodes { if (context.SelectedTreeNodes == null) return; - foreach (var node in context.SelectedTreeNodes) { + foreach (var node in context.SelectedTreeNodes) + { node.Delete(); } } @@ -361,8 +388,10 @@ namespace ICSharpCode.ILSpy.TreeNodes if (context.SelectedTreeNodes == null) return; var paths = new List(); - using (context.TreeView.LockUpdates()) { - foreach (var node in context.SelectedTreeNodes) { + using (context.TreeView.LockUpdates()) + { + foreach (var node in context.SelectedTreeNodes) + { paths.Add(MainWindow.GetPathForNode(node)); var la = ((AssemblyTreeNode)node).LoadedAssembly; la.AssemblyList.ReloadAssembly(la.FileName); @@ -392,12 +421,15 @@ namespace ICSharpCode.ILSpy.TreeNodes { if (context.SelectedTreeNodes == null) return; - foreach (var node in context.SelectedTreeNodes) { + foreach (var node in context.SelectedTreeNodes) + { var la = ((AssemblyTreeNode)node).LoadedAssembly; var module = la.GetPEFileOrNull(); - if (module != null) { + if (module != null) + { var metadata = module.Metadata; - foreach (var assyRef in metadata.AssemblyReferences) { + foreach (var assyRef in metadata.AssemblyReferences) + { la.LookupReferencedAssembly(new AssemblyReference(module, assyRef)); } } @@ -427,9 +459,11 @@ namespace ICSharpCode.ILSpy.TreeNodes { if (context.SelectedTreeNodes == null) return; - foreach (var node in context.SelectedTreeNodes) { + foreach (var node in context.SelectedTreeNodes) + { var loadedAssm = ((AssemblyTreeNode)node).LoadedAssembly; - if (!loadedAssm.HasLoadError && !loadedAssm.FileName.StartsWith("nupkg://")) { + if (!loadedAssm.HasLoadError && !loadedAssm.FileName.StartsWith("nupkg://")) + { loadedAssm.IsAutoLoaded = false; node.RaisePropertyChanged(nameof(node.Foreground)); } @@ -454,7 +488,8 @@ namespace ICSharpCode.ILSpy.TreeNodes internal static AssemblyTreeNode GetAssemblyTreeNode(SharpTreeNode node) { - while (node != null) { + while (node != null) + { if (node is AssemblyTreeNode a) return a; node = node.Parent; @@ -477,10 +512,12 @@ namespace ICSharpCode.ILSpy.TreeNodes { if (context.SelectedTreeNodes == null) return; - foreach (var n in context.SelectedTreeNodes) { + foreach (var n in context.SelectedTreeNodes) + { var node = GetAssemblyTreeNode(n); var path = node.LoadedAssembly.FileName; - if (File.Exists(path)) { + if (File.Exists(path)) + { MainWindow.ExecuteCommand("explorer.exe", $"/select,\"{path}\""); } } @@ -516,10 +553,12 @@ namespace ICSharpCode.ILSpy.TreeNodes { if (context.SelectedTreeNodes == null) return; - foreach (var n in context.SelectedTreeNodes) { + foreach (var n in context.SelectedTreeNodes) + { var node = OpenContainingFolder.GetAssemblyTreeNode(n); var path = Path.GetDirectoryName(node.LoadedAssembly.FileName); - if (Directory.Exists(path)) { + if (Directory.Exists(path)) + { MainWindow.ExecuteCommand("cmd.exe", $"/k \"cd {path}\""); } } diff --git a/ILSpy/TreeNodes/BaseTypesEntryNode.cs b/ILSpy/TreeNodes/BaseTypesEntryNode.cs index 96440c6c2..138c86e52 100644 --- a/ILSpy/TreeNodes/BaseTypesEntryNode.cs +++ b/ILSpy/TreeNodes/BaseTypesEntryNode.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Linq; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.TreeView; @@ -43,9 +44,11 @@ namespace ICSharpCode.ILSpy.TreeNodes internal static bool ActivateItem(SharpTreeNode node, ITypeDefinition def) { - if (def != null) { + if (def != null) + { var assemblyListNode = node.Ancestors().OfType().FirstOrDefault(); - if (assemblyListNode != null) { + if (assemblyListNode != null) + { assemblyListNode.Select(assemblyListNode.FindTypeNode(def)); return true; } diff --git a/ILSpy/TreeNodes/BaseTypesTreeNode.cs b/ILSpy/TreeNodes/BaseTypesTreeNode.cs index e04a0049d..7d52a33bf 100644 --- a/ILSpy/TreeNodes/BaseTypesTreeNode.cs +++ b/ILSpy/TreeNodes/BaseTypesTreeNode.cs @@ -60,7 +60,8 @@ namespace ICSharpCode.ILSpy.TreeNodes DecompilerTypeSystem typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver(), TypeSystemOptions.Default | TypeSystemOptions.Uncached); var t = typeSystem.MainModule.ResolveEntity(handle) as ITypeDefinition; - foreach (var td in t.GetAllBaseTypeDefinitions().Reverse().Skip(1)) { + foreach (var td in t.GetAllBaseTypeDefinitions().Reverse().Skip(1)) + { if (t.Kind != TypeKind.Interface || t.Kind == td.Kind) children.Add(new BaseTypesEntryNode(td)); } @@ -69,7 +70,8 @@ namespace ICSharpCode.ILSpy.TreeNodes public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(EnsureLazyChildren)); - foreach (ILSpyTreeNode child in this.Children) { + foreach (ILSpyTreeNode child in this.Children) + { child.Decompile(language, output, options); } } diff --git a/ILSpy/TreeNodes/DerivedTypesEntryNode.cs b/ILSpy/TreeNodes/DerivedTypesEntryNode.cs index e75214afe..c006f2002 100644 --- a/ILSpy/TreeNodes/DerivedTypesEntryNode.cs +++ b/ILSpy/TreeNodes/DerivedTypesEntryNode.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.TypeSystem; @@ -40,8 +41,7 @@ namespace ICSharpCode.ILSpy.TreeNodes public override bool ShowExpander => !type.IsSealed && base.ShowExpander; - public override object Text - { + public override object Text { get { return Language.TypeToString(type, includeNamespace: true) + type.MetadataToken.ToSuffixString(); } } @@ -51,18 +51,21 @@ namespace ICSharpCode.ILSpy.TreeNodes { if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI) return FilterResult.Hidden; - if (settings.SearchTermMatches(type.Name)) { + if (settings.SearchTermMatches(type.Name)) + { if (type.DeclaringType != null && (settings.ShowApiLevel != ApiVisibility.All || !settings.Language.ShowMember(type))) return FilterResult.Hidden; else return FilterResult.Match; - } else + } + else return FilterResult.Recurse; } - + public override bool IsPublicAPI { get { - switch (type.Accessibility) { + switch (type.Accessibility) + { case Accessibility.Public: case Accessibility.Internal: case Accessibility.ProtectedOrInternal: diff --git a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs index aec858d21..7f826b390 100644 --- a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs +++ b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs @@ -19,10 +19,12 @@ using System.Collections.Generic; using System.Linq; using System.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Properties; + using SRM = System.Reflection.Metadata; namespace ICSharpCode.ILSpy.TreeNodes @@ -65,19 +67,23 @@ namespace ICSharpCode.ILSpy.TreeNodes { var definitionMetadata = type.ParentModule.PEFile.Metadata; var metadataToken = (SRM.TypeDefinitionHandle)type.MetadataToken; - foreach (var module in assemblies) { + foreach (var module in assemblies) + { var metadata = module.Metadata; var assembly = (MetadataModule)module.GetTypeSystemOrNull().MainModule; - foreach (var h in metadata.TypeDefinitions) { + foreach (var h in metadata.TypeDefinitions) + { cancellationToken.ThrowIfCancellationRequested(); var td = metadata.GetTypeDefinition(h); - foreach (var iface in td.GetInterfaceImplementations()) { + foreach (var iface in td.GetInterfaceImplementations()) + { var ifaceImpl = metadata.GetInterfaceImplementation(iface); if (!ifaceImpl.Interface.IsNil && IsSameType(metadata, ifaceImpl.Interface, definitionMetadata, metadataToken)) yield return new DerivedTypesEntryNode(list, assembly.GetDefinition(h)); } SRM.EntityHandle baseType = td.GetBaseTypeOrNil(); - if (!baseType.IsNil && IsSameType(metadata, baseType, definitionMetadata, metadataToken)) { + if (!baseType.IsNil && IsSameType(metadata, baseType, definitionMetadata, metadataToken)) + { yield return new DerivedTypesEntryNode(list, assembly.GetDefinition(h)); } } @@ -86,7 +92,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } static bool IsSameType(SRM.MetadataReader referenceMetadata, SRM.EntityHandle typeRef, - SRM.MetadataReader definitionMetadata, SRM.TypeDefinitionHandle typeDef) + SRM.MetadataReader definitionMetadata, SRM.TypeDefinitionHandle typeDef) { // FullName contains only namespace, name and type parameter count, therefore this should suffice. return typeRef.GetFullTypeName(referenceMetadata) == typeDef.GetFullTypeName(definitionMetadata); diff --git a/ILSpy/TreeNodes/EventTreeNode.cs b/ILSpy/TreeNodes/EventTreeNode.cs index e8f9b6e4f..030b36b76 100644 --- a/ILSpy/TreeNodes/EventTreeNode.cs +++ b/ILSpy/TreeNodes/EventTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Windows.Media; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.TypeSystem; @@ -66,15 +67,16 @@ namespace ICSharpCode.ILSpy.TreeNodes else return FilterResult.Hidden; } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { language.DecompileEvent(EventDefinition, output, options); } - + public override bool IsPublicAPI { get { - switch (EventDefinition.Accessibility) { + switch (EventDefinition.Accessibility) + { case Accessibility.Public: case Accessibility.ProtectedOrInternal: case Accessibility.Protected: diff --git a/ILSpy/TreeNodes/FieldTreeNode.cs b/ILSpy/TreeNodes/FieldTreeNode.cs index ceb7c046e..45283602a 100644 --- a/ILSpy/TreeNodes/FieldTreeNode.cs +++ b/ILSpy/TreeNodes/FieldTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Windows.Media; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.TypeSystem; @@ -72,10 +73,11 @@ namespace ICSharpCode.ILSpy.TreeNodes { language.DecompileField(FieldDefinition, output, options); } - + public override bool IsPublicAPI { get { - switch (FieldDefinition.Accessibility) { + switch (FieldDefinition.Accessibility) + { case Accessibility.Public: case Accessibility.Protected: case Accessibility.ProtectedOrInternal: diff --git a/ILSpy/TreeNodes/ILSpyTreeNode.cs b/ILSpy/TreeNodes/ILSpyTreeNode.cs index 7465f0856..40f5afb57 100644 --- a/ILSpy/TreeNodes/ILSpyTreeNode.cs +++ b/ILSpy/TreeNodes/ILSpyTreeNode.cs @@ -22,6 +22,7 @@ using System.ComponentModel; using System.Linq; using System.Windows; using System.Windows.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.TreeView; @@ -35,20 +36,18 @@ namespace ICSharpCode.ILSpy.TreeNodes FilterSettings filterSettings; bool childrenNeedFiltering; - public FilterSettings FilterSettings - { + public FilterSettings FilterSettings { get { return filterSettings; } - set - { - if (filterSettings != value) { + set { + if (filterSettings != value) + { filterSettings = value; OnFilterSettingsChanged(); } } } - public Language Language - { + public Language Language { get { return filterSettings != null ? filterSettings.Language : Languages.AllLanguages[0]; } } @@ -90,11 +89,15 @@ namespace ICSharpCode.ILSpy.TreeNodes protected override void OnChildrenChanged(NotifyCollectionChangedEventArgs e) { - if (e.NewItems != null) { - if (IsVisible) { + if (e.NewItems != null) + { + if (IsVisible) + { foreach (ILSpyTreeNode node in e.NewItems) ApplyFilterToChild(node); - } else { + } + else + { childrenNeedFiltering = true; } } @@ -108,7 +111,8 @@ namespace ICSharpCode.ILSpy.TreeNodes r = FilterResult.Match; else r = child.Filter(this.FilterSettings); - switch (r) { + switch (r) + { case FilterResult.Hidden: child.IsHidden = true; break; @@ -135,7 +139,8 @@ namespace ICSharpCode.ILSpy.TreeNodes { if (filterSettings == null) return null; - if (!string.IsNullOrEmpty(filterSettings.SearchTerm)) { + if (!string.IsNullOrEmpty(filterSettings.SearchTerm)) + { filterSettings = filterSettings.Clone(); filterSettings.SearchTerm = null; } @@ -145,10 +150,13 @@ namespace ICSharpCode.ILSpy.TreeNodes protected virtual void OnFilterSettingsChanged() { RaisePropertyChanged(nameof(Text)); - if (IsVisible) { + if (IsVisible) + { foreach (ILSpyTreeNode node in this.Children.OfType()) ApplyFilterToChild(node); - } else { + } + else + { childrenNeedFiltering = true; } } @@ -162,30 +170,32 @@ namespace ICSharpCode.ILSpy.TreeNodes internal void EnsureChildrenFiltered() { EnsureLazyChildren(); - if (childrenNeedFiltering) { + if (childrenNeedFiltering) + { childrenNeedFiltering = false; foreach (ILSpyTreeNode node in this.Children.OfType()) ApplyFilterToChild(node); } } - + public virtual bool IsPublicAPI { get { return true; } } - public virtual bool IsAutoLoaded - { + public virtual bool IsAutoLoaded { get { return false; } } - + public override System.Windows.Media.Brush Foreground { get { if (IsPublicAPI) - if (IsAutoLoaded) { + if (IsAutoLoaded) + { // HACK: should not be hard coded? return System.Windows.Media.Brushes.SteelBlue; } - else { + else + { return base.Foreground; } else diff --git a/ILSpy/TreeNodes/MethodTreeNode.cs b/ILSpy/TreeNodes/MethodTreeNode.cs index ed743dc56..a6420404b 100644 --- a/ILSpy/TreeNodes/MethodTreeNode.cs +++ b/ILSpy/TreeNodes/MethodTreeNode.cs @@ -65,7 +65,8 @@ namespace ICSharpCode.ILSpy.TreeNodes internal static AccessOverlayIcon GetOverlayIcon(Accessibility accessibility) { - switch (accessibility) { + switch (accessibility) + { case Accessibility.Public: return AccessOverlayIcon.Public; case Accessibility.Internal: @@ -100,7 +101,8 @@ namespace ICSharpCode.ILSpy.TreeNodes public override bool IsPublicAPI { get { - switch (MethodDefinition.Accessibility) { + switch (MethodDefinition.Accessibility) + { case Accessibility.Public: case Accessibility.Protected: case Accessibility.ProtectedOrInternal: diff --git a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs index 4d51f46af..6c53ad1cb 100644 --- a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs +++ b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Reflection.Metadata; + using ICSharpCode.Decompiler; namespace ICSharpCode.ILSpy.TreeNodes @@ -35,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes readonly AssemblyFile file; readonly string moduleName; readonly bool containsMetadata; - + public ModuleReferenceTreeNode(AssemblyTreeNode parentAssembly, ModuleReferenceHandle r, MetadataReader module) { this.parentAssembly = parentAssembly ?? throw new ArgumentNullException(nameof(parentAssembly)); @@ -46,9 +47,11 @@ namespace ICSharpCode.ILSpy.TreeNodes this.reference = module.GetModuleReference(r); this.moduleName = metadata.GetString(reference.Name); - foreach (var h in module.AssemblyFiles) { + foreach (var h in module.AssemblyFiles) + { var file = module.GetAssemblyFile(h); - if (module.StringComparer.Equals(file.Name, moduleName)) { + if (module.StringComparer.Equals(file.Name, moduleName)) + { this.file = file; this.fileHandle = h; this.containsMetadata = file.ContainsMetadata; @@ -56,7 +59,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - + public override object Text { get { return moduleName + ((EntityHandle)handle).ToSuffixString(); } } @@ -66,7 +69,8 @@ namespace ICSharpCode.ILSpy.TreeNodes public override void ActivateItem(System.Windows.RoutedEventArgs e) { var assemblyListNode = parentAssembly.Parent as AssemblyListTreeNode; - if (assemblyListNode != null && containsMetadata) { + if (assemblyListNode != null && containsMetadata) + { assemblyListNode.Select(assemblyListNode.FindAssemblyNode(parentAssembly.LoadedAssembly.LookupReferencedModule(parentAssembly.LoadedAssembly.GetPEFileOrNull(), metadata.GetString(reference.Name)))); e.Handled = true; } diff --git a/ILSpy/TreeNodes/NamespaceTreeNode.cs b/ILSpy/TreeNodes/NamespaceTreeNode.cs index d054603dc..c51111558 100644 --- a/ILSpy/TreeNodes/NamespaceTreeNode.cs +++ b/ILSpy/TreeNodes/NamespaceTreeNode.cs @@ -18,6 +18,7 @@ using System; using System.Linq; + using ICSharpCode.Decompiler; namespace ICSharpCode.ILSpy.TreeNodes @@ -28,26 +29,26 @@ namespace ICSharpCode.ILSpy.TreeNodes public sealed class NamespaceTreeNode : ILSpyTreeNode { readonly string name; - + public string Name { get { return name; } } - + public NamespaceTreeNode(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); this.name = name; } - + public override object Text { get { return name.Length == 0 ? "-" : name; } } - + public override object Icon { get { return Images.Namespace; } } - + public override FilterResult Filter(FilterSettings settings) { if (settings.SearchTermMatches(name)) @@ -55,7 +56,7 @@ namespace ICSharpCode.ILSpy.TreeNodes else return FilterResult.Recurse; } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { language.DecompileNamespace(name, this.Children.OfType().Select(t => t.TypeDefinition), output, options); diff --git a/ILSpy/TreeNodes/PropertyTreeNode.cs b/ILSpy/TreeNodes/PropertyTreeNode.cs index a9df0df87..444018149 100644 --- a/ILSpy/TreeNodes/PropertyTreeNode.cs +++ b/ILSpy/TreeNodes/PropertyTreeNode.cs @@ -20,9 +20,11 @@ using System; using System.Reflection; using System.Reflection.Metadata; using System.Windows.Media; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; + using SRM = System.Reflection.Metadata; namespace ICSharpCode.ILSpy.TreeNodes @@ -81,7 +83,8 @@ namespace ICSharpCode.ILSpy.TreeNodes public override bool IsPublicAPI { get { - switch (PropertyDefinition.Accessibility) { + switch (PropertyDefinition.Accessibility) + { case Accessibility.Public: case Accessibility.ProtectedOrInternal: case Accessibility.Protected: diff --git a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs index a23a4bfe5..f42b0e765 100644 --- a/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs +++ b/ILSpy/TreeNodes/ReferenceFolderTreeNode.cs @@ -19,6 +19,7 @@ using System; using System.Linq; using System.Windows.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Properties; @@ -32,7 +33,7 @@ namespace ICSharpCode.ILSpy.TreeNodes { readonly PEFile module; readonly AssemblyTreeNode parentAssembly; - + public ReferenceFolderTreeNode(PEFile module, AssemblyTreeNode parentAssembly) { this.module = module; @@ -52,7 +53,7 @@ namespace ICSharpCode.ILSpy.TreeNodes foreach (var r in metadata.GetModuleReferences().OrderBy(r => metadata.GetString(metadata.GetModuleReference(r).Name))) this.Children.Add(new ModuleReferenceTreeNode(parentAssembly, r, metadata)); } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { language.WriteCommentLine(output, $"Detected Target-Framework-Id: {parentAssembly.LoadedAssembly.GetTargetFrameworkIdAsync().Result}"); @@ -68,10 +69,12 @@ namespace ICSharpCode.ILSpy.TreeNodes // Show full assembly load log: language.WriteCommentLine(output, "Assembly load log including transitive references:"); var info = parentAssembly.LoadedAssembly.LoadedAssemblyReferencesInfo; - foreach (var asm in info.Entries) { + foreach (var asm in info.Entries) + { language.WriteCommentLine(output, asm.FullName); output.Indent(); - foreach (var item in asm.Messages) { + foreach (var item in asm.Messages) + { language.WriteCommentLine(output, $"{item.Item1}: {item.Item2}"); } output.Unindent(); diff --git a/ILSpy/TreeNodes/ResourceListTreeNode.cs b/ILSpy/TreeNodes/ResourceListTreeNode.cs index e379160a2..c753b14dd 100644 --- a/ILSpy/TreeNodes/ResourceListTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceListTreeNode.cs @@ -19,6 +19,7 @@ using System; using System.Linq; using System.Windows.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Properties; @@ -31,7 +32,7 @@ namespace ICSharpCode.ILSpy.TreeNodes sealed class ResourceListTreeNode : ILSpyTreeNode { readonly PEFile module; - + public ResourceListTreeNode(PEFile module) { this.LazyLoading = true; @@ -49,7 +50,7 @@ namespace ICSharpCode.ILSpy.TreeNodes foreach (Resource r in module.Resources.OrderBy(m => m.Name, NaturalStringComparer.Instance)) this.Children.Add(ResourceTreeNode.Create(r)); } - + public override FilterResult Filter(FilterSettings settings) { if (string.IsNullOrEmpty(settings.SearchTerm)) @@ -57,11 +58,12 @@ namespace ICSharpCode.ILSpy.TreeNodes else return FilterResult.Recurse; } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(EnsureLazyChildren)); - foreach (ILSpyTreeNode child in this.Children) { + foreach (ILSpyTreeNode child in this.Children) + { child.Decompile(language, output, options); output.WriteLine(); } diff --git a/ILSpy/TreeNodes/ResourceNodes/CursorResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceNodes/CursorResourceEntryNode.cs index 8a1581c17..c3ecedae6 100644 --- a/ILSpy/TreeNodes/ResourceNodes/CursorResourceEntryNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/CursorResourceEntryNode.cs @@ -21,6 +21,7 @@ using System.ComponentModel.Composition; using System.IO; using System.Windows.Controls; using System.Windows.Media.Imaging; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; @@ -44,8 +45,9 @@ namespace ICSharpCode.ILSpy.TreeNodes public ILSpyTreeNode CreateNode(string key, object data) { if (!(data is Stream)) - return null; - foreach (string fileExt in imageFileExtensions) { + return null; + foreach (string fileExt in imageFileExtensions) + { if (key.EndsWith(fileExt, StringComparison.OrdinalIgnoreCase)) return new CursorResourceEntryNode(key, (Stream)data); } @@ -64,7 +66,8 @@ namespace ICSharpCode.ILSpy.TreeNodes public override bool View(TabPageModel tabPage) { - try { + try + { AvalonEditTextOutput output = new AvalonEditTextOutput(); Data.Position = 0; BitmapImage image = new BitmapImage(); @@ -80,7 +83,8 @@ namespace ICSharpCode.ILSpy.TreeNodes } byte[] curData = s.ToArray(); curData[2] = 1; - using (Stream stream = new MemoryStream(curData)) { + using (Stream stream = new MemoryStream(curData)) + { image.BeginInit(); image.StreamSource = stream; image.EndInit(); @@ -95,7 +99,8 @@ namespace ICSharpCode.ILSpy.TreeNodes tabPage.SupportsLanguageSwitching = false; return true; } - catch (Exception) { + catch (Exception) + { return false; } } diff --git a/ILSpy/TreeNodes/ResourceNodes/IconResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceNodes/IconResourceEntryNode.cs index b237f9c6b..acb57fbcc 100644 --- a/ILSpy/TreeNodes/ResourceNodes/IconResourceEntryNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/IconResourceEntryNode.cs @@ -21,6 +21,7 @@ using System.ComponentModel.Composition; using System.IO; using System.Windows.Controls; using System.Windows.Media.Imaging; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; @@ -41,7 +42,8 @@ namespace ICSharpCode.ILSpy.TreeNodes public ILSpyTreeNode CreateNode(string key, object data) { - if (data is System.Drawing.Icon) { + if (data is System.Drawing.Icon) + { MemoryStream s = new MemoryStream(); ((System.Drawing.Icon)data).Save(s); return new IconResourceEntryNode(key, s); @@ -63,11 +65,13 @@ namespace ICSharpCode.ILSpy.TreeNodes public override bool View(TabPageModel tabPage) { - try { + try + { AvalonEditTextOutput output = new AvalonEditTextOutput(); Data.Position = 0; IconBitmapDecoder decoder = new IconBitmapDecoder(Data, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None); - foreach (var frame in decoder.Frames) { + foreach (var frame in decoder.Frames) + { output.Write(String.Format("{0}x{1}, {2} bit: ", frame.PixelHeight, frame.PixelWidth, frame.Thumbnail.Format.BitsPerPixel)); AddIcon(output, frame); output.WriteLine(); @@ -78,7 +82,9 @@ namespace ICSharpCode.ILSpy.TreeNodes tabPage.ShowTextView(textView => textView.ShowNode(output, this)); tabPage.SupportsLanguageSwitching = false; return true; - } catch (Exception) { + } + catch (Exception) + { return false; } } diff --git a/ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs index 97710629f..56276dd14 100644 --- a/ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs @@ -19,6 +19,7 @@ using System.ComponentModel.Composition; using System.Drawing; using System.Windows.Forms; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; @@ -53,8 +54,7 @@ namespace ICSharpCode.ILSpy.TreeNodes this.data.ImageStream = data; } - public override object Text - { + public override object Text { get { return key; } } @@ -63,7 +63,8 @@ namespace ICSharpCode.ILSpy.TreeNodes protected override void LoadChildren() { int i = 0; - foreach (Image image in this.data.Images) { + foreach (Image image in this.data.Images) + { var node = ResourceEntryNode.Create("Image" + i.ToString(), image); if (node != null) Children.Add(node); diff --git a/ILSpy/TreeNodes/ResourceNodes/ImageResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceNodes/ImageResourceEntryNode.cs index a78997c1f..ea0ecc0d4 100644 --- a/ILSpy/TreeNodes/ResourceNodes/ImageResourceEntryNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/ImageResourceEntryNode.cs @@ -21,6 +21,7 @@ using System.ComponentModel.Composition; using System.IO; using System.Windows.Controls; using System.Windows.Media.Imaging; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; @@ -50,8 +51,9 @@ namespace ICSharpCode.ILSpy.TreeNodes return new ImageResourceEntryNode(key, s); } if (!(data is Stream)) - return null; - foreach (string fileExt in imageFileExtensions) { + return null; + foreach (string fileExt in imageFileExtensions) + { if (key.EndsWith(fileExt, StringComparison.OrdinalIgnoreCase)) return new ImageResourceEntryNode(key, (Stream)data); } @@ -70,7 +72,8 @@ namespace ICSharpCode.ILSpy.TreeNodes public override bool View(TabPageModel tabPage) { - try { + try + { AvalonEditTextOutput output = new AvalonEditTextOutput(); Data.Position = 0; BitmapImage image = new BitmapImage(); @@ -86,7 +89,8 @@ namespace ICSharpCode.ILSpy.TreeNodes tabPage.SupportsLanguageSwitching = false; return true; } - catch (Exception) { + catch (Exception) + { return false; } } diff --git a/ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs index d15409b2a..160ad478c 100644 --- a/ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs @@ -18,8 +18,10 @@ using System; using System.IO; + using ICSharpCode.Decompiler; using ICSharpCode.ILSpy.TextView; + using Microsoft.Win32; namespace ICSharpCode.ILSpy.TreeNodes @@ -51,14 +53,15 @@ namespace ICSharpCode.ILSpy.TreeNodes public static ILSpyTreeNode Create(string key, object data) { ILSpyTreeNode result = null; - foreach (var factory in App.ExportProvider.GetExportedValues()) { + foreach (var factory in App.ExportProvider.GetExportedValues()) + { result = factory.CreateNode(key, data); if (result != null) return result; } var streamData = data as Stream; - if(streamData !=null) - result = new ResourceEntryNode(key, data as Stream); + if (streamData != null) + result = new ResourceEntryNode(key, data as Stream); return result; } @@ -72,9 +75,11 @@ namespace ICSharpCode.ILSpy.TreeNodes { SaveFileDialog dlg = new SaveFileDialog(); dlg.FileName = Path.GetFileName(DecompilerTextView.CleanUpName(key)); - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { data.Position = 0; - using (var fs = dlg.OpenFile()) { + using (var fs = dlg.OpenFile()) + { data.CopyTo(fs); } } diff --git a/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs b/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs index b3c525c1f..308e29c67 100644 --- a/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs @@ -20,6 +20,7 @@ using System; using System.IO; using System.Reflection; using System.Text; + using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Utils; using ICSharpCode.Decompiler; @@ -27,6 +28,7 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.ViewModels; + using Microsoft.Win32; namespace ICSharpCode.ILSpy.TreeNodes @@ -65,7 +67,8 @@ namespace ICSharpCode.ILSpy.TreeNodes language.WriteCommentLine(output, string.Format("{0} ({1}, {2})", Resource.Name, Resource.ResourceType, Resource.Attributes)); ISmartTextOutput smartOutput = output as ISmartTextOutput; - if (smartOutput != null) { + if (smartOutput != null) + { smartOutput.AddButton(Images.Save, Resources.Save, delegate { Save(Docking.DockWorkspace.Instance.ActiveTabPage); }); output.WriteLine(); } @@ -74,10 +77,12 @@ namespace ICSharpCode.ILSpy.TreeNodes public override bool View(TabPageModel tabPage) { Stream s = Resource.TryOpenStream(); - if (s != null && s.Length < DecompilerTextView.DefaultOutputLengthLimit) { + if (s != null && s.Length < DecompilerTextView.DefaultOutputLengthLimit) + { s.Position = 0; FileType type = GuessFileType.DetectFileType(s); - if (type != FileType.Binary) { + if (type != FileType.Binary) + { s.Position = 0; AvalonEditTextOutput output = new AvalonEditTextOutput(); output.Write(FileReader.OpenStream(s, Encoding.UTF8).ReadToEnd()); @@ -101,9 +106,11 @@ namespace ICSharpCode.ILSpy.TreeNodes return false; SaveFileDialog dlg = new SaveFileDialog(); dlg.FileName = DecompilerTextView.CleanUpName(Resource.Name); - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { s.Position = 0; - using (var fs = dlg.OpenFile()) { + using (var fs = dlg.OpenFile()) + { s.CopyTo(fs); } } @@ -113,7 +120,8 @@ namespace ICSharpCode.ILSpy.TreeNodes public static ILSpyTreeNode Create(Resource resource) { ILSpyTreeNode result = null; - foreach (var factory in App.ExportProvider.GetExportedValues()) { + foreach (var factory in App.ExportProvider.GetExportedValues()) + { result = factory.CreateNode(resource); if (result != null) break; diff --git a/ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs b/ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs index 218d747b0..28662c597 100644 --- a/ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs @@ -22,15 +22,17 @@ using System.Collections.ObjectModel; using System.ComponentModel.Composition; using System.IO; using System.Linq; + using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpy.Controls; -using ICSharpCode.ILSpy.TextView; -using Microsoft.Win32; using ICSharpCode.ILSpy.Properties; +using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.ViewModels; +using Microsoft.Win32; + namespace ICSharpCode.ILSpy.TreeNodes { [Export(typeof(IResourceNodeFactory))] @@ -38,7 +40,8 @@ namespace ICSharpCode.ILSpy.TreeNodes { public ILSpyTreeNode CreateNode(Resource resource) { - if (resource.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) { + if (resource.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) + { return new ResourcesFileTreeNode(resource); } return null; @@ -66,42 +69,57 @@ namespace ICSharpCode.ILSpy.TreeNodes protected override void LoadChildren() { Stream s = Resource.TryOpenStream(); - if (s == null) return; + if (s == null) + return; s.Position = 0; - try { - foreach (var entry in new ResourcesFile(s).OrderBy(e => e.Key, NaturalStringComparer.Instance)) { + try + { + foreach (var entry in new ResourcesFile(s).OrderBy(e => e.Key, NaturalStringComparer.Instance)) + { ProcessResourceEntry(entry); } - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { // ignore errors - } catch (EndOfStreamException) { + } + catch (EndOfStreamException) + { // ignore errors } } private void ProcessResourceEntry(KeyValuePair entry) { - if (entry.Value is string) { + if (entry.Value is string) + { stringTableEntries.Add(new KeyValuePair(entry.Key, (string)entry.Value)); return; } - if (entry.Value is byte[]) { + if (entry.Value is byte[]) + { Children.Add(ResourceEntryNode.Create(entry.Key, new MemoryStream((byte[])entry.Value))); return; } var node = ResourceEntryNode.Create(entry.Key, entry.Value); - if (node != null) { + if (node != null) + { Children.Add(node); return; } - if (entry.Value == null) { + if (entry.Value == null) + { otherEntries.Add(new SerializedObjectRepresentation(entry.Key, "null", "")); - } else if (entry.Value is ResourceSerializedObject so) { + } + else if (entry.Value is ResourceSerializedObject so) + { otherEntries.Add(new SerializedObjectRepresentation(entry.Key, so.TypeName, "")); - } else { + } + else + { otherEntries.Add(new SerializedObjectRepresentation(entry.Key, entry.Value.GetType().FullName, entry.Value.ToString())); } } @@ -109,29 +127,40 @@ namespace ICSharpCode.ILSpy.TreeNodes public override bool Save(TabPageModel tabPage) { Stream s = Resource.TryOpenStream(); - if (s == null) return false; + if (s == null) + return false; SaveFileDialog dlg = new SaveFileDialog(); dlg.FileName = DecompilerTextView.CleanUpName(Resource.Name); dlg.Filter = Resources.ResourcesFileFilter; - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { s.Position = 0; - switch (dlg.FilterIndex) { + switch (dlg.FilterIndex) + { case 1: - using (var fs = dlg.OpenFile()) { + using (var fs = dlg.OpenFile()) + { s.CopyTo(fs); } break; case 2: - try { + try + { using (var fs = dlg.OpenFile()) - using (var writer = new ResXResourceWriter(fs)) { - foreach (var entry in new ResourcesFile(s)) { + using (var writer = new ResXResourceWriter(fs)) + { + foreach (var entry in new ResourcesFile(s)) + { writer.AddResource(entry.Key, entry.Value); } } - } catch (BadImageFormatException) { + } + catch (BadImageFormatException) + { // ignore errors - } catch (EndOfStreamException) { + } + catch (EndOfStreamException) + { // ignore errors } break; @@ -146,9 +175,11 @@ namespace ICSharpCode.ILSpy.TreeNodes EnsureLazyChildren(); base.Decompile(language, output, options); var textView = (DecompilerTextView)Docking.DockWorkspace.Instance.ActiveTabPage.Content; - if (stringTableEntries.Count != 0) { + if (stringTableEntries.Count != 0) + { ISmartTextOutput smartOutput = output as ISmartTextOutput; - if (null != smartOutput) { + if (null != smartOutput) + { smartOutput.AddUIElement( delegate { return new ResourceStringTable(stringTableEntries, textView); @@ -158,9 +189,11 @@ namespace ICSharpCode.ILSpy.TreeNodes output.WriteLine(); output.WriteLine(); } - if (otherEntries.Count != 0) { + if (otherEntries.Count != 0) + { ISmartTextOutput smartOutput = output as ISmartTextOutput; - if (null != smartOutput) { + if (null != smartOutput) + { smartOutput.AddUIElement( delegate { return new ResourceObjectTable(otherEntries, textView); diff --git a/ILSpy/TreeNodes/ResourceNodes/XamlResourceNode.cs b/ILSpy/TreeNodes/ResourceNodes/XamlResourceNode.cs index f8eedbe31..caf9f5fd1 100644 --- a/ILSpy/TreeNodes/ResourceNodes/XamlResourceNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/XamlResourceNode.cs @@ -36,7 +36,7 @@ namespace ICSharpCode.ILSpy.Xaml { return null; } - + public ILSpyTreeNode CreateNode(string key, object data) { if (key.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase) && data is Stream) @@ -45,15 +45,15 @@ namespace ICSharpCode.ILSpy.Xaml return null; } } - + sealed class XamlResourceEntryNode : ResourceEntryNode { string xaml; - + public XamlResourceEntryNode(string key, Stream data) : base(key, data) { } - + public override bool View(TabPageModel tabPage) { AvalonEditTextOutput output = new AvalonEditTextOutput(); @@ -62,16 +62,21 @@ namespace ICSharpCode.ILSpy.Xaml tabPage.ShowTextView(textView => textView.RunWithCancellation( token => Task.Factory.StartNew( () => { - try { + try + { // cache read XAML because stream will be closed after first read - if (xaml == null) { - using (var reader = new StreamReader(Data)) { + if (xaml == null) + { + using (var reader = new StreamReader(Data)) + { xaml = reader.ReadToEnd(); } } output.Write(xaml); highlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml"); - } catch (Exception ex) { + } + catch (Exception ex) + { output.Write(ex.ToString()); } return output; diff --git a/ILSpy/TreeNodes/ResourceNodes/XmlResourceNode.cs b/ILSpy/TreeNodes/ResourceNodes/XmlResourceNode.cs index 73420d92b..3c10fc964 100644 --- a/ILSpy/TreeNodes/ResourceNodes/XmlResourceNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/XmlResourceNode.cs @@ -41,11 +41,11 @@ namespace ICSharpCode.ILSpy.Xaml return null; return CreateNode(resource.Name, stream); } - + public ILSpyTreeNode CreateNode(string key, object data) { if (!(data is Stream)) - return null; + return null; foreach (string fileExt in xmlFileExtensions) { if (key.EndsWith(fileExt, StringComparison.OrdinalIgnoreCase)) @@ -54,20 +54,18 @@ namespace ICSharpCode.ILSpy.Xaml return null; } } - + sealed class XmlResourceEntryNode : ResourceEntryNode { string xml; - + public XmlResourceEntryNode(string key, Stream data) : base(key, data) { } - - public override object Icon - { - get - { + + public override object Icon { + get { string text = (string)Text; if (text.EndsWith(".xml", StringComparison.OrdinalIgnoreCase)) return Images.ResourceXml; @@ -88,17 +86,21 @@ namespace ICSharpCode.ILSpy.Xaml tabPage.ShowTextView(textView => textView.RunWithCancellation( token => Task.Factory.StartNew( () => { - try { + try + { // cache read XAML because stream will be closed after first read - if (xml == null) { - using (var reader = new StreamReader(Data)) { + if (xml == null) + { + using (var reader = new StreamReader(Data)) + { xml = reader.ReadToEnd(); } } output.Write(xml); highlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml"); } - catch (Exception ex) { + catch (Exception ex) + { output.Write(ex.ToString()); } return output; diff --git a/ILSpy/TreeNodes/ThreadingSupport.cs b/ILSpy/TreeNodes/ThreadingSupport.cs index e95787efc..13487ad7f 100644 --- a/ILSpy/TreeNodes/ThreadingSupport.cs +++ b/ILSpy/TreeNodes/ThreadingSupport.cs @@ -24,6 +24,7 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; + using ICSharpCode.Decompiler; using ICSharpCode.ILSpy.Analyzers; using ICSharpCode.ILSpy.Properties; @@ -38,40 +39,42 @@ namespace ICSharpCode.ILSpy.TreeNodes { Task> loadChildrenTask; CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); - + public bool IsRunning { get { return loadChildrenTask != null && !loadChildrenTask.IsCompleted; } } - + public void Cancel() { cancellationTokenSource.Cancel(); loadChildrenTask = null; cancellationTokenSource = new CancellationTokenSource(); } - + /// /// Starts loading the children of the specified node. /// public void LoadChildren(SharpTreeNode node, Func> fetchChildren) { node.Children.Add(new LoadingTreeNode()); - + CancellationToken ct = cancellationTokenSource.Token; - + var fetchChildrenEnumerable = fetchChildren(ct); Task> thisTask = null; thisTask = new Task>( delegate { List result = new List(); - foreach (SharpTreeNode child in fetchChildrenEnumerable) { + foreach (SharpTreeNode child in fetchChildrenEnumerable) + { ct.ThrowIfCancellationRequested(); result.Add(child); App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action( delegate (SharpTreeNode newChild) { // don't access "child" here, // the background thread might already be running the next loop iteration - if (loadChildrenTask == thisTask) { + if (loadChildrenTask == thisTask) + { node.Children.Insert(node.Children.Count - 1, newChild); } }), child); @@ -84,73 +87,80 @@ namespace ICSharpCode.ILSpy.TreeNodes delegate (Task continuation) { App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action( delegate { - if (loadChildrenTask == thisTask) { + if (loadChildrenTask == thisTask) + { node.Children.RemoveAt(node.Children.Count - 1); // remove 'Loading...' node.RaisePropertyChanged(nameof(node.Text)); } - if (continuation.Exception != null) { // observe exception even when task isn't current - if (loadChildrenTask == thisTask) { - foreach (Exception ex in continuation.Exception.InnerExceptions) { + if (continuation.Exception != null) + { // observe exception even when task isn't current + if (loadChildrenTask == thisTask) + { + foreach (Exception ex in continuation.Exception.InnerExceptions) + { node.Children.Add(new ErrorTreeNode(ex.ToString())); } } } })); }); - + // Give the task a bit time to complete before we return to WPF - this keeps "Loading..." // from showing up for very short waits. thisTask.Wait(TimeSpan.FromMilliseconds(200)); } - + public void Decompile(Language language, ITextOutput output, DecompilationOptions options, Action ensureLazyChildren) { var loadChildrenTask = this.loadChildrenTask; - if (loadChildrenTask == null) { + if (loadChildrenTask == null) + { App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, ensureLazyChildren); loadChildrenTask = this.loadChildrenTask; } - if (loadChildrenTask != null) { - foreach (ILSpyTreeNode child in loadChildrenTask.Result.Cast()) { + if (loadChildrenTask != null) + { + foreach (ILSpyTreeNode child in loadChildrenTask.Result.Cast()) + { child.Decompile(language, output, options); } } } - + sealed class LoadingTreeNode : ILSpyTreeNode { public override object Text { get { return Resources.Loading; } } - + public override FilterResult Filter(FilterSettings settings) { return FilterResult.Match; } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { } } - + sealed class ErrorTreeNode : ILSpyTreeNode { readonly string text; - + public override object Text { get { return text; } } - + public ErrorTreeNode(string text) { this.text = text; } - + public override FilterResult Filter(FilterSettings settings) { return FilterResult.Match; } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { } @@ -174,8 +184,10 @@ namespace ICSharpCode.ILSpy.TreeNodes public void Execute(TextViewContext context) { StringBuilder builder = new StringBuilder(); - if (context.SelectedTreeNodes != null) { - foreach (var node in context.SelectedTreeNodes.OfType()) { + if (context.SelectedTreeNodes != null) + { + foreach (var node in context.SelectedTreeNodes.OfType()) + { builder.AppendLine(node.Text.ToString()); } } diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index 1d6fef38c..5e56ca4da 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -23,6 +23,7 @@ using System.Windows.Media; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.TypeSystem; + using SRM = System.Reflection.Metadata; namespace ICSharpCode.ILSpy.TreeNodes @@ -45,7 +46,8 @@ namespace ICSharpCode.ILSpy.TreeNodes public override bool IsPublicAPI { get { - switch (TypeDefinition.Accessibility) { + switch (TypeDefinition.Accessibility) + { case Accessibility.Public: case Accessibility.Protected: case Accessibility.ProtectedOrInternal: @@ -55,48 +57,61 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - + public override FilterResult Filter(FilterSettings settings) { if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI) return FilterResult.Hidden; - if (settings.SearchTermMatches(TypeDefinition.Name)) { + if (settings.SearchTermMatches(TypeDefinition.Name)) + { if (settings.ShowApiLevel == ApiVisibility.All || settings.Language.ShowMember(TypeDefinition)) return FilterResult.Match; else return FilterResult.Hidden; - } else { + } + else + { return FilterResult.Recurse; } } - + protected override void LoadChildren() { if (TypeDefinition.DirectBaseTypes.Any()) this.Children.Add(new BaseTypesTreeNode(ParentAssemblyNode.LoadedAssembly.GetPEFileOrNull(), TypeDefinition)); if (!TypeDefinition.IsSealed) this.Children.Add(new DerivedTypesTreeNode(ParentAssemblyNode.AssemblyList, TypeDefinition)); - foreach (var nestedType in TypeDefinition.NestedTypes.OrderBy(t => t.Name, NaturalStringComparer.Instance)) { + foreach (var nestedType in TypeDefinition.NestedTypes.OrderBy(t => t.Name, NaturalStringComparer.Instance)) + { this.Children.Add(new TypeTreeNode(nestedType, ParentAssemblyNode)); } - if (TypeDefinition.Kind == TypeKind.Enum) { + if (TypeDefinition.Kind == TypeKind.Enum) + { // if the type is an enum, it's better to not sort by field name. - foreach (var field in TypeDefinition.Fields) { + foreach (var field in TypeDefinition.Fields) + { this.Children.Add(new FieldTreeNode(field)); } - } else { - foreach (var field in TypeDefinition.Fields.OrderBy(f => f.Name, NaturalStringComparer.Instance)) { + } + else + { + foreach (var field in TypeDefinition.Fields.OrderBy(f => f.Name, NaturalStringComparer.Instance)) + { this.Children.Add(new FieldTreeNode(field)); } } - foreach (var property in TypeDefinition.Properties.OrderBy(p => p.Name, NaturalStringComparer.Instance)) { + foreach (var property in TypeDefinition.Properties.OrderBy(p => p.Name, NaturalStringComparer.Instance)) + { this.Children.Add(new PropertyTreeNode(property)); } - foreach (var ev in TypeDefinition.Events.OrderBy(e => e.Name, NaturalStringComparer.Instance)) { + foreach (var ev in TypeDefinition.Events.OrderBy(e => e.Name, NaturalStringComparer.Instance)) + { this.Children.Add(new EventTreeNode(ev)); } - foreach (var method in TypeDefinition.Methods.OrderBy(m => m.Name, NaturalStringComparer.Instance)) { - if (method.MetadataToken.IsNil) continue; + foreach (var method in TypeDefinition.Methods.OrderBy(m => m.Name, NaturalStringComparer.Instance)) + { + if (method.MetadataToken.IsNil) + continue; this.Children.Add(new MethodTreeNode(method)); } } @@ -118,7 +133,8 @@ namespace ICSharpCode.ILSpy.TreeNodes internal static TypeIcon GetTypeIcon(IType type, out bool isStatic) { isStatic = false; - switch (type.Kind) { + switch (type.Kind) + { case TypeKind.Interface: return TypeIcon.Interface; case TypeKind.Struct: @@ -136,7 +152,8 @@ namespace ICSharpCode.ILSpy.TreeNodes static AccessOverlayIcon GetOverlayIcon(ITypeDefinition type) { - switch (type.Accessibility) { + switch (type.Accessibility) + { case Accessibility.Public: return AccessOverlayIcon.Public; case Accessibility.Internal: diff --git a/ILSpy/ViewModels/AssemblyListPaneModel.cs b/ILSpy/ViewModels/AssemblyListPaneModel.cs index 386cc1c1d..9d5a39295 100644 --- a/ILSpy/ViewModels/AssemblyListPaneModel.cs +++ b/ILSpy/ViewModels/AssemblyListPaneModel.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Windows; + using ICSharpCode.ILSpy.Properties; namespace ICSharpCode.ILSpy.ViewModels diff --git a/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs b/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs index 70306455f..871b10541 100644 --- a/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs +++ b/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs @@ -23,6 +23,7 @@ using System.IO; using System.Text.RegularExpressions; using System.Windows; using System.Windows.Input; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Commands; using ICSharpCode.ILSpy.Properties; @@ -67,10 +68,12 @@ namespace ICSharpCode.ILSpy.ViewModels Dictionary foundVersions = new Dictionary(); Dictionary latestRevision = new Dictionary(); - foreach (var sdkDir in Directory.GetDirectories(Path.Combine(basePath, "shared"))) { + foreach (var sdkDir in Directory.GetDirectories(Path.Combine(basePath, "shared"))) + { if (sdkDir.EndsWith(".Ref", StringComparison.OrdinalIgnoreCase)) continue; - foreach (var versionDir in Directory.GetDirectories(sdkDir)) { + foreach (var versionDir in Directory.GetDirectories(sdkDir)) + { var match = Regex.Match(versionDir, @"[/\\](?[A-z0-9.]+)[/\\](?\d+\.\d)+(.(?\d+))?$"); if (!match.Success) continue; @@ -82,14 +85,16 @@ namespace ICSharpCode.ILSpy.ViewModels if (!latestRevision.TryGetValue(text, out int revision)) revision = -1; int newRevision = int.Parse(match.Groups["revision"].Value); - if (newRevision > revision) { + if (newRevision > revision) + { latestRevision[text] = newRevision; foundVersions[text] = versionDir; } } } - foreach (var pair in foundVersions) { + foreach (var pair in foundVersions) + { yield return new PreconfiguredAssemblyList(pair.Key + "(." + latestRevision[pair.Key] + ")", pair.Value); } } @@ -103,7 +108,8 @@ namespace ICSharpCode.ILSpy.ViewModels public string SelectedAssemblyList { get => selectedAssemblyList; set { - if (selectedAssemblyList != value) { + if (selectedAssemblyList != value) + { selectedAssemblyList = value; RaisePropertyChanged(); } @@ -123,14 +129,17 @@ namespace ICSharpCode.ILSpy.ViewModels CreateListDialog dlg = new CreateListDialog(Resources.NewList); dlg.Owner = parent; dlg.Closing += (s, args) => { - if (dlg.DialogResult == true) { - if (manager.AssemblyLists.Contains(dlg.ListName)) { + if (dlg.DialogResult == true) + { + if (manager.AssemblyLists.Contains(dlg.ListName)) + { args.Cancel = true; MessageBox.Show(Resources.ListExistsAlready, null, MessageBoxButton.OK); } } }; - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { manager.CreateList(new AssemblyList(dlg.ListName)); } } @@ -145,14 +154,17 @@ namespace ICSharpCode.ILSpy.ViewModels CreateListDialog dlg = new CreateListDialog(Resources.NewList); dlg.Owner = parent; dlg.Closing += (s, args) => { - if (dlg.DialogResult == true) { - if (manager.AssemblyLists.Contains(dlg.ListName)) { + if (dlg.DialogResult == true) + { + if (manager.AssemblyLists.Contains(dlg.ListName)) + { args.Cancel = true; MessageBox.Show(Resources.ListExistsAlready, null, MessageBoxButton.OK); } } }; - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { manager.CloneList(SelectedAssemblyList, dlg.ListName); } } @@ -176,9 +188,11 @@ namespace ICSharpCode.ILSpy.ViewModels SelectedAssemblyList = null; int index = manager.AssemblyLists.IndexOf(assemblyList); manager.DeleteList(assemblyList); - if (manager.AssemblyLists.Count > 0) { + if (manager.AssemblyLists.Count > 0) + { SelectedAssemblyList = manager.AssemblyLists[Math.Max(0, index - 1)]; - if (MainWindow.Instance.sessionSettings.ActiveAssemblyList == assemblyList) { + if (MainWindow.Instance.sessionSettings.ActiveAssemblyList == assemblyList) + { MainWindow.Instance.sessionSettings.ActiveAssemblyList = SelectedAssemblyList; } } @@ -201,22 +215,27 @@ namespace ICSharpCode.ILSpy.ViewModels dlg.ListName = selectedAssemblyList; dlg.ListNameBox.SelectAll(); dlg.Closing += (s, args) => { - if (dlg.DialogResult == true) { - if (dlg.ListName == selectedAssemblyList) { + if (dlg.DialogResult == true) + { + if (dlg.ListName == selectedAssemblyList) + { args.Cancel = true; return; } - if (manager.AssemblyLists.Contains(dlg.ListName)) { + if (manager.AssemblyLists.Contains(dlg.ListName)) + { args.Cancel = true; MessageBox.Show(Resources.ListExistsAlready, null, MessageBoxButton.OK); } } }; - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { string assemblyList = SelectedAssemblyList; SelectedAssemblyList = dlg.ListName; manager.RenameList(assemblyList, dlg.ListName); - if (MainWindow.Instance.sessionSettings.ActiveAssemblyList == assemblyList) { + if (MainWindow.Instance.sessionSettings.ActiveAssemblyList == assemblyList) + { MainWindow.Instance.sessionSettings.ActiveAssemblyList = manager.AssemblyLists[manager.AssemblyLists.Count - 1]; } } @@ -225,7 +244,8 @@ namespace ICSharpCode.ILSpy.ViewModels internal static AssemblyList CreateDefaultList(string name, string path = null, string newName = null) { var list = new AssemblyList(newName ?? name); - switch (name) { + switch (name) + { case DotNet4List: AddToListFromGAC("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); AddToListFromGAC("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); @@ -279,7 +299,8 @@ namespace ICSharpCode.ILSpy.ViewModels AddToListFromGAC("Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); break; case object _ when path != null: - foreach (var file in Directory.GetFiles(path, "*.dll")) { + foreach (var file in Directory.GetFiles(path, "*.dll")) + { var dllname = Path.GetFileName(file); if (DoIncludeFile(dllname)) AddToListFromDirectory(file); @@ -325,16 +346,20 @@ namespace ICSharpCode.ILSpy.ViewModels dlg.ListName = config.Name; dlg.ListNameBox.SelectAll(); dlg.Closing += (s, args) => { - if (dlg.DialogResult == true) { - if (manager.AssemblyLists.Contains(dlg.ListName)) { + if (dlg.DialogResult == true) + { + if (manager.AssemblyLists.Contains(dlg.ListName)) + { args.Cancel = true; MessageBox.Show(Properties.Resources.ListExistsAlready, null, MessageBoxButton.OK); } } }; - if (dlg.ShowDialog() == true) { + if (dlg.ShowDialog() == true) + { var list = CreateDefaultList(config.Name, config.Path, dlg.ListName); - if (list.assemblies.Count > 0) { + if (list.assemblies.Count > 0) + { manager.CreateList(list); } } diff --git a/ILSpy/ViewModels/PaneModel.cs b/ILSpy/ViewModels/PaneModel.cs index e490fd307..b214c9d97 100644 --- a/ILSpy/ViewModels/PaneModel.cs +++ b/ILSpy/ViewModels/PaneModel.cs @@ -36,7 +36,8 @@ namespace ICSharpCode.ILSpy.ViewModels private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == nameof(model.IsCloseable)) { + if (e.PropertyName == nameof(model.IsCloseable)) + { CanExecuteChanged?.Invoke(this, EventArgs.Empty); } } @@ -70,7 +71,8 @@ namespace ICSharpCode.ILSpy.ViewModels public bool IsSelected { get => isSelected; set { - if (isSelected != value) { + if (isSelected != value) + { isSelected = value; RaisePropertyChanged(nameof(IsSelected)); } @@ -81,7 +83,8 @@ namespace ICSharpCode.ILSpy.ViewModels public bool IsActive { get => isActive; set { - if (isActive != value) { + if (isActive != value) + { isActive = value; RaisePropertyChanged(nameof(IsActive)); } @@ -92,7 +95,8 @@ namespace ICSharpCode.ILSpy.ViewModels public bool IsVisible { get { return isVisible; } set { - if (isVisible != value) { + if (isVisible != value) + { isVisible = value; RaisePropertyChanged(nameof(IsVisible)); } @@ -103,7 +107,8 @@ namespace ICSharpCode.ILSpy.ViewModels public bool IsCloseable { get { return isCloseable; } set { - if (isCloseable != value) { + if (isCloseable != value) + { isCloseable = value; RaisePropertyChanged(nameof(IsCloseable)); } @@ -114,7 +119,8 @@ namespace ICSharpCode.ILSpy.ViewModels public ICommand CloseCommand { get { return closeCommand; } set { - if (closeCommand != value) { + if (closeCommand != value) + { closeCommand = value; RaisePropertyChanged(nameof(CloseCommand)); } @@ -125,7 +131,8 @@ namespace ICSharpCode.ILSpy.ViewModels public string ContentId { get => contentId; set { - if (contentId != value) { + if (contentId != value) + { contentId = value; RaisePropertyChanged(nameof(ContentId)); } @@ -136,7 +143,8 @@ namespace ICSharpCode.ILSpy.ViewModels public string Title { get => title; set { - if (title != value) { + if (title != value) + { title = value; RaisePropertyChanged(nameof(Title)); } diff --git a/ILSpy/ViewModels/TabPageModel.cs b/ILSpy/ViewModels/TabPageModel.cs index faa4c7f83..f4c42c23d 100644 --- a/ILSpy/ViewModels/TabPageModel.cs +++ b/ILSpy/ViewModels/TabPageModel.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using ICSharpCode.ILSpy.TextView; namespace ICSharpCode.ILSpy.ViewModels @@ -37,19 +38,27 @@ namespace ICSharpCode.ILSpy.ViewModels public Language Language { get => language; set { - if (language != value) { - if (language != null && language.HasLanguageVersions) { + if (language != value) + { + if (language != null && language.HasLanguageVersions) + { languageVersionHistory[language] = languageVersion; } language = value; RaisePropertyChanged(nameof(Language)); - if (language.HasLanguageVersions) { - if (languageVersionHistory.TryGetValue(value, out var version)) { + if (language.HasLanguageVersions) + { + if (languageVersionHistory.TryGetValue(value, out var version)) + { LanguageVersion = version; - } else { + } + else + { LanguageVersion = Language.LanguageVersions.Last(); } - } else { + } + else + { LanguageVersion = default; } } @@ -60,9 +69,11 @@ namespace ICSharpCode.ILSpy.ViewModels public LanguageVersion LanguageVersion { get => languageVersion; set { - if (languageVersion != value) { + if (languageVersion != value) + { languageVersion = value; - if (language.HasLanguageVersions) { + if (language.HasLanguageVersions) + { languageVersionHistory[language] = languageVersion; } RaisePropertyChanged(nameof(LanguageVersion)); @@ -74,7 +85,8 @@ namespace ICSharpCode.ILSpy.ViewModels public bool SupportsLanguageSwitching { get => supportsLanguageSwitching; set { - if (supportsLanguageSwitching != value) { + if (supportsLanguageSwitching != value) + { supportsLanguageSwitching = value; RaisePropertyChanged(nameof(SupportsLanguageSwitching)); } @@ -85,7 +97,8 @@ namespace ICSharpCode.ILSpy.ViewModels public object Content { get => content; set { - if (content != value) { + if (content != value) + { content = value; RaisePropertyChanged(nameof(Content)); } @@ -102,7 +115,8 @@ namespace ICSharpCode.ILSpy.ViewModels { public static Task ShowTextViewAsync(this TabPageModel tabPage, Func> action) { - if (!(tabPage.Content is DecompilerTextView textView)) { + if (!(tabPage.Content is DecompilerTextView textView)) + { textView = new DecompilerTextView(); tabPage.Content = textView; } @@ -111,7 +125,8 @@ namespace ICSharpCode.ILSpy.ViewModels public static Task ShowTextViewAsync(this TabPageModel tabPage, Func action) { - if (!(tabPage.Content is DecompilerTextView textView)) { + if (!(tabPage.Content is DecompilerTextView textView)) + { textView = new DecompilerTextView(); tabPage.Content = textView; } @@ -120,7 +135,8 @@ namespace ICSharpCode.ILSpy.ViewModels public static void ShowTextView(this TabPageModel tabPage, Action action) { - if (!(tabPage.Content is DecompilerTextView textView)) { + if (!(tabPage.Content is DecompilerTextView textView)) + { textView = new DecompilerTextView(); tabPage.Content = textView; } diff --git a/ILSpy/Views/CreateListDialog.xaml.cs b/ILSpy/Views/CreateListDialog.xaml.cs index 273b57d05..d46ccdaa9 100644 --- a/ILSpy/Views/CreateListDialog.xaml.cs +++ b/ILSpy/Views/CreateListDialog.xaml.cs @@ -27,8 +27,7 @@ namespace ICSharpCode.ILSpy } } - public string ListName - { + public string ListName { get => ListNameBox.Text; set => ListNameBox.Text = value; } diff --git a/ILSpy/Views/DebugSteps.xaml.cs b/ILSpy/Views/DebugSteps.xaml.cs index d0870f496..d04ce4ebd 100644 --- a/ILSpy/Views/DebugSteps.xaml.cs +++ b/ILSpy/Views/DebugSteps.xaml.cs @@ -2,6 +2,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Input; + using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.ILSpy.Docking; @@ -31,7 +32,8 @@ namespace ICSharpCode.ILSpy MainWindow.Instance.SelectionChanged += SelectionChanged; writingOptions.PropertyChanged += WritingOptions_PropertyChanged; - if (MainWindow.Instance.CurrentLanguage is ILAstLanguage l) { + if (MainWindow.Instance.CurrentLanguage is ILAstLanguage l) + { l.StepperUpdated += ILAstStepperUpdated; language = l; ILAstStepperUpdated(null, null); @@ -55,11 +57,14 @@ namespace ICSharpCode.ILSpy private void FilterSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { #if DEBUG - if (e.PropertyName == "Language") { - if (language != null) { + if (e.PropertyName == "Language") + { + if (language != null) + { language.StepperUpdated -= ILAstStepperUpdated; } - if (MainWindow.Instance.CurrentLanguage is ILAstLanguage l) { + if (MainWindow.Instance.CurrentLanguage is ILAstLanguage l) + { l.StepperUpdated += ILAstStepperUpdated; language = l; ILAstStepperUpdated(null, null); @@ -71,7 +76,8 @@ namespace ICSharpCode.ILSpy private void ILAstStepperUpdated(object sender, EventArgs e) { #if DEBUG - if (language == null) return; + if (language == null) + return; Dispatcher.Invoke(() => { tree.ItemsSource = language.Stepper.Steps; lastSelectedStep = int.MaxValue; @@ -82,21 +88,24 @@ namespace ICSharpCode.ILSpy private void ShowStateAfter_Click(object sender, RoutedEventArgs e) { Stepper.Node n = (Stepper.Node)tree.SelectedItem; - if (n == null) return; + if (n == null) + return; DecompileAsync(n.EndStep); } private void ShowStateBefore_Click(object sender, RoutedEventArgs e) { Stepper.Node n = (Stepper.Node)tree.SelectedItem; - if (n == null) return; + if (n == null) + return; DecompileAsync(n.BeginStep); } private void DebugStep_Click(object sender, RoutedEventArgs e) { Stepper.Node n = (Stepper.Node)tree.SelectedItem; - if (n == null) return; + if (n == null) + return; DecompileAsync(n.BeginStep, true); } @@ -117,7 +126,8 @@ namespace ICSharpCode.ILSpy private void tree_KeyDown(object sender, KeyEventArgs e) { - if (e.Key == Key.Enter || e.Key == Key.Return) { + if (e.Key == Key.Enter || e.Key == Key.Return) + { if (e.KeyboardDevice.Modifiers == ModifierKeys.Shift) ShowStateBefore_Click(sender, e); else diff --git a/ILSpy/Views/ManageAssemblyLIstsDialog.xaml.cs b/ILSpy/Views/ManageAssemblyLIstsDialog.xaml.cs index 25d231700..111c3c7c7 100644 --- a/ILSpy/Views/ManageAssemblyLIstsDialog.xaml.cs +++ b/ILSpy/Views/ManageAssemblyLIstsDialog.xaml.cs @@ -19,6 +19,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; + using ICSharpCode.ILSpy.ViewModels; namespace ICSharpCode.ILSpy diff --git a/ILSpy/Views/NugetPackageBrowserDialog.xaml.cs b/ILSpy/Views/NugetPackageBrowserDialog.xaml.cs index 13fc6b553..17e78120b 100644 --- a/ILSpy/Views/NugetPackageBrowserDialog.xaml.cs +++ b/ILSpy/Views/NugetPackageBrowserDialog.xaml.cs @@ -56,7 +56,8 @@ namespace ICSharpCode.ILSpy void Package_PropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == nameof(Package.SelectedEntries)) { + if (e.PropertyName == nameof(Package.SelectedEntries)) + { OnPropertyChanged(new PropertyChangedEventArgs("HasSelection")); } } diff --git a/ILSpy/Views/OpenFromGacDialog.xaml.cs b/ILSpy/Views/OpenFromGacDialog.xaml.cs index 73add55bb..22a1a00aa 100644 --- a/ILSpy/Views/OpenFromGacDialog.xaml.cs +++ b/ILSpy/Views/OpenFromGacDialog.xaml.cs @@ -26,6 +26,7 @@ using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Threading; + using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Controls; @@ -123,12 +124,15 @@ namespace ICSharpCode.ILSpy UpdateProgressBar(pg => { pg.Visibility = Visibility.Visible; pg.IsIndeterminate = true; }); var list = UniversalAssemblyResolver.EnumerateGac().TakeWhile(_ => !cancelFetchThread).ToList(); UpdateProgressBar(pg => { pg.IsIndeterminate = false; pg.Maximum = list.Count; }); - foreach (var r in list) { + foreach (var r in list) + { if (cancelFetchThread) break; - if (fullNames.Add(r.FullName)) { // filter duplicates + if (fullNames.Add(r.FullName)) + { // filter duplicates var file = UniversalAssemblyResolver.GetAssemblyInGac(r); - if (file != null) { + if (file != null) + { var entry = new GacEntry(r, file); UpdateProgressBar(pg => { pg.Value++; AddNewEntry(entry); }); } @@ -155,7 +159,8 @@ namespace ICSharpCode.ILSpy string filterString = filterTextBox.Text.Trim(); if (filterString.Length == 0) filterMethod = _ => true; - else { + else + { var elements = filterString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); filterMethod = entry => elements.All(el => Contains(entry.FullName, el) || Contains(entry.FormattedVersion, el)); } diff --git a/SharpTreeView/Converters.cs b/SharpTreeView/Converters.cs index 8991e14bb..87c31ee37 100644 --- a/SharpTreeView/Converters.cs +++ b/SharpTreeView/Converters.cs @@ -17,10 +17,10 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Globalization; using System.Windows; -using System.Windows.Markup; using System.Windows.Data; -using System.Globalization; +using System.Windows.Markup; namespace ICSharpCode.TreeView { diff --git a/SharpTreeView/EditTextBox.cs b/SharpTreeView/EditTextBox.cs index e3191945d..965c035c8 100644 --- a/SharpTreeView/EditTextBox.cs +++ b/SharpTreeView/EditTextBox.cs @@ -16,9 +16,9 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using System.Windows; namespace ICSharpCode.TreeView { @@ -50,16 +50,20 @@ namespace ICSharpCode.TreeView protected override void OnKeyDown(KeyEventArgs e) { - if (e.Key == Key.Enter) { + if (e.Key == Key.Enter) + { Commit(); - } else if (e.Key == Key.Escape) { + } + else if (e.Key == Key.Escape) + { Node.IsEditing = false; } } protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) { - if (Node.IsEditing) { + if (Node.IsEditing) + { Commit(); } } @@ -68,11 +72,13 @@ namespace ICSharpCode.TreeView void Commit() { - if (!committing) { + if (!committing) + { committing = true; Node.IsEditing = false; - if (!Node.SaveEditText(Text)) { + if (!Node.SaveEditText(Text)) + { Item.Focus(); } Node.RaisePropertyChanged(nameof(Text)); diff --git a/SharpTreeView/ExtensionMethods.cs b/SharpTreeView/ExtensionMethods.cs index f9e1db2a3..6ae130d25 100644 --- a/SharpTreeView/ExtensionMethods.cs +++ b/SharpTreeView/ExtensionMethods.cs @@ -16,11 +16,11 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Windows.Media; using System.Windows; -using System.Collections; +using System.Windows.Media; namespace ICSharpCode.TreeView { @@ -33,7 +33,8 @@ namespace ICSharpCode.TreeView public static IEnumerable AncestorsAndSelf(this DependencyObject d) { - while (d != null) { + while (d != null) + { yield return d; d = VisualTreeHelper.GetParent(d); } @@ -41,7 +42,8 @@ namespace ICSharpCode.TreeView public static void AddOnce(this IList list, object item) { - if (!list.Contains(item)) { + if (!list.Contains(item)) + { list.Add(item); } } diff --git a/SharpTreeView/FlatListTreeNode.cs b/SharpTreeView/FlatListTreeNode.cs index cd9111e8f..6ae54e74e 100644 --- a/SharpTreeView/FlatListTreeNode.cs +++ b/SharpTreeView/FlatListTreeNode.cs @@ -30,24 +30,24 @@ namespace ICSharpCode.TreeView internal SharpTreeNode listParent; /// Left/right nodes in the flat list SharpTreeNode left, right; - + internal TreeFlattener treeFlattener; - + /// Subtree height in the flat list tree byte height = 1; - + /// Length in the flat list, including children (children within the flat list). -1 = invalidated int totalListLength = -1; - + int Balance { get { return Height(right) - Height(left); } } - + static int Height(SharpTreeNode node) { return node != null ? node.height : 0; } - + internal SharpTreeNode GetListRoot() { SharpTreeNode node = this; @@ -55,14 +55,14 @@ namespace ICSharpCode.TreeView node = node.listParent; return node; } - + #region Debugging [Conditional("DEBUG")] void CheckRootInvariants() { GetListRoot().CheckInvariants(); } - + [Conditional("DATACONSISTENCYCHECK")] void CheckInvariants() { @@ -71,16 +71,18 @@ namespace ICSharpCode.TreeView Debug.Assert(height == 1 + Math.Max(Height(left), Height(right))); Debug.Assert(Math.Abs(this.Balance) <= 1); Debug.Assert(totalListLength == -1 || totalListLength == (left != null ? left.totalListLength : 0) + (isVisible ? 1 : 0) + (right != null ? right.totalListLength : 0)); - if (left != null) left.CheckInvariants(); - if (right != null) right.CheckInvariants(); + if (left != null) + left.CheckInvariants(); + if (right != null) + right.CheckInvariants(); } - + [Conditional("DEBUG")] static void DumpTree(SharpTreeNode node) { node.GetListRoot().DumpTree(); } - + [Conditional("DEBUG")] void DumpTree() { @@ -95,7 +97,7 @@ namespace ICSharpCode.TreeView Debug.Unindent(); } #endregion - + #region GetNodeByVisibleIndex / GetVisibleIndexForNode internal static SharpTreeNode GetNodeByVisibleIndex(SharpTreeNode root, int index) { @@ -103,14 +105,20 @@ namespace ICSharpCode.TreeView Debug.Assert(index >= 0); Debug.Assert(index < root.totalListLength); SharpTreeNode node = root; - while (true) { - if (node.left != null && index < node.left.totalListLength) { + while (true) + { + if (node.left != null && index < node.left.totalListLength) + { node = node.left; - } else { - if (node.left != null) { + } + else + { + if (node.left != null) + { index -= node.left.totalListLength; } - if (node.isVisible) { + if (node.isVisible) + { if (index == 0) return node; index--; @@ -119,12 +127,14 @@ namespace ICSharpCode.TreeView } } } - + internal static int GetVisibleIndexForNode(SharpTreeNode node) { int index = node.left != null ? node.left.GetTotalListLength() : 0; - while (node.listParent != null) { - if (node == node.listParent.right) { + while (node.listParent != null) + { + if (node == node.listParent.right) + { if (node.listParent.left != null) index += node.listParent.left.GetTotalListLength(); if (node.listParent.isVisible) @@ -135,7 +145,7 @@ namespace ICSharpCode.TreeView return index; } #endregion - + #region Balancing /// /// Balances the subtree rooted in and recomputes the 'height' field. @@ -148,19 +158,25 @@ namespace ICSharpCode.TreeView Debug.Assert(node.right == null || Math.Abs(node.right.Balance) <= 1); // Keep looping until it's balanced. Not sure if this is stricly required; this is based on // the Rope code where node merging made this necessary. - while (Math.Abs(node.Balance) > 1) { + while (Math.Abs(node.Balance) > 1) + { // AVL balancing // note: because we don't care about the identity of concat nodes, this works a little different than usual // tree rotations: in our implementation, the "this" node will stay at the top, only its children are rearranged - if (node.Balance > 1) { - if (node.right.Balance < 0) { + if (node.Balance > 1) + { + if (node.right.Balance < 0) + { node.right = node.right.RotateRight(); } node = node.RotateLeft(); // If 'node' was unbalanced by more than 2, we've shifted some of the inbalance to the left node; so rebalance that. node.left = Rebalance(node.left); - } else if (node.Balance < -1) { - if (node.left.Balance > 0) { + } + else if (node.Balance < -1) + { + if (node.left.Balance > 0) + { node.left = node.left.RotateLeft(); } node = node.RotateRight(); @@ -171,24 +187,26 @@ namespace ICSharpCode.TreeView Debug.Assert(Math.Abs(node.Balance) <= 1); node.height = (byte)(1 + Math.Max(Height(node.left), Height(node.right))); node.totalListLength = -1; // mark for recalculation - // since balancing checks the whole tree up to the root, the whole path will get marked as invalid + // since balancing checks the whole tree up to the root, the whole path will get marked as invalid return node; } - + internal int GetTotalListLength() { if (totalListLength >= 0) return totalListLength; int length = (isVisible ? 1 : 0); - if (left != null) { + if (left != null) + { length += left.GetTotalListLength(); } - if (right != null) { + if (right != null) + { length += right.GetTotalListLength(); } return totalListLength = length; } - + SharpTreeNode RotateLeft() { /* Rotate tree to the left @@ -201,8 +219,9 @@ namespace ICSharpCode.TreeView */ SharpTreeNode b = right.left; SharpTreeNode newTop = right; - - if (b != null) b.listParent = this; + + if (b != null) + b.listParent = this; this.right = b; newTop.left = this; newTop.listParent = this.listParent; @@ -211,7 +230,7 @@ namespace ICSharpCode.TreeView newTop.left = Rebalance(this); return newTop; } - + SharpTreeNode RotateRight() { /* Rotate tree to the right @@ -224,8 +243,9 @@ namespace ICSharpCode.TreeView */ SharpTreeNode b = left.right; SharpTreeNode newTop = left; - - if (b != null) b.listParent = this; + + if (b != null) + b.listParent = this; this.left = b; newTop.right = this; newTop.listParent = this.listParent; @@ -233,20 +253,25 @@ namespace ICSharpCode.TreeView newTop.right = Rebalance(this); return newTop; } - + static void RebalanceUntilRoot(SharpTreeNode pos) { - while (pos.listParent != null) { - if (pos == pos.listParent.left) { + while (pos.listParent != null) + { + if (pos == pos.listParent.left) + { pos = pos.listParent.left = Rebalance(pos); - } else { + } + else + { Debug.Assert(pos == pos.listParent.right); pos = pos.listParent.right = Rebalance(pos); } pos = pos.listParent; } SharpTreeNode newRoot = Rebalance(pos); - if (newRoot != pos && pos.treeFlattener != null) { + if (newRoot != pos && pos.treeFlattener != null) + { Debug.Assert(newRoot.treeFlattener == null); newRoot.treeFlattener = pos.treeFlattener; pos.treeFlattener = null; @@ -256,16 +281,19 @@ namespace ICSharpCode.TreeView newRoot.CheckInvariants(); } #endregion - + #region Insertion static void InsertNodeAfter(SharpTreeNode pos, SharpTreeNode newNode) { // newNode might be the model root of a whole subtree, so go to the list root of that subtree: newNode = newNode.GetListRoot(); - if (pos.right == null) { + if (pos.right == null) + { pos.right = newNode; newNode.listParent = pos; - } else { + } + else + { // insert before pos.right's leftmost: pos = pos.right; while (pos.left != null) @@ -277,27 +305,30 @@ namespace ICSharpCode.TreeView RebalanceUntilRoot(pos); } #endregion - + #region Removal void RemoveNodes(SharpTreeNode start, SharpTreeNode end) { // Removes all nodes from start to end (inclusive) // All removed nodes will be reorganized in a separate tree, do not delete // regions that don't belong together in the tree model! - + List removedSubtrees = new List(); SharpTreeNode oldPos; SharpTreeNode pos = start; - do { + do + { // recalculate the endAncestors every time, because the tree might have been rebalanced HashSet endAncestors = new HashSet(); for (SharpTreeNode tmp = end; tmp != null; tmp = tmp.listParent) endAncestors.Add(tmp); - + removedSubtrees.Add(pos); - if (!endAncestors.Contains(pos)) { + if (!endAncestors.Contains(pos)) + { // we can remove pos' right subtree in a single step: - if (pos.right != null) { + if (pos.right != null) + { removedSubtrees.Add(pos.right); pos.right.listParent = null; pos.right = null; @@ -305,18 +336,19 @@ namespace ICSharpCode.TreeView } SharpTreeNode succ = pos.Successor(); DeleteNode(pos); // this will also rebalance out the deletion of the right subtree - + oldPos = pos; pos = succ; } while (oldPos != end); - + // merge back together the removed subtrees: SharpTreeNode removed = removedSubtrees[0]; - for (int i = 1; i < removedSubtrees.Count; i++) { + for (int i = 1; i < removedSubtrees.Count; i++) + { removed = ConcatTrees(removed, removedSubtrees[i]); } } - + static SharpTreeNode ConcatTrees(SharpTreeNode first, SharpTreeNode second) { SharpTreeNode tmp = first; @@ -325,18 +357,22 @@ namespace ICSharpCode.TreeView InsertNodeAfter(tmp, second); return tmp.GetListRoot(); } - + SharpTreeNode Successor() { - if (right != null) { + if (right != null) + { SharpTreeNode node = right; while (node.left != null) node = node.left; return node; - } else { + } + else + { SharpTreeNode node = this; SharpTreeNode oldNode; - do { + do + { oldNode = node; node = node.listParent; // loop while we are on the way up from the right part @@ -344,19 +380,24 @@ namespace ICSharpCode.TreeView return node; } } - + static void DeleteNode(SharpTreeNode node) { SharpTreeNode balancingNode; - if (node.left == null) { + if (node.left == null) + { balancingNode = node.listParent; node.ReplaceWith(node.right); node.right = null; - } else if (node.right == null) { + } + else if (node.right == null) + { balancingNode = node.listParent; node.ReplaceWith(node.left); node.left = null; - } else { + } + else + { SharpTreeNode tmp = node.right; while (tmp.left != null) tmp = tmp.left; @@ -367,10 +408,14 @@ namespace ICSharpCode.TreeView Debug.Assert(tmp.left == null); Debug.Assert(tmp.listParent == null); // Now move node's children to tmp: - tmp.left = node.left; node.left = null; - tmp.right = node.right; node.right = null; - if (tmp.left != null) tmp.left.listParent = tmp; - if (tmp.right != null) tmp.right.listParent = tmp; + tmp.left = node.left; + node.left = null; + tmp.right = node.right; + node.right = null; + if (tmp.left != null) + tmp.left.listParent = tmp; + if (tmp.right != null) + tmp.right.listParent = tmp; // Then replace node with tmp node.ReplaceWith(tmp); if (balancingNode == node) @@ -384,24 +429,31 @@ namespace ICSharpCode.TreeView if (balancingNode != null) RebalanceUntilRoot(balancingNode); } - + void ReplaceWith(SharpTreeNode node) { - if (listParent != null) { - if (listParent.left == this) { + if (listParent != null) + { + if (listParent.left == this) + { listParent.left = node; - } else { + } + else + { Debug.Assert(listParent.right == this); listParent.right = node; } if (node != null) node.listParent = listParent; listParent = null; - } else { + } + else + { // this was a root node Debug.Assert(node != null); // cannot delete the only node in the tree node.listParent = null; - if (treeFlattener != null) { + if (treeFlattener != null) + { Debug.Assert(node.treeFlattener == null); node.treeFlattener = this.treeFlattener; this.treeFlattener = null; diff --git a/SharpTreeView/GeneralAdorner.cs b/SharpTreeView/GeneralAdorner.cs index 5486fae9c..e1188bf41 100644 --- a/SharpTreeView/GeneralAdorner.cs +++ b/SharpTreeView/GeneralAdorner.cs @@ -16,8 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System.Windows.Documents; using System.Windows; +using System.Windows.Documents; using System.Windows.Media; namespace ICSharpCode.TreeView @@ -31,15 +31,13 @@ namespace ICSharpCode.TreeView FrameworkElement child; - public FrameworkElement Child - { - get - { + public FrameworkElement Child { + get { return child; } - set - { - if (child != value) { + set { + if (child != value) + { RemoveVisualChild(child); RemoveLogicalChild(child); child = value; @@ -50,8 +48,7 @@ namespace ICSharpCode.TreeView } } - protected override int VisualChildrenCount - { + protected override int VisualChildrenCount { get { return child == null ? 0 : 1; } } @@ -62,7 +59,8 @@ namespace ICSharpCode.TreeView protected override Size MeasureOverride(Size constraint) { - if (child != null) { + if (child != null) + { child.Measure(constraint); return child.DesiredSize; } @@ -71,7 +69,8 @@ namespace ICSharpCode.TreeView protected override Size ArrangeOverride(Size finalSize) { - if (child != null) { + if (child != null) + { child.Arrange(new Rect(finalSize)); return finalSize; } diff --git a/SharpTreeView/InsertMarker.cs b/SharpTreeView/InsertMarker.cs index 90d0ea675..7bbc6bb27 100644 --- a/SharpTreeView/InsertMarker.cs +++ b/SharpTreeView/InsertMarker.cs @@ -16,8 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System.Windows.Controls; using System.Windows; +using System.Windows.Controls; namespace ICSharpCode.TreeView { diff --git a/SharpTreeView/LinesRenderer.cs b/SharpTreeView/LinesRenderer.cs index fe47445bf..66aac78f8 100644 --- a/SharpTreeView/LinesRenderer.cs +++ b/SharpTreeView/LinesRenderer.cs @@ -16,9 +16,9 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System.Diagnostics; using System.Windows; using System.Windows.Media; -using System.Diagnostics; namespace ICSharpCode.TreeView { @@ -32,14 +32,14 @@ namespace ICSharpCode.TreeView static Pen pen; - SharpTreeNodeView NodeView - { + SharpTreeNodeView NodeView { get { return TemplatedParent as SharpTreeNodeView; } } protected override void OnRender(DrawingContext dc) { - if (NodeView.Node == null) { + if (NodeView.Node == null) + { // This seems to happen sometimes with DataContext==DisconnectedItem, // though I'm not sure why WPF would call OnRender() on a disconnected node Debug.WriteLine($"LinesRenderer.OnRender() called with DataContext={NodeView.DataContext}"); @@ -48,25 +48,32 @@ namespace ICSharpCode.TreeView var indent = NodeView.CalculateIndent(); var p = new Point(indent + 4.5, 0); - if (!NodeView.Node.IsRoot || NodeView.ParentTreeView.ShowRootExpander) { + if (!NodeView.Node.IsRoot || NodeView.ParentTreeView.ShowRootExpander) + { dc.DrawLine(pen, new Point(p.X, ActualHeight / 2), new Point(p.X + 10, ActualHeight / 2)); } - if (NodeView.Node.IsRoot) return; + if (NodeView.Node.IsRoot) + return; - if (NodeView.Node.IsLast) { + if (NodeView.Node.IsLast) + { dc.DrawLine(pen, p, new Point(p.X, ActualHeight / 2)); } - else { + else + { dc.DrawLine(pen, p, new Point(p.X, ActualHeight)); } var current = NodeView.Node; - while (true) { + while (true) + { p.X -= 19; current = current.Parent; - if (p.X < 0) break; - if (!current.IsLast) { + if (p.X < 0) + break; + if (!current.IsLast) + { dc.DrawLine(pen, p, new Point(p.X, ActualHeight)); } } diff --git a/SharpTreeView/Properties/GlobalAssemblyInfo.cs b/SharpTreeView/Properties/GlobalAssemblyInfo.cs index 678d45210..52976c664 100644 --- a/SharpTreeView/Properties/GlobalAssemblyInfo.cs +++ b/SharpTreeView/Properties/GlobalAssemblyInfo.cs @@ -25,8 +25,8 @@ ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// -using System.Resources; using System.Reflection; +using System.Resources; [assembly: System.Runtime.InteropServices.ComVisible(false)] [assembly: AssemblyCompany("ic#code")] @@ -46,6 +46,6 @@ internal static class RevisionClass public const string Build = "0"; public const string Revision = "8752"; public const string VersionName = "Beta 2"; - + public const string FullVersion = Major + "." + Minor + "." + Build + ".8752-Beta 2"; } diff --git a/SharpTreeView/SharpGridView.cs b/SharpTreeView/SharpGridView.cs index b7224a5c0..9487d936d 100644 --- a/SharpTreeView/SharpGridView.cs +++ b/SharpTreeView/SharpGridView.cs @@ -16,8 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System.Windows.Controls; using System.Windows; +using System.Windows.Controls; namespace ICSharpCode.TreeView { @@ -31,10 +31,8 @@ namespace ICSharpCode.TreeView public static ResourceKey ItemContainerStyleKey { get; private set; } - protected override object ItemContainerDefaultStyleKey - { - get - { + protected override object ItemContainerDefaultStyleKey { + get { return ItemContainerStyleKey; } } diff --git a/SharpTreeView/SharpTreeNode.cs b/SharpTreeView/SharpTreeNode.cs index af568e067..97cd399cd 100644 --- a/SharpTreeView/SharpTreeNode.cs +++ b/SharpTreeView/SharpTreeNode.cs @@ -18,13 +18,13 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Windows; -using System.ComponentModel; -using System.Collections.Specialized; -using System.Windows.Media; using System.Windows.Input; +using System.Windows.Media; namespace ICSharpCode.TreeView { @@ -33,44 +33,51 @@ namespace ICSharpCode.TreeView SharpTreeNodeCollection modelChildren; internal SharpTreeNode modelParent; bool isVisible = true; - + void UpdateIsVisible(bool parentIsVisible, bool updateFlattener) { bool newIsVisible = parentIsVisible && !isHidden; - if (isVisible != newIsVisible) { + if (isVisible != newIsVisible) + { isVisible = newIsVisible; - + // invalidate the augmented data SharpTreeNode node = this; - while (node != null && node.totalListLength >= 0) { + while (node != null && node.totalListLength >= 0) + { node.totalListLength = -1; node = node.listParent; } // Remember the removed nodes: List removedNodes = null; - if (updateFlattener && !newIsVisible) { + if (updateFlattener && !newIsVisible) + { removedNodes = VisibleDescendantsAndSelf().ToList(); } // also update the model children: UpdateChildIsVisible(false); - + // Validate our invariants: if (updateFlattener) CheckRootInvariants(); - + // Tell the flattener about the removed nodes: - if (removedNodes != null) { + if (removedNodes != null) + { var flattener = GetListRoot().treeFlattener; - if (flattener != null) { + if (flattener != null) + { flattener.NodesRemoved(GetVisibleIndexForNode(this), removedNodes); foreach (var n in removedNodes) n.OnIsVisibleChanged(); } } // Tell the flattener about the new nodes: - if (updateFlattener && newIsVisible) { + if (updateFlattener && newIsVisible) + { var flattener = GetListRoot().treeFlattener; - if (flattener != null) { + if (flattener != null) + { flattener.NodesInserted(GetVisibleIndexForNode(this), VisibleDescendantsAndSelf()); foreach (var n in VisibleDescendantsAndSelf()) n.OnIsVisibleChanged(); @@ -78,25 +85,27 @@ namespace ICSharpCode.TreeView } } } - - protected virtual void OnIsVisibleChanged() {} - + + protected virtual void OnIsVisibleChanged() { } + void UpdateChildIsVisible(bool updateFlattener) { - if (modelChildren != null && modelChildren.Count > 0) { + if (modelChildren != null && modelChildren.Count > 0) + { bool showChildren = isVisible && isExpanded; - foreach (SharpTreeNode child in modelChildren) { + foreach (SharpTreeNode child in modelChildren) + { child.UpdateIsVisible(showChildren, updateFlattener); } } } - + #region Main - + public SharpTreeNode() { } - + public SharpTreeNodeCollection Children { get { if (modelChildren == null) @@ -104,47 +113,42 @@ namespace ICSharpCode.TreeView return modelChildren; } } - + public SharpTreeNode Parent { get { return modelParent; } } - - public virtual object Text - { + + public virtual object Text { get { return null; } } - + public virtual Brush Foreground { get { return SystemColors.WindowTextBrush; } } - - public virtual object Icon - { + + public virtual object Icon { get { return null; } } - - public virtual object ToolTip - { + + public virtual object ToolTip { get { return null; } } - - public int Level - { + + public int Level { get { return Parent != null ? Parent.Level + 1 : 0; } } - - public bool IsRoot - { + + public bool IsRoot { get { return Parent == null; } } - + bool isHidden; - - public bool IsHidden - { + + public bool IsHidden { get { return isHidden; } set { - if (isHidden != value) { + if (isHidden != value) + { isHidden = value; if (modelParent != null) UpdateIsVisible(modelParent.isVisible && modelParent.isExpanded, true); @@ -154,115 +158,126 @@ namespace ICSharpCode.TreeView } } } - + /// /// Return true when this node is not hidden and when all parent nodes are expanded and not hidden. /// public bool IsVisible { get { return isVisible; } } - + bool isSelected; - + public bool IsSelected { get { return isSelected; } set { - if (isSelected != value) { + if (isSelected != value) + { isSelected = value; RaisePropertyChanged(nameof(IsSelected)); } } } - + #endregion - + #region OnChildrenChanged internal protected virtual void OnChildrenChanged(NotifyCollectionChangedEventArgs e) { - if (e.OldItems != null) { - foreach (SharpTreeNode node in e.OldItems) { + if (e.OldItems != null) + { + foreach (SharpTreeNode node in e.OldItems) + { Debug.Assert(node.modelParent == this); node.modelParent = null; Debug.WriteLine("Removing {0} from {1}", node, this); SharpTreeNode removeEnd = node; while (removeEnd.modelChildren != null && removeEnd.modelChildren.Count > 0) removeEnd = removeEnd.modelChildren.Last(); - + List removedNodes = null; int visibleIndexOfRemoval = 0; - if (node.isVisible) { + if (node.isVisible) + { visibleIndexOfRemoval = GetVisibleIndexForNode(node); removedNodes = node.VisibleDescendantsAndSelf().ToList(); } - + RemoveNodes(node, removeEnd); - - if (removedNodes != null) { + + if (removedNodes != null) + { var flattener = GetListRoot().treeFlattener; - if (flattener != null) { + if (flattener != null) + { flattener.NodesRemoved(visibleIndexOfRemoval, removedNodes); } } } } - if (e.NewItems != null) { + if (e.NewItems != null) + { SharpTreeNode insertionPos; if (e.NewStartingIndex == 0) insertionPos = null; else insertionPos = modelChildren[e.NewStartingIndex - 1]; - - foreach (SharpTreeNode node in e.NewItems) { + + foreach (SharpTreeNode node in e.NewItems) + { Debug.Assert(node.modelParent == null); node.modelParent = this; node.UpdateIsVisible(isVisible && isExpanded, false); //Debug.WriteLine("Inserting {0} after {1}", node, insertionPos); - - while (insertionPos != null && insertionPos.modelChildren != null && insertionPos.modelChildren.Count > 0) { + + while (insertionPos != null && insertionPos.modelChildren != null && insertionPos.modelChildren.Count > 0) + { insertionPos = insertionPos.modelChildren.Last(); } InsertNodeAfter(insertionPos ?? this, node); - + insertionPos = node; - if (node.isVisible) { + if (node.isVisible) + { var flattener = GetListRoot().treeFlattener; - if (flattener != null) { + if (flattener != null) + { flattener.NodesInserted(GetVisibleIndexForNode(node), node.VisibleDescendantsAndSelf()); } } } } - + RaisePropertyChanged(nameof(ShowExpander)); RaiseIsLastChangedIfNeeded(e); } #endregion - + #region Expanding / LazyLoading - - public virtual object ExpandedIcon - { + + public virtual object ExpandedIcon { get { return Icon; } } - - public virtual bool ShowExpander - { + + public virtual bool ShowExpander { get { return LazyLoading || Children.Any(c => !c.isHidden); } } - + bool isExpanded; - - public bool IsExpanded - { + + public bool IsExpanded { get { return isExpanded; } - set - { - if (isExpanded != value) { + set { + if (isExpanded != value) + { isExpanded = value; - if (isExpanded) { + if (isExpanded) + { EnsureLazyChildren(); OnExpanding(); - } else { + } + else + { OnCollapsing(); } UpdateChildIsVisible(true); @@ -270,21 +285,21 @@ namespace ICSharpCode.TreeView } } } - - protected virtual void OnExpanding() {} - protected virtual void OnCollapsing() {} - + + protected virtual void OnExpanding() { } + protected virtual void OnCollapsing() { } + bool lazyLoading; - - public bool LazyLoading - { + + public bool LazyLoading { get { return lazyLoading; } - set - { + set { lazyLoading = value; - if (lazyLoading) { + if (lazyLoading) + { IsExpanded = false; - if (canExpandRecursively) { + if (canExpandRecursively) + { canExpandRecursively = false; RaisePropertyChanged(nameof(CanExpandRecursively)); } @@ -293,9 +308,9 @@ namespace ICSharpCode.TreeView RaisePropertyChanged(nameof(ShowExpander)); } } - + bool canExpandRecursively = true; - + /// /// Gets whether this node can be expanded recursively. /// If not overridden, this property returns false if the node is using lazy-loading, and true otherwise. @@ -303,156 +318,164 @@ namespace ICSharpCode.TreeView public virtual bool CanExpandRecursively { get { return canExpandRecursively; } } - - public virtual bool ShowIcon - { + + public virtual bool ShowIcon { get { return Icon != null; } } - + protected virtual void LoadChildren() { throw new NotSupportedException(GetType().Name + " does not support lazy loading"); } - + /// /// Ensures the children were initialized (loads children if lazy loading is enabled) /// public void EnsureLazyChildren() { - if (LazyLoading) { + if (LazyLoading) + { LazyLoading = false; LoadChildren(); } } - + #endregion - + #region Ancestors / Descendants - + public IEnumerable Descendants() { return TreeTraversal.PreOrder(this.Children, n => n.Children); } - + public IEnumerable DescendantsAndSelf() { return TreeTraversal.PreOrder(this, n => n.Children); } - + internal IEnumerable VisibleDescendants() { return TreeTraversal.PreOrder(this.Children.Where(c => c.isVisible), n => n.Children.Where(c => c.isVisible)); } - + internal IEnumerable VisibleDescendantsAndSelf() { return TreeTraversal.PreOrder(this, n => n.Children.Where(c => c.isVisible)); } - + public IEnumerable Ancestors() { for (SharpTreeNode n = this.Parent; n != null; n = n.Parent) yield return n; } - + public IEnumerable AncestorsAndSelf() { for (SharpTreeNode n = this; n != null; n = n.Parent) yield return n; } - + #endregion - + #region Editing - - public virtual bool IsEditable - { + + public virtual bool IsEditable { get { return false; } } - + bool isEditing; - - public bool IsEditing - { + + public bool IsEditing { get { return isEditing; } - set - { - if (isEditing != value) { + set { + if (isEditing != value) + { isEditing = value; RaisePropertyChanged(nameof(IsEditing)); } } } - + public virtual string LoadEditText() { return null; } - + public virtual bool SaveEditText(string value) { return true; } - + #endregion - + #region Checkboxes - + public virtual bool IsCheckable { get { return false; } } - + bool? isChecked; - + public bool? IsChecked { get { return isChecked; } set { SetIsChecked(value, true); } } - + void SetIsChecked(bool? value, bool update) { - if (isChecked != value) { + if (isChecked != value) + { isChecked = value; - - if (update) { - if (IsChecked != null) { - foreach (var child in Descendants()) { - if (child.IsCheckable) { + + if (update) + { + if (IsChecked != null) + { + foreach (var child in Descendants()) + { + if (child.IsCheckable) + { child.SetIsChecked(IsChecked, false); } } } - - foreach (var parent in Ancestors()) { - if (parent.IsCheckable) { - if (!parent.TryValueForIsChecked(true)) { - if (!parent.TryValueForIsChecked(false)) { + + foreach (var parent in Ancestors()) + { + if (parent.IsCheckable) + { + if (!parent.TryValueForIsChecked(true)) + { + if (!parent.TryValueForIsChecked(false)) + { parent.SetIsChecked(null, false); } } } } } - + RaisePropertyChanged(nameof(IsChecked)); } } - + bool TryValueForIsChecked(bool? value) { - if (Children.Where(n => n.IsCheckable).All(n => n.IsChecked == value)) { + if (Children.Where(n => n.IsCheckable).All(n => n.IsChecked == value)) + { SetIsChecked(value, false); return true; } return false; } - + #endregion - + #region Cut / Copy / Paste / Delete - + public bool IsCut { get { return false; } } /* static List cuttedNodes = new List(); @@ -549,27 +572,27 @@ namespace ICSharpCode.TreeView } } */ - + public virtual bool CanDelete() { return false; } - + public virtual void Delete() { throw new NotSupportedException(GetType().Name + " does not support deletion"); } - + public virtual void DeleteCore() { throw new NotSupportedException(GetType().Name + " does not support deletion"); } - + public virtual IDataObject Copy(SharpTreeNode[] nodes) { throw new NotSupportedException(GetType().Name + " does not support copy/paste or drag'n'drop"); } - + /* public virtual bool CanCopy(SharpTreeNode[] nodes) { @@ -588,93 +611,99 @@ namespace ICSharpCode.TreeView } */ #endregion - + #region Drag and Drop public virtual bool CanDrag(SharpTreeNode[] nodes) { return false; } - + public virtual void StartDrag(DependencyObject dragSource, SharpTreeNode[] nodes) { DragDropEffects effects = DragDropEffects.All; if (!nodes.All(n => n.CanDelete())) effects &= ~DragDropEffects.Move; DragDropEffects result = DragDrop.DoDragDrop(dragSource, Copy(nodes), effects); - if (result == DragDropEffects.Move) { + if (result == DragDropEffects.Move) + { foreach (SharpTreeNode node in nodes) node.DeleteCore(); } } - + public virtual bool CanDrop(DragEventArgs e, int index) { return false; } - + internal void InternalDrop(DragEventArgs e, int index) { - if (LazyLoading) { + if (LazyLoading) + { EnsureLazyChildren(); index = Children.Count; } - + Drop(e, index); } - + public virtual void Drop(DragEventArgs e, int index) { throw new NotSupportedException(GetType().Name + " does not support Drop()"); } #endregion - + #region IsLast (for TreeView lines) - - public bool IsLast - { - get - { + + public bool IsLast { + get { return Parent == null || Parent.Children[Parent.Children.Count - 1] == this; } } - + void RaiseIsLastChangedIfNeeded(NotifyCollectionChangedEventArgs e) { - switch (e.Action) { + switch (e.Action) + { case NotifyCollectionChangedAction.Add: - if (e.NewStartingIndex == Children.Count - 1) { - if (Children.Count > 1) { + if (e.NewStartingIndex == Children.Count - 1) + { + if (Children.Count > 1) + { Children[Children.Count - 2].RaisePropertyChanged(nameof(IsLast)); } Children[Children.Count - 1].RaisePropertyChanged(nameof(IsLast)); } break; case NotifyCollectionChangedAction.Remove: - if (e.OldStartingIndex == Children.Count) { - if (Children.Count > 0) { + if (e.OldStartingIndex == Children.Count) + { + if (Children.Count > 0) + { Children[Children.Count - 1].RaisePropertyChanged(nameof(IsLast)); } } break; } } - + #endregion - + #region INotifyPropertyChanged Members - + public event PropertyChangedEventHandler PropertyChanged; - + public void RaisePropertyChanged(string name) { - if (PropertyChanged != null) { + if (PropertyChanged != null) + { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } - + #endregion - + /// /// Gets called when the item is double-clicked. /// diff --git a/SharpTreeView/SharpTreeNodeCollection.cs b/SharpTreeView/SharpTreeNodeCollection.cs index 08939522f..3d65737b8 100644 --- a/SharpTreeView/SharpTreeNodeCollection.cs +++ b/SharpTreeView/SharpTreeNodeCollection.cs @@ -18,9 +18,9 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.Diagnostics; using System.Linq; -using System.Collections.Specialized; namespace ICSharpCode.TreeView { @@ -32,33 +32,36 @@ namespace ICSharpCode.TreeView readonly SharpTreeNode parent; List list = new List(); bool isRaisingEvent; - + public SharpTreeNodeCollection(SharpTreeNode parent) { this.parent = parent; } - + public event NotifyCollectionChangedEventHandler CollectionChanged; - + void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { Debug.Assert(!isRaisingEvent); isRaisingEvent = true; - try { + try + { parent.OnChildrenChanged(e); if (CollectionChanged != null) CollectionChanged(this, e); - } finally { + } + finally + { isRaisingEvent = false; } } - + void ThrowOnReentrancy() { if (isRaisingEvent) throw new InvalidOperationException(); } - + void ThrowIfValueIsNullOrHasParent(SharpTreeNode node) { if (node == null) @@ -66,7 +69,7 @@ namespace ICSharpCode.TreeView if (node.modelParent != null) throw new ArgumentException("The node already has a parent", "node"); } - + public SharpTreeNode this[int index] { get { return list[index]; @@ -81,15 +84,15 @@ namespace ICSharpCode.TreeView OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, oldItem, index)); } } - + public int Count { get { return list.Count; } } - + bool ICollection.IsReadOnly { get { return false; } } - + public int IndexOf(SharpTreeNode node) { if (node == null || node.modelParent != parent) @@ -97,7 +100,7 @@ namespace ICSharpCode.TreeView else return list.IndexOf(node); } - + public void Insert(int index, SharpTreeNode node) { ThrowOnReentrancy(); @@ -105,7 +108,7 @@ namespace ICSharpCode.TreeView list.Insert(index, node); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, node, index)); } - + public void InsertRange(int index, IEnumerable nodes) { if (nodes == null) @@ -114,13 +117,14 @@ namespace ICSharpCode.TreeView List newNodes = nodes.ToList(); if (newNodes.Count == 0) return; - foreach (SharpTreeNode node in newNodes) { + foreach (SharpTreeNode node in newNodes) + { ThrowIfValueIsNullOrHasParent(node); } list.InsertRange(index, newNodes); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newNodes, index)); } - + public void RemoveAt(int index) { ThrowOnReentrancy(); @@ -128,7 +132,7 @@ namespace ICSharpCode.TreeView list.RemoveAt(index); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItem, index)); } - + public void RemoveRange(int index, int count) { ThrowOnReentrancy(); @@ -138,7 +142,7 @@ namespace ICSharpCode.TreeView list.RemoveRange(index, count); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItems, index)); } - + public void Add(SharpTreeNode node) { ThrowOnReentrancy(); @@ -146,12 +150,12 @@ namespace ICSharpCode.TreeView list.Add(node); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, node, list.Count - 1)); } - + public void AddRange(IEnumerable nodes) { InsertRange(this.Count, nodes); } - + public void Clear() { ThrowOnReentrancy(); @@ -159,63 +163,75 @@ namespace ICSharpCode.TreeView list = new List(); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldList, 0)); } - + public bool Contains(SharpTreeNode node) { return IndexOf(node) >= 0; } - + public void CopyTo(SharpTreeNode[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); } - + public bool Remove(SharpTreeNode item) { int pos = IndexOf(item); - if (pos >= 0) { + if (pos >= 0) + { RemoveAt(pos); return true; - } else { + } + else + { return false; } } - + public IEnumerator GetEnumerator() { return list.GetEnumerator(); } - + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return list.GetEnumerator(); } - + public void RemoveAll(Predicate match) { if (match == null) throw new ArgumentNullException("match"); ThrowOnReentrancy(); int firstToRemove = 0; - for (int i = 0; i < list.Count; i++) { + for (int i = 0; i < list.Count; i++) + { bool removeNode; isRaisingEvent = true; - try { + try + { removeNode = match(list[i]); - } finally { + } + finally + { isRaisingEvent = false; } - if (!removeNode) { - if (firstToRemove < i) { + if (!removeNode) + { + if (firstToRemove < i) + { RemoveRange(firstToRemove, i - firstToRemove); i = firstToRemove - 1; - } else { + } + else + { firstToRemove = i + 1; } Debug.Assert(firstToRemove == i + 1); } } - if (firstToRemove < list.Count) { + if (firstToRemove < list.Count) + { RemoveRange(firstToRemove, list.Count - firstToRemove); } } diff --git a/SharpTreeView/SharpTreeNodeView.cs b/SharpTreeView/SharpTreeNodeView.cs index 0ff16996f..30c8c13a1 100644 --- a/SharpTreeView/SharpTreeNodeView.cs +++ b/SharpTreeView/SharpTreeNodeView.cs @@ -17,12 +17,12 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Windows.Controls; +using System.ComponentModel; +using System.Diagnostics; using System.Windows; +using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Media; -using System.ComponentModel; -using System.Diagnostics; namespace ICSharpCode.TreeView { @@ -31,36 +31,33 @@ namespace ICSharpCode.TreeView static SharpTreeNodeView() { DefaultStyleKeyProperty.OverrideMetadata(typeof(SharpTreeNodeView), - new FrameworkPropertyMetadata(typeof(SharpTreeNodeView))); + new FrameworkPropertyMetadata(typeof(SharpTreeNodeView))); } public static readonly DependencyProperty TextBackgroundProperty = DependencyProperty.Register("TextBackground", typeof(Brush), typeof(SharpTreeNodeView)); - public Brush TextBackground - { + public Brush TextBackground { get { return (Brush)GetValue(TextBackgroundProperty); } set { SetValue(TextBackgroundProperty, value); } } - public SharpTreeNode Node - { + public SharpTreeNode Node { get { return DataContext as SharpTreeNode; } } public SharpTreeViewItem ParentItem { get; private set; } - + public static readonly DependencyProperty CellEditorProperty = DependencyProperty.Register("CellEditor", typeof(Control), typeof(SharpTreeNodeView), - new FrameworkPropertyMetadata()); - + new FrameworkPropertyMetadata()); + public Control CellEditor { get { return (Control)GetValue(CellEditorProperty); } set { SetValue(CellEditorProperty, value); } } - public SharpTreeView ParentTreeView - { + public SharpTreeView ParentTreeView { get { return ParentItem.ParentTreeView; } } @@ -83,38 +80,50 @@ namespace ICSharpCode.TreeView protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { base.OnPropertyChanged(e); - if (e.Property == DataContextProperty) { + if (e.Property == DataContextProperty) + { UpdateDataContext(e.OldValue as SharpTreeNode, e.NewValue as SharpTreeNode); } } void UpdateDataContext(SharpTreeNode oldNode, SharpTreeNode newNode) { - if (newNode != null) { + if (newNode != null) + { newNode.PropertyChanged += Node_PropertyChanged; - if (Template != null) { + if (Template != null) + { UpdateTemplate(); } } - if (oldNode != null) { + if (oldNode != null) + { oldNode.PropertyChanged -= Node_PropertyChanged; } } void Node_PropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == "IsEditing") { + if (e.PropertyName == "IsEditing") + { OnIsEditingChanged(); - } else if (e.PropertyName == "IsLast") { - if (ParentTreeView.ShowLines) { - foreach (var child in Node.VisibleDescendantsAndSelf()) { + } + else if (e.PropertyName == "IsLast") + { + if (ParentTreeView.ShowLines) + { + foreach (var child in Node.VisibleDescendantsAndSelf()) + { var container = ParentTreeView.ItemContainerGenerator.ContainerFromItem(child) as SharpTreeViewItem; - if (container != null && container.NodeView != null) { + if (container != null && container.NodeView != null) + { container.NodeView.LinesRenderer.InvalidateVisual(); } } } - } else if (e.PropertyName == "IsExpanded") { + } + else if (e.PropertyName == "IsExpanded") + { if (Node.IsExpanded) ParentTreeView.HandleExpanding(Node); } @@ -123,13 +132,15 @@ namespace ICSharpCode.TreeView void OnIsEditingChanged() { var textEditorContainer = Template.FindName("textEditorContainer", this) as Border; - if (Node.IsEditing) { + if (Node.IsEditing) + { if (CellEditor == null) textEditorContainer.Child = new EditTextBox() { Item = ParentItem }; else textEditorContainer.Child = CellEditor; } - else { + else + { textEditorContainer.Child = null; } } @@ -140,10 +151,12 @@ namespace ICSharpCode.TreeView spacer.Width = CalculateIndent(); var expander = Template.FindName("expander", this) as ToggleButton; - if (ParentTreeView.Root == Node && !ParentTreeView.ShowRootExpander) { + if (ParentTreeView.Root == Node && !ParentTreeView.ShowRootExpander) + { expander.Visibility = Visibility.Collapsed; } - else { + else + { expander.ClearValue(VisibilityProperty); } } @@ -151,17 +164,22 @@ namespace ICSharpCode.TreeView internal double CalculateIndent() { var result = 19 * Node.Level; - if (ParentTreeView.ShowRoot) { - if (!ParentTreeView.ShowRootExpander) { - if (ParentTreeView.Root != Node) { + if (ParentTreeView.ShowRoot) + { + if (!ParentTreeView.ShowRootExpander) + { + if (ParentTreeView.Root != Node) + { result -= 15; } } } - else { + else + { result -= 19; } - if (result < 0) { + if (result < 0) + { Debug.WriteLine("Negative indent level detected for node " + Node); return 0; } diff --git a/SharpTreeView/SharpTreeView.cs b/SharpTreeView/SharpTreeView.cs index ec7b7b9bf..c2b1ebe61 100644 --- a/SharpTreeView/SharpTreeView.cs +++ b/SharpTreeView/SharpTreeView.cs @@ -35,20 +35,20 @@ namespace ICSharpCode.TreeView static SharpTreeView() { DefaultStyleKeyProperty.OverrideMetadata(typeof(SharpTreeView), - new FrameworkPropertyMetadata(typeof(SharpTreeView))); + new FrameworkPropertyMetadata(typeof(SharpTreeView))); SelectionModeProperty.OverrideMetadata(typeof(SharpTreeView), - new FrameworkPropertyMetadata(SelectionMode.Extended)); + new FrameworkPropertyMetadata(SelectionMode.Extended)); AlternationCountProperty.OverrideMetadata(typeof(SharpTreeView), - new FrameworkPropertyMetadata(2)); + new FrameworkPropertyMetadata(2)); DefaultItemContainerStyleKey = new ComponentResourceKey(typeof(SharpTreeView), "DefaultItemContainerStyleKey"); VirtualizingStackPanel.VirtualizationModeProperty.OverrideMetadata(typeof(SharpTreeView), - new FrameworkPropertyMetadata(VirtualizationMode.Recycling)); - + new FrameworkPropertyMetadata(VirtualizationMode.Recycling)); + RegisterCommands(); } @@ -62,28 +62,25 @@ namespace ICSharpCode.TreeView public static readonly DependencyProperty RootProperty = DependencyProperty.Register("Root", typeof(SharpTreeNode), typeof(SharpTreeView)); - public SharpTreeNode Root - { + public SharpTreeNode Root { get { return (SharpTreeNode)GetValue(RootProperty); } set { SetValue(RootProperty, value); } } public static readonly DependencyProperty ShowRootProperty = DependencyProperty.Register("ShowRoot", typeof(bool), typeof(SharpTreeView), - new FrameworkPropertyMetadata(true)); + new FrameworkPropertyMetadata(true)); - public bool ShowRoot - { + public bool ShowRoot { get { return (bool)GetValue(ShowRootProperty); } set { SetValue(ShowRootProperty, value); } } public static readonly DependencyProperty ShowRootExpanderProperty = DependencyProperty.Register("ShowRootExpander", typeof(bool), typeof(SharpTreeView), - new FrameworkPropertyMetadata(false)); + new FrameworkPropertyMetadata(false)); - public bool ShowRootExpander - { + public bool ShowRootExpander { get { return (bool)GetValue(ShowRootExpanderProperty); } set { SetValue(ShowRootExpanderProperty, value); } } @@ -91,18 +88,16 @@ namespace ICSharpCode.TreeView public static readonly DependencyProperty AllowDropOrderProperty = DependencyProperty.Register("AllowDropOrder", typeof(bool), typeof(SharpTreeView)); - public bool AllowDropOrder - { + public bool AllowDropOrder { get { return (bool)GetValue(AllowDropOrderProperty); } set { SetValue(AllowDropOrderProperty, value); } } public static readonly DependencyProperty ShowLinesProperty = DependencyProperty.Register("ShowLines", typeof(bool), typeof(SharpTreeView), - new FrameworkPropertyMetadata(true)); + new FrameworkPropertyMetadata(true)); - public bool ShowLines - { + public bool ShowLines { get { return (bool)GetValue(ShowLinesProperty); } set { SetValue(ShowLinesProperty, value); } } @@ -119,14 +114,15 @@ namespace ICSharpCode.TreeView public static readonly DependencyProperty ShowAlternationProperty = DependencyProperty.RegisterAttached("ShowAlternation", typeof(bool), typeof(SharpTreeView), - new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits)); - + new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits)); + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { base.OnPropertyChanged(e); if (e.Property == RootProperty || - e.Property == ShowRootProperty || - e.Property == ShowRootExpanderProperty) { + e.Property == ShowRootProperty || + e.Property == ShowRootExpanderProperty) + { Reload(); } } @@ -157,11 +153,14 @@ namespace ICSharpCode.TreeView void Reload() { - if (flattener != null) { + if (flattener != null) + { flattener.Stop(); } - if (Root != null) { - if (!(ShowRoot && ShowRootExpander)) { + if (Root != null) + { + if (!(ShowRoot && ShowRootExpander)) + { Root.IsExpanded = true; } flattener = new TreeFlattener(Root, ShowRoot); @@ -173,16 +172,20 @@ namespace ICSharpCode.TreeView void flattener_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { // Deselect nodes that are being hidden, if any remain in the tree - if (e.Action == NotifyCollectionChangedAction.Remove && Items.Count > 0) { + if (e.Action == NotifyCollectionChangedAction.Remove && Items.Count > 0) + { List selectedOldItems = null; - foreach (SharpTreeNode node in e.OldItems) { - if (node.IsSelected) { + foreach (SharpTreeNode node in e.OldItems) + { + if (node.IsSelected) + { if (selectedOldItems == null) selectedOldItems = new List(); selectedOldItems.Add(node); } } - if (!updatesLocked && selectedOldItems != null) { + if (!updatesLocked && selectedOldItems != null) + { var list = SelectedItems.Cast().Except(selectedOldItems).ToList(); UpdateFocusedNode(list, Math.Max(0, e.OldStartingIndex - 1)); } @@ -191,9 +194,11 @@ namespace ICSharpCode.TreeView void UpdateFocusedNode(List newSelection, int topSelectedIndex) { - if (updatesLocked) return; + if (updatesLocked) + return; SetSelectedItems(newSelection ?? Enumerable.Empty()); - if (SelectedItem == null && this.IsKeyboardFocusWithin) { + if (SelectedItem == null && this.IsKeyboardFocusWithin) + { // if we removed all selected nodes, then move the focus to the node // preceding the first of the old selected nodes SelectedIndex = topSelectedIndex; @@ -201,7 +206,7 @@ namespace ICSharpCode.TreeView FocusNode((SharpTreeNode)SelectedItem); } } - + protected override DependencyObject GetContainerForItemOverride() { return new SharpTreeViewItem(); @@ -218,13 +223,14 @@ namespace ICSharpCode.TreeView SharpTreeViewItem container = element as SharpTreeViewItem; container.ParentTreeView = this; // Make sure that the line renderer takes into account the new bound data - if (container.NodeView != null) { + if (container.NodeView != null) + { container.NodeView.LinesRenderer.InvalidateVisual(); } } - + bool doNotScrollOnExpanding; - + /// /// Handles the node expanding event in the tree view. /// This method gets called only if the node is in the visible region (a SharpTreeNodeView exists). @@ -234,15 +240,20 @@ namespace ICSharpCode.TreeView if (doNotScrollOnExpanding) return; SharpTreeNode lastVisibleChild = node; - while (true) { + while (true) + { SharpTreeNode tmp = lastVisibleChild.Children.LastOrDefault(c => c.IsVisible); - if (tmp != null) { + if (tmp != null) + { lastVisibleChild = tmp; - } else { + } + else + { break; } } - if (lastVisibleChild != node) { + if (lastVisibleChild != node) + { // Make the the expanded children are visible; but don't scroll down // to much (keep node itself visible) base.ScrollIntoView(lastVisibleChild); @@ -253,26 +264,35 @@ namespace ICSharpCode.TreeView })); } } - + protected override void OnKeyDown(KeyEventArgs e) { SharpTreeViewItem container = e.OriginalSource as SharpTreeViewItem; - switch (e.Key) { + switch (e.Key) + { case Key.Left: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { - if (container.Node.IsExpanded) { + if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) + { + if (container.Node.IsExpanded) + { container.Node.IsExpanded = false; - } else if (container.Node.Parent != null) { + } + else if (container.Node.Parent != null) + { this.FocusNode(container.Node.Parent); } e.Handled = true; } break; case Key.Right: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { - if (!container.Node.IsExpanded && container.Node.ShowExpander) { + if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) + { + if (!container.Node.IsExpanded && container.Node.ShowExpander) + { container.Node.IsExpanded = true; - } else if (container.Node.Children.Count > 0) { + } + else if (container.Node.Children.Count > 0) + { // jump to first child: container.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down)); } @@ -280,47 +300,57 @@ namespace ICSharpCode.TreeView } break; case Key.Return: - if (container != null && Keyboard.Modifiers == ModifierKeys.None && this.SelectedItems.Count == 1 && this.SelectedItem == container.Node) { + if (container != null && Keyboard.Modifiers == ModifierKeys.None && this.SelectedItems.Count == 1 && this.SelectedItem == container.Node) + { e.Handled = true; container.Node.ActivateItem(e); } break; case Key.Space: - if (container != null && Keyboard.Modifiers == ModifierKeys.None && this.SelectedItems.Count == 1 && this.SelectedItem == container.Node) { + if (container != null && Keyboard.Modifiers == ModifierKeys.None && this.SelectedItems.Count == 1 && this.SelectedItem == container.Node) + { e.Handled = true; - if (container.Node.IsCheckable) { + if (container.Node.IsCheckable) + { if (container.Node.IsChecked == null) // If partially selected, we want to select everything container.Node.IsChecked = true; else container.Node.IsChecked = !container.Node.IsChecked; - } else { + } + else + { container.Node.ActivateItem(e); } } break; case Key.Add: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { + if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) + { container.Node.IsExpanded = true; e.Handled = true; } break; case Key.Subtract: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { + if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) + { container.Node.IsExpanded = false; e.Handled = true; } break; case Key.Multiply: - if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { + if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) + { container.Node.IsExpanded = true; ExpandRecursively(container.Node); e.Handled = true; } break; case Key.Back: - if (IsTextSearchEnabled) { + if (IsTextSearchEnabled) + { var instance = SharpTreeViewTextSearch.GetInstance(this); - if (instance != null) { + if (instance != null) + { instance.RevertLastCharacter(); e.Handled = true; } @@ -333,9 +363,11 @@ namespace ICSharpCode.TreeView protected override void OnTextInput(TextCompositionEventArgs e) { - if (!string.IsNullOrEmpty(e.Text) && IsTextSearchEnabled && (e.OriginalSource == this || ItemsControl.ItemsControlFromItemContainer(e.OriginalSource as DependencyObject) == this)) { + if (!string.IsNullOrEmpty(e.Text) && IsTextSearchEnabled && (e.OriginalSource == this || ItemsControl.ItemsControlFromItemContainer(e.OriginalSource as DependencyObject) == this)) + { var instance = SharpTreeViewTextSearch.GetInstance(this); - if (instance != null) { + if (instance != null) + { instance.Search(e.Text); e.Handled = true; } @@ -346,14 +378,16 @@ namespace ICSharpCode.TreeView void ExpandRecursively(SharpTreeNode node) { - if (node.CanExpandRecursively) { + if (node.CanExpandRecursively) + { node.IsExpanded = true; - foreach (SharpTreeNode child in node.Children) { + foreach (SharpTreeNode child in node.Children) + { ExpandRecursively(child); } } } - + /// /// Scrolls the specified node in view and sets keyboard focus on it. /// @@ -363,13 +397,16 @@ namespace ICSharpCode.TreeView throw new ArgumentNullException("node"); ScrollIntoView(node); // WPF's ScrollIntoView() uses the same if/dispatcher construct, so we call OnFocusItem() after the item was brought into view. - if (this.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) { + if (this.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) + { OnFocusItem(node); - } else { + } + else + { this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(this.OnFocusItem), node); } } - + public void ScrollIntoView(SharpTreeNode node) { if (node == null) @@ -380,11 +417,12 @@ namespace ICSharpCode.TreeView doNotScrollOnExpanding = false; base.ScrollIntoView(node); } - + object OnFocusItem(object item) { FrameworkElement element = this.ItemContainerGenerator.ContainerFromItem(item) as FrameworkElement; - if (element != null) { + if (element != null) + { element.Focus(); } return null; @@ -398,17 +436,19 @@ namespace ICSharpCode.TreeView protected override void OnSelectionChanged(SelectionChangedEventArgs e) { - foreach (SharpTreeNode node in e.RemovedItems) { + foreach (SharpTreeNode node in e.RemovedItems) + { node.IsSelected = false; } - foreach (SharpTreeNode node in e.AddedItems) { + foreach (SharpTreeNode node in e.AddedItems) + { node.IsSelected = true; } base.OnSelectionChanged(e); } - + #endregion - + #region Drag and Drop protected override void OnDragEnter(DragEventArgs e) { @@ -418,8 +458,9 @@ namespace ICSharpCode.TreeView protected override void OnDragOver(DragEventArgs e) { e.Effects = DragDropEffects.None; - - if (Root != null && !ShowRoot) { + + if (Root != null && !ShowRoot) + { e.Handled = true; Root.CanDrop(e, Root.Children.Count); } @@ -429,7 +470,8 @@ namespace ICSharpCode.TreeView { e.Effects = DragDropEffects.None; - if (Root != null && !ShowRoot) { + if (Root != null && !ShowRoot) + { e.Handled = true; Root.InternalDrop(e, Root.Children.Count); } @@ -445,7 +487,8 @@ namespace ICSharpCode.TreeView HidePreview(); var target = GetDropTarget(item, e); - if (target != null) { + if (target != null) + { e.Handled = true; ShowPreview(target.Item, target.Place); } @@ -453,15 +496,19 @@ namespace ICSharpCode.TreeView internal void HandleDrop(SharpTreeViewItem item, DragEventArgs e) { - try { + try + { HidePreview(); var target = GetDropTarget(item, e); - if (target != null) { + if (target != null) + { e.Handled = true; target.Node.InternalDrop(e, target.Index); } - } catch (Exception ex) { + } + catch (Exception ex) + { Debug.WriteLine(ex.ToString()); throw; } @@ -486,8 +533,10 @@ namespace ICSharpCode.TreeView { var dropTargets = BuildDropTargets(item, e); var y = e.GetPosition(item).Y; - foreach (var target in dropTargets) { - if (target.Y >= y) { + foreach (var target in dropTargets) + { + if (target.Y >= y) + { return target; } } @@ -499,18 +548,22 @@ namespace ICSharpCode.TreeView var result = new List(); var node = item.Node; - if (AllowDropOrder) { + if (AllowDropOrder) + { TryAddDropTarget(result, item, DropPlace.Before, e); } TryAddDropTarget(result, item, DropPlace.Inside, e); - if (AllowDropOrder) { - if (node.IsExpanded && node.Children.Count > 0) { + if (AllowDropOrder) + { + if (node.IsExpanded && node.Children.Count > 0) + { var firstChildItem = ItemContainerGenerator.ContainerFromItem(node.Children[0]) as SharpTreeViewItem; TryAddDropTarget(result, firstChildItem, DropPlace.Before, e); } - else { + else + { TryAddDropTarget(result, item, DropPlace.After, e); } } @@ -520,24 +573,30 @@ namespace ICSharpCode.TreeView var y2 = h / 2; var y3 = h - y1; - if (result.Count == 2) { + if (result.Count == 2) + { if (result[0].Place == DropPlace.Inside && - result[1].Place != DropPlace.Inside) { + result[1].Place != DropPlace.Inside) + { result[0].Y = y3; } else if (result[0].Place != DropPlace.Inside && - result[1].Place == DropPlace.Inside) { + result[1].Place == DropPlace.Inside) + { result[0].Y = y1; } - else { + else + { result[0].Y = y2; } } - else if (result.Count == 3) { + else if (result.Count == 3) + { result[0].Y = y1; result[1].Y = y3; } - if (result.Count > 0) { + if (result.Count > 0) + { result[result.Count - 1].Y = h; } return result; @@ -550,9 +609,11 @@ namespace ICSharpCode.TreeView GetNodeAndIndex(item, place, out node, out index); - if (node != null) { + if (node != null) + { e.Effects = DragDropEffects.None; - if (node.CanDrop(e, index)) { + if (node.CanDrop(e, index)) + { DropTarget target = new DropTarget() { Item = item, Place = place, @@ -569,18 +630,23 @@ namespace ICSharpCode.TreeView node = null; index = 0; - if (place == DropPlace.Inside) { + if (place == DropPlace.Inside) + { node = item.Node; index = node.Children.Count; } - else if (place == DropPlace.Before) { - if (item.Node.Parent != null) { + else if (place == DropPlace.Before) + { + if (item.Node.Parent != null) + { node = item.Node.Parent; index = node.Children.IndexOf(item.Node); } } - else { - if (item.Node.Parent != null) { + else + { + if (item.Node.Parent != null) + { node = item.Node.Parent; index = node.Children.IndexOf(item.Node) + 1; } @@ -601,12 +667,15 @@ namespace ICSharpCode.TreeView previewNodeView = item.NodeView; previewPlace = place; - if (place == DropPlace.Inside) { + if (place == DropPlace.Inside) + { previewNodeView.TextBackground = SystemColors.HighlightBrush; previewNodeView.Foreground = SystemColors.HighlightTextBrush; } - else { - if (insertMarker == null) { + else + { + if (insertMarker == null) + { var adornerLayer = AdornerLayer.GetAdornerLayer(this); var adorner = new GeneralAdorner(this); insertMarker = new InsertMarker(); @@ -619,27 +688,32 @@ namespace ICSharpCode.TreeView var p1 = previewNodeView.TransformToVisual(this).Transform(new Point()); var p = new Point(p1.X + previewNodeView.CalculateIndent() + 4.5, p1.Y - 3); - if (place == DropPlace.After) { + if (place == DropPlace.After) + { p.Y += previewNodeView.ActualHeight; } insertMarker.Margin = new Thickness(p.X, p.Y, 0, 0); - + SharpTreeNodeView secondNodeView = null; var index = flattener.IndexOf(item.Node); - if (place == DropPlace.Before) { - if (index > 0) { + if (place == DropPlace.Before) + { + if (index > 0) + { secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index - 1) as SharpTreeViewItem).NodeView; } } - else if (index + 1 < flattener.Count) { + else if (index + 1 < flattener.Count) + { secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index + 1) as SharpTreeViewItem).NodeView; } - + var w = p1.X + previewNodeView.ActualWidth - p.X; - if (secondNodeView != null) { + if (secondNodeView != null) + { var p2 = secondNodeView.TransformToVisual(this).Transform(new Point()); w = Math.Max(w, p2.X + secondNodeView.ActualWidth - p.X); } @@ -650,37 +724,39 @@ namespace ICSharpCode.TreeView void HidePreview() { - if (previewNodeView != null) { + if (previewNodeView != null) + { previewNodeView.ClearValue(SharpTreeNodeView.TextBackgroundProperty); previewNodeView.ClearValue(SharpTreeNodeView.ForegroundProperty); - if (insertMarker != null) { + if (insertMarker != null) + { insertMarker.Visibility = Visibility.Collapsed; } previewNodeView = null; } } #endregion - + #region Cut / Copy / Paste / Delete Commands static void RegisterCommands() { CommandManager.RegisterClassCommandBinding(typeof(SharpTreeView), - new CommandBinding(ApplicationCommands.Cut, HandleExecuted_Cut, HandleCanExecute_Cut)); + new CommandBinding(ApplicationCommands.Cut, HandleExecuted_Cut, HandleCanExecute_Cut)); CommandManager.RegisterClassCommandBinding(typeof(SharpTreeView), - new CommandBinding(ApplicationCommands.Copy, HandleExecuted_Copy, HandleCanExecute_Copy)); + new CommandBinding(ApplicationCommands.Copy, HandleExecuted_Copy, HandleCanExecute_Copy)); CommandManager.RegisterClassCommandBinding(typeof(SharpTreeView), - new CommandBinding(ApplicationCommands.Paste, HandleExecuted_Paste, HandleCanExecute_Paste)); + new CommandBinding(ApplicationCommands.Paste, HandleExecuted_Paste, HandleCanExecute_Paste)); CommandManager.RegisterClassCommandBinding(typeof(SharpTreeView), - new CommandBinding(ApplicationCommands.Delete, HandleExecuted_Delete, HandleCanExecute_Delete)); + new CommandBinding(ApplicationCommands.Delete, HandleExecuted_Delete, HandleCanExecute_Delete)); } static void HandleExecuted_Cut(object sender, ExecutedRoutedEventArgs e) { - + } static void HandleCanExecute_Cut(object sender, CanExecuteRoutedEventArgs e) @@ -690,7 +766,7 @@ namespace ICSharpCode.TreeView static void HandleExecuted_Copy(object sender, ExecutedRoutedEventArgs e) { - + } static void HandleCanExecute_Copy(object sender, CanExecuteRoutedEventArgs e) @@ -700,7 +776,7 @@ namespace ICSharpCode.TreeView static void HandleExecuted_Paste(object sender, ExecutedRoutedEventArgs e) { - + } static void HandleCanExecute_Paste(object sender, CanExecuteRoutedEventArgs e) @@ -713,13 +789,17 @@ namespace ICSharpCode.TreeView SharpTreeView treeView = (SharpTreeView)sender; treeView.updatesLocked = true; int selectedIndex = -1; - try { - foreach (SharpTreeNode node in treeView.GetTopLevelSelection().ToArray()) { + try + { + foreach (SharpTreeNode node in treeView.GetTopLevelSelection().ToArray()) + { if (selectedIndex == -1) selectedIndex = treeView.flattener.IndexOf(node); node.Delete(); } - } finally { + } + finally + { treeView.updatesLocked = false; treeView.UpdateFocusedNode(null, Math.Max(0, selectedIndex - 1)); } @@ -730,7 +810,7 @@ namespace ICSharpCode.TreeView SharpTreeView treeView = (SharpTreeView)sender; e.CanExecute = treeView.GetTopLevelSelection().All(node => node.CanDelete()); } - + /// /// Gets the selected items which do not have any of their ancestors selected. /// diff --git a/SharpTreeView/SharpTreeViewAutomationPeer.cs b/SharpTreeView/SharpTreeViewAutomationPeer.cs index 11574bb0c..0f8967b03 100644 --- a/SharpTreeView/SharpTreeViewAutomationPeer.cs +++ b/SharpTreeView/SharpTreeViewAutomationPeer.cs @@ -22,7 +22,7 @@ namespace ICSharpCode.TreeView { class SharpTreeViewAutomationPeer : FrameworkElementAutomationPeer { - internal SharpTreeViewAutomationPeer(SharpTreeView owner ): base(owner) + internal SharpTreeViewAutomationPeer(SharpTreeView owner) : base(owner) { } diff --git a/SharpTreeView/SharpTreeViewItem.cs b/SharpTreeView/SharpTreeViewItem.cs index dc6e85964..6785b1f85 100644 --- a/SharpTreeView/SharpTreeViewItem.cs +++ b/SharpTreeView/SharpTreeViewItem.cs @@ -18,8 +18,8 @@ using System; using System.Linq; -using System.Windows.Controls; using System.Windows; +using System.Windows.Controls; using System.Windows.Input; namespace ICSharpCode.TreeView @@ -29,11 +29,10 @@ namespace ICSharpCode.TreeView static SharpTreeViewItem() { DefaultStyleKeyProperty.OverrideMetadata(typeof(SharpTreeViewItem), - new FrameworkPropertyMetadata(typeof(SharpTreeViewItem))); + new FrameworkPropertyMetadata(typeof(SharpTreeViewItem))); } - public SharpTreeNode Node - { + public SharpTreeNode Node { get { return DataContext as SharpTreeNode; } } @@ -42,15 +41,18 @@ namespace ICSharpCode.TreeView protected override void OnKeyDown(KeyEventArgs e) { - switch (e.Key) { + switch (e.Key) + { case Key.F2: - if (Node.IsEditable && ParentTreeView != null && ParentTreeView.SelectedItems.Count == 1 && ParentTreeView.SelectedItems[0] == Node) { + if (Node.IsEditable && ParentTreeView != null && ParentTreeView.SelectedItems.Count == 1 && ParentTreeView.SelectedItems[0] == Node) + { Node.IsEditing = true; e.Handled = true; } break; case Key.Escape: - if (Node.IsEditing) { + if (Node.IsEditing) + { Node.IsEditing = false; e.Handled = true; } @@ -72,15 +74,18 @@ namespace ICSharpCode.TreeView protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { wasSelected = IsSelected; - if (!IsSelected) { + if (!IsSelected) + { base.OnMouseLeftButtonDown(e); } - if (Mouse.LeftButton == MouseButtonState.Pressed) { + if (Mouse.LeftButton == MouseButtonState.Pressed) + { startPoint = e.GetPosition(null); CaptureMouse(); - if (e.ClickCount == 2) { + if (e.ClickCount == 2) + { wasDoubleClick = true; } } @@ -88,13 +93,16 @@ namespace ICSharpCode.TreeView protected override void OnMouseMove(MouseEventArgs e) { - if (IsMouseCaptured) { + if (IsMouseCaptured) + { var currentPoint = e.GetPosition(null); if (Math.Abs(currentPoint.X - startPoint.X) >= SystemParameters.MinimumHorizontalDragDistance || - Math.Abs(currentPoint.Y - startPoint.Y) >= SystemParameters.MinimumVerticalDragDistance) { + Math.Abs(currentPoint.Y - startPoint.Y) >= SystemParameters.MinimumVerticalDragDistance) + { var selection = ParentTreeView.GetTopLevelSelection().ToArray(); - if (Node.CanDrag(selection)) { + if (Node.CanDrag(selection)) + { Node.StartDrag(this, selection); } } @@ -103,27 +111,34 @@ namespace ICSharpCode.TreeView protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) { - if (wasDoubleClick) { + if (wasDoubleClick) + { wasDoubleClick = false; Node.ActivateItem(e); - if (!e.Handled) { - if (!Node.IsRoot || ParentTreeView.ShowRootExpander) { + if (!e.Handled) + { + if (!Node.IsRoot || ParentTreeView.ShowRootExpander) + { Node.IsExpanded = !Node.IsExpanded; } } } - + ReleaseMouseCapture(); - if (wasSelected) { + if (wasSelected) + { base.OnMouseLeftButtonDown(e); } } protected override void OnMouseUp(MouseButtonEventArgs e) { - if (e.ChangedButton == MouseButton.Middle) { + if (e.ChangedButton == MouseButton.Middle) + { Node.ActivateItemSecondary(e); - } else { + } + else + { base.OnMouseUp(e); } } diff --git a/SharpTreeView/SharpTreeViewItemAutomationPeer.cs b/SharpTreeView/SharpTreeViewItemAutomationPeer.cs index b0f3591c3..174f5b0cc 100644 --- a/SharpTreeView/SharpTreeViewItemAutomationPeer.cs +++ b/SharpTreeView/SharpTreeViewItemAutomationPeer.cs @@ -24,18 +24,19 @@ using System.Windows.Automation.Provider; namespace ICSharpCode.TreeView { - class SharpTreeViewItemAutomationPeer : FrameworkElementAutomationPeer, IExpandCollapseProvider + class SharpTreeViewItemAutomationPeer : FrameworkElementAutomationPeer, IExpandCollapseProvider { internal SharpTreeViewItemAutomationPeer(SharpTreeViewItem owner) : base(owner) { SharpTreeViewItem.DataContextChanged += OnDataContextChanged; SharpTreeNode node = SharpTreeViewItem.DataContext as SharpTreeNode; - if (node == null) return; - + if (node == null) + return; + node.PropertyChanged += OnPropertyChanged; } - private SharpTreeViewItem SharpTreeViewItem { get { return (SharpTreeViewItem)base.Owner; } } + private SharpTreeViewItem SharpTreeViewItem { get { return (SharpTreeViewItem)base.Owner; } } protected override AutomationControlType GetAutomationControlTypeCore() { return AutomationControlType.TreeItem; @@ -47,7 +48,7 @@ namespace ICSharpCode.TreeView return this; return base.GetPattern(patternInterface); } - + public void Collapse() { } @@ -64,12 +65,14 @@ namespace ICSharpCode.TreeView return node.IsExpanded ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed; } } - + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName != "IsExpanded") return; - SharpTreeNode node = sender as SharpTreeNode; - if (node == null || node.Children.Count == 0) return; + if (e.PropertyName != "IsExpanded") + return; + SharpTreeNode node = sender as SharpTreeNode; + if (node == null || node.Children.Count == 0) + return; bool newValue = node.IsExpanded; bool oldValue = !newValue; RaisePropertyChangedEvent( @@ -77,7 +80,7 @@ namespace ICSharpCode.TreeView oldValue ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed, newValue ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed); } - + private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { SharpTreeNode oldNode = e.OldValue as SharpTreeNode; diff --git a/SharpTreeView/SharpTreeViewTextSearch.cs b/SharpTreeView/SharpTreeViewTextSearch.cs index 5a660928e..32cf7cbef 100644 --- a/SharpTreeView/SharpTreeViewTextSearch.cs +++ b/SharpTreeView/SharpTreeViewTextSearch.cs @@ -58,7 +58,8 @@ namespace ICSharpCode.TreeView public static SharpTreeViewTextSearch GetInstance(SharpTreeView sharpTreeView) { var textSearch = (SharpTreeViewTextSearch)sharpTreeView.GetValue(TextSearchInstanceProperty); - if (textSearch == null) { + if (textSearch == null) + { textSearch = new SharpTreeViewTextSearch(sharpTreeView); sharpTreeView.SetValue(TextSearchInstancePropertyKey, textSearch); } @@ -79,19 +80,23 @@ namespace ICSharpCode.TreeView int startIndex = isActive ? lastMatchIndex : Math.Max(0, treeView.SelectedIndex); bool lookBackwards = inputStack.Count > 0 && string.Compare(inputStack.Peek(), nextChar, StringComparison.OrdinalIgnoreCase) == 0; int nextMatchIndex = IndexOfMatch(matchPrefix + nextChar, startIndex, lookBackwards, out bool wasNewCharUsed); - if (nextMatchIndex != -1) { - if (!isActive || nextMatchIndex != startIndex) { + if (nextMatchIndex != -1) + { + if (!isActive || nextMatchIndex != startIndex) + { treeView.SelectedItem = treeView.Items[nextMatchIndex]; treeView.FocusNode((SharpTreeNode)treeView.SelectedItem); lastMatchIndex = nextMatchIndex; } - if (wasNewCharUsed) { + if (wasNewCharUsed) + { matchPrefix += nextChar; inputStack.Push(nextChar); } isActive = true; } - if (isActive) { + if (isActive) + { ResetTimeout(); } return nextMatchIndex != -1; @@ -107,21 +112,29 @@ namespace ICSharpCode.TreeView bool fallbackMatch = false; int i = startIndex; var comparisonType = treeView.IsTextSearchCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase; - do { + do + { var item = (SharpTreeNode)treeView.Items[i]; - if (item != null && item.Text != null) { + if (item != null && item.Text != null) + { string text = item.Text.ToString(); - if (text.StartsWith(needle, comparisonType)) { + if (text.StartsWith(needle, comparisonType)) + { charWasUsed = true; index = i; break; } - if (tryBackward) { - if (fallbackMatch && matchPrefix != string.Empty) { - if (fallbackIndex == -1 && text.StartsWith(matchPrefix, comparisonType)) { + if (tryBackward) + { + if (fallbackMatch && matchPrefix != string.Empty) + { + if (fallbackIndex == -1 && text.StartsWith(matchPrefix, comparisonType)) + { fallbackIndex = i; } - } else { + } + else + { fallbackMatch = true; } } @@ -145,10 +158,13 @@ namespace ICSharpCode.TreeView void ResetTimeout() { - if (timer == null) { + if (timer == null) + { timer = new DispatcherTimer(DispatcherPriority.Normal); timer.Tick += (sender, e) => ClearState(); - } else { + } + else + { timer.Stop(); } timer.Interval = TimeSpan.FromMilliseconds(GetDoubleClickTime() * 2); diff --git a/SharpTreeView/TreeFlattener.cs b/SharpTreeView/TreeFlattener.cs index 8206a811b..eb23fbcfb 100644 --- a/SharpTreeView/TreeFlattener.cs +++ b/SharpTreeView/TreeFlattener.cs @@ -33,7 +33,7 @@ namespace ICSharpCode.TreeView internal SharpTreeNode root; readonly bool includeRoot; readonly object syncRoot = new object(); - + public TreeFlattener(SharpTreeNode modelRoot, bool includeRoot) { this.root = modelRoot; @@ -44,35 +44,39 @@ namespace ICSharpCode.TreeView } public event NotifyCollectionChangedEventHandler CollectionChanged; - + public void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e) { if (CollectionChanged != null) CollectionChanged(this, e); } - + public void NodesInserted(int index, IEnumerable nodes) { - if (!includeRoot) index--; - foreach (SharpTreeNode node in nodes) { + if (!includeRoot) + index--; + foreach (SharpTreeNode node in nodes) + { RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, node, index++)); } } - + public void NodesRemoved(int index, IEnumerable nodes) { - if (!includeRoot) index--; - foreach (SharpTreeNode node in nodes) { + if (!includeRoot) + index--; + foreach (SharpTreeNode node in nodes) + { RaiseCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, node, index)); } } - + public void Stop() { Debug.Assert(root.treeFlattener == this); root.treeFlattener = null; } - + public object this[int index] { get { if (index < 0 || index >= this.Count) @@ -83,83 +87,87 @@ namespace ICSharpCode.TreeView throw new NotSupportedException(); } } - + public int Count { get { return includeRoot ? root.GetTotalListLength() : root.GetTotalListLength() - 1; } } - + public int IndexOf(object item) { SharpTreeNode node = item as SharpTreeNode; - if (node != null && node.IsVisible && node.GetListRoot() == root) { + if (node != null && node.IsVisible && node.GetListRoot() == root) + { if (includeRoot) return SharpTreeNode.GetVisibleIndexForNode(node); else return SharpTreeNode.GetVisibleIndexForNode(node) - 1; - } else { + } + else + { return -1; } } - + bool IList.IsReadOnly { get { return true; } } - + bool IList.IsFixedSize { get { return false; } } - + bool ICollection.IsSynchronized { get { return false; } } - + object ICollection.SyncRoot { get { return syncRoot; } } - + void IList.Insert(int index, object item) { throw new NotSupportedException(); } - + void IList.RemoveAt(int index) { throw new NotSupportedException(); } - + int IList.Add(object item) { throw new NotSupportedException(); } - + void IList.Clear() { throw new NotSupportedException(); } - + public bool Contains(object item) { return IndexOf(item) >= 0; } - + public void CopyTo(Array array, int arrayIndex) { foreach (object item in this) array.SetValue(item, arrayIndex++); } - + void IList.Remove(object item) { throw new NotSupportedException(); } - + public IEnumerator GetEnumerator() { - for (int i = 0; i < this.Count; i++) { + for (int i = 0; i < this.Count; i++) + { yield return this[i]; } } diff --git a/SharpTreeView/TreeTraversal.cs b/SharpTreeView/TreeTraversal.cs index aafe25cce..ef196a61d 100644 --- a/SharpTreeView/TreeTraversal.cs +++ b/SharpTreeView/TreeTraversal.cs @@ -36,7 +36,7 @@ namespace ICSharpCode.TreeView { return PreOrder(new T[] { root }, recursion); } - + /// /// Converts a tree data structure into a flat list by traversing it in pre-order. /// @@ -46,21 +46,28 @@ namespace ICSharpCode.TreeView public static IEnumerable PreOrder(IEnumerable input, Func> recursion) { Stack> stack = new Stack>(); - try { + try + { stack.Push(input.GetEnumerator()); - while (stack.Count > 0) { - while (stack.Peek().MoveNext()) { + while (stack.Count > 0) + { + while (stack.Peek().MoveNext()) + { T element = stack.Peek().Current; yield return element; IEnumerable children = recursion(element); - if (children != null) { + if (children != null) + { stack.Push(children.GetEnumerator()); } } stack.Pop().Dispose(); } - } finally { - while (stack.Count > 0) { + } + finally + { + while (stack.Count > 0) + { stack.Pop().Dispose(); } } diff --git a/TestPlugin/ContextMenuCommand.cs b/TestPlugin/ContextMenuCommand.cs index d312acd12..6bbf3475b 100644 --- a/TestPlugin/ContextMenuCommand.cs +++ b/TestPlugin/ContextMenuCommand.cs @@ -2,8 +2,10 @@ // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System.Linq; + using ICSharpCode.ILSpy; using ICSharpCode.ILSpy.TreeNodes; + using Microsoft.Win32; namespace TestPlugin @@ -15,19 +17,20 @@ namespace TestPlugin { return context.SelectedTreeNodes != null && context.SelectedTreeNodes.All(n => n is AssemblyTreeNode); } - + public bool IsEnabled(TextViewContext context) { return context.SelectedTreeNodes != null && context.SelectedTreeNodes.Length == 1; } - + public void Execute(TextViewContext context) { if (context.SelectedTreeNodes == null) return; AssemblyTreeNode node = (AssemblyTreeNode)context.SelectedTreeNodes[0]; var asm = node.LoadedAssembly.GetPEFileOrNull(); - if (asm != null) { + if (asm != null) + { /*SaveFileDialog dlg = new SaveFileDialog(); dlg.FileName = node.LoadedAssembly.FileName; dlg.Filter = "Assembly|*.dll;*.exe"; diff --git a/TestPlugin/CustomLanguage.cs b/TestPlugin/CustomLanguage.cs index b0405cbf9..4914edc26 100644 --- a/TestPlugin/CustomLanguage.cs +++ b/TestPlugin/CustomLanguage.cs @@ -4,6 +4,7 @@ using System.ComponentModel.Composition; using System.Reflection.Metadata; using System.Windows.Controls; + using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; @@ -22,7 +23,7 @@ namespace TestPlugin return "Custom"; } } - + public override string FileExtension { get { // used in 'Save As' dialog @@ -35,12 +36,14 @@ namespace TestPlugin { var module = ((MetadataModule)method.ParentModule).PEFile; var methodDef = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); - if (methodDef.HasBody()) { + if (methodDef.HasBody()) + { var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); output.WriteLine("Size of method: {0} bytes", methodBody.GetCodeSize()); - + ISmartTextOutput smartOutput = output as ISmartTextOutput; - if (smartOutput != null) { + if (smartOutput != null) + { // when writing to the text view (but not when writing to a file), we can even add UI elements such as buttons: smartOutput.AddButton(null, "Click me!", (sender, e) => (sender as Button).Content = "I was clicked!"); smartOutput.WriteLine(); diff --git a/TestPlugin/CustomOptionPage.xaml.cs b/TestPlugin/CustomOptionPage.xaml.cs index ad675a6f9..3e252aaa3 100644 --- a/TestPlugin/CustomOptionPage.xaml.cs +++ b/TestPlugin/CustomOptionPage.xaml.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Windows.Controls; using System.Xml.Linq; + using ICSharpCode.ILSpy; using ICSharpCode.ILSpy.Options; @@ -13,12 +14,12 @@ namespace TestPlugin partial class CustomOptionPage : UserControl, IOptionPage { static readonly XNamespace ns = "http://www.ilspy.net/testplugin"; - + public CustomOptionPage() { InitializeComponent(); } - + public void Load(ILSpySettings settings) { // For loading options, use ILSpySetting's indexer. @@ -43,7 +44,7 @@ namespace TestPlugin XElement section = new XElement(ns + "CustomOptions"); section.SetAttributeValue("useless1", s.UselessOption1); section.SetAttributeValue("useless2", s.UselessOption2); - + // Replace the existing section in the settings file, or add a new section, // if required. XElement existingElement = root.Element(ns + "CustomOptions"); @@ -53,38 +54,41 @@ namespace TestPlugin root.Add(section); } } - + class Options : INotifyPropertyChanged { bool uselessOption1; - + public bool UselessOption1 { get { return uselessOption1; } set { - if (uselessOption1 != value) { + if (uselessOption1 != value) + { uselessOption1 = value; OnPropertyChanged("UselessOption1"); } } } - + double uselessOption2; - + public double UselessOption2 { get { return uselessOption2; } set { - if (uselessOption2 != value) { + if (uselessOption2 != value) + { uselessOption2 = value; OnPropertyChanged("UselessOption2"); } } } - + public event PropertyChangedEventHandler PropertyChanged; - + protected virtual void OnPropertyChanged(string propertyName) { - if (PropertyChanged != null) { + if (PropertyChanged != null) + { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } diff --git a/TestPlugin/MainMenuCommand.cs b/TestPlugin/MainMenuCommand.cs index 3a563ff33..2a83f7c63 100644 --- a/TestPlugin/MainMenuCommand.cs +++ b/TestPlugin/MainMenuCommand.cs @@ -20,7 +20,8 @@ namespace TestPlugin { public override void Execute(object parameter) { - foreach (var loadedAssembly in MainWindow.Instance.CurrentAssemblyList.GetAssemblies()) { + foreach (var loadedAssembly in MainWindow.Instance.CurrentAssemblyList.GetAssemblies()) + { loadedAssembly.AssemblyList.Unload(loadedAssembly); } }