From e43f6abcf01ee980402f91cb0f228105a6be4481 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Tue, 3 May 2011 02:34:33 +1000 Subject: [PATCH 01/65] Analyzer - Limit scope of overrides search --- .../AnalyzedEventOverridesTreeNode.cs | 33 ++++------ .../AnalyzedMethodOverridesTreeNode.cs | 51 ++++++--------- .../AnalyzedPropertyOverridesTreeNode.cs | 40 ++++-------- .../Analyzer/ScopedWhereUsedAnalyzer.cs | 65 +++++++++++++------ 4 files changed, 85 insertions(+), 104 deletions(-) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs index 113ffd029..fef82644d 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs @@ -68,36 +68,25 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct); - } - - private IEnumerable FindReferences(IEnumerable assemblies, CancellationToken ct) - { - assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null); + ScopedWhereUsedScopeAnalyzer analyzer; - // use parallelism only on the assembly level (avoid locks within Cecil) - return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct)); + analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedEvent, FindReferencesInType); + return analyzer.PerformAnalysis(ct); } - private IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) + private IEnumerable FindReferencesInType(TypeDefinition type) { - string asmName = asm.AssemblyDefinition.Name.Name; string name = analyzedEvent.Name; string declTypeName = analyzedEvent.DeclaringType.FullName; - foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) { - ct.ThrowIfCancellationRequested(); - - if (!TypesHierarchyHelpers.IsBaseType(analyzedEvent.DeclaringType, type, resolveTypeArguments: false)) - continue; - foreach (EventDefinition eventDef in type.Events) { - ct.ThrowIfCancellationRequested(); + if (!TypesHierarchyHelpers.IsBaseType(analyzedEvent.DeclaringType, type, resolveTypeArguments: false)) + yield break; - if (TypesHierarchyHelpers.IsBaseEvent(analyzedEvent, eventDef)) { - MethodDefinition anyAccessor = eventDef.AddMethod ?? eventDef.RemoveMethod; - bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; - yield return new AnalyzedEventTreeNode(eventDef, hidesParent ? "(hides) " : ""); - } + foreach (EventDefinition eventDef in type.Events) { + if (TypesHierarchyHelpers.IsBaseEvent(analyzedEvent, eventDef)) { + MethodDefinition anyAccessor = eventDef.AddMethod ?? eventDef.RemoveMethod; + bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; + yield return new AnalyzedEventTreeNode(eventDef, hidesParent ? "(hides) " : ""); } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs index f8f891d2d..7ddb0178e 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs @@ -73,45 +73,32 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct); - } - - private IEnumerable FindReferences(IEnumerable assemblies, CancellationToken ct) - { - assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null); + ScopedWhereUsedScopeAnalyzer analyzer; - // use parallelism only on the assembly level (avoid locks within Cecil) - return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct)); + analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); + return analyzer.PerformAnalysis(ct); } - private IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) + private IEnumerable FindReferencesInType(TypeDefinition type) { - string asmName = asm.AssemblyDefinition.Name.Name; - string name = analyzedMethod.Name; - string declTypeName = analyzedMethod.DeclaringType.FullName; - foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) { - ct.ThrowIfCancellationRequested(); - SharpTreeNode newNode = null; - try { - if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false)) - continue; - - foreach (MethodDefinition method in type.Methods) { - ct.ThrowIfCancellationRequested(); - - if (TypesHierarchyHelpers.IsBaseMethod(analyzedMethod, method)) { - bool hidesParent = !method.IsVirtual ^ method.IsNewSlot; - newNode = new AnalyzedMethodTreeNode(method, hidesParent ? "(hides) " : ""); - } + SharpTreeNode newNode = null; + try { + if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false)) + yield break; + + foreach (MethodDefinition method in type.Methods) { + if (TypesHierarchyHelpers.IsBaseMethod(analyzedMethod, method)) { + bool hidesParent = !method.IsVirtual ^ method.IsNewSlot; + newNode = new AnalyzedMethodTreeNode(method, hidesParent ? "(hides) " : ""); } } - catch (ReferenceResolvingException) { - // ignore this type definition. maybe add a notification about such cases. - } - - if (newNode != null) - yield return newNode; } + catch (ReferenceResolvingException) { + // ignore this type definition. maybe add a notification about such cases. + } + + if (newNode != null) + yield return newNode; } public static bool CanShow(MethodDefinition method) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs index 440a54f6e..81efb1676 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs @@ -69,45 +69,27 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - return FindReferences(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), ct); - } - - private IEnumerable FindReferences(IEnumerable assemblies, CancellationToken ct) - { - assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null); + ScopedWhereUsedScopeAnalyzer analyzer; - // use parallelism only on the assembly level (avoid locks within Cecil) - return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct)); + analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedProperty, FindReferencesInType); + return analyzer.PerformAnalysis(ct); } - private IEnumerable FindReferences(LoadedAssembly asm, CancellationToken ct) + private IEnumerable FindReferencesInType(TypeDefinition type) { - string asmName = asm.AssemblyDefinition.Name.Name; string name = analyzedProperty.Name; string declTypeName = analyzedProperty.DeclaringType.FullName; - foreach (TypeDefinition type in TreeTraversal.PreOrder(asm.AssemblyDefinition.MainModule.Types, t => t.NestedTypes)) { - ct.ThrowIfCancellationRequested(); - SharpTreeNode newNode = null; - try { - if (!TypesHierarchyHelpers.IsBaseType(analyzedProperty.DeclaringType, type, resolveTypeArguments: false)) - continue; + if (!TypesHierarchyHelpers.IsBaseType(analyzedProperty.DeclaringType, type, resolveTypeArguments: false)) + yield break; - foreach (PropertyDefinition property in type.Properties) { - ct.ThrowIfCancellationRequested(); + foreach (PropertyDefinition property in type.Properties) { - if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) { - MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod; - bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; - newNode = new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : ""); - } - } - } - catch (ReferenceResolvingException) { - // ignore this type definition. + if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) { + MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod; + bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; + yield return new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : ""); } - if (newNode != null) - yield return newNode; } } diff --git a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs index 48eb21bc5..98942939f 100644 --- a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs +++ b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs @@ -47,27 +47,23 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer public ScopedWhereUsedScopeAnalyzer(MethodDefinition method, Func> typeAnalysisFunction) : this(method.DeclaringType, typeAnalysisFunction) { - switch (method.Attributes & MethodAttributes.MemberAccessMask) { - case MethodAttributes.Private: - default: - memberAccessibility = Accessibility.Private; - break; - case MethodAttributes.FamANDAssem: - memberAccessibility = Accessibility.FamilyAndInternal; - break; - case MethodAttributes.Family: - memberAccessibility = Accessibility.Family; - break; - case MethodAttributes.Assembly: - memberAccessibility = Accessibility.Internal; - break; - case MethodAttributes.FamORAssem: - memberAccessibility = Accessibility.FamilyOrInternal; - break; - case MethodAttributes.Public: - memberAccessibility = Accessibility.Public; - break; - } + this.memberAccessibility = GetMethodAccessibility(method); + } + + public ScopedWhereUsedScopeAnalyzer(PropertyDefinition property, Func> typeAnalysisFunction) + : this(property.DeclaringType, typeAnalysisFunction) + { + Accessibility getterAccessibility = (property.GetMethod == null) ? Accessibility.Private : GetMethodAccessibility(property.GetMethod); + Accessibility setterAccessibility = (property.SetMethod == null) ? Accessibility.Private : GetMethodAccessibility(property.SetMethod); + this.memberAccessibility = (Accessibility)Math.Max((int)getterAccessibility, (int)setterAccessibility); + } + + public ScopedWhereUsedScopeAnalyzer(EventDefinition eventDef, Func> typeAnalysisFunction) + : this(eventDef.DeclaringType, typeAnalysisFunction) + { + // we only have to check the accessibility of the the get method + // [CLS Rule 30: The accessibility of an event and of its accessors shall be identical.] + this.memberAccessibility = GetMethodAccessibility(eventDef.AddMethod); } public ScopedWhereUsedScopeAnalyzer(FieldDefinition field, Func> typeAnalysisFunction) @@ -96,6 +92,33 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } } + private Accessibility GetMethodAccessibility(MethodDefinition method) + { + Accessibility accessibility; + switch (method.Attributes & MethodAttributes.MemberAccessMask) { + case MethodAttributes.Private: + default: + accessibility = Accessibility.Private; + break; + case MethodAttributes.FamANDAssem: + accessibility = Accessibility.FamilyAndInternal; + break; + case MethodAttributes.Family: + accessibility = Accessibility.Family; + break; + case MethodAttributes.Assembly: + accessibility = Accessibility.Internal; + break; + case MethodAttributes.FamORAssem: + accessibility = Accessibility.FamilyOrInternal; + break; + case MethodAttributes.Public: + accessibility = Accessibility.Public; + break; + } + return accessibility; + } + public IEnumerable PerformAnalysis(CancellationToken ct) { if (memberAccessibility == Accessibility.Private) { From b408accceac0a912de9ee08638dc942054e62bce Mon Sep 17 00:00:00 2001 From: Ivan Hamilton Date: Thu, 5 May 2011 17:42:43 +1000 Subject: [PATCH 02/65] Fix local variable post-increment recognition for split local variables. --- .../ILAst/PeepholeTransform.cs | 61 +++++++++++++++---- .../Tests/IncrementDecrement.cs | 6 ++ 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs b/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs index 270b9f7d4..e4771eb48 100644 --- a/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs +++ b/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs @@ -440,6 +440,7 @@ namespace ICSharpCode.Decompiler.ILAst #endregion #region IntroducePostIncrement + bool IntroducePostIncrement(List body, ILExpression expr, int pos) { bool modified = IntroducePostIncrementForVariables(body, expr, pos); @@ -452,6 +453,13 @@ namespace ICSharpCode.Decompiler.ILAst } return modified; } + + private static IDictionary _postIncrementPairs = new Dictionary + { + {ILCode.Ldloc, ILCode.Stloc}, + {ILCode.Ldsfld, ILCode.Stsfld}, + {ILCode.CallGetter, ILCode.CallSetter} + }; bool IntroducePostIncrementForVariables(List body, ILExpression expr, int pos) { @@ -465,19 +473,40 @@ namespace ICSharpCode.Decompiler.ILAst ILExpression exprInit; if (!(expr.Match(ILCode.Stloc, out exprVar, out exprInit) && exprVar.IsGenerated)) return false; - if (!(exprInit.Code == ILCode.Ldloc || exprInit.Code == ILCode.Ldsfld || (exprInit.Code == ILCode.CallGetter && exprInit.Arguments.Count == 0))) + + ILCode loadInstruction = exprInit.Code; + //We only recognise local variables, fields & getters with no arguments + if (!_postIncrementPairs.ContainsKey(loadInstruction)) + return false; + if (loadInstruction == ILCode.CallGetter && exprInit.Arguments.Count != 0) return false; + //The next expression ILExpression nextExpr = body.ElementAtOrDefault(pos + 1) as ILExpression; if (nextExpr == null) return false; - if (exprInit.Code == ILCode.CallGetter) { - if (!(nextExpr.Code == ILCode.CallSetter && IsGetterSetterPair(exprInit.Operand, nextExpr.Operand))) - return false; - } else { - if (!(nextExpr.Code == (exprInit.Code == ILCode.Ldloc ? ILCode.Stloc : ILCode.Stsfld) && nextExpr.Operand == exprInit.Operand)) + ILCode storeInstruction = nextExpr.Code; + //Must be a matching store type + if (_postIncrementPairs[loadInstruction] != storeInstruction) + return false; + + object nextExprOperand = nextExpr.Operand; + object exprInitOperand = exprInit.Operand; + if (loadInstruction == ILCode.CallGetter) + if (!IsGetterSetterPair(exprInitOperand, nextExprOperand)) return false; - } + + if (loadInstruction == ILCode.Ldloc) + if ((nextExprOperand != exprInitOperand)) + if (((ILVariable) nextExprOperand).OriginalVariable == ((ILVariable) exprInitOperand).OriginalVariable) + //Spit local variable, unsplit these two instances + foreach (var ilExpression in body.SelectMany( + node => node.GetSelfAndChildrenRecursive( + expression => expression.Operand == nextExprOperand))) + ilExpression.Operand = exprInitOperand; + else + return false; + ILExpression addExpr = nextExpr.Arguments[0]; int incrementAmount; @@ -485,12 +514,18 @@ namespace ICSharpCode.Decompiler.ILAst if (!(incrementAmount != 0 && addExpr.Arguments[0].MatchLdloc(exprVar))) return false; - if (exprInit.Code == ILCode.Ldloc) - exprInit.Code = ILCode.Ldloca; - else if (exprInit.Code == ILCode.CallGetter) - exprInit = new ILExpression(ILCode.AddressOf, null, exprInit); - else - exprInit.Code = ILCode.Ldsflda; + switch (loadInstruction) + { + case ILCode.Ldloc: + exprInit.Code = ILCode.Ldloca; + break; + case ILCode.Ldsfld: + exprInit.Code = ILCode.Ldsflda; + break; + case ILCode.CallGetter: + exprInit = new ILExpression(ILCode.AddressOf, null, exprInit); + break; + } expr.Arguments[0] = new ILExpression(incrementCode, incrementAmount, exprInit); body.RemoveAt(pos + 1); // TODO ILRanges return true; diff --git a/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs b/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs index 02a72190f..12c47186d 100644 --- a/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs +++ b/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs @@ -176,6 +176,12 @@ public class IncrementDecrement return i++ + j; } + public void PostIncrementInlineLocalVariable(Func f) + { + int num = 0; + f(num++); + } + public int PostIncrementArrayElement(int[] array, int pos) { return array[pos]--; From e1ccd3586a7893f828166655fed21eb32f98ad64 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Sat, 7 May 2011 18:42:24 +1000 Subject: [PATCH 03/65] Analyzer: Limit search to assemblies with TypeRef to required type. --- .../Analyzer/ScopedWhereUsedAnalyzer.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs index 98942939f..6b741d6da 100644 --- a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs +++ b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs @@ -254,7 +254,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer break; } } - if (found) + if (found && AssemblyReferencesScopeType(assembly.AssemblyDefinition)) yield return assembly.AssemblyDefinition; } } @@ -278,12 +278,24 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (var assembly in assemblies) { ct.ThrowIfCancellationRequested(); - if (friendAssemblies.Contains(assembly.ShortName)) { + if (friendAssemblies.Contains(assembly.ShortName) && AssemblyReferencesScopeType(assembly.AssemblyDefinition)) { yield return assembly.AssemblyDefinition; } } } } } + + private bool AssemblyReferencesScopeType(AssemblyDefinition asm) + { + bool hasRef = false; + foreach (var typeref in asm.MainModule.GetTypeReferences()) { + if (typeref.Name == typeScope.Name && typeref.Namespace == typeScope.Namespace) { + hasRef = true; + break; + } + } + return hasRef; + } } } From 4e95f435a43d0e2e332f86280d7fbcfce47f931f Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Sat, 7 May 2011 18:45:56 +1000 Subject: [PATCH 04/65] Analyzer: Redirect result from compiler-generated type/method to original code location. --- ILSpy/CSharpLanguage.cs | 110 ++++++++++-------- ILSpy/Language.cs | 69 ++++++----- .../Analyzer/AnalyzedFieldAccessTreeNode.cs | 32 ++++- .../Analyzer/AnalyzedMethodUsedByTreeNode.cs | 37 ++++-- ILSpy/TreeNodes/Analyzer/Helpers.cs | 64 ++++++++++ 5 files changed, 226 insertions(+), 86 deletions(-) diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs index 8e6948e14..9f2c05c3a 100644 --- a/ILSpy/CSharpLanguage.cs +++ b/ILSpy/CSharpLanguage.cs @@ -46,12 +46,12 @@ namespace ICSharpCode.ILSpy string name = "C#"; bool showAllMembers = false; Predicate transformAbortCondition = null; - + public CSharpLanguage() { } - - #if DEBUG + +#if DEBUG internal static IEnumerable GetDebugLanguages() { DecompilerContext context = new DecompilerContext(ModuleDefinition.CreateModule("dummy", ModuleKind.Dll)); @@ -70,20 +70,23 @@ namespace ICSharpCode.ILSpy showAllMembers = true }; } - #endif - - public override string Name { +#endif + + public override string Name + { get { return name; } } - - public override string FileExtension { + + public override string FileExtension + { get { return ".cs"; } } - - public override string ProjectFileExtension { + + public override string ProjectFileExtension + { get { return ".csproj"; } } - + public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true)); @@ -92,7 +95,7 @@ namespace ICSharpCode.ILSpy codeDomBuilder.RunTransformations(transformAbortCondition); codeDomBuilder.GenerateCode(output); } - + public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(property.DeclaringType, includeNamespace: true)); @@ -101,7 +104,7 @@ namespace ICSharpCode.ILSpy codeDomBuilder.RunTransformations(transformAbortCondition); codeDomBuilder.GenerateCode(output); } - + public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true)); @@ -110,7 +113,7 @@ namespace ICSharpCode.ILSpy codeDomBuilder.RunTransformations(transformAbortCondition); codeDomBuilder.GenerateCode(output); } - + public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(ev.DeclaringType, includeNamespace: true)); @@ -119,7 +122,7 @@ namespace ICSharpCode.ILSpy codeDomBuilder.RunTransformations(transformAbortCondition); codeDomBuilder.GenerateCode(output); } - + public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options) { AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: type); @@ -127,7 +130,7 @@ namespace ICSharpCode.ILSpy codeDomBuilder.RunTransformations(transformAbortCondition); codeDomBuilder.GenerateCode(output); } - + public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { if (options.FullDecompilation && options.SaveAsProjectDirectory != null) { @@ -146,7 +149,7 @@ namespace ICSharpCode.ILSpy } } } - + #region WriteProjectFile void WriteProjectFile(TextWriter writer, IEnumerable> files, ModuleDefinition module) { @@ -174,20 +177,20 @@ namespace ICSharpCode.ILSpy w.WriteStartElement("Project", ns); w.WriteAttributeString("ToolsVersion", "4.0"); w.WriteAttributeString("DefaultTargets", "Build"); - + w.WriteStartElement("PropertyGroup"); w.WriteElementString("ProjectGuid", Guid.NewGuid().ToString().ToUpperInvariant()); - + w.WriteStartElement("Configuration"); w.WriteAttributeString("Condition", " '$(Configuration)' == '' "); w.WriteValue("Debug"); w.WriteEndElement(); // - + w.WriteStartElement("Platform"); w.WriteAttributeString("Condition", " '$(Platform)' == '' "); w.WriteValue(platformName); w.WriteEndElement(); // - + switch (module.Kind) { case ModuleKind.Windows: w.WriteElementString("OutputType", "WinExe"); @@ -199,7 +202,7 @@ namespace ICSharpCode.ILSpy w.WriteElementString("OutputType", "Library"); break; } - + w.WriteElementString("AssemblyName", module.Assembly.Name.Name); switch (module.Runtime) { case TargetRuntime.Net_1_0: @@ -218,14 +221,14 @@ namespace ICSharpCode.ILSpy break; } w.WriteElementString("WarningLevel", "4"); - + w.WriteEndElement(); // - + w.WriteStartElement("PropertyGroup"); // platform-specific w.WriteAttributeString("Condition", " '$(Platform)' == '" + platformName + "' "); w.WriteElementString("PlatformTarget", platformName); w.WriteEndElement(); // (platform-specific) - + w.WriteStartElement("PropertyGroup"); // Debug w.WriteAttributeString("Condition", " '$(Configuration)' == 'Debug' "); w.WriteElementString("OutputPath", "bin\\Debug\\"); @@ -233,7 +236,7 @@ namespace ICSharpCode.ILSpy w.WriteElementString("DebugType", "full"); w.WriteElementString("Optimize", "false"); w.WriteEndElement(); // (Debug) - + w.WriteStartElement("PropertyGroup"); // Release w.WriteAttributeString("Condition", " '$(Configuration)' == 'Release' "); w.WriteElementString("OutputPath", "bin\\Release\\"); @@ -241,8 +244,8 @@ namespace ICSharpCode.ILSpy w.WriteElementString("DebugType", "pdbonly"); w.WriteElementString("Optimize", "true"); w.WriteEndElement(); // (Release) - - + + w.WriteStartElement("ItemGroup"); // References foreach (AssemblyNameReference r in module.AssemblyReferences) { if (r.Name != "mscorlib") { @@ -253,7 +256,7 @@ namespace ICSharpCode.ILSpy } } w.WriteEndElement(); // (References) - + foreach (IGrouping gr in (from f in files group f.Item2 by f.Item1 into g orderby g.Key select g)) { w.WriteStartElement("ItemGroup"); foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)) { @@ -263,16 +266,16 @@ namespace ICSharpCode.ILSpy } w.WriteEndElement(); } - + w.WriteStartElement("Import"); w.WriteAttributeString("Project", "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"); w.WriteEndElement(); - + w.WriteEndDocument(); } } #endregion - + #region WriteCodeFilesInProject bool IncludeTypeWhenDecompilingProject(TypeDefinition type, DecompilationOptions options) { @@ -282,11 +285,11 @@ namespace ICSharpCode.ILSpy return false; return true; } - + IEnumerable> WriteCodeFilesInProject(AssemblyDefinition assembly, DecompilationOptions options, HashSet directories) { var files = assembly.MainModule.Types.Where(t => IncludeTypeWhenDecompilingProject(t, options)).GroupBy( - delegate (TypeDefinition type) { + delegate(TypeDefinition type) { string file = TextView.DecompilerTextView.CleanUpName(type.Name) + this.FileExtension; if (string.IsNullOrEmpty(type.Namespace)) { return file; @@ -301,7 +304,7 @@ namespace ICSharpCode.ILSpy Parallel.ForEach( files, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, - delegate (IGrouping file) { + delegate(IGrouping file) { using (StreamWriter w = new StreamWriter(Path.Combine(options.SaveAsProjectDirectory, file.Key))) { AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: assembly.MainModule); foreach (TypeDefinition type in file) { @@ -315,7 +318,7 @@ namespace ICSharpCode.ILSpy return files.Select(f => Tuple.Create("Compile", f.Key)); } #endregion - + #region WriteResourceFilesInProject IEnumerable> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet directories) { @@ -329,7 +332,8 @@ namespace ICSharpCode.ILSpy IEnumerable rs = null; try { rs = new ResourceSet(s).Cast(); - } catch (ArgumentException) { + } + catch (ArgumentException) { } if (rs != null && rs.All(e => e.Value is Stream)) { foreach (var pair in rs) { @@ -347,7 +351,8 @@ namespace ICSharpCode.ILSpy string xaml = null; try { xaml = decompiler.DecompileBaml(ms, assembly.FileName, new ConnectMethodDecompiler(assembly), new AssemblyResolver(assembly)); - } catch (XamlXmlWriterException) {} // ignore XAML writer exceptions + } + catch (XamlXmlWriterException) { } // ignore XAML writer exceptions if (xaml != null) { File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml); yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml")); @@ -368,12 +373,13 @@ namespace ICSharpCode.ILSpy } yield return Tuple.Create("EmbeddedResource", fileName); } - } finally { + } + finally { if (bamlDecompilerAppDomain != null) AppDomain.Unload(bamlDecompilerAppDomain); } } - + string GetFileNameForResource(string fullName, HashSet directories) { string[] splitName = fullName.Split('.'); @@ -389,7 +395,7 @@ namespace ICSharpCode.ILSpy return fileName; } #endregion - + AstBuilder CreateAstBuilder(DecompilationOptions options, ModuleDefinition currentModule = null, TypeDefinition currentType = null, bool isSingleMember = false) { if (currentModule == null) @@ -413,7 +419,7 @@ namespace ICSharpCode.ILSpy if (includeNamespace) options |= ConvertTypeOptions.IncludeNamespace; AstType astType = AstBuilder.ConvertType(type, typeAttributes, options); - + StringWriter w = new StringWriter(); if (type.IsByReference) { ParameterDefinition pd = typeAttributes as ParameterDefinition; @@ -421,11 +427,11 @@ namespace ICSharpCode.ILSpy w.Write("out "); else w.Write("ref "); - + if (astType is ComposedType && ((ComposedType)astType).PointerRank > 0) ((ComposedType)astType).PointerRank--; } - + astType.AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); return w.ToString(); } @@ -460,12 +466,20 @@ namespace ICSharpCode.ILSpy } else return property.Name; } - + public override bool ShowMember(MemberReference member) { return showAllMembers || !AstBuilder.MemberIsHidden(member, new DecompilationOptions().DecompilerSettings); } - + + public override MemberReference GetOriginalCodeLocation(MemberReference member) + { + if (showAllMembers || !DecompilerSettingsPanel.CurrentDecompilerSettings.AnonymousMethods) + return member; + else + return ICSharpCode.ILSpy.TreeNodes.Analyzer.Helpers.GetOriginalCodeLocation(member); + } + public override string GetTooltip(MemberReference member) { MethodDefinition md = member as MethodDefinition; @@ -486,12 +500,12 @@ namespace ICSharpCode.ILSpy b.RunTransformations(); foreach (var attribute in b.CompilationUnit.Descendants.OfType()) attribute.Remove(); - + StringWriter w = new StringWriter(); b.GenerateCode(new PlainTextOutput(w)); return Regex.Replace(w.ToString(), @"\s+", " ").TrimEnd(); } - + return base.GetTooltip(member); } } diff --git a/ILSpy/Language.cs b/ILSpy/Language.cs index 539de51c8..c29818621 100644 --- a/ILSpy/Language.cs +++ b/ILSpy/Language.cs @@ -35,66 +35,69 @@ namespace ICSharpCode.ILSpy /// Gets the name of the language (as shown in the UI) /// public abstract string Name { get; } - + /// /// Gets the file extension used by source code files in this language. /// public abstract string FileExtension { get; } - - public virtual string ProjectFileExtension { + + public virtual string ProjectFileExtension + { get { return null; } } - + /// /// 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); } } - + public virtual void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(method.DeclaringType, true) + "." + method.Name); } - + public virtual void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(property.DeclaringType, true) + "." + property.Name); } - + public virtual void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(field.DeclaringType, true) + "." + field.Name); } - + public virtual void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(ev.DeclaringType, true) + "." + ev.Name); } - + public virtual void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, TypeToString(type, true)); } - + public virtual void DecompileNamespace(string nameSpace, IEnumerable types, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, nameSpace); } - + public virtual void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { WriteCommentLine(output, assembly.FileName); WriteCommentLine(output, assembly.AssemblyDefinition.FullName); } - + public virtual void WriteCommentLine(ITextOutput output, string comment) { output.WriteLine("// " + comment); } - + /// /// Converts a type reference into a string. This method is used by the member tree node for parameter and return types. /// @@ -105,7 +108,7 @@ namespace ICSharpCode.ILSpy else return type.Name; } - + /// /// Converts a member signature to a string. /// This is used for displaying the tooltip on a member reference. @@ -117,14 +120,14 @@ namespace ICSharpCode.ILSpy else return member.ToString(); } - + public virtual string FormatPropertyName(PropertyDefinition property, bool? isIndexer = null) { if (property == null) throw new ArgumentNullException("property"); return property.Name; } - + /// /// Used for WPF keyboard navigation. /// @@ -132,39 +135,49 @@ namespace ICSharpCode.ILSpy { return Name; } - + public virtual bool ShowMember(MemberReference member) { return true; } + + /// + /// Used by the analyzer to map compiler generated code back to the original code's location + /// + public virtual MemberReference GetOriginalCodeLocation(MemberReference member) + { + return member; + } } - + public static class Languages { static ReadOnlyCollection allLanguages; - + /// /// A list of all languages. /// - public static ReadOnlyCollection AllLanguages { - get { + public static ReadOnlyCollection AllLanguages + { + get + { return allLanguages; } } - - + + internal static void Initialize(CompositionContainer composition) { List languages = new List(); languages.AddRange(composition.GetExportedValues()); languages.Add(new ILLanguage(true)); - #if DEBUG +#if DEBUG languages.AddRange(ILAstLanguage.GetDebugLanguages()); languages.AddRange(CSharpLanguage.GetDebugLanguages()); - #endif +#endif allLanguages = languages.AsReadOnly(); } - + /// /// Gets a language using its name. /// If the language is not found, C# is returned instead. diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs index c18b62d0f..d95232ee6 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs @@ -22,6 +22,7 @@ using System.Threading; using ICSharpCode.TreeView; using Mono.Cecil; using Mono.Cecil.Cil; +using System.Collections; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { @@ -30,6 +31,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private readonly bool showWrites; // true: show writes; false: show read access private readonly FieldDefinition analyzedField; private readonly ThreadingSupport threading; + private Lazy foundMethods; + private object hashLock = new object(); public AnalyzedFieldAccessTreeNode(FieldDefinition analyzedField, bool showWrites) { @@ -68,8 +71,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { + foundMethods = new Lazy(LazyThreadSafetyMode.ExecutionAndPublication); + var analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedField, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + foreach (var child in analyzer.PerformAnalysis(ct)) { + yield return child; + } + + foundMethods = null; } private IEnumerable FindReferencesInType(TypeDefinition type) @@ -95,8 +104,12 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer method.Body = null; - if (found) - yield return new AnalyzedMethodTreeNode(method); + if (found) { + MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition; + if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) { + yield return new AnalyzedMethodTreeNode(codeLocation); + } + } } } @@ -116,5 +129,18 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return false; } } + + private bool HasAlreadyBeenFound(MethodDefinition method) + { + Hashtable hashtable = foundMethods.Value; + lock (hashLock) { + if (hashtable.Contains(method)) { + return true; + } else { + hashtable.Add(method, null); + return false; + } + } + } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index 2a7cf784f..dff573890 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections; using System.Collections.Generic; using System.Threading; using ICSharpCode.TreeView; @@ -29,6 +30,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { private readonly MethodDefinition analyzedMethod; private readonly ThreadingSupport threading; + private Lazy foundMethods; + private object hashLock = new object(); public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod) { @@ -66,10 +69,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - ScopedWhereUsedScopeAnalyzer analyzer; + foundMethods = new Lazy(LazyThreadSafetyMode.ExecutionAndPublication); - analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); - return analyzer.PerformAnalysis(ct); + var analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); + foreach (var child in analyzer.PerformAnalysis(ct)) { + yield return child; + } + + foundMethods = null; } private IEnumerable FindReferencesInType(TypeDefinition type) @@ -81,8 +88,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer continue; foreach (Instruction instr in method.Body.Instructions) { MethodReference mr = instr.Operand as MethodReference; - if (mr != null && - mr.Name == name && + if (mr != null && mr.Name == name && Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && mr.Resolve() == analyzedMethod) { found = true; @@ -92,8 +98,25 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer method.Body = null; - if (found) - yield return new AnalyzedMethodTreeNode(method); + if (found) { + MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition; + if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) { + yield return new AnalyzedMethodTreeNode(codeLocation); + } + } + } + } + + private bool HasAlreadyBeenFound(MethodDefinition method) + { + Hashtable hashtable = foundMethods.Value; + lock (hashLock) { + if (hashtable.Contains(method)) { + return true; + } else { + hashtable.Add(method, null); + return false; + } } } } diff --git a/ILSpy/TreeNodes/Analyzer/Helpers.cs b/ILSpy/TreeNodes/Analyzer/Helpers.cs index 778996a72..961880197 100644 --- a/ILSpy/TreeNodes/Analyzer/Helpers.cs +++ b/ILSpy/TreeNodes/Analyzer/Helpers.cs @@ -20,7 +20,10 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using ICSharpCode.Decompiler; using Mono.Cecil; +using ICSharpCode.Decompiler.ILAst; +using Mono.Cecil.Cil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { @@ -50,5 +53,66 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer return true; } + + public static MemberReference GetOriginalCodeLocation(MemberReference member) + { + if (member is MethodDefinition) + return GetOriginalCodeLocation((MethodDefinition)member); + return member; + } + + public static MethodDefinition GetOriginalCodeLocation(MethodDefinition method) + { + if (method.Name.StartsWith("<", StringComparison.Ordinal) && method.IsCompilerGenerated()) { + return FindMethodUsageInType(method.DeclaringType, method); + } + + var typeUsage = GetOriginalCodeLocation(method.DeclaringType, method); + + return typeUsage ?? method; + } + public static MethodDefinition GetOriginalCodeLocation(TypeDefinition type, MethodDefinition method) + { + if (type != null && type.DeclaringType != null && + type.Name.StartsWith("<", StringComparison.Ordinal) && type.IsCompilerGenerated()) { + MethodDefinition constructor = GetTypeConstructor(type); + return FindMethodUsageInType(type.DeclaringType, constructor); + } + return null; + } + + private static MethodDefinition GetTypeConstructor(TypeDefinition type) + { + foreach (MethodDefinition method in type.Methods) { + if (method.Name == ".ctor") + return method; + } + return null; + } + + private static MethodDefinition FindMethodUsageInType(TypeDefinition type, MethodDefinition analyzedMethod) + { + string name = analyzedMethod.Name; + foreach (MethodDefinition method in type.Methods) { + bool found = false; + if (!method.HasBody) + continue; + foreach (Instruction instr in method.Body.Instructions) { + MethodReference mr = instr.Operand as MethodReference; + if (mr != null && mr.Name == name && + Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && + mr.Resolve() == analyzedMethod) { + found = true; + break; + } + } + + method.Body = null; + + if (found) + return method; + } + return null; + } } } From 91376b44f613c96a55b71227471251b2f501ade1 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Sat, 7 May 2011 19:38:12 +1000 Subject: [PATCH 05/65] Analyzer: remove property & event 'accessors' node and promote its children up one level. --- ILSpy/ILSpy.csproj | 4 +- ...de.cs => AnalyzedEventAccessorTreeNode.cs} | 43 +++---------------- .../Analyzer/AnalyzedEventTreeNode.cs | 17 +++++--- ...cs => AnalyzedPropertyAccessorTreeNode.cs} | 43 +++---------------- .../Analyzer/AnalyzedPropertyTreeNode.cs | 13 ++++-- 5 files changed, 34 insertions(+), 86 deletions(-) rename ILSpy/TreeNodes/Analyzer/{AnalyzedEventAccessorsTreeNode.cs => AnalyzedEventAccessorTreeNode.cs} (50%) rename ILSpy/TreeNodes/Analyzer/{AnalyzedPropertyAccessorsTreeNode.cs => AnalyzedPropertyAccessorTreeNode.cs} (50%) diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 836318799..526be03db 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -139,21 +139,21 @@ Code - + + - diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorTreeNode.cs similarity index 50% rename from ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs rename to ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorTreeNode.cs index d350147f1..041e4ef86 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventAccessorTreeNode.cs @@ -21,50 +21,19 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedEventAccessorsTreeNode : AnalyzerTreeNode + internal class AnalyzedEventAccessorTreeNode : AnalyzedMethodTreeNode { - public AnalyzedEventAccessorsTreeNode(EventDefinition analyzedEvent) - { - if (analyzedEvent == null) - throw new ArgumentNullException("analyzedEvent"); - - if (analyzedEvent.AddMethod != null) - this.Children.Add(new AnalyzedEventAccessorTreeNode(analyzedEvent.AddMethod, "add")); - if (analyzedEvent.RemoveMethod != null) - this.Children.Add(new AnalyzedEventAccessorTreeNode(analyzedEvent.RemoveMethod, "remove")); - foreach (var accessor in analyzedEvent.OtherMethods) - this.Children.Add(new AnalyzedEventAccessorTreeNode(accessor, null)); - } + private string name; - public override object Icon + public AnalyzedEventAccessorTreeNode(MethodDefinition analyzedMethod, string name) + : base(analyzedMethod) { - get { return Images.Search; } + this.name = name; } public override object Text { - get { return "Accessors"; } - } - - public static bool CanShow(EventDefinition property) - { - return !MainWindow.Instance.CurrentLanguage.ShowMember(property.AddMethod ?? property.RemoveMethod); - } - - internal class AnalyzedEventAccessorTreeNode : AnalyzedMethodTreeNode - { - private string name; - - public AnalyzedEventAccessorTreeNode(MethodDefinition analyzedMethod, string name) - : base(analyzedMethod) - { - this.name = name; - } - - public override object Text - { - get { return name ?? base.Text; } - } + get { return name ?? base.Text; } } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs index 3ebf2d23b..89903abd4 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventTreeNode.cs @@ -57,8 +57,13 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer protected override void LoadChildren() { - if (AnalyzedEventAccessorsTreeNode.CanShow(analyzedEvent)) - this.Children.Add(new AnalyzedEventAccessorsTreeNode(analyzedEvent)); + if (analyzedEvent.AddMethod != null) + this.Children.Add(new AnalyzedEventAccessorTreeNode(analyzedEvent.AddMethod, "add")); + if (analyzedEvent.RemoveMethod != null) + this.Children.Add(new AnalyzedEventAccessorTreeNode(analyzedEvent.RemoveMethod, "remove")); + foreach (var accessor in analyzedEvent.OtherMethods) + this.Children.Add(new AnalyzedEventAccessorTreeNode(accessor, null)); + if (AnalyzedEventOverridesTreeNode.CanShow(analyzedEvent)) this.Children.Add(new AnalyzedEventOverridesTreeNode(analyzedEvent)); if (AnalyzedInterfaceEventImplementedByTreeNode.CanShow(analyzedEvent)) @@ -75,12 +80,12 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer public static bool CanShow(MemberReference member) { - var property = member as EventDefinition; - if (property == null) + var eventDef = member as EventDefinition; + if (eventDef == null) return false; - return AnalyzedEventAccessorsTreeNode.CanShow(property) - || AnalyzedEventOverridesTreeNode.CanShow(property); + return !MainWindow.Instance.CurrentLanguage.ShowMember(eventDef.AddMethod ?? eventDef.RemoveMethod) + || AnalyzedEventOverridesTreeNode.CanShow(eventDef); } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorTreeNode.cs similarity index 50% rename from ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs rename to ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorTreeNode.cs index 621417d2b..e9b898cba 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyAccessorTreeNode.cs @@ -21,50 +21,19 @@ using Mono.Cecil; namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { - internal sealed class AnalyzedPropertyAccessorsTreeNode : AnalyzerTreeNode + internal class AnalyzedPropertyAccessorTreeNode : AnalyzedMethodTreeNode { - public AnalyzedPropertyAccessorsTreeNode(PropertyDefinition analyzedProperty) - { - if (analyzedProperty == null) - throw new ArgumentNullException("analyzedProperty"); - - if (analyzedProperty.GetMethod != null) - this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.GetMethod, "get")); - if (analyzedProperty.SetMethod != null) - this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.SetMethod, "set")); - foreach (var accessor in analyzedProperty.OtherMethods) - this.Children.Add(new AnalyzedPropertyAccessorTreeNode(accessor, null)); - } + private readonly string name; - public override object Icon + public AnalyzedPropertyAccessorTreeNode(MethodDefinition analyzedMethod, string name) + : base(analyzedMethod) { - get { return Images.Search; } + this.name = name; } public override object Text { - get { return "Accessors"; } - } - - public static bool CanShow(PropertyDefinition property) - { - return !MainWindow.Instance.CurrentLanguage.ShowMember(property.GetMethod ?? property.SetMethod); - } - - private class AnalyzedPropertyAccessorTreeNode : AnalyzedMethodTreeNode - { - private readonly string name; - - public AnalyzedPropertyAccessorTreeNode(MethodDefinition analyzedMethod, string name) - : base(analyzedMethod) - { - this.name = name; - } - - public override object Text - { - get { return name ?? base.Text; } - } + get { return name ?? base.Text; } } } } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs index bba0b3362..b08127b52 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs @@ -60,8 +60,13 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer protected override void LoadChildren() { - if (AnalyzedPropertyAccessorsTreeNode.CanShow(analyzedProperty)) - this.Children.Add(new AnalyzedPropertyAccessorsTreeNode(analyzedProperty)); + if (analyzedProperty.GetMethod != null) + this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.GetMethod, "get")); + if (analyzedProperty.SetMethod != null) + this.Children.Add(new AnalyzedPropertyAccessorTreeNode(analyzedProperty.SetMethod, "set")); + foreach (var accessor in analyzedProperty.OtherMethods) + this.Children.Add(new AnalyzedPropertyAccessorTreeNode(accessor, null)); + if (AnalyzedPropertyOverridesTreeNode.CanShow(analyzedProperty)) this.Children.Add(new AnalyzedPropertyOverridesTreeNode(analyzedProperty)); if (AnalyzedInterfacePropertyImplementedByTreeNode.CanShow(analyzedProperty)) @@ -82,8 +87,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer if (property == null) return false; - return AnalyzedPropertyAccessorsTreeNode.CanShow(property) - || AnalyzedPropertyOverridesTreeNode.CanShow(property); + return !MainWindow.Instance.CurrentLanguage.ShowMember(property.GetMethod ?? property.SetMethod) + || AnalyzedPropertyOverridesTreeNode.CanShow(property); } } } From 637a91236ce4a79ef0d0cc3227f77ae170eb98aa Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Sat, 7 May 2011 22:05:24 +1000 Subject: [PATCH 06/65] Add tree node icon for Static Class. --- ILSpy/ILSpy.csproj | 2 +- ILSpy/Images/Images.cs | 5 +++++ ILSpy/Images/StaticClass.png | Bin 0 -> 569 bytes ILSpy/Images/TypeIcon.cs | 3 ++- ILSpy/TreeNodes/TypeTreeNode.cs | 18 +++++++++++++++++- 5 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 ILSpy/Images/StaticClass.png diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 526be03db..fb0484079 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -236,6 +236,7 @@ + @@ -303,6 +304,5 @@ ICSharpCode.TreeView - \ No newline at end of file diff --git a/ILSpy/Images/Images.cs b/ILSpy/Images/Images.cs index 361f6a5a8..8755e772e 100644 --- a/ILSpy/Images/Images.cs +++ b/ILSpy/Images/Images.cs @@ -65,6 +65,7 @@ namespace ICSharpCode.ILSpy public static readonly BitmapImage Interface = LoadBitmap("Interface"); public static readonly BitmapImage Delegate = LoadBitmap("Delegate"); public static readonly BitmapImage Enum = LoadBitmap("Enum"); + public static readonly BitmapImage StaticClass = LoadBitmap("StaticClass"); public static readonly BitmapImage Field = LoadBitmap("Field"); @@ -133,6 +134,7 @@ namespace ICSharpCode.ILSpy PreloadPublicIconToCache(TypeIcon.Struct, Images.Struct); PreloadPublicIconToCache(TypeIcon.Interface, Images.Interface); PreloadPublicIconToCache(TypeIcon.Delegate, Images.Delegate); + PreloadPublicIconToCache(TypeIcon.StaticClass, Images.StaticClass); } protected override ImageSource GetBaseImage(TypeIcon icon) @@ -154,6 +156,9 @@ namespace ICSharpCode.ILSpy case TypeIcon.Delegate: baseImage = Images.Delegate; break; + case TypeIcon.StaticClass: + baseImage = Images.StaticClass; + break; default: throw new NotSupportedException(); } diff --git a/ILSpy/Images/StaticClass.png b/ILSpy/Images/StaticClass.png new file mode 100644 index 0000000000000000000000000000000000000000..af9ebd06a631b7049e1858a2a3e986de4031887a GIT binary patch literal 569 zcmV-90>=G`P)004R=004l4008;_004mL004C`008P>0026e000+nl3&F}00009 za7bBm000tl000tl0bXTW;{X5v7IZ~ebW?9;ba!ELWdLwtX>N2bZe?^JG%heZ==Es; z00E6jL_t(IPh()92B_Y3hqYnYYVjNLE)+bp>BPpo|2 zf0zL<&A-1i834jCn@Q4)>?M#3Op~_~Z!@;=00$f~&c+u-*g_uwZM-T~VI@L(00000NkvXX Hu0mjfVxS9o literal 0 HcmV?d00001 diff --git a/ILSpy/Images/TypeIcon.cs b/ILSpy/Images/TypeIcon.cs index 2e5f3f498..7bbb0d08a 100644 --- a/ILSpy/Images/TypeIcon.cs +++ b/ILSpy/Images/TypeIcon.cs @@ -26,6 +26,7 @@ namespace ICSharpCode.ILSpy Enum, Struct, Interface, - Delegate + Delegate, + StaticClass } } diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index 23bce5df7..c62e53e9f 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -146,8 +146,10 @@ namespace ICSharpCode.ILSpy.TreeNodes } else { if (type.IsInterface) return TypeIcon.Interface; - else if (type.BaseType != null && type.BaseType.FullName == typeof(MulticastDelegate).FullName) + else if (IsDelegate(type)) return TypeIcon.Delegate; + else if (IsStaticClass(type)) + return TypeIcon.StaticClass; else return TypeIcon.Class; } @@ -178,6 +180,20 @@ namespace ICSharpCode.ILSpy.TreeNodes } return overlay; } + + private static bool IsDelegate(TypeDefinition type) + { + return type.BaseType != null && type.BaseType.FullName == typeof(MulticastDelegate).FullName; + } + + private static bool IsStaticClass(TypeDefinition type) + { + if(type.IsSealed) + return !type.Methods.Where(m => m.Name == ".ctor").Any(m => !m.IsPrivate); + + return false; + } + #endregion MemberReference IMemberTreeNode.Member { From 5bf46e3d19367ce3ca7fdb01119b43e6e17b323c Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Sat, 7 May 2011 22:37:44 +1000 Subject: [PATCH 07/65] Analyzer: result redirection - don't require that name starts with '<'. Always attempt redirect if member is compiler generated. --- ILSpy/TreeNodes/Analyzer/Helpers.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ILSpy/TreeNodes/Analyzer/Helpers.cs b/ILSpy/TreeNodes/Analyzer/Helpers.cs index 961880197..bef4e486a 100644 --- a/ILSpy/TreeNodes/Analyzer/Helpers.cs +++ b/ILSpy/TreeNodes/Analyzer/Helpers.cs @@ -63,8 +63,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer public static MethodDefinition GetOriginalCodeLocation(MethodDefinition method) { - if (method.Name.StartsWith("<", StringComparison.Ordinal) && method.IsCompilerGenerated()) { - return FindMethodUsageInType(method.DeclaringType, method); + if (method.IsCompilerGenerated()) { + return FindMethodUsageInType(method.DeclaringType, method) ?? method; } var typeUsage = GetOriginalCodeLocation(method.DeclaringType, method); @@ -73,10 +73,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer } public static MethodDefinition GetOriginalCodeLocation(TypeDefinition type, MethodDefinition method) { - if (type != null && type.DeclaringType != null && - type.Name.StartsWith("<", StringComparison.Ordinal) && type.IsCompilerGenerated()) { - MethodDefinition constructor = GetTypeConstructor(type); - return FindMethodUsageInType(type.DeclaringType, constructor); + if (type != null && type.DeclaringType != null && type.IsCompilerGenerated()) { + MethodDefinition constructor = GetTypeConstructor(type); + return FindMethodUsageInType(type.DeclaringType, constructor); } return null; } From 54d777f8332333f550e30551dc6f3b39ecdddbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zgodzi=C5=84ski?= Date: Sun, 8 May 2011 09:08:08 +0200 Subject: [PATCH 08/65] Fixed navigation to preserve state of decompiler's text view. --- ILSpy/AboutPage.cs | 4 ++-- ILSpy/App.xaml.cs | 2 +- ILSpy/BamlDecompiler.cs | 2 +- ILSpy/Commands.cs | 2 +- ILSpy/MainWindow.xaml.cs | 15 ++++++++++----- ILSpy/NavigationHistory.cs | 12 ++++++++---- ILSpy/NavigationState.cs | 10 ++++++++-- ILSpy/TextView/DecompilerTextView.cs | 21 ++++++++++++++++++++- ILSpy/TreeNodes/ResourceEntryNode.cs | 2 +- ILSpy/TreeNodes/ResourceTreeNode.cs | 2 +- ILSpy/TreeNodes/XamlResourceNode.cs | 2 +- 11 files changed, 54 insertions(+), 20 deletions(-) diff --git a/ILSpy/AboutPage.cs b/ILSpy/AboutPage.cs index c88f832dc..fd4fb4891 100644 --- a/ILSpy/AboutPage.cs +++ b/ILSpy/AboutPage.cs @@ -93,7 +93,7 @@ namespace ICSharpCode.ILSpy output.AddVisualLineElementGenerator(new MyLinkElementGenerator("SharpDevelop", "http://www.icsharpcode.net/opensource/sd/")); output.AddVisualLineElementGenerator(new MyLinkElementGenerator("MIT License", "resource:license.txt")); output.AddVisualLineElementGenerator(new MyLinkElementGenerator("LGPL", "resource:LGPL.txt")); - textView.Show(output); + textView.ShowText(output); } sealed class MyLinkElementGenerator : LinkElementGenerator @@ -130,7 +130,7 @@ namespace ICSharpCode.ILSpy } catch (Exception ex) { AvalonEditTextOutput exceptionOutput = new AvalonEditTextOutput(); exceptionOutput.WriteLine(ex.ToString()); - textView.Show(exceptionOutput); + textView.ShowText(exceptionOutput); } }, TaskScheduler.FromCurrentSynchronizationContext()); }; diff --git a/ILSpy/App.xaml.cs b/ILSpy/App.xaml.cs index f0644d70a..0eab2937f 100644 --- a/ILSpy/App.xaml.cs +++ b/ILSpy/App.xaml.cs @@ -165,7 +165,7 @@ namespace ICSharpCode.ILSpy } } } - ILSpy.MainWindow.Instance.TextView.Show(output); + ILSpy.MainWindow.Instance.TextView.ShowText(output); } else { Process.Start(e.Uri.ToString()); } diff --git a/ILSpy/BamlDecompiler.cs b/ILSpy/BamlDecompiler.cs index c223dcb82..07c60b13e 100644 --- a/ILSpy/BamlDecompiler.cs +++ b/ILSpy/BamlDecompiler.cs @@ -401,7 +401,7 @@ namespace ICSharpCode.ILSpy.Baml } return output; }), - t => textView.Show(t.Result, highlighting) + t => textView.ShowNode(t.Result, this, highlighting) ); return true; } diff --git a/ILSpy/Commands.cs b/ILSpy/Commands.cs index 67775f43d..8d89e9afc 100644 --- a/ILSpy/Commands.cs +++ b/ILSpy/Commands.cs @@ -122,7 +122,7 @@ namespace ICSharpCode.ILSpy return output; } ), - task => MainWindow.Instance.TextView.Show(task.Result)); + task => MainWindow.Instance.TextView.ShowText(task.Result)); } } #endif diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 262365ed0..4425555af 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -242,7 +242,7 @@ namespace ICSharpCode.ILSpy if (!found) { AvalonEditTextOutput output = new AvalonEditTextOutput(); output.Write("Cannot find " + args.NavigateTo); - decompilerTextView.Show(output); + decompilerTextView.ShowText(output); } } commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore @@ -511,8 +511,12 @@ namespace ICSharpCode.ILSpy if (ignoreDecompilationRequests) return; - if (recordHistory) - history.Record(new NavigationState(treeView.SelectedItems.OfType(), decompilerTextView.GetState())); + if (recordHistory) { + var dtState = decompilerTextView.GetState(); + if(dtState != null) + history.UpdateCurrent(new NavigationState(dtState)); + history.Record(new NavigationState(treeView.SelectedItems.OfType())); + } if (treeView.SelectedItems.Count == 1) { ILSpyTreeNode node = treeView.SelectedItem as ILSpyTreeNode; @@ -586,8 +590,9 @@ namespace ICSharpCode.ILSpy void NavigateHistory(bool forward) { - var combinedState = new NavigationState(treeView.SelectedItems.OfType(), decompilerTextView.GetState()); - history.Record(combinedState, replace: true, clearForward: false); + var dtState = decompilerTextView.GetState(); + if(dtState != null) + history.UpdateCurrent(new NavigationState(dtState)); var newState = forward ? history.GoForward() : history.GoBack(); ignoreDecompilationRequests = true; diff --git a/ILSpy/NavigationHistory.cs b/ILSpy/NavigationHistory.cs index 0fb1bed05..c5983a96d 100644 --- a/ILSpy/NavigationHistory.cs +++ b/ILSpy/NavigationHistory.cs @@ -71,13 +71,18 @@ namespace ICSharpCode.ILSpy back.Clear(); forward.Clear(); } + + public void UpdateCurrent(T node) + { + current = node; + } - public void Record(T node, bool replace = false, bool clearForward = true) + public void Record(T node) { var navigationTime = DateTime.Now; var period = navigationTime - lastNavigationTime; - if (period.TotalSeconds < NavigationSecondsBeforeNewEntry || replace) { + if (period.TotalSeconds < NavigationSecondsBeforeNewEntry) { current = node; } else { if (current != null) @@ -88,8 +93,7 @@ namespace ICSharpCode.ILSpy current = node; } - if (clearForward) - forward.Clear(); + forward.Clear(); lastNavigationTime = navigationTime; } diff --git a/ILSpy/NavigationState.cs b/ILSpy/NavigationState.cs index 7a86ebec5..123c0b642 100644 --- a/ILSpy/NavigationState.cs +++ b/ILSpy/NavigationState.cs @@ -32,12 +32,18 @@ namespace ICSharpCode.ILSpy public IEnumerable TreeNodes { get { return treeNodes; } } public DecompilerTextViewState ViewState { get; private set; } - public NavigationState(IEnumerable treeNodes, DecompilerTextViewState viewState) + public NavigationState(DecompilerTextViewState viewState) { - this.treeNodes = new HashSet(treeNodes); + this.treeNodes = new HashSet(viewState.DecompiledNodes); ViewState = viewState; } + public NavigationState(IEnumerable treeNodes) + { + this.treeNodes = new HashSet(treeNodes); + } + + public bool Equals(NavigationState other) { // TODO: should this care about the view state as well? diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 1241037b1..75f837620 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -60,6 +60,7 @@ namespace ICSharpCode.ILSpy.TextView readonly UIElementGenerator uiElementGenerator; List activeCustomElementGenerators = new List(); FoldingManager foldingManager; + ILSpyTreeNode[] decompiledNodes; DefinitionLookup definitionLookup; CancellationTokenSource currentCancellationTokenSource; @@ -207,11 +208,21 @@ namespace ICSharpCode.ILSpy.TextView #endregion #region ShowOutput + public void ShowText(AvalonEditTextOutput textOutput) + { + ShowNodes(textOutput, null); + } + + public void ShowNode(AvalonEditTextOutput textOutput, ILSpyTreeNode node, IHighlightingDefinition highlighting = null) + { + ShowNodes(textOutput, new[] { node }, highlighting); + } + /// /// Shows the given output in the text view. /// Cancels any currently running decompilation tasks. /// - public void Show(AvalonEditTextOutput textOutput, IHighlightingDefinition highlighting = null) + public void ShowNodes(AvalonEditTextOutput textOutput, ILSpyTreeNode[] nodes, IHighlightingDefinition highlighting = null) { // Cancel the decompilation task: if (currentCancellationTokenSource != null) { @@ -220,6 +231,7 @@ namespace ICSharpCode.ILSpy.TextView } this.nextDecompilationRun = null; // remove scheduled decompilation run ShowOutput(textOutput, highlighting); + decompiledNodes = nodes; } /// @@ -340,6 +352,7 @@ namespace ICSharpCode.ILSpy.TextView } ShowOutput(output); } + decompiledNodes = context.TreeNodes; }); } @@ -513,6 +526,7 @@ namespace ICSharpCode.ILSpy.TextView output.WriteLine(ex.ToString()); ShowOutput(output); } + decompiledNodes = context.TreeNodes; }); } @@ -575,11 +589,15 @@ namespace ICSharpCode.ILSpy.TextView public DecompilerTextViewState GetState() { + if (decompiledNodes == null) + return null; + var state = new DecompilerTextViewState(); if (foldingManager != null) state.SaveFoldingsState(foldingManager.AllFoldings); state.VerticalOffset = textEditor.VerticalOffset; state.HorizontalOffset = textEditor.HorizontalOffset; + state.DecompiledNodes = decompiledNodes; return state; } } @@ -590,6 +608,7 @@ namespace ICSharpCode.ILSpy.TextView private int FoldingsChecksum; public double VerticalOffset; public double HorizontalOffset; + public ILSpyTreeNode[] DecompiledNodes; public void SaveFoldingsState(IEnumerable foldings) { diff --git a/ILSpy/TreeNodes/ResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceEntryNode.cs index 787c82dc3..43638064d 100644 --- a/ILSpy/TreeNodes/ResourceEntryNode.cs +++ b/ILSpy/TreeNodes/ResourceEntryNode.cs @@ -144,7 +144,7 @@ namespace ICSharpCode.ILSpy.TreeNodes output.AddUIElement(() => new Image { Source = image }); output.WriteLine(); output.AddButton(Images.Save, "Save", delegate { Save(null); }); - textView.Show(output, null); + textView.ShowNode(output, this, null); return true; } catch (Exception) { diff --git a/ILSpy/TreeNodes/ResourceTreeNode.cs b/ILSpy/TreeNodes/ResourceTreeNode.cs index 3b277a983..5e79845ba 100644 --- a/ILSpy/TreeNodes/ResourceTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceTreeNode.cs @@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.TreeNodes ext = ".xml"; else ext = Path.GetExtension(DecompilerTextView.CleanUpName(er.Name)); - textView.Show(output, HighlightingManager.Instance.GetDefinitionByExtension(ext)); + textView.ShowNode(output, this, HighlightingManager.Instance.GetDefinitionByExtension(ext)); return true; } } diff --git a/ILSpy/TreeNodes/XamlResourceNode.cs b/ILSpy/TreeNodes/XamlResourceNode.cs index 9e42fb431..0ed226a1d 100644 --- a/ILSpy/TreeNodes/XamlResourceNode.cs +++ b/ILSpy/TreeNodes/XamlResourceNode.cs @@ -74,7 +74,7 @@ namespace ICSharpCode.ILSpy.Xaml } return output; }), - t => textView.Show(t.Result, highlighting) + t => textView.ShowNode(t.Result, this, highlighting) ); return true; } From e54bade36a198b9fccae8b9a7235ff577af5f743 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Mon, 9 May 2011 11:05:59 +1000 Subject: [PATCH 09/65] Analyzer: simplify concurrency handling --- ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index dff573890..6c4f12025 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { private readonly MethodDefinition analyzedMethod; private readonly ThreadingSupport threading; - private Lazy foundMethods; + private Hashtable foundMethods; private object hashLock = new object(); public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod) @@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - foundMethods = new Lazy(LazyThreadSafetyMode.ExecutionAndPublication); + foundMethods = new Hashtable(); var analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct)) { @@ -109,12 +109,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private bool HasAlreadyBeenFound(MethodDefinition method) { - Hashtable hashtable = foundMethods.Value; lock (hashLock) { - if (hashtable.Contains(method)) { + if (foundMethods.Contains(method)) { return true; } else { - hashtable.Add(method, null); + foundMethods.Add(method, null); return false; } } From e7caa3f43fa03c6480a76ba492eb7c53f858f617 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Tue, 10 May 2011 17:47:02 +1000 Subject: [PATCH 10/65] More efficient/correct test for static class icon --- ILSpy/TreeNodes/TypeTreeNode.cs | 56 ++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index c62e53e9f..2291bb074 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.ILSpy.TreeNodes { readonly TypeDefinition type; readonly AssemblyTreeNode parentAssemblyNode; - + public TypeTreeNode(TypeDefinition type, AssemblyTreeNode parentAssemblyNode) { if (parentAssemblyNode == null) @@ -41,29 +41,36 @@ namespace ICSharpCode.ILSpy.TreeNodes this.parentAssemblyNode = parentAssemblyNode; this.LazyLoading = true; } - - public TypeDefinition TypeDefinition { + + public TypeDefinition TypeDefinition + { get { return type; } } - - public AssemblyTreeNode ParentAssemblyNode { + + public AssemblyTreeNode ParentAssemblyNode + { get { return parentAssemblyNode; } } - - public string Name { + + public string Name + { get { return type.Name; } } - - public string Namespace { + + public string Namespace + { get { return type.Namespace; } } - - public override object Text { + + public override object Text + { get { return HighlightSearchMatch(this.Language.TypeToString(type, includeNamespace: false)); } } - - public bool IsPublicAPI { - get { + + public bool IsPublicAPI + { + get + { switch (type.Attributes & TypeAttributes.VisibilityMask) { case TypeAttributes.Public: case TypeAttributes.NestedPublic: @@ -75,7 +82,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - + public override FilterResult Filter(FilterSettings settings) { if (!settings.ShowInternalApi && !IsPublicAPI) @@ -89,7 +96,7 @@ namespace ICSharpCode.ILSpy.TreeNodes return FilterResult.Recurse; } } - + protected override void LoadChildren() { if (type.BaseType != null || type.HasInterfaces) @@ -102,7 +109,7 @@ namespace ICSharpCode.ILSpy.TreeNodes foreach (FieldDefinition field in type.Fields.OrderBy(m => m.Name)) { this.Children.Add(new FieldTreeNode(field)); } - + foreach (PropertyDefinition property in type.Properties.OrderBy(m => m.Name)) { this.Children.Add(new PropertyTreeNode(property)); } @@ -116,7 +123,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { language.DecompileType(type, output, options); @@ -188,15 +195,20 @@ namespace ICSharpCode.ILSpy.TreeNodes private static bool IsStaticClass(TypeDefinition type) { - if(type.IsSealed) - return !type.Methods.Where(m => m.Name == ".ctor").Any(m => !m.IsPrivate); + if (type.IsSealed) { + if (type.IsAbstract) + return true; + else + return !type.Methods.Where(m => m.Name == ".ctor").Any(m => !m.IsPrivate); + } return false; } #endregion - - MemberReference IMemberTreeNode.Member { + + MemberReference IMemberTreeNode.Member + { get { return type; } } } From 5efacf4860efc601e365c392b7a16df5a74d5db1 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Wed, 11 May 2011 12:22:05 +1000 Subject: [PATCH 11/65] Analyzer: renamed class. Previous name was nonsensical and did not match file name. --- .../Analyzer/AnalyzedEventOverridesTreeNode.cs | 4 ++-- .../Analyzer/AnalyzedFieldAccessTreeNode.cs | 2 +- .../AnalyzedInterfaceEventImplementedByTreeNode.cs | 4 ++-- .../AnalyzedInterfaceMethodImplementedByTreeNode.cs | 4 ++-- ...AnalyzedInterfacePropertyImplementedByTreeNode.cs | 4 ++-- .../Analyzer/AnalyzedMethodOverridesTreeNode.cs | 4 ++-- .../Analyzer/AnalyzedMethodUsedByTreeNode.cs | 2 +- .../Analyzer/AnalyzedPropertyOverridesTreeNode.cs | 4 ++-- .../Analyzer/AnalyzedTypeExposedByTreeNode.cs | 4 ++-- .../Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs | 4 ++-- .../Analyzer/AnalyzedTypeInstantiationsTreeNode.cs | 4 ++-- ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs | 12 ++++++------ 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs index fef82644d..549152bb7 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs @@ -68,9 +68,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - ScopedWhereUsedScopeAnalyzer analyzer; + ScopedWhereUsedAnalyzer analyzer; - analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedEvent, FindReferencesInType); + analyzer = new ScopedWhereUsedAnalyzer(analyzedEvent, FindReferencesInType); return analyzer.PerformAnalysis(ct); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs index d95232ee6..850ab3141 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs @@ -73,7 +73,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { foundMethods = new Lazy(LazyThreadSafetyMode.ExecutionAndPublication); - var analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedField, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedField, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct)) { yield return child; } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs index c17f3ec36..09cab0bf3 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs @@ -69,8 +69,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - ScopedWhereUsedScopeAnalyzer analyzer; - analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); + ScopedWhereUsedAnalyzer analyzer; + analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); return analyzer.PerformAnalysis(ct); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs index 6ce86fc8b..960f48f89 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs @@ -67,8 +67,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - ScopedWhereUsedScopeAnalyzer analyzer; - analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); + ScopedWhereUsedAnalyzer analyzer; + analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); return analyzer.PerformAnalysis(ct); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs index 06a4fb961..35d9bc3d0 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs @@ -69,8 +69,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - ScopedWhereUsedScopeAnalyzer analyzer; - analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); + ScopedWhereUsedAnalyzer analyzer; + analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); return analyzer.PerformAnalysis(ct); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs index 7ddb0178e..05a3f5d6a 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs @@ -73,9 +73,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - ScopedWhereUsedScopeAnalyzer analyzer; + ScopedWhereUsedAnalyzer analyzer; - analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); + analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); return analyzer.PerformAnalysis(ct); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index 6c4f12025..aef82d346 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -71,7 +71,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { foundMethods = new Hashtable(); - var analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedMethod, FindReferencesInType); + var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct)) { yield return child; } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs index 81efb1676..6a6ea0f32 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs @@ -69,9 +69,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - ScopedWhereUsedScopeAnalyzer analyzer; + ScopedWhereUsedAnalyzer analyzer; - analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedProperty, FindReferencesInType); + analyzer = new ScopedWhereUsedAnalyzer(analyzedProperty, FindReferencesInType); return analyzer.PerformAnalysis(ct); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs index 00e09e37d..cd14c0575 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs @@ -65,9 +65,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - ScopedWhereUsedScopeAnalyzer analyzer; + ScopedWhereUsedAnalyzer analyzer; - analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedType, FindReferencesInType); + analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); return analyzer.PerformAnalysis(ct); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs index c88ece234..3bd42506c 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs @@ -66,9 +66,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - ScopedWhereUsedScopeAnalyzer analyzer; + ScopedWhereUsedAnalyzer analyzer; - analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedType, FindReferencesInType); + analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); return analyzer.PerformAnalysis(ct); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs index f11fca495..0c2d9465a 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs @@ -71,9 +71,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - ScopedWhereUsedScopeAnalyzer analyzer; + ScopedWhereUsedAnalyzer analyzer; - analyzer = new ScopedWhereUsedScopeAnalyzer(analyzedType, FindReferencesInType); + analyzer = new ScopedWhereUsedAnalyzer(analyzedType, FindReferencesInType); return analyzer.PerformAnalysis(ct); } diff --git a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs index 6b741d6da..2840901a9 100644 --- a/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs +++ b/ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer /// /// Determines the accessibility domain of a member for where-used analysis. /// - internal class ScopedWhereUsedScopeAnalyzer + internal class ScopedWhereUsedAnalyzer { private AssemblyDefinition assemblyScope; private TypeDefinition typeScope; @@ -37,20 +37,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private Accessibility typeAccessibility = Accessibility.Public; private Func> typeAnalysisFunction; - public ScopedWhereUsedScopeAnalyzer(TypeDefinition type, Func> typeAnalysisFunction) + public ScopedWhereUsedAnalyzer(TypeDefinition type, Func> typeAnalysisFunction) { this.typeScope = type; this.assemblyScope = type.Module.Assembly; this.typeAnalysisFunction = typeAnalysisFunction; } - public ScopedWhereUsedScopeAnalyzer(MethodDefinition method, Func> typeAnalysisFunction) + public ScopedWhereUsedAnalyzer(MethodDefinition method, Func> typeAnalysisFunction) : this(method.DeclaringType, typeAnalysisFunction) { this.memberAccessibility = GetMethodAccessibility(method); } - public ScopedWhereUsedScopeAnalyzer(PropertyDefinition property, Func> typeAnalysisFunction) + public ScopedWhereUsedAnalyzer(PropertyDefinition property, Func> typeAnalysisFunction) : this(property.DeclaringType, typeAnalysisFunction) { Accessibility getterAccessibility = (property.GetMethod == null) ? Accessibility.Private : GetMethodAccessibility(property.GetMethod); @@ -58,7 +58,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.memberAccessibility = (Accessibility)Math.Max((int)getterAccessibility, (int)setterAccessibility); } - public ScopedWhereUsedScopeAnalyzer(EventDefinition eventDef, Func> typeAnalysisFunction) + public ScopedWhereUsedAnalyzer(EventDefinition eventDef, Func> typeAnalysisFunction) : this(eventDef.DeclaringType, typeAnalysisFunction) { // we only have to check the accessibility of the the get method @@ -66,7 +66,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer this.memberAccessibility = GetMethodAccessibility(eventDef.AddMethod); } - public ScopedWhereUsedScopeAnalyzer(FieldDefinition field, Func> typeAnalysisFunction) + public ScopedWhereUsedAnalyzer(FieldDefinition field, Func> typeAnalysisFunction) : this(field.DeclaringType, typeAnalysisFunction) { switch (field.Attributes & FieldAttributes.FieldAccessMask) { From db114400ba8896fbec99ad9be592ed91b2c72cbf Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Fri, 13 May 2011 10:35:04 +1000 Subject: [PATCH 12/65] Reverse Static Class icon changes to TypeTreeNode.cs Commit:637a91236ce4a79ef0d0cc3227f77ae170eb98aa Commit:e7caa3f43fa03c6480a76ba492eb7c53f858f617 --- ILSpy/TreeNodes/TypeTreeNode.cs | 70 ++++++++++----------------------- 1 file changed, 21 insertions(+), 49 deletions(-) diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index 2291bb074..23bce5df7 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.ILSpy.TreeNodes { readonly TypeDefinition type; readonly AssemblyTreeNode parentAssemblyNode; - + public TypeTreeNode(TypeDefinition type, AssemblyTreeNode parentAssemblyNode) { if (parentAssemblyNode == null) @@ -41,36 +41,29 @@ namespace ICSharpCode.ILSpy.TreeNodes this.parentAssemblyNode = parentAssemblyNode; this.LazyLoading = true; } - - public TypeDefinition TypeDefinition - { + + public TypeDefinition TypeDefinition { get { return type; } } - - public AssemblyTreeNode ParentAssemblyNode - { + + public AssemblyTreeNode ParentAssemblyNode { get { return parentAssemblyNode; } } - - public string Name - { + + public string Name { get { return type.Name; } } - - public string Namespace - { + + public string Namespace { get { return type.Namespace; } } - - public override object Text - { + + public override object Text { get { return HighlightSearchMatch(this.Language.TypeToString(type, includeNamespace: false)); } } - - public bool IsPublicAPI - { - get - { + + public bool IsPublicAPI { + get { switch (type.Attributes & TypeAttributes.VisibilityMask) { case TypeAttributes.Public: case TypeAttributes.NestedPublic: @@ -82,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - + public override FilterResult Filter(FilterSettings settings) { if (!settings.ShowInternalApi && !IsPublicAPI) @@ -96,7 +89,7 @@ namespace ICSharpCode.ILSpy.TreeNodes return FilterResult.Recurse; } } - + protected override void LoadChildren() { if (type.BaseType != null || type.HasInterfaces) @@ -109,7 +102,7 @@ namespace ICSharpCode.ILSpy.TreeNodes foreach (FieldDefinition field in type.Fields.OrderBy(m => m.Name)) { this.Children.Add(new FieldTreeNode(field)); } - + foreach (PropertyDefinition property in type.Properties.OrderBy(m => m.Name)) { this.Children.Add(new PropertyTreeNode(property)); } @@ -123,7 +116,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } } } - + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { language.DecompileType(type, output, options); @@ -153,10 +146,8 @@ namespace ICSharpCode.ILSpy.TreeNodes } else { if (type.IsInterface) return TypeIcon.Interface; - else if (IsDelegate(type)) + else if (type.BaseType != null && type.BaseType.FullName == typeof(MulticastDelegate).FullName) return TypeIcon.Delegate; - else if (IsStaticClass(type)) - return TypeIcon.StaticClass; else return TypeIcon.Class; } @@ -187,28 +178,9 @@ namespace ICSharpCode.ILSpy.TreeNodes } return overlay; } - - private static bool IsDelegate(TypeDefinition type) - { - return type.BaseType != null && type.BaseType.FullName == typeof(MulticastDelegate).FullName; - } - - private static bool IsStaticClass(TypeDefinition type) - { - if (type.IsSealed) { - if (type.IsAbstract) - return true; - else - return !type.Methods.Where(m => m.Name == ".ctor").Any(m => !m.IsPrivate); - } - - return false; - } - #endregion - - MemberReference IMemberTreeNode.Member - { + + MemberReference IMemberTreeNode.Member { get { return type; } } } From 87d700d4d9462f3a5be631cef8e9234f067dddb3 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Fri, 13 May 2011 10:45:44 +1000 Subject: [PATCH 13/65] Add tree node icon for Static Class. --- ILSpy/TreeNodes/TypeTreeNode.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index 23bce5df7..e2e5c70dd 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -146,8 +146,10 @@ namespace ICSharpCode.ILSpy.TreeNodes } else { if (type.IsInterface) return TypeIcon.Interface; - else if (type.BaseType != null && type.BaseType.FullName == typeof(MulticastDelegate).FullName) + else if (IsDelegate(type)) return TypeIcon.Delegate; + else if (IsStaticClass(type)) + return TypeIcon.StaticClass; else return TypeIcon.Class; } @@ -178,6 +180,17 @@ namespace ICSharpCode.ILSpy.TreeNodes } return overlay; } + + private static bool IsDelegate(TypeDefinition type) + { + return type.BaseType != null && type.BaseType.FullName == typeof(MulticastDelegate).FullName; + } + + private static bool IsStaticClass(TypeDefinition type) + { + return type.IsSealed && type.IsAbstract; + } + #endregion MemberReference IMemberTreeNode.Member { From 0ccbbb2e1e32fd9712869021a5e146d60fd5a41f Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Fri, 13 May 2011 11:08:40 +1000 Subject: [PATCH 14/65] Analyzer: simplify concurrency handling --- .../Analyzer/AnalyzedMethodUsedByTreeNode.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index aef82d346..7a820f517 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -17,7 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using ICSharpCode.TreeView; @@ -30,7 +30,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { private readonly MethodDefinition analyzedMethod; private readonly ThreadingSupport threading; - private Hashtable foundMethods; + private ConcurrentDictionary foundMethods; private object hashLock = new object(); public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod) @@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private IEnumerable FetchChildren(CancellationToken ct) { - foundMethods = new Hashtable(); + foundMethods = new ConcurrentDictionary(); var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); foreach (var child in analyzer.PerformAnalysis(ct)) { @@ -109,14 +109,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private bool HasAlreadyBeenFound(MethodDefinition method) { - lock (hashLock) { - if (foundMethods.Contains(method)) { - return true; - } else { - foundMethods.Add(method, null); - return false; - } - } + return !foundMethods.TryAdd(method, 0); } } } From 323ea1a35f7b25adde917708636438c2c2f4a5c6 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Fri, 13 May 2011 11:43:44 +1000 Subject: [PATCH 15/65] Analyzer: removed redundant field from AnalyzedMethodUsedByTreeNode --- ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs index 7a820f517..f3f9504e6 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs @@ -31,7 +31,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer private readonly MethodDefinition analyzedMethod; private readonly ThreadingSupport threading; private ConcurrentDictionary foundMethods; - private object hashLock = new object(); public AnalyzedMethodUsedByTreeNode(MethodDefinition analyzedMethod) { From 4c2e64e92b364bf2fc510ffb10fe6772737195f8 Mon Sep 17 00:00:00 2001 From: Ed Harvey Date: Mon, 16 May 2011 14:06:28 +1000 Subject: [PATCH 16/65] Analyzer: Improved where-used analysis for virtual methods --- ILSpy/ILSpy.csproj | 1 + .../Analyzer/AnalyzedMethodTreeNode.cs | 8 +- .../AnalyzedVirtualMethodUsedByTreeNode.cs | 151 ++++++++++++++++++ 3 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index fb0484079..8c90134d6 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -150,6 +150,7 @@ + diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs index 2ecc053f8..ad7654eae 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedMethodTreeNode.cs @@ -58,9 +58,15 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer { if (analyzedMethod.HasBody) this.Children.Add(new AnalyzedMethodUsesTreeNode(analyzedMethod)); - this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedMethod)); + + if (analyzedMethod.IsVirtual && !(analyzedMethod.IsNewSlot && analyzedMethod.IsFinal)) + this.Children.Add(new AnalyzedVirtualMethodUsedByTreeNode(analyzedMethod)); + else + this.Children.Add(new AnalyzedMethodUsedByTreeNode(analyzedMethod)); + if (AnalyzedMethodOverridesTreeNode.CanShow(analyzedMethod)) this.Children.Add(new AnalyzedMethodOverridesTreeNode(analyzedMethod)); + if (AnalyzedInterfaceMethodImplementedByTreeNode.CanShow(analyzedMethod)) this.Children.Add(new AnalyzedInterfaceMethodImplementedByTreeNode(analyzedMethod)); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs b/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs new file mode 100644 index 000000000..993ef36d7 --- /dev/null +++ b/ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs @@ -0,0 +1,151 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using ICSharpCode.TreeView; +using Mono.Cecil; +using Mono.Cecil.Cil; +using ICSharpCode.Decompiler.Ast; + +namespace ICSharpCode.ILSpy.TreeNodes.Analyzer +{ + internal sealed class AnalyzedVirtualMethodUsedByTreeNode : AnalyzerTreeNode + { + private readonly MethodDefinition analyzedMethod; + private readonly ThreadingSupport threading; + private ConcurrentDictionary foundMethods; + private MethodDefinition baseMethod; + private List possibleTypes; + + public AnalyzedVirtualMethodUsedByTreeNode(MethodDefinition analyzedMethod) + { + if (analyzedMethod == null) + throw new ArgumentNullException("analyzedMethod"); + + this.analyzedMethod = analyzedMethod; + this.threading = new ThreadingSupport(); + this.LazyLoading = true; + } + + public override object Text + { + get { return "Used By"; } + } + + public override object Icon + { + get { return Images.Search; } + } + + protected override void LoadChildren() + { + threading.LoadChildren(this, FetchChildren); + } + + protected override void OnCollapsing() + { + if (threading.IsRunning) { + this.LazyLoading = true; + threading.Cancel(); + this.Children.Clear(); + } + } + + private IEnumerable FetchChildren(CancellationToken ct) + { + InitializeAnalyzer(); + + var analyzer = new ScopedWhereUsedAnalyzer(analyzedMethod, FindReferencesInType); + foreach (var child in analyzer.PerformAnalysis(ct)) { + yield return child; + } + + ReleaseAnalyzer(); + } + + private void InitializeAnalyzer() + { + foundMethods = new ConcurrentDictionary(); + + var BaseMethods = TypesHierarchyHelpers.FindBaseMethods(analyzedMethod).ToArray(); + if (BaseMethods.Length > 0) { + baseMethod = BaseMethods[BaseMethods.Length - 1]; + } + + possibleTypes = new List(); + + TypeReference type = analyzedMethod.DeclaringType.BaseType; + while (type !=null) + { + possibleTypes.Add(type); + type = type.Resolve().BaseType; + } + } + + private void ReleaseAnalyzer() + { + foundMethods = null; + baseMethod = null; + } + + private IEnumerable FindReferencesInType(TypeDefinition type) + { + string name = analyzedMethod.Name; + foreach (MethodDefinition method in type.Methods) { + bool found = false; + string prefix = string.Empty; + if (!method.HasBody) + continue; + foreach (Instruction instr in method.Body.Instructions) { + MethodReference mr = instr.Operand as MethodReference; + if (mr != null && mr.Name == name) { + // explicit call to the requested method + if (Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType) && mr.Resolve() == analyzedMethod) { + found = true; + prefix = "(as base) "; + break; + } + // virtual call to base method + if (instr.OpCode.Code == Code.Callvirt && Helpers.IsReferencedBy(baseMethod.DeclaringType, mr.DeclaringType) && mr.Resolve() == baseMethod) { + found = true; + break; + } + } + } + + method.Body = null; + + if (found) { + MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition; + if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) { + yield return new AnalyzedMethodTreeNode(codeLocation, prefix); + } + } + } + } + + private bool HasAlreadyBeenFound(MethodDefinition method) + { + return !foundMethods.TryAdd(method, 0); + } + } +} From 01493897c7285ccfc93b59e68375ac030c99ff0e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 17 May 2011 16:23:46 +0200 Subject: [PATCH 17/65] fix https://github.com/icsharpcode/ILSpy/issues/177 --- .../CSharp/OutputVisitor/OutputVisitor.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index 1c770b634..eb5e9d2ba 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -963,7 +963,9 @@ namespace ICSharpCode.NRefactory.CSharp case '\v': return "\\v"; default: - if (char.IsControl(ch) || char.IsSurrogate(ch)) { + if (char.IsControl(ch) || char.IsSurrogate(ch) || + // print all uncommon white spaces as numbers + (char.IsWhiteSpace(ch) && ch != ' ')) { return "\\u" + ((int)ch).ToString("x4"); } else { return ch.ToString(); From e654e336137e426974e3b27154acfb7ecc65cf5a Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 18 May 2011 22:25:47 +0200 Subject: [PATCH 18/65] Add display settings to the options dialog: allows to configure font family and size used in the DecompilerTextView. fixes #176 --- ILSpy/DisplaySettings.cs | 65 +++++++++++++ ILSpy/DisplaySettingsPanel.xaml | 57 +++++++++++ ILSpy/DisplaySettingsPanel.xaml.cs | 137 +++++++++++++++++++++++++++ ILSpy/ILSpy.csproj | 6 ++ ILSpy/TextView/DecompilerTextView.cs | 3 + 5 files changed, 268 insertions(+) create mode 100644 ILSpy/DisplaySettings.cs create mode 100644 ILSpy/DisplaySettingsPanel.xaml create mode 100644 ILSpy/DisplaySettingsPanel.xaml.cs diff --git a/ILSpy/DisplaySettings.cs b/ILSpy/DisplaySettings.cs new file mode 100644 index 000000000..fe8cbe9e4 --- /dev/null +++ b/ILSpy/DisplaySettings.cs @@ -0,0 +1,65 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.ComponentModel; +using System.Windows.Media; + +namespace ICSharpCode.ILSpy +{ + /// + /// Description of DisplaySettings. + /// + public class DisplaySettings : INotifyPropertyChanged + { + public DisplaySettings() + { + } + + #region INotifyPropertyChanged implementation + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) + { + if (PropertyChanged != null) { + PropertyChanged(this, e); + } + } + + protected void OnPropertyChanged(string propertyName) + { + OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); + } + #endregion + + FontFamily selectedFont; + + public FontFamily SelectedFont { + get { return selectedFont; } + set { + if (selectedFont != value) { + selectedFont = value; + OnPropertyChanged("SelectedFont"); + } + } + } + + double selectedFontSize; + + public double SelectedFontSize { + get { return selectedFontSize; } + set { + if (selectedFontSize != value) { + selectedFontSize = value; + OnPropertyChanged("SelectedFontSize"); + } + } + } + + public void CopyValues(DisplaySettings s) + { + this.SelectedFont = s.selectedFont; + this.SelectedFontSize = s.selectedFontSize; + } + } +} diff --git a/ILSpy/DisplaySettingsPanel.xaml b/ILSpy/DisplaySettingsPanel.xaml new file mode 100644 index 000000000..b7282b268 --- /dev/null +++ b/ILSpy/DisplaySettingsPanel.xaml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + + + + + + + + \ No newline at end of file diff --git a/ILSpy/DisplaySettingsPanel.xaml.cs b/ILSpy/DisplaySettingsPanel.xaml.cs new file mode 100644 index 000000000..21943746b --- /dev/null +++ b/ILSpy/DisplaySettingsPanel.xaml.cs @@ -0,0 +1,137 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Threading; +using System.Xml.Linq; +using ICSharpCode.Decompiler; + +namespace ICSharpCode.ILSpy +{ + /// + /// Interaction logic for DisplaySettingsPanel.xaml + /// + [ExportOptionPage("Display")] + public partial class DisplaySettingsPanel : UserControl, IOptionPage + { + public DisplaySettingsPanel() + { + InitializeComponent(); + + Task task = new Task(FontLoader); + task.Start(); + task.ContinueWith( + 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) { + MessageBox.Show(ex.ToString()); + } + } + }) + ); + } + ); + } + + public void Load(ILSpySettings settings) + { + 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()) { + GlyphTypeface glyph; + try { + if (tf.TryGetGlyphTypeface(out glyph)) + return glyph.Symbol; + } catch (Exception) { + return true; + } + } + return false; + } + + static FontFamily[] FontLoader() + { + return Fonts.SystemFontFamilies + .Where(ff => !IsSymbolFont(ff)) + .OrderBy(ff => ff.Source) + .ToArray(); + } + + public static DisplaySettings LoadDisplaySettings(ILSpySettings settings) + { + XElement e = settings["DisplaySettings"]; + DisplaySettings s = new DisplaySettings(); + s.SelectedFont = new FontFamily((string)e.Attribute("Font") ?? "Consolas"); + s.SelectedFontSize = (double?)e.Attribute("FontSize") ?? 10.0 * 4 / 3; + + return s; + } + + public void Save(XElement root) + { + DisplaySettings s = (DisplaySettings)this.DataContext; + + currentDisplaySettings.CopyValues(s); + + XElement section = new XElement("DisplaySettings"); + section.SetAttributeValue("Font", s.SelectedFont.Source); + section.SetAttributeValue("FontSize", s.SelectedFontSize); + + XElement existingElement = root.Element("DisplaySettings"); + if (existingElement != null) + existingElement.ReplaceWith(section); + else + root.Add(section); + } + } + + public class FontSizeConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (value is double) { + return Math.Round((double)value / 4 * 3); + } + + throw new NotImplementedException(); + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (value is string) { + double d; + if (double.TryParse((string)value, out d)) + return d * 4 / 3; + return 11 * 4 / 3; + } + + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index e14465833..3eeb462a2 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -102,6 +102,7 @@ DecompilerSettingsPanel.xaml Code + @@ -138,6 +139,10 @@ Code + + DisplaySettingsPanel.xaml + Code + @@ -230,6 +235,7 @@ SearchPane.cs + DecompilerTextView.cs diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 1241037b1..6b6a26f84 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -29,6 +29,7 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; @@ -85,6 +86,8 @@ namespace ICSharpCode.ILSpy.TextView textEditor.Options.RequireControlModifierForHyperlinkClick = false; textEditor.TextArea.TextView.MouseHover += TextViewMouseHover; textEditor.TextArea.TextView.MouseHoverStopped += TextViewMouseHoverStopped; + textEditor.SetBinding(TextEditor.FontFamilyProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("SelectedFont") }); + textEditor.SetBinding(TextEditor.FontSizeProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("SelectedFontSize") }); } #endregion From 975be57b62f65ea253bce84d61538a76228bd76d Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 19 May 2011 18:54:56 +0200 Subject: [PATCH 19/65] implement DecimalConstantTransform closes #184 --- .../Transforms/DecimalConstantTransform.cs | 146 ++++++++++++++++++ .../Ast/Transforms/TransformationPipeline.cs | 1 + .../ICSharpCode.Decompiler.csproj | 1 + 3 files changed, 148 insertions(+) create mode 100644 ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs new file mode 100644 index 000000000..2d75b8bc8 --- /dev/null +++ b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs @@ -0,0 +1,146 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.CSharp; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.Decompiler.Ast.Transforms +{ + /// + /// Description of DecimalConstantTransform. + /// + public class DecimalConstantTransform : DepthFirstAstVisitor, IAstTransform + { + static readonly ICSharpCode.NRefactory.CSharp.Attribute decimalConstantAttribute = new ICSharpCode.NRefactory.CSharp.Attribute { + Type = new SimpleType("DecimalConstant"), + Arguments = { new Repeat(new AnyNode()) } + }; + + static readonly FieldDeclaration decimalConstantPattern = new FieldDeclaration { + Attributes = { + new AttributeSection { + Attributes = { + decimalConstantAttribute + } + } + }, + Modifiers = Modifiers.Any, + Variables = { new Repeat(new AnyNode()) }, + ReturnType = new PrimitiveType("decimal") + }; + + Expression ConstructExpression(string typeName, string member) + { + return new AssignmentExpression( + new MemberReferenceExpression( + new TypeReferenceExpression(new SimpleType(typeName)), + member + ), + AssignmentOperatorType.Assign, + new AnyNode() + ); + } + + class ClassInfo + { + public ClassInfo() + { + Fields = new List(); + } + + public List Fields { get; private set; } + public TypeDeclaration Declaration { get; set; } + } + + Stack replaceableFields; + + public DecimalConstantTransform() + { + } + + void IAstTransform.Run(AstNode compilationUnit) + { + this.replaceableFields = new Stack(); + compilationUnit.AcceptVisitor(this, null); + } + + public override object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) + { + base.VisitFieldDeclaration(fieldDeclaration, data); + + var match = decimalConstantPattern.Match(fieldDeclaration); + + if (match.Success) { + Modifiers pattern = Modifiers.Static | Modifiers.Readonly; + if ((fieldDeclaration.Modifiers & pattern) == pattern) { + replaceableFields.Peek().Fields.AddRange(fieldDeclaration.Variables.Select(v => v.Name)); + fieldDeclaration.ReplaceWith(ReplaceFieldWithConstant); + } + } + + return null; + } + + AstNode ReplaceFieldWithConstant(AstNode node) + { + var old = node as FieldDeclaration; + var fd = new FieldDeclaration { + Modifiers = old.Modifiers & ~(Modifiers.Readonly | Modifiers.Static) | Modifiers.Const, + ReturnType = new PrimitiveType("decimal") + }; + + var foundAttr = old.Attributes.SelectMany(section => section.Attributes) + .First(a => decimalConstantAttribute.IsMatch(a)); + foundAttr.Remove(); + foreach (var attr in old.Attributes.Where(section => section.Attributes.Count == 0)) + attr.Remove(); + + old.Attributes.MoveTo(fd.Attributes); + old.Variables.MoveTo(fd.Variables); + + fd.Variables.Single().Initializer = new PrimitiveExpression(CreateDecimalValue(foundAttr)); + + return fd; + } + + object CreateDecimalValue(ICSharpCode.NRefactory.CSharp.Attribute foundAttr) + { + byte scale = (byte)((PrimitiveExpression)foundAttr.Arguments.ElementAt(0)).Value; + byte sign = (byte)((PrimitiveExpression)foundAttr.Arguments.ElementAt(1)).Value; + int high = (int)(uint)((PrimitiveExpression)foundAttr.Arguments.ElementAt(2)).Value; + int mid = (int)(uint)((PrimitiveExpression)foundAttr.Arguments.ElementAt(3)).Value; + int low = (int)(uint)((PrimitiveExpression)foundAttr.Arguments.ElementAt(4)).Value; + + return new Decimal(low, mid, high, sign == 1, scale); + } + + public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) + { + if ((constructorDeclaration.Modifiers & Modifiers.Static) == Modifiers.Static && replaceableFields.Count > 0) { + var current = replaceableFields.Peek(); + + foreach (var fieldName in current.Fields) { + var pattern = ConstructExpression(current.Declaration.Name, fieldName); + foreach (var expr in constructorDeclaration.Body + .OfType()) { + if (pattern.IsMatch(expr.Expression)) + expr.Remove(); + } + } + } + + return null; + } + + public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + { + replaceableFields.Push(new ClassInfo() { Declaration = typeDeclaration }); + base.VisitTypeDeclaration(typeDeclaration, data); + replaceableFields.Pop(); + return null; + } + } +} diff --git a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs index 686a73a61..1433f0ef5 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs @@ -32,6 +32,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms public static IAstTransform[] CreatePipeline(DecompilerContext context) { return new IAstTransform[] { + new DecimalConstantTransform(), new PushNegation(), new DelegateConstruction(context), new PatternStatementTransform(context), diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index d003c00cd..603543820 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -61,6 +61,7 @@ + From 66c0e844dfd448ac02dae5c87d81c65e784595b7 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 19 May 2011 19:19:21 +0200 Subject: [PATCH 20/65] fix ugly layout of font combobox and preview in DisplaySettingsPanel --- ILSpy/DisplaySettingsPanel.xaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ILSpy/DisplaySettingsPanel.xaml b/ILSpy/DisplaySettingsPanel.xaml index b7282b268..0eb6f9294 100644 --- a/ILSpy/DisplaySettingsPanel.xaml +++ b/ILSpy/DisplaySettingsPanel.xaml @@ -16,18 +16,18 @@ - + - - + + - + - - + + 6 7 8 @@ -48,7 +48,7 @@ 23 24 - + From 184a6fc4f03e94b38523a4bcbec48bfe5ead5be1 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 19 May 2011 19:43:07 +0200 Subject: [PATCH 21/65] replace file header in some files --- .../Transforms/DecimalConstantTransform.cs | 19 +++++++++++++++++-- ILSpy/ConnectMethodDecompiler.cs | 19 +++++++++++++++++-- ILSpy/DisplaySettings.cs | 19 +++++++++++++++++-- ILSpy/DisplaySettingsPanel.xaml.cs | 19 +++++++++++++++++-- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs index 2d75b8bc8..66df123d2 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; diff --git a/ILSpy/ConnectMethodDecompiler.cs b/ILSpy/ConnectMethodDecompiler.cs index b5487f06a..7cb2c1760 100644 --- a/ILSpy/ConnectMethodDecompiler.cs +++ b/ILSpy/ConnectMethodDecompiler.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; diff --git a/ILSpy/DisplaySettings.cs b/ILSpy/DisplaySettings.cs index fe8cbe9e4..4135ec7a5 100644 --- a/ILSpy/DisplaySettings.cs +++ b/ILSpy/DisplaySettings.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.ComponentModel; diff --git a/ILSpy/DisplaySettingsPanel.xaml.cs b/ILSpy/DisplaySettingsPanel.xaml.cs index 21943746b..d7e262c7e 100644 --- a/ILSpy/DisplaySettingsPanel.xaml.cs +++ b/ILSpy/DisplaySettingsPanel.xaml.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; From 51fc2f10cc1cd224ea2c9d6f5b692e8ebaf2c956 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 20 May 2011 09:19:41 +0200 Subject: [PATCH 22/65] Look for generic type parameters defined in TypeDefinition, allows us to display angle brackets in unbound type names, e.g., typeof(List<>) fixes #179 --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index b4860eb7d..45013b6aa 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -436,6 +436,15 @@ namespace ICSharpCode.Decompiler.Ast astType = new MemberType { Target = nsType, MemberName = name }; } else { astType = new SimpleType(name); + + // Look for generic type parameters defined in TypeDefinition + // allows us to display angle brackets in unbound type names + // e.g. typeof(List<>) + TypeDefinition resolvedType = type.Resolve(); + + for (int i = 0; i < resolvedType.GenericParameters.Count; i++) { + ((SimpleType)astType).TypeArguments.Add(new SimpleType("")); + } } astType.AddAnnotation(type); @@ -1433,7 +1442,7 @@ namespace ICSharpCode.Decompiler.Ast if (baseType.HasFields && AnyIsHiddenBy(baseType.Fields, member)) return true; if (includeBaseMethods && baseType.HasMethods - && AnyIsHiddenBy(baseType.Methods, member, m => !m.IsSpecialName)) + && AnyIsHiddenBy(baseType.Methods, member, m => !m.IsSpecialName)) return true; if (baseType.HasNestedTypes && AnyIsHiddenBy(baseType.NestedTypes, member)) return true; @@ -1447,8 +1456,8 @@ namespace ICSharpCode.Decompiler.Ast where T : IMemberDefinition { return members.Any(m => m.Name == derived.Name - && (condition == null || condition(m)) - && TypesHierarchyHelpers.IsVisibleFromDerived(m, derived.DeclaringType)); + && (condition == null || condition(m)) + && TypesHierarchyHelpers.IsVisibleFromDerived(m, derived.DeclaringType)); } /// From ba0b80856cb49813a383a135dfb03b79271ff581 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 20 May 2011 11:17:39 +0200 Subject: [PATCH 23/65] add foldings to documentation comments; closes #165 --- ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs | 13 +++++++++++-- .../CSharp/OutputVisitor/IOutputFormatter.cs | 2 +- .../CSharp/OutputVisitor/OutputVisitor.cs | 4 +++- .../OutputVisitor/TextWriterOutputFormatter.cs | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs b/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs index 1e6915872..f380c7790 100644 --- a/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs +++ b/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs @@ -17,6 +17,7 @@ namespace ICSharpCode.Decompiler.Ast readonly ITextOutput output; readonly Stack nodeStack = new Stack(); int braceLevelWithinType = -1; + bool inDocumentationComment = false; public TextOutputFormatter(ITextOutput output) { @@ -102,7 +103,7 @@ namespace ICSharpCode.Decompiler.Ast output.WriteLine(); } - public void WriteComment(CommentType commentType, string content) + public void WriteComment(CommentType commentType, string content, bool isLastLine = false) { switch (commentType) { case CommentType.SingleLine: @@ -115,8 +116,16 @@ namespace ICSharpCode.Decompiler.Ast output.Write("*/"); break; case CommentType.Documentation: + if (!inDocumentationComment) + output.MarkFoldStart("///" + content, true); output.Write("///"); - output.WriteLine(content); + output.Write(content); + inDocumentationComment = true; + if (isLastLine) { + inDocumentationComment = false; + output.MarkFoldEnd(); + } + output.WriteLine(); break; } } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs index ac1966296..58f8c23ed 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs @@ -39,6 +39,6 @@ namespace ICSharpCode.NRefactory.CSharp void NewLine(); - void WriteComment(CommentType commentType, string content); + void WriteComment(CommentType commentType, string content, bool isLastLine = false); } } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index eb5e9d2ba..e715324ef 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -2147,7 +2147,9 @@ namespace ICSharpCode.NRefactory.CSharp // "1.0 / /*comment*/a", then we need to insert a space in front of the comment. formatter.Space(); } - formatter.WriteComment(comment.CommentType, comment.Content); + bool isContinuing = (comment.NextSibling is Comment && ((Comment)comment.NextSibling).CommentType == comment.CommentType); + + formatter.WriteComment(comment.CommentType, comment.Content, !isContinuing); lastWritten = LastWritten.Whitespace; return null; } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs index f8c1340e5..c6081d4f5 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs @@ -88,7 +88,7 @@ namespace ICSharpCode.NRefactory.CSharp indentation--; } - public void WriteComment(CommentType commentType, string content) + public void WriteComment(CommentType commentType, string content, bool isLastLine = false) { WriteIndentation(); switch (commentType) { From 8c228a4df161e1ed4ce3e3f81e3c7592eb6c41f9 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 20 May 2011 11:26:42 +0200 Subject: [PATCH 24/65] fix bug when printing type names introduced by commit 51fc2f10cc1cd224ea2c9d6f5b692e8ebaf2c956 --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 45013b6aa..97d3d55e8 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -437,13 +437,15 @@ namespace ICSharpCode.Decompiler.Ast } else { astType = new SimpleType(name); - // Look for generic type parameters defined in TypeDefinition - // allows us to display angle brackets in unbound type names - // e.g. typeof(List<>) - TypeDefinition resolvedType = type.Resolve(); - - for (int i = 0; i < resolvedType.GenericParameters.Count; i++) { - ((SimpleType)astType).TypeArguments.Add(new SimpleType("")); + if (!type.HasGenericParameters) { + // Look for generic type parameters defined in TypeDefinition + // allows us to display angle brackets in unbound type names + // e.g. typeof(List<>) + TypeDefinition resolvedType = type.Resolve(); + + for (int i = 0; i < resolvedType.GenericParameters.Count; i++) { + ((SimpleType)astType).TypeArguments.Add(new SimpleType("")); + } } } astType.AddAnnotation(type); From 7513c8c64bdb3182e2ee996249f50397dd684308 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 17 May 2011 00:21:12 +0200 Subject: [PATCH 25/65] Show attributes on parameters in IL view. Closes #187. --- .../Disassembler/ReflectionDisassembler.cs | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index 5231b78c1..bff343db7 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -18,8 +18,8 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; - using Mono.Cecil; using Mono.Collections.Generic; @@ -143,9 +143,12 @@ namespace ICSharpCode.Decompiler.Disassembler WriteFlags(method.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl); output.Unindent(); - if (method.HasBody || method.HasCustomAttributes) { + if (method.HasBody || method.HasCustomAttributes || method.Parameters.Any(HasParameterAttributes)) { OpenBlock(defaultCollapsed: isInType); WriteAttributes(method.CustomAttributes); + foreach (var p in method.Parameters) { + WriteParameterAttributes(p); + } if (method.HasBody) { // create IL code mappings - used in debugger @@ -163,6 +166,12 @@ namespace ICSharpCode.Decompiler.Disassembler { for (int i = 0; i < parameters.Count; i++) { var p = parameters[i]; + if (p.IsIn) + output.Write("[in] "); + if (p.IsOut) + output.Write("[out] "); + if (p.IsOptional) + output.Write("[opt] "); p.ParameterType.WriteTo(output); output.Write(' '); output.WriteDefinition(DisassemblerHelpers.Escape(p.Name), p); @@ -171,6 +180,27 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(); } } + + bool HasParameterAttributes(ParameterDefinition p) + { + return p.HasConstant || p.HasCustomAttributes; + } + + void WriteParameterAttributes(ParameterDefinition p) + { + if (!HasParameterAttributes(p)) + return; + output.Write(".param [{0}]", p.Index); + if (p.HasConstant) { + output.Write(" = "); + if (p.Constant != null) + DisassemblerHelpers.WriteOperand(output, p.Constant); + else + output.Write("nullref"); + } + output.WriteLine(); + WriteAttributes(p.CustomAttributes); + } #endregion #region Disassemble Field From 0e648ef19b564517d32c8796a74518a2ec2c27ae Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 11:58:10 +0200 Subject: [PATCH 26/65] Add support for recursively expanding tree nodes to SharpTreeView. --- ILSpy/TreeNodes/AssemblyTreeNode.cs | 4 ++++ ILSpy/TreeNodes/TypeTreeNode.cs | 4 ++++ SharpTreeView/SharpTreeNode.cs | 14 ++++++++++++++ SharpTreeView/SharpTreeView.cs | 17 +++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs index 73dbb38da..864759152 100644 --- a/ILSpy/TreeNodes/AssemblyTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs @@ -134,6 +134,10 @@ namespace ICSharpCode.ILSpy.TreeNodes this.Children.Add(ns); } } + + public override bool CanExpandRecursively { + get { return true; } + } public TypeTreeNode FindTypeNode(TypeDefinition def) { diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index 23bce5df7..efefb2928 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -117,6 +117,10 @@ namespace ICSharpCode.ILSpy.TreeNodes } } + public override bool CanExpandRecursively { + get { return true; } + } + public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { language.DecompileType(type, output, options); diff --git a/SharpTreeView/SharpTreeNode.cs b/SharpTreeView/SharpTreeNode.cs index 3de3c9f9f..ae0a0e646 100644 --- a/SharpTreeView/SharpTreeNode.cs +++ b/SharpTreeView/SharpTreeNode.cs @@ -267,12 +267,26 @@ namespace ICSharpCode.TreeView lazyLoading = value; if (lazyLoading) { IsExpanded = false; + if (canExpandRecursively) { + canExpandRecursively = false; + RaisePropertyChanged("CanExpandRecursively"); + } } RaisePropertyChanged("LazyLoading"); RaisePropertyChanged("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. + /// + public virtual bool CanExpandRecursively { + get { return canExpandRecursively; } + } + public virtual bool ShowIcon { get { return Icon != null; } diff --git a/SharpTreeView/SharpTreeView.cs b/SharpTreeView/SharpTreeView.cs index d9409b79b..f2a66c797 100644 --- a/SharpTreeView/SharpTreeView.cs +++ b/SharpTreeView/SharpTreeView.cs @@ -227,11 +227,28 @@ namespace ICSharpCode.TreeView e.Handled = true; } break; + case Key.Multiply: + if (container != null && ItemsControl.ItemsControlFromItemContainer(container) == this) { + container.Node.IsExpanded = true; + ExpandRecursively(container.Node); + e.Handled = true; + } + break; } if (!e.Handled) base.OnKeyDown(e); } + void ExpandRecursively(SharpTreeNode node) + { + if (node.CanExpandRecursively) { + node.IsExpanded = true; + foreach (SharpTreeNode child in node.Children) { + ExpandRecursively(child); + } + } + } + /// /// Scrolls the specified node in view and sets keyboard focus on it. /// From 508073d6ac4659ddc3962bb698b5a770ae82ff1d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 12:46:16 +0200 Subject: [PATCH 27/65] Applied some of the optimizations suggested by Kris Vandermotten. #150 --- ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs | 2 +- .../Ast/Transforms/DelegateConstruction.cs | 2 +- ICSharpCode.Decompiler/ILAst/GotoRemoval.cs | 10 +++++----- ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs | 4 ++-- ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs | 2 +- ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs | 4 ++-- .../ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs | 4 ++-- .../ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs | 2 +- .../CSharp/Parser/TypeSystemConvertVisitor.cs | 4 ++-- .../CSharp/Resolver/ResolveVisitor.cs | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs b/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs index f380c7790..b97deb091 100644 --- a/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs +++ b/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs @@ -136,7 +136,7 @@ namespace ICSharpCode.Decompiler.Ast if (ranges != null && ranges.Count > 0) { // find the ancestor that has method mapping as annotation - if (node.Ancestors != null && node.Ancestors.Count() > 0) + if (node.Parent != null) { var n = node.Ancestors.FirstOrDefault(a => a.Annotation() != null); if (n != null) { diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs index 6a5256b44..1d58a021f 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) { - if (objectCreateExpression.Arguments.Count() == 2) { + if (objectCreateExpression.Arguments.Count == 2) { Expression obj = objectCreateExpression.Arguments.First(); Expression func = objectCreateExpression.Arguments.Last(); Annotation annotation = func.Annotation(); diff --git a/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs b/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs index b1d883019..351c28428 100644 --- a/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs +++ b/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs @@ -91,7 +91,7 @@ namespace ICSharpCode.Decompiler.ILAst } } - var defaultCase = ilSwitch.CaseBlocks.Where(cb => cb.Values == null).SingleOrDefault(); + var defaultCase = ilSwitch.CaseBlocks.SingleOrDefault(cb => cb.Values == null); // If there is no default block, remove empty case blocks if (defaultCase == null || (defaultCase.Body.Count == 1 && defaultCase.Body.Single().Match(ILCode.LoopOrSwitchBreak))) { ilSwitch.CaseBlocks.RemoveAll(b => b.Body.Count == 1 && b.Body.Single().Match(ILCode.LoopOrSwitchBreak)); @@ -140,14 +140,14 @@ namespace ICSharpCode.Decompiler.ILAst return true; } - ILNode breakBlock = GetParents(gotoExpr).Where(n => n is ILWhileLoop || n is ILSwitch).FirstOrDefault(); + ILNode breakBlock = GetParents(gotoExpr).FirstOrDefault(n => n is ILWhileLoop || n is ILSwitch); if (breakBlock != null && target == Exit(breakBlock, new HashSet() { gotoExpr })) { gotoExpr.Code = ILCode.LoopOrSwitchBreak; gotoExpr.Operand = null; return true; } - ILNode continueBlock = GetParents(gotoExpr).Where(n => n is ILWhileLoop).FirstOrDefault(); + ILNode continueBlock = GetParents(gotoExpr).FirstOrDefault(n => n is ILWhileLoop); if (continueBlock != null && target == Enter(continueBlock, new HashSet() { gotoExpr })) { gotoExpr.Code = ILCode.LoopContinue; gotoExpr.Operand = null; @@ -209,10 +209,10 @@ namespace ICSharpCode.Decompiler.ILAst } else if (expr.Code == ILCode.Nop) { return Exit(expr, visitedNodes); } else if (expr.Code == ILCode.LoopOrSwitchBreak) { - ILNode breakBlock = GetParents(expr).Where(n => n is ILWhileLoop || n is ILSwitch).First(); + ILNode breakBlock = GetParents(expr).First(n => n is ILWhileLoop || n is ILSwitch); return Exit(breakBlock, new HashSet() { expr }); } else if (expr.Code == ILCode.LoopContinue) { - ILNode continueBlock = GetParents(expr).Where(n => n is ILWhileLoop).First(); + ILNode continueBlock = GetParents(expr).First(n => n is ILWhileLoop); return Enter(continueBlock, new HashSet() { expr }); } else { return expr; diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index 9c845293b..aed211f56 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -455,7 +455,7 @@ namespace ICSharpCode.Decompiler.ILAst if (byteCode.StoreTo != null && byteCode.StoreTo.Count > 1) { var locVars = byteCode.StoreTo; // For each of the variables, find the location where it is loaded - there should be preciesly one - var loadedBy = locVars.Select(locVar => reachableBody.SelectMany(bc => bc.StackBefore).Where(s => s.LoadFrom == locVar).Single()).ToList(); + var loadedBy = locVars.Select(locVar => reachableBody.SelectMany(bc => bc.StackBefore).Single(s => s.LoadFrom == locVar)).ToList(); // We now know that all the variables have a single load, // Let's make sure that they have also a single store - us if (loadedBy.All(slot => slot.PushedBy.Length == 1 && slot.PushedBy[0] == byteCode)) { @@ -572,7 +572,7 @@ namespace ICSharpCode.Decompiler.ILAst Loads = new List() { load } }); } else if (storedBy.Length == 1) { - VariableInfo newVar = newVars.Where(v => v.Stores.Contains(storedBy[0])).Single(); + VariableInfo newVar = newVars.Single(v => v.Stores.Contains(storedBy[0])); newVar.Loads.Add(load); } else { List mergeVars = newVars.Where(v => v.Stores.Union(storedBy).Any()).ToList(); diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index be7e16e2d..1e4ebeddd 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -398,7 +398,7 @@ namespace ICSharpCode.Decompiler.ILAst lastNode.IsUnconditionalControlFlow()) { // Try to reuse the label - ILLabel label = currNode is ILLabel ? ((ILLabel)currNode) : new ILLabel() { Name = "Block_" + (nextLabelIndex++) }; + ILLabel label = currNode as ILLabel ?? new ILLabel() { Name = "Block_" + (nextLabelIndex++).ToString() }; // Terminate the last block if (!lastNode.IsUnconditionalControlFlow()) { diff --git a/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs b/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs index cd5656c9d..e5409a2e5 100644 --- a/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs +++ b/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.ILAst { Dictionary labelToCfNode = new Dictionary(); - DecompilerContext context; + readonly DecompilerContext context; uint nextLabelIndex = 0; @@ -286,7 +286,7 @@ namespace ICSharpCode.Decompiler.ILAst ILLabel condLabel = caseLabels[i]; // Find or create new case block - ILSwitch.CaseBlock caseBlock = ilSwitch.CaseBlocks.Where(b => b.EntryGoto.Operand == condLabel).FirstOrDefault(); + ILSwitch.CaseBlock caseBlock = ilSwitch.CaseBlocks.FirstOrDefault(b => b.EntryGoto.Operand == condLabel); if (caseBlock == null) { caseBlock = new ILSwitch.CaseBlock() { Values = new List(), diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs index b888cdea2..813f47213 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp public int PointerRank { get { - return GetChildrenByRole(PointerRole).Count(); + return GetChildrenByRole(PointerRole).Count; } set { if (value < 0) @@ -141,7 +141,7 @@ namespace ICSharpCode.NRefactory.CSharp } public int Dimensions { - get { return 1 + GetChildrenByRole(Roles.Comma).Count(); } + get { return 1 + GetChildrenByRole(Roles.Comma).Count; } set { int d = this.Dimensions; while (d > value) { diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs index 70f1ddca4..6db26e523 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs @@ -96,7 +96,7 @@ namespace ICSharpCode.NRefactory.CSharp { if (name == null) throw new ArgumentNullException("name"); - IsVerbatim = name.StartsWith ("@"); + IsVerbatim = name.Length > 0 && name[0] == '@'; this.Name = IsVerbatim ? name.Substring (1) : name; this.startLocation = location; } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs index 66865d53c..756adce40 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs @@ -263,7 +263,7 @@ namespace ICSharpCode.NRefactory.CSharp #region Fields public override IEntity VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) { - bool isSingleField = fieldDeclaration.Variables.Count() == 1; + bool isSingleField = fieldDeclaration.Variables.Count == 1; Modifiers modifiers = fieldDeclaration.Modifiers; DefaultField field = null; foreach (VariableInitializer vi in fieldDeclaration.Variables) { @@ -476,7 +476,7 @@ namespace ICSharpCode.NRefactory.CSharp #region Events public override IEntity VisitEventDeclaration(EventDeclaration eventDeclaration, object data) { - bool isSingleEvent = eventDeclaration.Variables.Count() == 1; + bool isSingleEvent = eventDeclaration.Variables.Count == 1; Modifiers modifiers = eventDeclaration.Modifiers; DefaultEvent ev = null; foreach (VariableInitializer vi in eventDeclaration.Variables) { diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs index 3bcea943b..162f5c2bf 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs @@ -241,7 +241,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult VisitFieldOrEventDeclaration(AttributedNode fieldOrEventDeclaration) { - int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(FieldDeclaration.Roles.Variable).Count(); + int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(FieldDeclaration.Roles.Variable).Count; ResolveResult result = null; for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) { if (node.Role == FieldDeclaration.Roles.Variable) { @@ -939,7 +939,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver firstInitializer != null ? firstInitializer.Initializer : null, false); - int initializerCount = variableDeclarationStatement.Variables.Count(); + int initializerCount = variableDeclarationStatement.Variables.Count; ResolveResult result = null; for (AstNode node = variableDeclarationStatement.FirstChild; node != null; node = node.NextSibling) { if (node.Role == FieldDeclaration.Roles.Variable) { From 30fe30c2361880314d00c68906feeb90981efe01 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 14:19:09 +0200 Subject: [PATCH 28/65] Fix DecimalConstantTransform. --- .../Transforms/DecimalConstantTransform.cs | 137 +++--------------- .../Ast/Transforms/TransformationPipeline.cs | 2 +- 2 files changed, 18 insertions(+), 121 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs index 66df123d2..298682afb 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs @@ -17,145 +17,42 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections.Generic; -using System.Linq; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.PatternMatching; +using Mono.Cecil; namespace ICSharpCode.Decompiler.Ast.Transforms { /// - /// Description of DecimalConstantTransform. + /// Transforms decimal constant fields. /// public class DecimalConstantTransform : DepthFirstAstVisitor, IAstTransform { - static readonly ICSharpCode.NRefactory.CSharp.Attribute decimalConstantAttribute = new ICSharpCode.NRefactory.CSharp.Attribute { - Type = new SimpleType("DecimalConstant"), - Arguments = { new Repeat(new AnyNode()) } - }; - - static readonly FieldDeclaration decimalConstantPattern = new FieldDeclaration { - Attributes = { - new AttributeSection { - Attributes = { - decimalConstantAttribute - } - } - }, - Modifiers = Modifiers.Any, - Variables = { new Repeat(new AnyNode()) }, - ReturnType = new PrimitiveType("decimal") - }; - - Expression ConstructExpression(string typeName, string member) - { - return new AssignmentExpression( - new MemberReferenceExpression( - new TypeReferenceExpression(new SimpleType(typeName)), - member - ), - AssignmentOperatorType.Assign, - new AnyNode() - ); - } - - class ClassInfo - { - public ClassInfo() - { - Fields = new List(); - } - - public List Fields { get; private set; } - public TypeDeclaration Declaration { get; set; } - } - - Stack replaceableFields; - - public DecimalConstantTransform() - { - } - - void IAstTransform.Run(AstNode compilationUnit) - { - this.replaceableFields = new Stack(); - compilationUnit.AcceptVisitor(this, null); - } + static readonly PrimitiveType decimalType = new PrimitiveType("decimal"); public override object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) { - base.VisitFieldDeclaration(fieldDeclaration, data); - - var match = decimalConstantPattern.Match(fieldDeclaration); - - if (match.Success) { - Modifiers pattern = Modifiers.Static | Modifiers.Readonly; - if ((fieldDeclaration.Modifiers & pattern) == pattern) { - replaceableFields.Peek().Fields.AddRange(fieldDeclaration.Variables.Select(v => v.Name)); - fieldDeclaration.ReplaceWith(ReplaceFieldWithConstant); - } - } - - return null; - } - - AstNode ReplaceFieldWithConstant(AstNode node) - { - var old = node as FieldDeclaration; - var fd = new FieldDeclaration { - Modifiers = old.Modifiers & ~(Modifiers.Readonly | Modifiers.Static) | Modifiers.Const, - ReturnType = new PrimitiveType("decimal") - }; - - var foundAttr = old.Attributes.SelectMany(section => section.Attributes) - .First(a => decimalConstantAttribute.IsMatch(a)); - foundAttr.Remove(); - foreach (var attr in old.Attributes.Where(section => section.Attributes.Count == 0)) - attr.Remove(); - - old.Attributes.MoveTo(fd.Attributes); - old.Variables.MoveTo(fd.Variables); - - fd.Variables.Single().Initializer = new PrimitiveExpression(CreateDecimalValue(foundAttr)); - - return fd; - } - - object CreateDecimalValue(ICSharpCode.NRefactory.CSharp.Attribute foundAttr) - { - byte scale = (byte)((PrimitiveExpression)foundAttr.Arguments.ElementAt(0)).Value; - byte sign = (byte)((PrimitiveExpression)foundAttr.Arguments.ElementAt(1)).Value; - int high = (int)(uint)((PrimitiveExpression)foundAttr.Arguments.ElementAt(2)).Value; - int mid = (int)(uint)((PrimitiveExpression)foundAttr.Arguments.ElementAt(3)).Value; - int low = (int)(uint)((PrimitiveExpression)foundAttr.Arguments.ElementAt(4)).Value; - - return new Decimal(low, mid, high, sign == 1, scale); - } - - public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) - { - if ((constructorDeclaration.Modifiers & Modifiers.Static) == Modifiers.Static && replaceableFields.Count > 0) { - var current = replaceableFields.Peek(); - - foreach (var fieldName in current.Fields) { - var pattern = ConstructExpression(current.Declaration.Name, fieldName); - foreach (var expr in constructorDeclaration.Body - .OfType()) { - if (pattern.IsMatch(expr.Expression)) - expr.Remove(); + 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) { + TypeReference tr = attribute.Type.Annotation(); + if (tr != null && tr.Name == "DecimalConstantAttribute" && tr.Namespace == "System.Runtime.CompilerServices") { + attribute.Remove(); + if (attributeSection.Attributes.Count == 0) + attributeSection.Remove(); + fieldDeclaration.Modifiers = (fieldDeclaration.Modifiers & ~staticReadOnly) | Modifiers.Const; + return null; + } } } } - return null; } - public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + public void Run(AstNode compilationUnit) { - replaceableFields.Push(new ClassInfo() { Declaration = typeDeclaration }); - base.VisitTypeDeclaration(typeDeclaration, data); - replaceableFields.Pop(); - return null; + compilationUnit.AcceptVisitor(this, null); } } } diff --git a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs index 1433f0ef5..13730ea1d 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs @@ -32,7 +32,6 @@ namespace ICSharpCode.Decompiler.Ast.Transforms public static IAstTransform[] CreatePipeline(DecompilerContext context) { return new IAstTransform[] { - new DecimalConstantTransform(), new PushNegation(), new DelegateConstruction(context), new PatternStatementTransform(context), @@ -41,6 +40,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms new AddCheckedBlocks(), new DeclareVariables(context), // should run after most transforms that modify statements new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables + new DecimalConstantTransform(), new IntroduceUsingDeclarations(context), new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods From 478035dfd9608f1c1ef2524dbf61a75331e69fa0 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 15:00:43 +0200 Subject: [PATCH 29/65] Fix issues introduced when merging #166. --- .../ILAst/PeepholeTransform.cs | 76 ++++++++++--------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs b/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs index e4771eb48..93c8aa5d0 100644 --- a/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs +++ b/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs @@ -454,13 +454,6 @@ namespace ICSharpCode.Decompiler.ILAst return modified; } - private static IDictionary _postIncrementPairs = new Dictionary - { - {ILCode.Ldloc, ILCode.Stloc}, - {ILCode.Ldsfld, ILCode.Stsfld}, - {ILCode.CallGetter, ILCode.CallSetter} - }; - bool IntroducePostIncrementForVariables(List body, ILExpression expr, int pos) { // Works for variables and static fields/properties @@ -474,38 +467,48 @@ namespace ICSharpCode.Decompiler.ILAst if (!(expr.Match(ILCode.Stloc, out exprVar, out exprInit) && exprVar.IsGenerated)) return false; - ILCode loadInstruction = exprInit.Code; - //We only recognise local variables, fields & getters with no arguments - if (!_postIncrementPairs.ContainsKey(loadInstruction)) - return false; - if (loadInstruction == ILCode.CallGetter && exprInit.Arguments.Count != 0) - return false; - //The next expression ILExpression nextExpr = body.ElementAtOrDefault(pos + 1) as ILExpression; if (nextExpr == null) return false; + + ILCode loadInstruction = exprInit.Code; ILCode storeInstruction = nextExpr.Code; - //Must be a matching store type - if (_postIncrementPairs[loadInstruction] != storeInstruction) - return false; + bool recombineVariable = false; - object nextExprOperand = nextExpr.Operand; - object exprInitOperand = exprInit.Operand; - if (loadInstruction == ILCode.CallGetter) - if (!IsGetterSetterPair(exprInitOperand, nextExprOperand)) - return false; - - if (loadInstruction == ILCode.Ldloc) - if ((nextExprOperand != exprInitOperand)) - if (((ILVariable) nextExprOperand).OriginalVariable == ((ILVariable) exprInitOperand).OriginalVariable) - //Spit local variable, unsplit these two instances - foreach (var ilExpression in body.SelectMany( - node => node.GetSelfAndChildrenRecursive( - expression => expression.Operand == nextExprOperand))) - ilExpression.Operand = exprInitOperand; - else + // We only recognise local variables, static fields, and static getters with no arguments + switch (loadInstruction) { + case ILCode.Ldloc: + //Must be a matching store type + if (storeInstruction != ILCode.Stloc) return false; + ILVariable loadVar = (ILVariable)exprInit.Operand; + ILVariable storeVar = (ILVariable)nextExpr.Operand; + if (loadVar != storeVar) { + if (loadVar.OriginalVariable != null && loadVar.OriginalVariable == storeVar.OriginalVariable) + recombineVariable = true; + else + return false; + } + break; + case ILCode.Ldsfld: + if (storeInstruction != ILCode.Stsfld) + return false; + if (exprInit.Operand != nextExpr.Operand) + return false; + break; + case ILCode.CallGetter: + // non-static getters would have the 'this' argument + if (exprInit.Arguments.Count != 0) + return false; + if (storeInstruction != ILCode.CallSetter) + return false; + if (!IsGetterSetterPair(exprInit.Operand, nextExpr.Operand)) + return false; + break; + default: + return false; + } ILExpression addExpr = nextExpr.Arguments[0]; @@ -514,8 +517,13 @@ namespace ICSharpCode.Decompiler.ILAst if (!(incrementAmount != 0 && addExpr.Arguments[0].MatchLdloc(exprVar))) return false; - switch (loadInstruction) - { + if (recombineVariable) { + // Split local variable, unsplit these two instances + foreach (var ilExpression in method.GetSelfAndChildrenRecursive(expression => expression.Operand == nextExpr.Operand)) + ilExpression.Operand = exprInit.Operand; + } + + switch (loadInstruction) { case ILCode.Ldloc: exprInit.Code = ILCode.Ldloca; break; From ee2cae3d1ab76967953188ebed12e123e9241d2d Mon Sep 17 00:00:00 2001 From: Eusebiu Marcu Date: Fri, 20 May 2011 17:14:34 +0300 Subject: [PATCH 30/65] Add line numbers to text editor and in display settings. --- ILSpy/DisplaySettings.cs | 13 +++++++++++++ ILSpy/DisplaySettingsPanel.xaml | 7 +++++++ ILSpy/DisplaySettingsPanel.xaml.cs | 2 ++ ILSpy/TextView/DecompilerTextView.cs | 1 + 4 files changed, 23 insertions(+) diff --git a/ILSpy/DisplaySettings.cs b/ILSpy/DisplaySettings.cs index 4135ec7a5..569bc0509 100644 --- a/ILSpy/DisplaySettings.cs +++ b/ILSpy/DisplaySettings.cs @@ -71,10 +71,23 @@ namespace ICSharpCode.ILSpy } } + bool showLineNumbers; + + public bool ShowLineNumbers { + get { return showLineNumbers; } + set { + if (showLineNumbers != value) { + showLineNumbers = value; + OnPropertyChanged("ShowLineNumbers"); + } + } + } + public void CopyValues(DisplaySettings s) { this.SelectedFont = s.selectedFont; this.SelectedFontSize = s.selectedFontSize; + this.ShowLineNumbers = s.showLineNumbers; } } } diff --git a/ILSpy/DisplaySettingsPanel.xaml b/ILSpy/DisplaySettingsPanel.xaml index 0eb6f9294..97131eca3 100644 --- a/ILSpy/DisplaySettingsPanel.xaml +++ b/ILSpy/DisplaySettingsPanel.xaml @@ -6,6 +6,10 @@ + + + + @@ -53,5 +57,8 @@ + + Show line numbers + \ No newline at end of file diff --git a/ILSpy/DisplaySettingsPanel.xaml.cs b/ILSpy/DisplaySettingsPanel.xaml.cs index d7e262c7e..b66bb316d 100644 --- a/ILSpy/DisplaySettingsPanel.xaml.cs +++ b/ILSpy/DisplaySettingsPanel.xaml.cs @@ -104,6 +104,7 @@ namespace ICSharpCode.ILSpy DisplaySettings s = new DisplaySettings(); s.SelectedFont = new FontFamily((string)e.Attribute("Font") ?? "Consolas"); s.SelectedFontSize = (double?)e.Attribute("FontSize") ?? 10.0 * 4 / 3; + s.ShowLineNumbers = (bool?)e.Attribute("ShowLineNumbers") ?? false; return s; } @@ -117,6 +118,7 @@ namespace ICSharpCode.ILSpy XElement section = new XElement("DisplaySettings"); section.SetAttributeValue("Font", s.SelectedFont.Source); section.SetAttributeValue("FontSize", s.SelectedFontSize); + section.SetAttributeValue("ShowLineNumbers", s.ShowLineNumbers); XElement existingElement = root.Element("DisplaySettings"); if (existingElement != null) diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 6b6a26f84..748210427 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -88,6 +88,7 @@ namespace ICSharpCode.ILSpy.TextView textEditor.TextArea.TextView.MouseHoverStopped += TextViewMouseHoverStopped; textEditor.SetBinding(TextEditor.FontFamilyProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("SelectedFont") }); textEditor.SetBinding(TextEditor.FontSizeProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("SelectedFontSize") }); + textEditor.SetBinding(TextEditor.ShowLineNumbersProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("ShowLineNumbers") }); } #endregion From 4ec92d9a558faad5afe1b75f485e682ffcc3e81f Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 15:23:01 +0200 Subject: [PATCH 31/65] Handle cpobj instruction as stobj(ldobj). --- .../Ast/AstMethodBodyBuilder.cs | 15 +++++++-------- ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs | 4 ++++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index 4d184ad02..babc9cd79 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -485,9 +485,12 @@ namespace ICSharpCode.Decompiler.Ast return arg1; else return arg1.CastTo(operandAsTypeRef); - case ILCode.Isinst: return arg1.CastAs(operandAsTypeRef); - case ILCode.Box: return arg1; - case ILCode.Unbox: return InlineAssembly(byteCode, args); + case ILCode.Isinst: + return arg1.CastAs(operandAsTypeRef); + case ILCode.Box: + return arg1; + case ILCode.Unbox: + return MakeRef(arg1.CastTo(operandAsTypeRef)); #endregion #region Indirect case ILCode.Ldind_Ref: @@ -539,11 +542,7 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Endfilter: return InlineAssembly(byteCode, args); case ILCode.Endfinally: return null; case ILCode.Initblk: return InlineAssembly(byteCode, args); - case ILCode.Initobj: - if (args[0] is DirectionExpression) - return new AssignmentExpression(((DirectionExpression)args[0]).Expression.Detach(), MakeDefaultValue((TypeReference)operand)); - else - return InlineAssembly(byteCode, args); + case ILCode.Initobj: return InlineAssembly(byteCode, args); case ILCode.DefaultValue: return MakeDefaultValue((TypeReference)operand); case ILCode.Jmp: return InlineAssembly(byteCode, args); diff --git a/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs b/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs index 93c8aa5d0..f9e596514 100644 --- a/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs +++ b/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs @@ -90,6 +90,10 @@ namespace ICSharpCode.Decompiler.ILAst expr.Code = ILCode.Stobj; expr.Arguments.Add(new ILExpression(ILCode.DefaultValue, expr.Operand)); modified = true; + } else if (expr.Code == ILCode.Cpobj) { + expr.Code = ILCode.Stobj; + expr.Arguments[1] = new ILExpression(ILCode.Ldobj, expr.Operand, expr.Arguments[1]); + modified = true; } ILExpression arg, arg2; TypeReference type; From faf3a29a08c0a2a871f5efcd797f365abb88af19 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 18:40:22 +0200 Subject: [PATCH 32/65] Fixed position of XML comments on nested types. --- .../ICSharpCode.AvalonEdit.csproj | 1 + ICSharpCode.Decompiler/Ast/AstBuilder.cs | 18 +++++++++--------- .../Documentation/XmlDocumentationProvider.cs | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj b/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj index 0b12dff5b..ee5e00268 100644 --- a/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj +++ b/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj @@ -215,6 +215,7 @@ + IBackgroundRenderer.cs diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 97d3d55e8..4da825fb4 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -228,15 +228,6 @@ namespace ICSharpCode.Decompiler.Ast astType.TypeParameters.AddRange(MakeTypeParameters(genericParameters)); astType.Constraints.AddRange(MakeConstraints(genericParameters)); - // Nested types - foreach (TypeDefinition nestedTypeDef in typeDef.NestedTypes) { - if (MemberIsHidden(nestedTypeDef, context.Settings)) - continue; - var nestedType = CreateType(nestedTypeDef); - SetNewModifier(nestedType); - astType.AddChild(nestedType, TypeDeclaration.MemberRole); - } - AttributedNode result = astType; if (typeDef.IsEnum) { long expectedEnumMemberValue = 0; @@ -608,6 +599,15 @@ namespace ICSharpCode.Decompiler.Ast void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef) { + // Nested types + foreach (TypeDefinition nestedTypeDef in typeDef.NestedTypes) { + if (MemberIsHidden(nestedTypeDef, context.Settings)) + continue; + var nestedType = CreateType(nestedTypeDef); + SetNewModifier(nestedType); + astType.AddChild(nestedType, TypeDeclaration.MemberRole); + } + // Add fields foreach(FieldDefinition fieldDef in typeDef.Fields) { if (MemberIsHidden(fieldDef, context.Settings)) continue; diff --git a/NRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs b/NRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs index 315f212eb..70d88aa16 100644 --- a/NRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs +++ b/NRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs @@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.Documentation static string GetRedirectionTarget(string target) { - string programFilesDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); + string programFilesDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); programFilesDir = AppendDirectorySeparator(programFilesDir); string corSysDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(); From e9eca059d5c1e19492d3b6b969620b2cde6ab58b Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 20 May 2011 13:23:44 +0200 Subject: [PATCH 33/65] remove isLastLine from interface - use stack instead; fix null reference if resolve of TypeDefinition fails --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 12 ++++++------ ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs | 3 ++- .../CSharp/OutputVisitor/IOutputFormatter.cs | 2 +- .../CSharp/OutputVisitor/OutputVisitor.cs | 4 +--- .../OutputVisitor/TextWriterOutputFormatter.cs | 2 +- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 4da825fb4..c7845c61d 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -427,13 +427,13 @@ namespace ICSharpCode.Decompiler.Ast astType = new MemberType { Target = nsType, MemberName = name }; } else { astType = new SimpleType(name); + + // Look for generic type parameters defined in TypeDefinition + // allows us to display angle brackets in unbound type names + // e.g. typeof(List<>) + TypeDefinition resolvedType = type.Resolve(); - if (!type.HasGenericParameters) { - // Look for generic type parameters defined in TypeDefinition - // allows us to display angle brackets in unbound type names - // e.g. typeof(List<>) - TypeDefinition resolvedType = type.Resolve(); - + if (!type.HasGenericParameters && resolvedType != null) { for (int i = 0; i < resolvedType.GenericParameters.Count; i++) { ((SimpleType)astType).TypeArguments.Add(new SimpleType("")); } diff --git a/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs b/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs index b97deb091..d0edf5bcc 100644 --- a/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs +++ b/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs @@ -103,7 +103,7 @@ namespace ICSharpCode.Decompiler.Ast output.WriteLine(); } - public void WriteComment(CommentType commentType, string content, bool isLastLine = false) + public void WriteComment(CommentType commentType, string content) { switch (commentType) { case CommentType.SingleLine: @@ -121,6 +121,7 @@ namespace ICSharpCode.Decompiler.Ast output.Write("///"); output.Write(content); inDocumentationComment = true; + bool isLastLine = !(nodeStack.Peek().NextSibling is Comment); if (isLastLine) { inDocumentationComment = false; output.MarkFoldEnd(); diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs index 58f8c23ed..ac1966296 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs @@ -39,6 +39,6 @@ namespace ICSharpCode.NRefactory.CSharp void NewLine(); - void WriteComment(CommentType commentType, string content, bool isLastLine = false); + void WriteComment(CommentType commentType, string content); } } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index e715324ef..eb5e9d2ba 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -2147,9 +2147,7 @@ namespace ICSharpCode.NRefactory.CSharp // "1.0 / /*comment*/a", then we need to insert a space in front of the comment. formatter.Space(); } - bool isContinuing = (comment.NextSibling is Comment && ((Comment)comment.NextSibling).CommentType == comment.CommentType); - - formatter.WriteComment(comment.CommentType, comment.Content, !isContinuing); + formatter.WriteComment(comment.CommentType, comment.Content); lastWritten = LastWritten.Whitespace; return null; } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs index c6081d4f5..f8c1340e5 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs @@ -88,7 +88,7 @@ namespace ICSharpCode.NRefactory.CSharp indentation--; } - public void WriteComment(CommentType commentType, string content, bool isLastLine = false) + public void WriteComment(CommentType commentType, string content) { WriteIndentation(); switch (commentType) { From 439de223bfa43ecfdb431e22f7ff618a02e35955 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 20 May 2011 19:45:40 +0200 Subject: [PATCH 34/65] implement proper fix for #179 + add unit test --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 11 -------- .../Ast/AstMethodBodyBuilder.cs | 28 ++++++++++++++++++- ICSharpCode.Decompiler/Tests/Generics.cs | 4 +++ 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index c7845c61d..be793f881 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -427,17 +427,6 @@ namespace ICSharpCode.Decompiler.Ast astType = new MemberType { Target = nsType, MemberName = name }; } else { astType = new SimpleType(name); - - // Look for generic type parameters defined in TypeDefinition - // allows us to display angle brackets in unbound type names - // e.g. typeof(List<>) - TypeDefinition resolvedType = type.Resolve(); - - if (!type.HasGenericParameters && resolvedType != null) { - for (int i = 0; i < resolvedType.GenericParameters.Count; i++) { - ((SimpleType)astType).TypeArguments.Add(new SimpleType("")); - } - } } astType.AddAnnotation(type); diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index babc9cd79..b54cd21ae 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -601,7 +601,7 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Ldstr: return new Ast.PrimitiveExpression(operand); case ILCode.Ldtoken: if (operand is Cecil.TypeReference) { - return new Ast.TypeOfExpression { Type = operandAsTypeRef }.Member("TypeHandle"); + return new Ast.TypeOfExpression { Type = AddEmptyTypeArgumentsForUnboundGenerics(operandAsTypeRef) }.Member("TypeHandle"); } else { return InlineAssembly(byteCode, args); } @@ -749,6 +749,32 @@ namespace ICSharpCode.Decompiler.Ast } } + AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type) + { + TypeDefinition typeDef = type.Annotation().Resolve(); + if (typeDef == null || !typeDef.HasGenericParameters) + return type; + SimpleType sType = type as SimpleType; + MemberType mType = type as MemberType; + if (sType != null) { + while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) { + sType.TypeArguments.Add(new SimpleType("")); + } + } + + if (mType != null) { + AddEmptyTypeArgumentsForUnboundGenerics(mType.Target); + + int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count; + + while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) { + mType.TypeArguments.Add(new SimpleType("")); + } + } + + return type; + } + static readonly AstNode objectInitializerPattern = new AssignmentExpression( new MemberReferenceExpression { Target = new InitializedObjectExpression() diff --git a/ICSharpCode.Decompiler/Tests/Generics.cs b/ICSharpCode.Decompiler/Tests/Generics.cs index 53cd5f623..4a1da99b5 100644 --- a/ICSharpCode.Decompiler/Tests/Generics.cs +++ b/ICSharpCode.Decompiler/Tests/Generics.cs @@ -60,6 +60,10 @@ public static class Generics } } + private static Type type1 = typeof(List<>); + private static Type type2 = typeof(Generics.MyArray<>); + private static Type type3 = typeof(List<>.Enumerator); + public static void MethodWithConstraint() where T : class, S where S : ICloneable, new() { } From b01fe1b4273b10bf34d332a2d0fe16e3535846a0 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 19:55:06 +0200 Subject: [PATCH 35/65] Fixed NullReferenceException when decompiling "typeof(List[])". --- ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs | 5 ++++- ICSharpCode.Decompiler/Tests/Generics.cs | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index b54cd21ae..c8666b73a 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -751,7 +751,10 @@ namespace ICSharpCode.Decompiler.Ast AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type) { - TypeDefinition typeDef = type.Annotation().Resolve(); + TypeReference typeRef = type.Annotation(); + if (typeRef == null) + return type; + TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters if (typeDef == null || !typeDef.HasGenericParameters) return type; SimpleType sType = type as SimpleType; diff --git a/ICSharpCode.Decompiler/Tests/Generics.cs b/ICSharpCode.Decompiler/Tests/Generics.cs index 4a1da99b5..e5b6e2eb7 100644 --- a/ICSharpCode.Decompiler/Tests/Generics.cs +++ b/ICSharpCode.Decompiler/Tests/Generics.cs @@ -63,6 +63,8 @@ public static class Generics private static Type type1 = typeof(List<>); private static Type type2 = typeof(Generics.MyArray<>); private static Type type3 = typeof(List<>.Enumerator); + private static Type type4 = typeof(Generics.MyArray<>.NestedClass<>); + private static Type type5 = typeof(List[]); public static void MethodWithConstraint() where T : class, S where S : ICloneable, new() { From e2794252fb1a5cde291a276aec9408d4bcff0b33 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 21:33:38 +0200 Subject: [PATCH 36/65] When decompiling a field, also decompile constructors to check whether there's an initializer on the field. When decompiling a constructor, display field initializers outside of the constructor. Closes #3. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 3 + .../ConvertConstructorCallIntoInitializer.cs | 56 +++++++--- ILSpy/CSharpLanguage.cs | 102 ++++++++++++++++-- .../CSharp/OutputVisitor/OutputVisitor.cs | 2 + 4 files changed, 141 insertions(+), 22 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index be793f881..f941af8b3 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -729,6 +729,9 @@ namespace ICSharpCode.Decompiler.Ast astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters); ConvertAttributes(astMethod, methodDef); astMethod.WithAnnotation(methodMapping); + if (methodDef.IsStatic && methodDef.DeclaringType.IsBeforeFieldInit && !astMethod.Body.IsNull) { + astMethod.Body.InsertChildAfter(null, new Comment(" Note: this type is marked as 'beforefieldinit'."), AstNode.Roles.Comment); + } return astMethod; } diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs b/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs index 716754595..054d3066e 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using System.Linq; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.PatternMatching; @@ -69,9 +70,29 @@ namespace ICSharpCode.Decompiler.Ast.Transforms public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { - var instanceCtors = typeDeclaration.Members.OfType().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); + // Handle initializers on instance fields + HandleInstanceFieldInitializers(typeDeclaration.Members); + + // Now convert base constructor calls to initializers: + base.VisitTypeDeclaration(typeDeclaration, data); + + // Remove single empty constructor: + RemoveSingleEmptyConstructor(typeDeclaration); + + // Handle initializers on static fields: + HandleStaticFieldInitializers(typeDeclaration.Members); + return null; + } + + void HandleInstanceFieldInitializers(IEnumerable members) + { + 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 && typeDeclaration.ClassType == NRefactory.TypeSystem.ClassType.Class) { + if (instanceCtorsNotChainingWithThis.Length > 0) { + MethodDefinition ctorMethodDef = instanceCtorsNotChainingWithThis[0].Annotation(); + if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsValueType) + return; + // Recognize field initializers: // Convert first statement in all ctors (if all ctors have the same statement) into a field initializer. bool allSame; @@ -83,7 +104,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms FieldDefinition fieldDef = m.Get("fieldAccess").Single().Annotation().ResolveWithinSameModule(); if (fieldDef == null) break; - AttributedNode fieldOrEventDecl = typeDeclaration.Members.FirstOrDefault(f => f.Annotation() == fieldDef); + AstNode fieldOrEventDecl = members.FirstOrDefault(f => f.Annotation() == fieldDef); if (fieldOrEventDecl == null) break; @@ -99,11 +120,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms } } while (allSame); } - - // Now convert base constructor calls to initializers: - base.VisitTypeDeclaration(typeDeclaration, data); - - // Remove single empty constructor: + } + + void RemoveSingleEmptyConstructor(TypeDeclaration typeDeclaration) + { + var instanceCtors = typeDeclaration.Members.OfType().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); if (instanceCtors.Length == 1) { ConstructorDeclaration emptyCtor = new ConstructorDeclaration(); emptyCtor.Modifiers = ((typeDeclaration.Modifiers & Modifiers.Abstract) == Modifiers.Abstract ? Modifiers.Protected : Modifiers.Public); @@ -111,12 +132,15 @@ namespace ICSharpCode.Decompiler.Ast.Transforms if (emptyCtor.IsMatch(instanceCtors[0])) instanceCtors[0].Remove(); } - + } + + void HandleStaticFieldInitializers(IEnumerable members) + { // Convert static constructor into field initializers if the class is BeforeFieldInit - var staticCtor = typeDeclaration.Members.OfType().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static); + var staticCtor = members.OfType().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static); if (staticCtor != null) { - TypeDefinition typeDef = typeDeclaration.Annotation(); - if (typeDef != null && typeDef.IsBeforeFieldInit) { + MethodDefinition ctorMethodDef = staticCtor.Annotation(); + if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsBeforeFieldInit) { while (true) { ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement; if (es == null) @@ -127,7 +151,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms FieldDefinition fieldDef = assignment.Left.Annotation().ResolveWithinSameModule(); if (fieldDef == null || !fieldDef.IsStatic) break; - FieldDeclaration fieldDecl = typeDeclaration.Members.OfType().FirstOrDefault(f => f.Annotation() == fieldDef); + FieldDeclaration fieldDecl = members.OfType().FirstOrDefault(f => f.Annotation() == fieldDef); if (fieldDecl == null) break; fieldDecl.Variables.Single().Initializer = assignment.Right.Detach(); @@ -137,11 +161,15 @@ namespace ICSharpCode.Decompiler.Ast.Transforms staticCtor.Remove(); } } - return null; } void IAstTransform.Run(AstNode node) { + // If we're viewing some set of members (fields are direct children of CompilationUnit), + // we also need to handle those: + HandleInstanceFieldInitializers(node.Children); + HandleStaticFieldInitializers(node.Children); + node.AcceptVisitor(this, null); } } diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs index 3cdcb966a..928e53a37 100644 --- a/ILSpy/CSharpLanguage.cs +++ b/ILSpy/CSharpLanguage.cs @@ -52,7 +52,7 @@ namespace ICSharpCode.ILSpy { } -#if DEBUG + #if DEBUG internal static IEnumerable GetDebugLanguages() { DecompilerContext context = new DecompilerContext(ModuleDefinition.CreateModule("dummy", ModuleKind.Dll)); @@ -71,7 +71,7 @@ namespace ICSharpCode.ILSpy showAllMembers = true }; } -#endif + #endif public override string Name { @@ -92,8 +92,50 @@ namespace ICSharpCode.ILSpy { WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true)); AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: method.DeclaringType, isSingleMember: true); - codeDomBuilder.AddMethod(method); - RunTransformsAndGenerateCode(codeDomBuilder, output, options); + if (method.IsConstructor && !method.IsStatic && !method.DeclaringType.IsValueType) { + // also fields and other ctors so that the field initializers can be shown as such + AddFieldsAndCtors(codeDomBuilder, method.DeclaringType, method.IsStatic); + RunTransformsAndGenerateCode(codeDomBuilder, output, options, new SelectCtorTransform(method)); + } else { + codeDomBuilder.AddMethod(method); + RunTransformsAndGenerateCode(codeDomBuilder, output, options); + } + } + + class SelectCtorTransform : IAstTransform + { + readonly MethodDefinition ctorDef; + + public SelectCtorTransform(MethodDefinition ctorDef) + { + this.ctorDef = ctorDef; + } + + public void Run(AstNode compilationUnit) + { + ConstructorDeclaration ctorDecl = null; + foreach (var node in compilationUnit.Children) { + ConstructorDeclaration ctor = node as ConstructorDeclaration; + if (ctor != null) { + if (ctor.Annotation() == ctorDef) { + ctorDecl = ctor; + } else { + // remove other ctors + ctor.Remove(); + } + } + // Remove any fields without initializers + FieldDeclaration fd = node as FieldDeclaration; + if (fd != null && fd.Variables.All(v => v.Initializer.IsNull)) + fd.Remove(); + } + if (ctorDecl.Initializer.ConstructorInitializerType == ConstructorInitializerType.This) { + // remove all fields + foreach (var node in compilationUnit.Children) + if (node is FieldDeclaration) + node.Remove(); + } + } } public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options) @@ -108,8 +150,48 @@ namespace ICSharpCode.ILSpy { WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true)); AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: field.DeclaringType, isSingleMember: true); - codeDomBuilder.AddField(field); - RunTransformsAndGenerateCode(codeDomBuilder, output, options); + if (field.IsLiteral) { + codeDomBuilder.AddField(field); + } else { + // also decompile ctors so that the field initializer can be shown + AddFieldsAndCtors(codeDomBuilder, field.DeclaringType, field.IsStatic); + } + RunTransformsAndGenerateCode(codeDomBuilder, output, options, new SelectFieldTransform(field)); + } + + /// + /// Removes all top-level members except for the specified fields. + /// + sealed class SelectFieldTransform : IAstTransform + { + readonly FieldDefinition field; + + public SelectFieldTransform(FieldDefinition field) + { + this.field = field; + } + + public void Run(AstNode compilationUnit) + { + foreach (var child in compilationUnit.Children) { + if (child is AttributedNode) { + if (child.Annotation() != field) + child.Remove(); + } + } + } + } + + void AddFieldsAndCtors(AstBuilder codeDomBuilder, TypeDefinition declaringType, bool isStatic) + { + foreach (var field in declaringType.Fields) { + if (field.IsStatic == isStatic) + codeDomBuilder.AddField(field); + } + foreach (var ctor in declaringType.Methods) { + if (ctor.IsConstructor && ctor.IsStatic == isStatic) + codeDomBuilder.AddMethod(ctor); + } } public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options) @@ -127,11 +209,15 @@ namespace ICSharpCode.ILSpy RunTransformsAndGenerateCode(codeDomBuilder, output, options); } - void RunTransformsAndGenerateCode(AstBuilder astBuilder, ITextOutput output, DecompilationOptions options) + void RunTransformsAndGenerateCode(AstBuilder astBuilder, ITextOutput output, DecompilationOptions options, IAstTransform additionalTransform = null) { astBuilder.RunTransformations(transformAbortCondition); - if (options.DecompilerSettings.ShowXmlDocumentation) + if (additionalTransform != null) { + additionalTransform.Run(astBuilder.CompilationUnit); + } + if (options.DecompilerSettings.ShowXmlDocumentation) { AddXmlDocTransform.Run(astBuilder.CompilationUnit); + } astBuilder.GenerateCode(output); } diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index eb5e9d2ba..ee76d82ee 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -2147,7 +2147,9 @@ namespace ICSharpCode.NRefactory.CSharp // "1.0 / /*comment*/a", then we need to insert a space in front of the comment. formatter.Space(); } + formatter.StartNode(comment); formatter.WriteComment(comment.CommentType, comment.Content); + formatter.EndNode(comment); lastWritten = LastWritten.Whitespace; return null; } From 4abc650ecd14bd31e2aa390b9d9d8193c31c2ab5 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 21:44:37 +0200 Subject: [PATCH 37/65] Fix NullReferenceException in TrransformSwitchOnString. Closes #95. --- .../Ast/Transforms/PatternStatementTransform.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs index bc17d13cc..6c34b1b4f 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs @@ -648,7 +648,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms // switchVar must be the same as switchExpr; or switchExpr must be an assignment and switchVar the left side of that assignment if (!m.Get("switchVar").Single().IsMatch(m.Get("switchExpr").Single())) { AssignmentExpression assign = m.Get("switchExpr").Single() as AssignmentExpression; - if (!m.Get("switchVar").Single().IsMatch(assign.Left)) + if (!(assign != null && m.Get("switchVar").Single().IsMatch(assign.Left))) return null; } FieldReference cachedDictField = m.Get("cachedDict").Single().Annotation(); From 5c08e10a07f5a2083386ca050d33b97d14573d1d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 20 May 2011 22:37:38 +0200 Subject: [PATCH 38/65] Fixed incorrect detection of the 'using' statement pattern when the code was assigning to the using variable. Closes #121. --- .../Transforms/PatternStatementTransform.cs | 107 +++++++++++++----- .../Tests/ExceptionHandling.cs | 26 +++++ 2 files changed, 102 insertions(+), 31 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs index 6c34b1b4f..46ff353c8 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs @@ -184,40 +184,67 @@ namespace ICSharpCode.Decompiler.Ast.Transforms Match m2 = usingTryCatchPattern.Match(tryCatch); if (!m2.Success) return null; string variableName = m1.Get("variable").Single().Identifier; - if (variableName == m2.Get("ident").Single().Identifier) { - if (m2.Has("valueType")) { - // if there's no if(x!=null), then it must be a value type - ILVariable v = m1.Get("variable").Single().Annotation(); - if (v == null || v.Type == null || !v.Type.IsValueType) - return null; - } - node.Remove(); - BlockStatement body = m2.Get("body").Single(); - UsingStatement usingStatement = new UsingStatement(); - usingStatement.ResourceAcquisition = node.Expression.Detach(); - usingStatement.EmbeddedStatement = body.Detach(); - tryCatch.ReplaceWith(usingStatement); - // Move the variable declaration into the resource acquisition, if possible - // This is necessary for the foreach-pattern to work on the result of the using-pattern - VariableDeclarationStatement varDecl = FindVariableDeclaration(usingStatement, variableName); - if (varDecl != null && varDecl.Parent is BlockStatement) { - Statement declarationPoint; - if (CanMoveVariableDeclarationIntoStatement(varDecl, usingStatement, out declarationPoint)) { - // Moving the variable into the UsingStatement is allowed: - usingStatement.ResourceAcquisition = new VariableDeclarationStatement { - Type = (AstType)varDecl.Type.Clone(), - Variables = { - new VariableInitializer { - Name = variableName, - Initializer = m1.Get("initializer").Single().Detach() - }.CopyAnnotationsFrom(usingStatement.ResourceAcquisition) - } - }.CopyAnnotationsFrom(node); - } + if (variableName != m2.Get("ident").Single().Identifier) + return null; + if (m2.Has("valueType")) { + // if there's no if(x!=null), then it must be a value type + ILVariable v = m1.Get("variable").Single().Annotation(); + if (v == null || v.Type == null || !v.Type.IsValueType) + return null; + } + + // There are two variants of the using statement: + // "using (var a = init)" and "using (expr)". + // The former declares a read-only variable 'a', and the latter declares an unnamed read-only variable + // to store the original value of 'expr'. + // This means that in order to introduce a using statement, in both cases we need to detect a read-only + // variable that is used only within that block. + + if (HasAssignment(tryCatch, variableName)) + return null; + + VariableDeclarationStatement varDecl = FindVariableDeclaration(node, variableName); + if (varDecl == null || !(varDecl.Parent is BlockStatement)) + return null; + + // Create the using statement so that we can use definite assignment analysis to check + // whether the variable is declared correctly there. + node.Remove(); + BlockStatement body = m2.Get("body").Single(); + UsingStatement usingStatement = new UsingStatement(); + usingStatement.ResourceAcquisition = node.Expression.Detach(); + usingStatement.EmbeddedStatement = body.Detach(); + tryCatch.ReplaceWith(usingStatement); + + // Check whether moving the variable declaration into the resource acquisition is possible + Statement declarationPoint; + if (CanMoveVariableDeclarationIntoStatement(varDecl, usingStatement, out declarationPoint)) { + // Moving the variable into the UsingStatement is allowed. + // But if possible, we'll eliminate the variable completely: + if (body.Descendants.OfType().Any(ident => ident.Identifier == variableName)) { + usingStatement.ResourceAcquisition = new VariableDeclarationStatement { + Type = (AstType)varDecl.Type.Clone(), + Variables = { + new VariableInitializer { + Name = variableName, + Initializer = m1.Get("initializer").Single().Detach() + }.CopyAnnotationsFrom(usingStatement.ResourceAcquisition) + } + }.CopyAnnotationsFrom(node); + } else { + // the variable is never used; eliminate it: + usingStatement.ResourceAcquisition = m1.Get("initializer").Single().Detach(); } return usingStatement; + } else { + // oops, we can't use a using statement after all; so revert back to try-finally + usingStatement.ReplaceWith(tryCatch); + ((TryCatchStatement)tryCatch).TryBlock = body.Detach(); + node.Expression = (Expression)usingStatement.ResourceAcquisition.Detach(); + + tryCatch.Parent.InsertChildBefore(tryCatch, node, BlockStatement.StatementRole); + return null; } - return null; } internal static VariableDeclarationStatement FindVariableDeclaration(AstNode node, string identifier) @@ -251,6 +278,24 @@ namespace ICSharpCode.Decompiler.Ast.Transforms } return true; } + + /// + /// Gets whether there is an assignment to 'variableName' anywhere within the given node. + /// + bool HasAssignment(AstNode root, string variableName) + { + foreach (AstNode node in root.DescendantsAndSelf) { + IdentifierExpression ident = node as IdentifierExpression; + if (ident != null && ident.Identifier == variableName) { + if (ident.Parent is AssignmentExpression && ident.Role == AssignmentExpression.LeftRole + || ident.Parent is DirectionExpression) + { + return true; + } + } + } + return false; + } #endregion #region foreach (generic) diff --git a/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs b/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs index 5fdc27dc5..9d81936a5 100644 --- a/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs +++ b/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs @@ -2,6 +2,7 @@ // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; +using System.Threading; public class ExceptionHandling { @@ -64,4 +65,29 @@ public class ExceptionHandling Console.WriteLine("other"); } } + + public void NoUsingStatementBecauseTheVariableIsAssignedTo() + { + CancellationTokenSource cancellationTokenSource = null; + try + { + cancellationTokenSource = new CancellationTokenSource(); + } + finally + { + if (cancellationTokenSource != null) + { + cancellationTokenSource.Dispose(); + } + } + } + + public void UsingStatementThatChangesTheVariable() + { + CancellationTokenSource cancellationTokenSource = null; + using (cancellationTokenSource) + { + cancellationTokenSource = new CancellationTokenSource(); + } + } } From 3833643aaf8a1df26ab68108b1051eca92aab502 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 May 2011 00:45:59 +0200 Subject: [PATCH 39/65] Fixed issues with detection of using statements. --- .../Transforms/PatternStatementTransform.cs | 80 +++++++++++-------- .../Analysis/DefiniteAssignmentAnalysis.cs | 12 +-- 2 files changed, 53 insertions(+), 39 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs index 46ff353c8..3d5c0e596 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs @@ -154,7 +154,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms } static readonly AstNode usingTryCatchPattern = new TryCatchStatement { - TryBlock = new AnyNode("body"), + TryBlock = new AnyNode(), FinallyBlock = new BlockStatement { new Choice { { "valueType", @@ -180,7 +180,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms { Match m1 = variableAssignPattern.Match(node); if (!m1.Success) return null; - AstNode tryCatch = node.NextSibling; + TryCatchStatement tryCatch = node.NextSibling as TryCatchStatement; Match m2 = usingTryCatchPattern.Match(tryCatch); if (!m2.Success) return null; string variableName = m1.Get("variable").Single().Identifier; @@ -207,44 +207,33 @@ namespace ICSharpCode.Decompiler.Ast.Transforms if (varDecl == null || !(varDecl.Parent is BlockStatement)) return null; - // Create the using statement so that we can use definite assignment analysis to check - // whether the variable is declared correctly there. + // Validate that the variable is not used after the using statement: + if (!IsVariableValueUnused(varDecl, tryCatch)) + return null; + node.Remove(); - BlockStatement body = m2.Get("body").Single(); + UsingStatement usingStatement = new UsingStatement(); - usingStatement.ResourceAcquisition = node.Expression.Detach(); - usingStatement.EmbeddedStatement = body.Detach(); + usingStatement.EmbeddedStatement = tryCatch.TryBlock.Detach(); tryCatch.ReplaceWith(usingStatement); - // Check whether moving the variable declaration into the resource acquisition is possible - Statement declarationPoint; - if (CanMoveVariableDeclarationIntoStatement(varDecl, usingStatement, out declarationPoint)) { - // Moving the variable into the UsingStatement is allowed. - // But if possible, we'll eliminate the variable completely: - if (body.Descendants.OfType().Any(ident => ident.Identifier == variableName)) { - usingStatement.ResourceAcquisition = new VariableDeclarationStatement { - Type = (AstType)varDecl.Type.Clone(), - Variables = { - new VariableInitializer { - Name = variableName, - Initializer = m1.Get("initializer").Single().Detach() - }.CopyAnnotationsFrom(usingStatement.ResourceAcquisition) - } - }.CopyAnnotationsFrom(node); - } else { - // the variable is never used; eliminate it: - usingStatement.ResourceAcquisition = m1.Get("initializer").Single().Detach(); - } - return usingStatement; + // If possible, we'll eliminate the variable completely: + if (usingStatement.EmbeddedStatement.Descendants.OfType().Any(ident => ident.Identifier == variableName)) { + // variable is used, so we'll create a variable declaration + usingStatement.ResourceAcquisition = new VariableDeclarationStatement { + Type = (AstType)varDecl.Type.Clone(), + Variables = { + new VariableInitializer { + Name = variableName, + Initializer = m1.Get("initializer").Single().Detach() + }.CopyAnnotationsFrom(node.Expression) + } + }.CopyAnnotationsFrom(node); } else { - // oops, we can't use a using statement after all; so revert back to try-finally - usingStatement.ReplaceWith(tryCatch); - ((TryCatchStatement)tryCatch).TryBlock = body.Detach(); - node.Expression = (Expression)usingStatement.ResourceAcquisition.Detach(); - - tryCatch.Parent.InsertChildBefore(tryCatch, node, BlockStatement.StatementRole); - return null; + // the variable is never used; eliminate it: + usingStatement.ResourceAcquisition = m1.Get("initializer").Single().Detach(); } + return usingStatement; } internal static VariableDeclarationStatement FindVariableDeclaration(AstNode node, string identifier) @@ -262,6 +251,29 @@ namespace ICSharpCode.Decompiler.Ast.Transforms return null; } + /// + /// Gets whether the old variable value (assigned inside 'targetStatement' or earlier) + /// is read anywhere in the remaining scope of the variable declaration. + /// + bool IsVariableValueUnused(VariableDeclarationStatement varDecl, Statement targetStatement) + { + Debug.Assert(targetStatement.Ancestors.Contains(varDecl.Parent)); + BlockStatement block = (BlockStatement)varDecl.Parent; + DefiniteAssignmentAnalysis daa = new DefiniteAssignmentAnalysis(block, context.CancellationToken); + daa.SetAnalyzedRange(targetStatement, block, startInclusive: false); + daa.Analyze(varDecl.Variables.Single().Name); + return daa.UnassignedVariableUses.Count == 0; + } + + // I used this in the first implementation of the using-statement transform, but now no longer + // because there were problems when multiple using statements were using the same variable + // - no single using statement could be transformed without making the C# code invalid, + // but transforming both would work. + // We now use 'IsVariableValueUnused' which will perform the transform + // even if it results in two variables with the same name and overlapping scopes. + // (this issue could be fixed later by renaming one of the variables) + + // I'm not sure whether the other consumers of 'CanMoveVariableDeclarationIntoStatement' should be changed the same way. bool CanMoveVariableDeclarationIntoStatement(VariableDeclarationStatement varDecl, Statement targetStatement, out Statement declarationPoint) { Debug.Assert(targetStatement.Ancestors.Contains(varDecl.Parent)); diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs index d4cc6e1c5..452ca686a 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs @@ -167,12 +167,14 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis /// This method can be used to restrict the analysis to only a part of the method. /// Only the control flow paths that are fully contained within the selected part will be analyzed. /// - /// Both 'start' and 'end' are inclusive. - public void SetAnalyzedRange(Statement start, Statement end) + /// By default, both 'start' and 'end' are inclusive. + public void SetAnalyzedRange(Statement start, Statement end, bool startInclusive = true, bool endInclusive = true) { - Debug.Assert(beginNodeDict.ContainsKey(start) && endNodeDict.ContainsKey(end)); - int startIndex = beginNodeDict[start].Index; - int endIndex = endNodeDict[end].Index; + var dictForStart = startInclusive ? beginNodeDict : endNodeDict; + var dictForEnd = endInclusive ? endNodeDict : beginNodeDict; + Debug.Assert(dictForStart.ContainsKey(start) && dictForEnd.ContainsKey(end)); + int startIndex = dictForStart[start].Index; + int endIndex = dictForEnd[end].Index; if (startIndex > endIndex) throw new ArgumentException("The start statement must be lexically preceding the end statement"); this.analyzedRangeStart = startIndex; From ae873ec18f1daee58548335649e86332a6029085 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 May 2011 11:53:00 +0200 Subject: [PATCH 40/65] Fixed decompilation of anonymous methods created by the VB compiler. Closes #127. --- .../Ast/Transforms/DelegateConstruction.cs | 13 ++++++++----- ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs index 1d58a021f..85ac9da1e 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs @@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms internal static bool IsAnonymousMethod(DecompilerContext context, MethodDefinition method) { - if (method == null || !method.Name.StartsWith("<", StringComparison.Ordinal)) + if (method == null || !(method.Name.StartsWith("<", StringComparison.Ordinal) || method.Name.Contains("$"))) return false; if (!(method.IsCompilerGenerated() || IsPotentialClosure(context, method.DeclaringType))) return false; @@ -388,10 +388,13 @@ namespace ICSharpCode.Decompiler.Ast.Transforms continue; // skip static fields if (dict.ContainsKey(field)) // skip field if it already was handled as parameter continue; - EnsureVariableNameIsAvailable(blockStatement, field.Name); - currentlyUsedVariableNames.Add(field.Name); - variablesToDeclare.Add(Tuple.Create(AstBuilder.ConvertType(field.FieldType, field), field.Name)); - dict[field] = new IdentifierExpression(field.Name); + string capturedVariableName = field.Name; + if (capturedVariableName.StartsWith("$VB$Local_", StringComparison.Ordinal) && capturedVariableName.Length > 10) + capturedVariableName = capturedVariableName.Substring(10); + EnsureVariableNameIsAvailable(blockStatement, capturedVariableName); + currentlyUsedVariableNames.Add(capturedVariableName); + variablesToDeclare.Add(Tuple.Create(AstBuilder.ConvertType(field.FieldType, field), capturedVariableName)); + dict[field] = new IdentifierExpression(capturedVariableName); } // Now figure out where the closure was accessed and use the simpler replacement expression there: diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index 1e4ebeddd..8a3cc466f 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -308,6 +308,8 @@ namespace ICSharpCode.Decompiler.ILAst /// Converts call and callvirt instructions that read/write properties into CallGetter/CallSetter instructions. /// /// CallGetter/CallSetter is used to allow the ILAst to represent "while ((SomeProperty = value) != null)". + /// + /// Also simplifies 'newobj(SomeDelegate, target, ldvirtftn(F, target))' to 'newobj(SomeDelegate, target, ldvirtftn(F))' /// void IntroducePropertyAccessInstructions(ILNode node) { @@ -365,6 +367,20 @@ namespace ICSharpCode.Decompiler.ILAst expr.Code = (expr.Code == ILCode.Call) ? ILCode.CallSetter : ILCode.CallvirtSetter; } } + } else if (expr.Code == ILCode.Newobj && expr.Arguments.Count == 2) { + // Might be 'newobj(SomeDelegate, target, ldvirtftn(F, target))'. + ILVariable target; + ILExpression ldvirtftnArg; + if (expr.Arguments[0].Match(ILCode.Ldloc, out target) + && expr.Arguments[1].Code == ILCode.Ldvirtftn + && expr.Arguments[1].Arguments.Count == 1 + && expr.Arguments[1].Arguments[0].MatchLdloc(target)) + { + // Remove the 'target' argument from the ldvirtftn instruction. + // It's not needed in the translation to C#, and needs to be eliminated so that the target expression + // can be inlined. + expr.Arguments[1].Arguments.Clear(); + } } } From a15ecd533b37d130f1213fae96339504333f40fe Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 May 2011 12:15:12 +0200 Subject: [PATCH 41/65] Fix NullReferenceException in XmlDocKeyProvider when decompiling C++/CLI code. Closes #173. --- ILSpy/XmlDoc/XmlDocKeyProvider.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ILSpy/XmlDoc/XmlDocKeyProvider.cs b/ILSpy/XmlDoc/XmlDocKeyProvider.cs index 7e9960067..fc503c115 100644 --- a/ILSpy/XmlDoc/XmlDocKeyProvider.cs +++ b/ILSpy/XmlDoc/XmlDocKeyProvider.cs @@ -79,6 +79,10 @@ namespace ICSharpCode.ILSpy.XmlDoc static void AppendTypeName(StringBuilder b, TypeReference type) { + if (type == null) { + // could happen when a TypeSpecification has no ElementType; e.g. function pointers in C++/CLI assemblies + return; + } if (type is GenericInstanceType) { GenericInstanceType giType = (GenericInstanceType)type; if (type.DeclaringType != null) { From d362f8d0f606398342cd10b549f0b0f52b5cd348 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 May 2011 14:43:12 +0200 Subject: [PATCH 42/65] Fixed several bugs in the IL disassembler. --- .../Disassembler/DisassemblerHelpers.cs | 155 +++++++++++++++--- .../Disassembler/MethodBodyDisassembler.cs | 59 +++++-- .../Disassembler/ReflectionDisassembler.cs | 130 +++++++++------ ICSharpCode.Decompiler/ILAst/ILAstTypes.cs | 14 +- ILSpy/ILAstLanguage.cs | 4 +- ILSpy/ILLanguage.cs | 44 ++++- 6 files changed, 301 insertions(+), 105 deletions(-) diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index 0060b71d8..672cf252c 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -22,6 +22,26 @@ using Mono.Cecil.Cil; namespace ICSharpCode.Decompiler.Disassembler { + public enum ILNameSyntax + { + /// + /// class/valuetype + TypeName (built-in types use keyword syntax) + /// + Signature, + /// + /// Like signature, but always refers to type parameters using their position + /// + SignatureNoNamedTypeParameters, + /// + /// [assembly]Full.Type.Name (even for built-in types) + /// + TypeName, + /// + /// Name (even for built-in types) + /// + ShortTypeName + } + public static class DisassemblerHelpers { public static void WriteOffsetReference(ITextOutput writer, Instruction instruction) @@ -35,6 +55,7 @@ namespace ICSharpCode.Decompiler.Disassembler WriteOffsetReference(writer, exceptionHandler.TryStart); writer.Write('-'); WriteOffsetReference(writer, exceptionHandler.TryEnd); + writer.Write(' '); writer.Write(exceptionHandler.HandlerType.ToString()); if (exceptionHandler.FilterStart != null) { writer.Write(' '); @@ -84,44 +105,70 @@ namespace ICSharpCode.Decompiler.Disassembler { if (method.HasThis) writer.Write("instance "); - method.ReturnType.WriteTo(writer); + method.ReturnType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters); writer.Write(' '); if (method.DeclaringType != null) { - method.DeclaringType.WriteTo(writer, true); + method.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write("::"); } - writer.WriteReference(method.Name, method); + writer.WriteReference(Escape(method.Name), method); + GenericInstanceMethod gim = method as GenericInstanceMethod; + if (gim != null) { + writer.Write('<'); + for (int i = 0; i < gim.GenericArguments.Count; i++) { + if (i > 0) + writer.Write(", "); + gim.GenericArguments[i].WriteTo(writer); + } + writer.Write('>'); + } writer.Write("("); var parameters = method.Parameters; for(int i = 0; i < parameters.Count; ++i) { if (i > 0) writer.Write(", "); - parameters[i].ParameterType.WriteTo(writer); + parameters[i].ParameterType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters); } writer.Write(")"); } static void WriteTo(this FieldReference field, ITextOutput writer) { - field.FieldType.WriteTo(writer); + field.FieldType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters); writer.Write(' '); - field.DeclaringType.WriteTo(writer); + field.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write("::"); - writer.WriteReference(field.Name, field); + writer.WriteReference(Escape(field.Name), field); + } + + static bool IsValidIdentifier(string identifier) + { + if (string.IsNullOrEmpty(identifier)) + return false; + if (!(char.IsLetter(identifier[0]) || identifier[0] == '_' || identifier[0] == '.')) + return false; + for (int i = 1; i < identifier.Length; i++) { + if (!(char.IsLetterOrDigit(identifier[i]) || identifier[i] == '_' || identifier[i] == '.' || identifier[i] == '`')) + return false; + } + return true; } public static string Escape(string identifier) { - return identifier; + if (IsValidIdentifier(identifier) && identifier != "value") + return identifier; + else + return "'" + identifier + "'"; } - public static void WriteTo(this TypeReference type, ITextOutput writer, bool onlyName = false, bool shortName = false) + public static void WriteTo(this TypeReference type, ITextOutput writer, ILNameSyntax syntax = ILNameSyntax.Signature) { if (type is PinnedType) { writer.Write("pinned "); - ((PinnedType)type).ElementType.WriteTo(writer, onlyName, shortName); + ((PinnedType)type).ElementType.WriteTo(writer, syntax); } else if (type is ArrayType) { ArrayType at = (ArrayType)type; - at.ElementType.WriteTo(writer, onlyName, shortName); + at.ElementType.WriteTo(writer, syntax); writer.Write('['); writer.Write(string.Join(", ", at.Dimensions)); writer.Write(']'); @@ -129,49 +176,54 @@ namespace ICSharpCode.Decompiler.Disassembler writer.Write('!'); if (((GenericParameter)type).Owner.GenericParameterType == GenericParameterType.Method) writer.Write('!'); - writer.Write(type.Name); + if (string.IsNullOrEmpty(type.Name) || type.Name[0] == '!' || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) + writer.Write(((GenericParameter)type).Position.ToString()); + else + writer.Write(Escape(type.Name)); } else if (type is ByReferenceType) { - ((ByReferenceType)type).ElementType.WriteTo(writer, onlyName, shortName); + ((ByReferenceType)type).ElementType.WriteTo(writer, syntax); writer.Write('&'); } else if (type is PointerType) { - ((PointerType)type).ElementType.WriteTo(writer, onlyName, shortName); + ((PointerType)type).ElementType.WriteTo(writer, syntax); writer.Write('*'); } else if (type is GenericInstanceType) { - type.GetElementType().WriteTo(writer, onlyName, shortName); + type.GetElementType().WriteTo(writer, syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature); writer.Write('<'); var arguments = ((GenericInstanceType)type).GenericArguments; for (int i = 0; i < arguments.Count; i++) { if (i > 0) writer.Write(", "); - arguments[i].WriteTo(writer, onlyName, shortName); + arguments[i].WriteTo(writer, syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature); } writer.Write('>'); } else if (type is OptionalModifierType) { writer.Write("modopt("); - ((OptionalModifierType)type).ModifierType.WriteTo(writer, true, shortName); + ((OptionalModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write(") "); - ((OptionalModifierType)type).ElementType.WriteTo(writer, onlyName, shortName); + ((OptionalModifierType)type).ElementType.WriteTo(writer, syntax); } else if (type is RequiredModifierType) { writer.Write("modreq("); - ((RequiredModifierType)type).ModifierType.WriteTo(writer, true, shortName); + ((RequiredModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write(") "); - ((RequiredModifierType)type).ElementType.WriteTo(writer, onlyName, shortName); + ((RequiredModifierType)type).ElementType.WriteTo(writer, syntax); } else { string name = PrimitiveTypeName(type); - if (name != null) { + if (syntax == ILNameSyntax.ShortTypeName) { + writer.WriteReference(Escape(type.Name), type); + } else if ((syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) && name != null) { writer.Write(name); } else { - if (!onlyName) + if (syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) writer.Write(type.IsValueType ? "valuetype " : "class "); if (type.DeclaringType != null) { - type.DeclaringType.WriteTo(writer, true, shortName); + type.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write('/'); writer.WriteReference(Escape(type.Name), type); } else { - if (!type.IsDefinition && type.Scope != null && !shortName && !(type is TypeSpecification)) + if (!type.IsDefinition && type.Scope != null && !(type is TypeSpecification)) writer.Write("[{0}]", Escape(type.Scope.Name)); - writer.WriteReference(shortName ? type.Name : type.FullName, type); + writer.WriteReference(Escape(type.FullName), type); } } } @@ -196,7 +248,19 @@ namespace ICSharpCode.Decompiler.Disassembler VariableReference variableRef = operand as VariableReference; if (variableRef != null) { - writer.WriteReference(variableRef.Index.ToString(), variableRef); + if (string.IsNullOrEmpty(variableRef.Name)) + writer.WriteReference(variableRef.Index.ToString(), variableRef); + else + writer.WriteReference(Escape(variableRef.Name), variableRef); + return; + } + + ParameterReference paramRef = operand as ParameterReference; + if (paramRef != null) { + if (string.IsNullOrEmpty(paramRef.Name)) + writer.WriteReference(paramRef.Index.ToString(), paramRef); + else + writer.WriteReference(Escape(paramRef.Name), paramRef); return; } @@ -208,7 +272,7 @@ namespace ICSharpCode.Decompiler.Disassembler TypeReference typeRef = operand as TypeReference; if (typeRef != null) { - typeRef.WriteTo(writer); + typeRef.WriteTo(writer, ILNameSyntax.TypeName); return; } @@ -224,6 +288,41 @@ namespace ICSharpCode.Decompiler.Disassembler return; } + if (operand is float) { + float val = (float)operand; + if (val == 0) { + writer.Write("0.0"); + } else if (float.IsInfinity(val) || float.IsNaN(val)) { + byte[] data = BitConverter.GetBytes(val); + writer.Write('('); + for (int i = 0; i < data.Length; i++) { + if (i > 0) + writer.Write(' '); + writer.Write(data[i].ToString("X2")); + } + writer.Write(')'); + } else { + writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture)); + } + return; + } else if (operand is double) { + double val = (double)operand; + if (val == 0) { + writer.Write("0.0"); + } else if (double.IsInfinity(val) || double.IsNaN(val)) { + byte[] data = BitConverter.GetBytes(val); + writer.Write('('); + for (int i = 0; i < data.Length; i++) { + if (i > 0) + writer.Write(' '); + writer.Write(data[i].ToString("X2")); + } + writer.Write(')'); + } else { + writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture)); + } + return; + } s = ToInvariantCultureString(operand); writer.Write(s); } @@ -261,6 +360,8 @@ namespace ICSharpCode.Decompiler.Disassembler return "char"; case "System.Object": return "object"; + case "System.IntPtr": + return "native int"; default: return null; } diff --git a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs index ef2f8a980..c446516b1 100644 --- a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs @@ -69,8 +69,12 @@ namespace ICSharpCode.Decompiler.Disassembler foreach (var v in method.Body.Variables) { output.WriteDefinition("[" + v.Index + "] ", v); v.VariableType.WriteTo(output); - output.Write(' '); - output.Write(DisassemblerHelpers.Escape(v.Name)); + if (!string.IsNullOrEmpty(v.Name)) { + output.Write(' '); + output.Write(DisassemblerHelpers.Escape(v.Name)); + } + if (v.Index + 1 < method.Body.Variables.Count) + output.Write(','); output.WriteLine(); } output.Unindent(); @@ -85,20 +89,24 @@ namespace ICSharpCode.Decompiler.Disassembler foreach (var inst in method.Body.Instructions) { inst.WriteTo(output); - // add IL code mappings - used in debugger - methodMapping.MemberCodeMappings.Add( - new SourceCodeMapping() { - SourceCodeLine = output.CurrentLine, - ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? method.Body.CodeSize : inst.Next.Offset }, - MemberMapping = methodMapping - }); + if (methodMapping != null) { + // add IL code mappings - used in debugger + methodMapping.MemberCodeMappings.Add( + new SourceCodeMapping() { + SourceCodeLine = output.CurrentLine, + ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? method.Body.CodeSize : inst.Next.Offset }, + MemberMapping = methodMapping + }); + } output.WriteLine(); } - output.WriteLine(); - foreach (var eh in method.Body.ExceptionHandlers) { - eh.WriteTo(output); + if (method.Body.HasExceptionHandlers) { output.WriteLine(); + foreach (var eh in method.Body.ExceptionHandlers) { + eh.WriteTo(output); + output.WriteLine(); + } } } } @@ -116,7 +124,8 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(); break; case ILStructureType.Try: - output.WriteLine(".try {"); + output.WriteLine(".try"); + output.WriteLine("{"); break; case ILStructureType.Handler: switch (s.ExceptionHandler.HandlerType) { @@ -125,22 +134,24 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write("catch"); if (s.ExceptionHandler.CatchType != null) { output.Write(' '); - s.ExceptionHandler.CatchType.WriteTo(output); + s.ExceptionHandler.CatchType.WriteTo(output, ILNameSyntax.TypeName); } - output.WriteLine(" {"); + output.WriteLine(); break; case Mono.Cecil.Cil.ExceptionHandlerType.Finally: - output.WriteLine("finally {"); + output.WriteLine("finally"); break; case Mono.Cecil.Cil.ExceptionHandlerType.Fault: - output.WriteLine("fault {"); + output.WriteLine("fault"); break; default: throw new NotSupportedException(); } + output.WriteLine("{"); break; case ILStructureType.Filter: - output.WriteLine("filter {"); + output.WriteLine("filter"); + output.WriteLine("{"); break; default: throw new NotSupportedException(); @@ -150,6 +161,7 @@ namespace ICSharpCode.Decompiler.Disassembler void WriteStructureBody(ILStructure s, ref Instruction inst, MemberMapping currentMethodMapping, int codeSize) { + bool prevInstructionWasBranch = false; int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { int offset = inst.Offset; @@ -158,7 +170,12 @@ namespace ICSharpCode.Decompiler.Disassembler WriteStructureHeader(child); WriteStructureBody(child, ref inst, currentMethodMapping, codeSize); WriteStructureFooter(child); + prevInstructionWasBranch = false; } else { + if (prevInstructionWasBranch) { + output.WriteLine(); // put empty line after branch instructions + } + inst.WriteTo(output); // add IL code mappings - used in debugger @@ -172,6 +189,12 @@ namespace ICSharpCode.Decompiler.Disassembler } output.WriteLine(); + + prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch + || inst.OpCode.FlowControl == FlowControl.Cond_Branch + || inst.OpCode.FlowControl == FlowControl.Return + || inst.OpCode.FlowControl == FlowControl.Throw; + inst = inst.Next; } } diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index bff343db7..3a1b48f6a 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -32,7 +32,6 @@ namespace ICSharpCode.Decompiler.Disassembler { ITextOutput output; CancellationToken cancellationToken; - bool detectControlStructure; bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings) MethodBodyDisassembler methodBodyDisassembler; @@ -42,23 +41,22 @@ namespace ICSharpCode.Decompiler.Disassembler throw new ArgumentNullException("output"); this.output = output; this.cancellationToken = cancellationToken; - this.detectControlStructure = detectControlStructure; this.methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken); } #region Disassemble Method EnumNameCollection methodAttributeFlags = new EnumNameCollection() { - { MethodAttributes.Static, "static" }, { MethodAttributes.Final, "final" }, - { MethodAttributes.Virtual, "virtual" }, { MethodAttributes.HideBySig, "hidebysig" }, - { MethodAttributes.Abstract, "abstract" }, { MethodAttributes.SpecialName, "specialname" }, { MethodAttributes.PInvokeImpl, "pinvokeimpl" }, { MethodAttributes.UnmanagedExport, "export" }, { MethodAttributes.RTSpecialName, "rtspecialname" }, { MethodAttributes.RequireSecObject, "requiresecobj" }, - { MethodAttributes.NewSlot, "newslot" } + { MethodAttributes.NewSlot, "newslot" }, + { MethodAttributes.Virtual, "virtual" }, + { MethodAttributes.Abstract, "abstract" }, + { MethodAttributes.Static, "static" } }; EnumNameCollection methodVisibility = new EnumNameCollection() { @@ -156,7 +154,7 @@ namespace ICSharpCode.Decompiler.Disassembler methodBodyDisassembler.Disassemble(method.Body, methodMapping); } - CloseBlock("End of method " + method.DeclaringType.Name + "." + method.Name); + CloseBlock("end of method " + method.DeclaringType.Name + "::" + method.Name); } else { output.WriteLine(); } @@ -234,12 +232,11 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(" = "); DisassemblerHelpers.WriteOperand(output, field.Constant); } + output.WriteLine(); if (field.HasCustomAttributes) { - OpenBlock(false); + output.MarkFoldStart(); WriteAttributes(field.CustomAttributes); - CloseBlock(); - } else { - output.WriteLine(); + output.MarkFoldEnd(); } } #endregion @@ -255,9 +252,21 @@ namespace ICSharpCode.Decompiler.Disassembler { output.WriteDefinition(".property ", property); WriteFlags(property.Attributes, propertyAttributes); + if (property.HasThis) + output.Write("instance "); property.PropertyType.WriteTo(output); output.Write(' '); output.Write(DisassemblerHelpers.Escape(property.Name)); + + output.Write("("); + if (property.HasParameters) { + output.WriteLine(); + output.Indent(); + WriteParameters(property.Parameters); + output.Unindent(); + } + output.Write(")"); + OpenBlock(false); WriteAttributes(property.CustomAttributes); WriteNestedMethod(".get", property.GetMethod); @@ -272,16 +281,10 @@ namespace ICSharpCode.Decompiler.Disassembler { if (method == null) return; - if (detectControlStructure) { - output.WriteDefinition(keyword, method); - output.Write(' '); - DisassembleMethodInternal(method); - } else { - output.Write(keyword); - output.Write(' '); - method.WriteTo(output); - output.WriteLine(); - } + output.Write(keyword); + output.Write(' '); + method.WriteTo(output); + output.WriteLine(); } #endregion @@ -361,7 +364,7 @@ namespace ICSharpCode.Decompiler.Disassembler const TypeAttributes masks = TypeAttributes.ClassSemanticMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask; WriteFlags(type.Attributes & ~masks, typeAttributes); - output.Write(DisassemblerHelpers.Escape(type.Name)); + output.Write(DisassemblerHelpers.Escape(type.DeclaringType != null ? type.Name : type.FullName)); WriteTypeParameters(output, type); output.MarkFoldStart(defaultCollapsed: isInType); output.WriteLine(); @@ -369,7 +372,7 @@ namespace ICSharpCode.Decompiler.Disassembler if (type.BaseType != null) { output.Indent(); output.Write("extends "); - type.BaseType.WriteTo(output, true); + type.BaseType.WriteTo(output, ILNameSyntax.TypeName); output.WriteLine(); output.Unindent(); } @@ -382,9 +385,7 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write("implements "); else output.Write(" "); - if (type.Interfaces[index].Namespace != null) - output.Write("{0}.", type.Interfaces[index].Namespace); - output.Write(type.Interfaces[index].Name); + type.Interfaces[index].WriteTo(output, ILNameSyntax.TypeName); } output.WriteLine(); output.Unindent(); @@ -417,6 +418,14 @@ namespace ICSharpCode.Decompiler.Disassembler } output.WriteLine(); } + if (type.HasMethods) { + output.WriteLine("// Methods"); + foreach (var m in type.Methods) { + cancellationToken.ThrowIfCancellationRequested(); + DisassembleMethod(m); + output.WriteLine(); + } + } if (type.HasProperties) { output.WriteLine("// Properties"); foreach (var prop in type.Properties) { @@ -434,18 +443,7 @@ namespace ICSharpCode.Decompiler.Disassembler } output.WriteLine(); } - if (type.HasMethods) { - output.WriteLine("// Methods"); - var accessorMethods = type.GetAccessorMethods(); - foreach (var m in type.Methods) { - cancellationToken.ThrowIfCancellationRequested(); - if (!(detectControlStructure && accessorMethods.Contains(m))) { - DisassembleMethod(m); - output.WriteLine(); - } - } - } - CloseBlock("End of class " + type.FullName); + CloseBlock("end of class " + (type.DeclaringType != null ? type.Name : type.FullName)); isInType = oldIsInType; } @@ -467,7 +465,7 @@ namespace ICSharpCode.Decompiler.Disassembler for (int j = 0; j < gp.Constraints.Count; j++) { if (j > 0) output.Write(", "); - gp.Constraints[j].WriteTo(output, true); + gp.Constraints[j].WriteTo(output, ILNameSyntax.TypeName); } output.Write(") "); } @@ -616,9 +614,11 @@ namespace ICSharpCode.Decompiler.Disassembler { output.Write(".assembly " + DisassemblerHelpers.Escape(asm.Name.Name)); OpenBlock(false); - Version v = asm.Name.Version; - if (v != null) { - output.WriteLine(".ver {0}:{1}:{2}:{3}", v.Major, v.Minor, v.Build, v.Revision); + WriteAttributes(asm.CustomAttributes); + if (asm.Name.PublicKey != null && asm.Name.PublicKey.Length > 0) { + output.Write(".publickey = "); + WriteBlob(asm.Name.PublicKey); + output.WriteLine(); } if (asm.Name.HashAlgorithm != AssemblyHashAlgorithm.None) { output.Write(".hash algorithm 0x{0:x8}", (int)asm.Name.HashAlgorithm); @@ -626,15 +626,51 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(" // SHA1"); output.WriteLine(); } - if (asm.Name.PublicKey != null && asm.Name.PublicKey.Length > 0) { - output.Write(".publickey = "); - WriteBlob(asm.Name.PublicKey); - output.WriteLine(); + Version v = asm.Name.Version; + if (v != null) { + output.WriteLine(".ver {0}:{1}:{2}:{3}", v.Major, v.Minor, v.Build, v.Revision); } - WriteAttributes(asm.CustomAttributes); CloseBlock(); } + public void WriteAssemblyReferences(ModuleDefinition module) + { + foreach (var mref in module.ModuleReferences) { + output.WriteLine(".module extern {0}", DisassemblerHelpers.Escape(mref.Name)); + } + foreach (var aref in module.AssemblyReferences) { + output.Write(".assembly extern {0}", DisassemblerHelpers.Escape(aref.Name)); + OpenBlock(false); + if (aref.PublicKeyToken != null) { + output.Write(".publickeytoken = "); + WriteBlob(aref.PublicKeyToken); + output.WriteLine(); + } + if (aref.Version != null) { + output.WriteLine(".ver {0}:{1}:{2}:{3}", aref.Version.Major, aref.Version.Minor, aref.Version.Build, aref.Version.Revision); + } + CloseBlock(); + } + } + + public void WriteModuleHeader(ModuleDefinition module) + { + output.WriteLine(".module {0}", module.Name); + output.WriteLine("// MVID: {0}", module.Mvid.ToString("B").ToUpperInvariant()); + // TODO: imagebase, file alignment, stackreserve, subsystem + output.WriteLine(".corflags 0x{0:x} // {1}", module.Attributes, module.Attributes.ToString()); + + WriteAttributes(module.CustomAttributes); + } + + public void WriteModuleContents(ModuleDefinition module) + { + foreach (TypeDefinition td in module.Types) { + DisassembleType(td); + output.WriteLine(); + } + } + /// public Tuple> CodeMappings { get; diff --git a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs index 1d366c06c..48312b080 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs @@ -378,10 +378,10 @@ namespace ICSharpCode.Decompiler.ILAst output.Write(((ILVariable)Operand).Name); if (this.InferredType != null) { output.Write(':'); - this.InferredType.WriteTo(output, true, true); + this.InferredType.WriteTo(output, ILNameSyntax.ShortTypeName); if (this.ExpectedType != null && this.ExpectedType.FullName != this.InferredType.FullName) { output.Write("[exp:"); - this.ExpectedType.WriteTo(output, true, true); + this.ExpectedType.WriteTo(output, ILNameSyntax.ShortTypeName); output.Write(']'); } } @@ -399,15 +399,15 @@ namespace ICSharpCode.Decompiler.ILAst output.Write(Code.GetName()); if (this.InferredType != null) { output.Write(':'); - this.InferredType.WriteTo(output, true, true); + this.InferredType.WriteTo(output, ILNameSyntax.ShortTypeName); if (this.ExpectedType != null && this.ExpectedType.FullName != this.InferredType.FullName) { output.Write("[exp:"); - this.ExpectedType.WriteTo(output, true, true); + this.ExpectedType.WriteTo(output, ILNameSyntax.ShortTypeName); output.Write(']'); } } else if (this.ExpectedType != null) { output.Write("[exp:"); - this.ExpectedType.WriteTo(output, true, true); + this.ExpectedType.WriteTo(output, ILNameSyntax.ShortTypeName); output.Write(']'); } output.Write('('); @@ -425,13 +425,13 @@ namespace ICSharpCode.Decompiler.ILAst } else if (Operand is MethodReference) { MethodReference method = (MethodReference)Operand; if (method.DeclaringType != null) { - method.DeclaringType.WriteTo(output, true, true); + method.DeclaringType.WriteTo(output, ILNameSyntax.ShortTypeName); output.Write("::"); } output.WriteReference(method.Name, method); } else if (Operand is FieldReference) { FieldReference field = (FieldReference)Operand; - field.DeclaringType.WriteTo(output, true, true); + field.DeclaringType.WriteTo(output, ILNameSyntax.ShortTypeName); output.Write("::"); output.WriteReference(field.Name, field); } else { diff --git a/ILSpy/ILAstLanguage.cs b/ILSpy/ILAstLanguage.cs index 84348a4de..a462c2f21 100644 --- a/ILSpy/ILAstLanguage.cs +++ b/ILSpy/ILAstLanguage.cs @@ -68,7 +68,7 @@ namespace ICSharpCode.ILSpy output.Write(" : "); if (v.IsPinned) output.Write("pinned "); - v.Type.WriteTo(output, true, true); + v.Type.WriteTo(output, ILNameSyntax.ShortTypeName); } output.WriteLine(); } @@ -100,7 +100,7 @@ namespace ICSharpCode.ILSpy public override string TypeToString(TypeReference t, bool includeNamespace, ICustomAttributeProvider attributeProvider) { PlainTextOutput output = new PlainTextOutput(); - t.WriteTo(output, true, shortName: !includeNamespace); + t.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName); return output.ToString(); } } diff --git a/ILSpy/ILLanguage.cs b/ILSpy/ILLanguage.cs index e77497fa5..7578f107f 100644 --- a/ILSpy/ILLanguage.cs +++ b/ILSpy/ILLanguage.cs @@ -62,12 +62,38 @@ namespace ICSharpCode.ILSpy public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options) { - new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken).DisassembleProperty(property); + ReflectionDisassembler rd = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken); + rd.DisassembleProperty(property); + if (property.GetMethod != null) { + output.WriteLine(); + rd.DisassembleMethod(property.GetMethod); + } + if (property.SetMethod != null) { + output.WriteLine(); + rd.DisassembleMethod(property.SetMethod); + } + foreach (var m in property.OtherMethods) { + output.WriteLine(); + rd.DisassembleMethod(m); + } } public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options) { - new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken).DisassembleEvent(ev); + ReflectionDisassembler rd = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken); + rd.DisassembleEvent(ev); + if (ev.AddMethod != null) { + output.WriteLine(); + rd.DisassembleMethod(ev.AddMethod); + } + if (ev.RemoveMethod != null) { + output.WriteLine(); + rd.DisassembleMethod(ev.RemoveMethod); + } + foreach (var m in ev.OtherMethods) { + output.WriteLine(); + rd.DisassembleMethod(m); + } } public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options) @@ -85,13 +111,23 @@ namespace ICSharpCode.ILSpy output.WriteLine("// " + assembly.FileName); output.WriteLine(); - new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken).WriteAssemblyHeader(assembly.AssemblyDefinition); + ReflectionDisassembler rd = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken); + if (options.FullDecompilation) + rd.WriteAssemblyReferences(assembly.AssemblyDefinition.MainModule); + rd.WriteAssemblyHeader(assembly.AssemblyDefinition); + output.WriteLine(); + rd.WriteModuleHeader(assembly.AssemblyDefinition.MainModule); + if (options.FullDecompilation) { + output.WriteLine(); + output.WriteLine(); + rd.WriteModuleContents(assembly.AssemblyDefinition.MainModule); + } } public override string TypeToString(TypeReference t, bool includeNamespace, ICustomAttributeProvider attributeProvider) { PlainTextOutput output = new PlainTextOutput(); - t.WriteTo(output, true, shortName: !includeNamespace); + t.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName); return output.ToString(); } } From ed08c83289ed63ed0a3322a6a8ae143ad1b1f749 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 May 2011 17:21:59 +0200 Subject: [PATCH 43/65] Make ConvertChar and ConvertString public. --- .../CSharp/OutputVisitor/OutputVisitor.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index ee76d82ee..da524257d 100644 --- a/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -941,7 +941,11 @@ namespace ICSharpCode.NRefactory.CSharp return ConvertChar(ch); } - static string ConvertChar(char ch) + /// + /// Gets the escape sequence for the specified character. + /// + /// This method does not convert ' or ". + public static string ConvertChar(char ch) { switch (ch) { case '\\': @@ -973,7 +977,10 @@ namespace ICSharpCode.NRefactory.CSharp } } - static string ConvertString(string str) + /// + /// Converts special characters to escape sequences within the given string. + /// + public static string ConvertString(string str) { StringBuilder sb = new StringBuilder(); foreach (char ch in str) { From dd4d090468edf4e2e1c0df27534fc12a9aa9db58 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 May 2011 17:41:51 +0200 Subject: [PATCH 44/65] Lots of improvements/fixes for the disassembler. --- .../Disassembler/DisassemblerHelpers.cs | 99 +++-- .../Disassembler/ILStructure.cs | 6 +- .../Disassembler/MethodBodyDisassembler.cs | 33 +- .../Disassembler/ReflectionDisassembler.cs | 365 +++++++++++++++--- ILSpy/TextView/DecompilerTextView.cs | 4 +- 5 files changed, 423 insertions(+), 84 deletions(-) diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index 672cf252c..555eae487 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using Mono.Cecil; using Mono.Cecil.Cil; @@ -77,8 +78,14 @@ namespace ICSharpCode.Decompiler.Disassembler writer.WriteDefinition(CecilExtensions.OffsetToString(instruction.Offset), instruction); writer.Write(": "); writer.WriteReference(instruction.OpCode.Name, instruction.OpCode); - if(null != instruction.Operand) { + if (instruction.Operand != null) { writer.Write(' '); + if (instruction.OpCode == OpCodes.Ldtoken) { + if (instruction.Operand is MethodReference) + writer.Write("method "); + else if (instruction.Operand is FieldReference) + writer.Write("field "); + } WriteOperand(writer, instruction.Operand); } } @@ -153,22 +160,62 @@ namespace ICSharpCode.Decompiler.Disassembler return true; } + static readonly HashSet ilKeywords = BuildKeywordList( + "abstract", "algorithm", "alignment", "ansi", "any", "arglist", + "array", "as", "assembly", "assert", "at", "auto", "autochar", "beforefieldinit", + "blob", "blob_object", "bool", "brnull", "brnull.s", "brzero", "brzero.s", "bstr", + "bytearray", "byvalstr", "callmostderived", "carray", "catch", "cdecl", "cf", + "char", "cil", "class", "clsid", "const", "currency", "custom", "date", "decimal", + "default", "demand", "deny", "endmac", "enum", "error", "explicit", "extends", "extern", + "false", "famandassem", "family", "famorassem", "fastcall", "fault", "field", "filetime", + "filter", "final", "finally", "fixed", "float", "float32", "float64", "forwardref", + "fromunmanaged", "handler", "hidebysig", "hresult", "idispatch", "il", "illegal", + "implements", "implicitcom", "implicitres", "import", "in", "inheritcheck", "init", + "initonly", "instance", "int", "int16", "int32", "int64", "int8", "interface", "internalcall", + "iunknown", "lasterr", "lcid", "linkcheck", "literal", "localloc", "lpstr", "lpstruct", "lptstr", + "lpvoid", "lpwstr", "managed", "marshal", "method", "modopt", "modreq", "native", "nested", + "newslot", "noappdomain", "noinlining", "nomachine", "nomangle", "nometadata", "noncasdemand", + "noncasinheritance", "noncaslinkdemand", "noprocess", "not", "not_in_gc_heap", "notremotable", + "notserialized", "null", "nullref", "object", "objectref", "opt", "optil", "out", + "permitonly", "pinned", "pinvokeimpl", "prefix1", "prefix2", "prefix3", "prefix4", "prefix5", "prefix6", + "prefix7", "prefixref", "prejitdeny", "prejitgrant", "preservesig", "private", "privatescope", "protected", + "public", "record", "refany", "reqmin", "reqopt", "reqrefuse", "reqsecobj", "request", "retval", + "rtspecialname", "runtime", "safearray", "sealed", "sequential", "serializable", "special", "specialname", + "static", "stdcall", "storage", "stored_object", "stream", "streamed_object", "string", "struct", + "synchronized", "syschar", "sysstring", "tbstr", "thiscall", "tls", "to", "true", "typedref", + "unicode", "unmanaged", "unmanagedexp", "unsigned", "unused", "userdefined", "value", "valuetype", + "vararg", "variant", "vector", "virtual", "void", "wchar", "winapi", "with", "wrapper", + + // These are not listed as keywords in spec, but ILAsm treats them as such + "property", "type", "flags", "callconv" + ); + + static HashSet BuildKeywordList(params string[] keywords) + { + HashSet s = new HashSet(keywords); + foreach (var field in typeof(OpCodes).GetFields()) { + s.Add(((OpCode)field.GetValue(null)).Name); + } + return s; + } + public static string Escape(string identifier) { - if (IsValidIdentifier(identifier) && identifier != "value") + if (IsValidIdentifier(identifier) && !ilKeywords.Contains(identifier)) return identifier; else - return "'" + identifier + "'"; + return "'" + NRefactory.CSharp.OutputVisitor.ConvertString(identifier).Replace("'", "\\'") + "'"; } public static void WriteTo(this TypeReference type, ITextOutput writer, ILNameSyntax syntax = ILNameSyntax.Signature) { + ILNameSyntax syntaxForElementTypes = syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature; if (type is PinnedType) { - writer.Write("pinned "); - ((PinnedType)type).ElementType.WriteTo(writer, syntax); + ((PinnedType)type).ElementType.WriteTo(writer, syntaxForElementTypes); + writer.Write(" pinned"); } else if (type is ArrayType) { ArrayType at = (ArrayType)type; - at.ElementType.WriteTo(writer, syntax); + at.ElementType.WriteTo(writer, syntaxForElementTypes); writer.Write('['); writer.Write(string.Join(", ", at.Dimensions)); writer.Write(']'); @@ -181,33 +228,33 @@ namespace ICSharpCode.Decompiler.Disassembler else writer.Write(Escape(type.Name)); } else if (type is ByReferenceType) { - ((ByReferenceType)type).ElementType.WriteTo(writer, syntax); + ((ByReferenceType)type).ElementType.WriteTo(writer, syntaxForElementTypes); writer.Write('&'); } else if (type is PointerType) { - ((PointerType)type).ElementType.WriteTo(writer, syntax); + ((PointerType)type).ElementType.WriteTo(writer, syntaxForElementTypes); writer.Write('*'); } else if (type is GenericInstanceType) { - type.GetElementType().WriteTo(writer, syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature); + type.GetElementType().WriteTo(writer, syntaxForElementTypes); writer.Write('<'); var arguments = ((GenericInstanceType)type).GenericArguments; for (int i = 0; i < arguments.Count; i++) { if (i > 0) writer.Write(", "); - arguments[i].WriteTo(writer, syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature); + arguments[i].WriteTo(writer, syntaxForElementTypes); } writer.Write('>'); } else if (type is OptionalModifierType) { - writer.Write("modopt("); + ((OptionalModifierType)type).ElementType.WriteTo(writer, syntax); + writer.Write(" modopt("); ((OptionalModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write(") "); - ((OptionalModifierType)type).ElementType.WriteTo(writer, syntax); } else if (type is RequiredModifierType) { - writer.Write("modreq("); + ((RequiredModifierType)type).ElementType.WriteTo(writer, syntax); + writer.Write(" modreq("); ((RequiredModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write(") "); - ((RequiredModifierType)type).ElementType.WriteTo(writer, syntax); } else { - string name = PrimitiveTypeName(type); + string name = PrimitiveTypeName(type.FullName); if (syntax == ILNameSyntax.ShortTypeName) { writer.WriteReference(Escape(type.Name), type); } else if ((syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) && name != null) { @@ -284,11 +331,10 @@ namespace ICSharpCode.Decompiler.Disassembler string s = operand as string; if (s != null) { - writer.Write("\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\""); - return; - } - - if (operand is float) { + writer.Write("\"" + NRefactory.CSharp.OutputVisitor.ConvertString(s) + "\""); + } else if (operand is char) { + writer.Write(((int)(char)operand).ToString()); + } else if (operand is float) { float val = (float)operand; if (val == 0) { writer.Write("0.0"); @@ -304,7 +350,6 @@ namespace ICSharpCode.Decompiler.Disassembler } else { writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture)); } - return; } else if (operand is double) { double val = (double)operand; if (val == 0) { @@ -321,15 +366,17 @@ namespace ICSharpCode.Decompiler.Disassembler } else { writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture)); } - return; + } else if (operand is bool) { + writer.Write((bool)operand ? "true" : "false"); + } else { + s = ToInvariantCultureString(operand); + writer.Write(s); } - s = ToInvariantCultureString(operand); - writer.Write(s); } - public static string PrimitiveTypeName(this TypeReference type) + public static string PrimitiveTypeName(string fullName) { - switch (type.FullName) { + switch (fullName) { case "System.SByte": return "int8"; case "System.Int16": diff --git a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs index 5fc29a9bd..4c681e3c1 100644 --- a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs +++ b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs @@ -88,8 +88,10 @@ namespace ICSharpCode.Decompiler.Disassembler : this(ILStructureType.Root, 0, body.CodeSize) { // Build the tree of exception structures: - foreach (ExceptionHandler eh in body.ExceptionHandlers) { - AddNestedStructure(new ILStructure(ILStructureType.Try, eh.TryStart.Offset, eh.TryEnd.Offset, eh)); + for (int i = 0; i < body.ExceptionHandlers.Count; i++) { + ExceptionHandler eh = body.ExceptionHandlers[i]; + if (!body.ExceptionHandlers.Take(i).Any(oldEh => oldEh.TryStart == eh.TryStart && oldEh.TryEnd == eh.TryEnd)) + AddNestedStructure(new ILStructure(ILStructureType.Try, eh.TryStart.Offset, eh.TryEnd.Offset, eh)); if (eh.HandlerType == ExceptionHandlerType.Filter) AddNestedStructure(new ILStructure(ILStructureType.Filter, eh.FilterStart.Offset, eh.HandlerStart.Offset, eh)); AddNestedStructure(new ILStructure(ILStructureType.Handler, eh.HandlerStart.Offset, eh.HandlerEnd == null ? body.CodeSize : eh.HandlerEnd.Offset, eh)); diff --git a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs index c446516b1..2fcde2335 100644 --- a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs @@ -52,9 +52,6 @@ namespace ICSharpCode.Decompiler.Disassembler // start writing IL code MethodDefinition method = body.Method; output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA); - if (method.HasOverrides) - foreach (var methodOverride in method.Overrides) - output.WriteLine(".override {0}::{1}", methodOverride.DeclaringType.FullName, methodOverride.Name); output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize); output.WriteLine(".maxstack {0}", body.MaxStackSize); if (method.DeclaringType.Module.Assembly.EntryPoint == method) @@ -84,7 +81,8 @@ namespace ICSharpCode.Decompiler.Disassembler if (detectControlStructure && body.Instructions.Count > 0) { Instruction inst = body.Instructions[0]; - WriteStructureBody(new ILStructure(body), ref inst, methodMapping, method.Body.CodeSize); + HashSet branchTargets = GetBranchTargets(body.Instructions); + WriteStructureBody(new ILStructure(body), branchTargets, ref inst, methodMapping, method.Body.CodeSize); } else { foreach (var inst in method.Body.Instructions) { inst.WriteTo(output); @@ -111,6 +109,21 @@ namespace ICSharpCode.Decompiler.Disassembler } } + HashSet GetBranchTargets(IEnumerable instructions) + { + HashSet branchTargets = new HashSet(); + foreach (var inst in instructions) { + Instruction target = inst.Operand as Instruction; + if (target != null) + branchTargets.Add(target.Offset); + Instruction[] targets = inst.Operand as Instruction[]; + if (targets != null) + foreach (Instruction t in targets) + branchTargets.Add(t.Offset); + } + return branchTargets; + } + void WriteStructureHeader(ILStructure s) { switch (s.Type) { @@ -159,8 +172,9 @@ namespace ICSharpCode.Decompiler.Disassembler output.Indent(); } - void WriteStructureBody(ILStructure s, ref Instruction inst, MemberMapping currentMethodMapping, int codeSize) + void WriteStructureBody(ILStructure s, HashSet branchTargets, ref Instruction inst, MemberMapping currentMethodMapping, int codeSize) { + bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { @@ -168,14 +182,12 @@ namespace ICSharpCode.Decompiler.Disassembler if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); - WriteStructureBody(child, ref inst, currentMethodMapping, codeSize); + WriteStructureBody(child, branchTargets, ref inst, currentMethodMapping, codeSize); WriteStructureFooter(child); - prevInstructionWasBranch = false; } else { - if (prevInstructionWasBranch) { - output.WriteLine(); // put empty line after branch instructions + if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { + output.WriteLine(); // put an empty line after branches, and in front of branch targets } - inst.WriteTo(output); // add IL code mappings - used in debugger @@ -197,6 +209,7 @@ namespace ICSharpCode.Decompiler.Disassembler inst = inst.Next; } + isFirstInstructionInStructure = false; } } diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index 3a1b48f6a..956848a3e 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -49,14 +49,16 @@ namespace ICSharpCode.Decompiler.Disassembler { MethodAttributes.Final, "final" }, { MethodAttributes.HideBySig, "hidebysig" }, { MethodAttributes.SpecialName, "specialname" }, - { MethodAttributes.PInvokeImpl, "pinvokeimpl" }, + { MethodAttributes.PInvokeImpl, null }, // handled separately { MethodAttributes.UnmanagedExport, "export" }, { MethodAttributes.RTSpecialName, "rtspecialname" }, - { MethodAttributes.RequireSecObject, "requiresecobj" }, + { MethodAttributes.RequireSecObject, "reqsecobj" }, { MethodAttributes.NewSlot, "newslot" }, - { MethodAttributes.Virtual, "virtual" }, + { MethodAttributes.CheckAccessOnOverride, "strict" }, { MethodAttributes.Abstract, "abstract" }, - { MethodAttributes.Static, "static" } + { MethodAttributes.Virtual, "virtual" }, + { MethodAttributes.Static, "static" }, + { MethodAttributes.HasSecurity, null }, // ?? also invisible in ILDasm }; EnumNameCollection methodVisibility = new EnumNameCollection() { @@ -74,7 +76,7 @@ namespace ICSharpCode.Decompiler.Disassembler { MethodCallingConvention.ThisCall, "unmanaged thiscall" }, { MethodCallingConvention.FastCall, "unmanaged fastcall" }, { MethodCallingConvention.VarArg, "vararg" }, - { MethodCallingConvention.Generic, "generic" }, + { MethodCallingConvention.Generic, null }, }; EnumNameCollection methodCodeType = new EnumNameCollection() { @@ -88,6 +90,8 @@ namespace ICSharpCode.Decompiler.Disassembler { MethodImplAttributes.Synchronized, "synchronized" }, { MethodImplAttributes.NoInlining, "noinlining" }, { MethodImplAttributes.NoOptimization, "nooptimization" }, + { MethodImplAttributes.PreserveSig, "preservesig" }, + { MethodImplAttributes.InternalCall, "internalcall" }, }; public void DisassembleMethod(MethodDefinition method) @@ -107,6 +111,44 @@ namespace ICSharpCode.Decompiler.Disassembler WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility); WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags); + if ((method.Attributes & MethodAttributes.PInvokeImpl) == MethodAttributes.PInvokeImpl) { + output.Write("pinvokeimpl"); + if (method.HasPInvokeInfo) { + PInvokeInfo info = method.PInvokeInfo; + output.Write("(\"" + NRefactory.CSharp.OutputVisitor.ConvertString(info.Module.Name) + "\""); + + if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != method.Name) + output.Write(" as \"" + NRefactory.CSharp.OutputVisitor.ConvertString(info.EntryPoint) + "\""); + + if (info.IsNoMangle) + output.Write(" nomangle"); + + if (info.IsCharSetAnsi) + output.Write(" ansi"); + else if (info.IsCharSetAuto) + output.Write(" autochar"); + else if (info.IsCharSetUnicode) + output.Write(" unicode"); + + if (info.SupportsLastError) + output.Write(" lasterr"); + + if (info.IsCallConvCdecl) + output.Write(" cdecl"); + else if (info.IsCallConvFastcall) + output.Write(" fastcall"); + else if (info.IsCallConvStdCall) + output.Write(" stdcall"); + else if (info.IsCallConvThiscall) + output.Write(" thiscall"); + else if (info.IsCallConvWinapi) + output.Write(" winapi"); + + output.Write(')'); + } + output.Write(' '); + } + output.WriteLine(); output.Indent(); @@ -120,6 +162,9 @@ namespace ICSharpCode.Decompiler.Disassembler //return type method.ReturnType.WriteTo(output); output.Write(' '); + if (method.MethodReturnType.HasMarshalInfo) { + WriteMarshalInfo(method.MethodReturnType.MarshalInfo); + } output.Write(DisassemblerHelpers.Escape(method.Name)); WriteTypeParameters(output, method); @@ -141,25 +186,228 @@ namespace ICSharpCode.Decompiler.Disassembler WriteFlags(method.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl); output.Unindent(); - if (method.HasBody || method.HasCustomAttributes || method.Parameters.Any(HasParameterAttributes)) { - OpenBlock(defaultCollapsed: isInType); - WriteAttributes(method.CustomAttributes); - foreach (var p in method.Parameters) { - WriteParameterAttributes(p); - } - - if (method.HasBody) { - // create IL code mappings - used in debugger - MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings); - methodBodyDisassembler.Disassemble(method.Body, methodMapping); + OpenBlock(defaultCollapsed: isInType); + WriteAttributes(method.CustomAttributes); + if (method.HasOverrides) { + foreach (var methodOverride in method.Overrides) { + output.Write(".override method "); + methodOverride.WriteTo(output); + output.WriteLine(); } - - CloseBlock("end of method " + method.DeclaringType.Name + "::" + method.Name); - } else { - output.WriteLine(); } + foreach (var p in method.Parameters) { + WriteParameterAttributes(p); + } + + if (method.HasBody) { + // create IL code mappings - used in debugger + MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings); + methodBodyDisassembler.Disassemble(method.Body, methodMapping); + } + + CloseBlock("end of method " + DisassemblerHelpers.Escape(method.DeclaringType.Name) + "::" + DisassemblerHelpers.Escape(method.Name)); } + #region WriteMarshalInfo + void WriteMarshalInfo(MarshalInfo marshalInfo) + { + output.Write("marshal("); + WriteNativeType(marshalInfo.NativeType, marshalInfo); + output.Write(") "); + } + + void WriteNativeType(NativeType nativeType, MarshalInfo marshalInfo = null) + { + switch (nativeType) { + case NativeType.None: + break; + case NativeType.Boolean: + output.Write("bool"); + break; + case NativeType.I1: + output.Write("int8"); + break; + case NativeType.U1: + output.Write("unsigned int8"); + break; + case NativeType.I2: + output.Write("int16"); + break; + case NativeType.U2: + output.Write("unsigned int16"); + break; + case NativeType.I4: + output.Write("int32"); + break; + case NativeType.U4: + output.Write("unsigned int32"); + break; + case NativeType.I8: + output.Write("int64"); + break; + case NativeType.U8: + output.Write("unsigned int64"); + break; + case NativeType.R4: + output.Write("float32"); + break; + case NativeType.R8: + output.Write("float64"); + break; + case NativeType.LPStr: + output.Write("lpstr"); + break; + case NativeType.Int: + output.Write("int"); + break; + case NativeType.UInt: + output.Write("unsigned int"); + break; + case NativeType.Func: + goto default; // ?? + case NativeType.Array: + ArrayMarshalInfo ami = (ArrayMarshalInfo)marshalInfo; + if (ami == null) + goto default; + WriteNativeType(ami.ElementType); + output.Write("[size={0}, sizeParameterIndex={1}, sizeParameterMultiplier={2}]", ami.Size, ami.SizeParameterIndex, ami.SizeParameterMultiplier); + break; + case NativeType.Currency: + output.Write("currency"); + break; + case NativeType.BStr: + output.Write("bstr"); + break; + case NativeType.LPWStr: + output.Write("lpwstr"); + break; + case NativeType.LPTStr: + output.Write("lptstr"); + break; + case NativeType.FixedSysString: + output.Write("fixed sysstring[{0}]", ((FixedSysStringMarshalInfo)marshalInfo).Size); + break; + case NativeType.IUnknown: + output.Write("iunknown"); + break; + case NativeType.IDispatch: + output.Write("idispatch"); + break; + case NativeType.Struct: + output.Write("struct"); + break; + case NativeType.IntF: + output.Write("interface"); + break; + case NativeType.SafeArray: + output.Write("safearray "); + SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo; + if (sami != null) { + switch (sami.ElementType) { + case VariantType.None: + break; + case VariantType.I2: + output.Write("int16"); + break; + case VariantType.I4: + output.Write("int32"); + break; + case VariantType.R4: + output.Write("float32"); + break; + case VariantType.R8: + output.Write("float64"); + break; + case VariantType.CY: + output.Write("currency"); + break; + case VariantType.Date: + output.Write("date"); + break; + case VariantType.BStr: + output.Write("bstr"); + break; + case VariantType.Dispatch: + output.Write("idispatch"); + break; + case VariantType.Error: + output.Write("error"); + break; + case VariantType.Bool: + output.Write("bool"); + break; + case VariantType.Variant: + output.Write("variant"); + break; + case VariantType.Unknown: + output.Write("iunknown"); + break; + case VariantType.Decimal: + output.Write("decimal"); + break; + case VariantType.I1: + output.Write("int8"); + break; + case VariantType.UI1: + output.Write("unsigned int8"); + break; + case VariantType.UI2: + output.Write("unsigned int16"); + break; + case VariantType.UI4: + output.Write("unsigned int32"); + break; + case VariantType.Int: + output.Write("int"); + break; + case VariantType.UInt: + output.Write("unsigned int"); + break; + default: + output.Write(sami.ElementType.ToString()); + break; + } + } + break; + case NativeType.FixedArray: + output.Write("fixed sysstring"); + FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo; + if (fami != null) + output.Write("[{0}]", ((FixedArrayMarshalInfo)marshalInfo).Size); + break; + case NativeType.ByValStr: + output.Write("byvalstr"); + break; + case NativeType.ANSIBStr: + output.Write("ansi bstr"); + break; + case NativeType.TBStr: + output.Write("tbstr"); + break; + case NativeType.VariantBool: + output.Write("variant bool"); + break; + case NativeType.ASAny: + output.Write("as any"); + break; + case NativeType.LPStruct: + output.Write("lpstruct"); + break; + case NativeType.CustomMarshaler: + CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo; + goto default; // ??? + case NativeType.Error: + output.Write("error"); + break; + case NativeType.Max: + // ??? + default: + output.Write(nativeType.ToString()); + break; + } + } + #endregion + void WriteParameters(Collection parameters) { for (int i = 0; i < parameters.Count; i++) { @@ -188,17 +436,39 @@ namespace ICSharpCode.Decompiler.Disassembler { if (!HasParameterAttributes(p)) return; - output.Write(".param [{0}]", p.Index); + output.Write(".param [{0}]", p.Index + 1); if (p.HasConstant) { output.Write(" = "); - if (p.Constant != null) - DisassemblerHelpers.WriteOperand(output, p.Constant); - else - output.Write("nullref"); + WriteConstant(p.Constant); } output.WriteLine(); WriteAttributes(p.CustomAttributes); } + + void WriteConstant(object constant) + { + if (constant == null) { + output.Write("nullref"); + } else { + string typeName = DisassemblerHelpers.PrimitiveTypeName(constant.GetType().FullName); + if (typeName != null && typeName != "string") { + output.Write(typeName); + output.Write('('); + float? cf = constant as float?; + double? cd = constant as double?; + 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))) { + output.Write("0x{0:x16}", BitConverter.DoubleToInt64Bits(cd.Value)); + } else { + DisassemblerHelpers.WriteOperand(output, constant); + } + output.Write(')'); + } else { + DisassemblerHelpers.WriteOperand(output, constant); + } + } + } #endregion #region Disassemble Field @@ -224,13 +494,20 @@ namespace ICSharpCode.Decompiler.Disassembler { output.WriteDefinition(".field ", field); WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility); - WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | FieldAttributes.HasDefault), fieldAttributes); + const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA; + WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), fieldAttributes); + if (field.HasMarshalInfo) { + WriteMarshalInfo(field.MarshalInfo); + } field.FieldType.WriteTo(output); output.Write(' '); output.Write(DisassemblerHelpers.Escape(field.Name)); + if ((field.Attributes & FieldAttributes.HasFieldRVA) == FieldAttributes.HasFieldRVA) { + output.Write(" at I_{0:x8}", field.RVA); + } if (field.HasConstant) { output.Write(" = "); - DisassemblerHelpers.WriteOperand(output, field.Constant); + WriteConstant(field.Constant); } output.WriteLine(); if (field.HasCustomAttributes) { @@ -272,7 +549,7 @@ namespace ICSharpCode.Decompiler.Disassembler WriteNestedMethod(".get", property.GetMethod); WriteNestedMethod(".set", property.SetMethod); foreach (var method in property.OtherMethods) { - WriteNestedMethod(".method", method); + WriteNestedMethod(".other", method); } CloseBlock(); } @@ -298,16 +575,16 @@ namespace ICSharpCode.Decompiler.Disassembler { output.WriteDefinition(".event ", ev); WriteFlags(ev.Attributes, eventAttributes); - ev.EventType.WriteTo(output); + ev.EventType.WriteTo(output, ILNameSyntax.TypeName); output.Write(' '); output.Write(DisassemblerHelpers.Escape(ev.Name)); OpenBlock(false); WriteAttributes(ev.CustomAttributes); - WriteNestedMethod(".add", ev.AddMethod); - WriteNestedMethod(".remove", ev.RemoveMethod); - WriteNestedMethod(".invoke", ev.InvokeMethod); + WriteNestedMethod(".addon", ev.AddMethod); + WriteNestedMethod(".removeon", ev.RemoveMethod); + WriteNestedMethod(".fire", ev.InvokeMethod); foreach (var method in ev.OtherMethods) { - WriteNestedMethod(".method", method); + WriteNestedMethod(".other", method); } CloseBlock(); } @@ -426,14 +703,6 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(); } } - if (type.HasProperties) { - output.WriteLine("// Properties"); - foreach (var prop in type.Properties) { - cancellationToken.ThrowIfCancellationRequested(); - DisassembleProperty(prop); - } - output.WriteLine(); - } if (type.HasEvents) { output.WriteLine("// Events"); foreach (var ev in type.Events) { @@ -443,6 +712,14 @@ namespace ICSharpCode.Decompiler.Disassembler } output.WriteLine(); } + if (type.HasProperties) { + output.WriteLine("// Properties"); + foreach (var prop in type.Properties) { + cancellationToken.ThrowIfCancellationRequested(); + DisassembleProperty(prop); + } + output.WriteLine(); + } CloseBlock("end of class " + (type.DeclaringType != null ? type.Name : type.FullName)); isInType = oldIsInType; } @@ -460,6 +737,9 @@ namespace ICSharpCode.Decompiler.Disassembler } else if (gp.HasNotNullableValueTypeConstraint) { output.Write("valuetype "); } + if (gp.HasDefaultConstructorConstraint) { + output.Write(".ctor "); + } if (gp.HasConstraints) { output.Write('('); for (int j = 0; j < gp.Constraints.Count; j++) { @@ -469,9 +749,6 @@ namespace ICSharpCode.Decompiler.Disassembler } output.Write(") "); } - if (gp.HasDefaultConstructorConstraint) { - output.Write(".ctor "); - } if (gp.IsContravariant) { output.Write('-'); } else if (gp.IsCovariant) { diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index b312abf8a..024994462 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -617,12 +617,12 @@ namespace ICSharpCode.ILSpy.TextView public void SaveFoldingsState(IEnumerable foldings) { ExpandedFoldings = foldings.Where(f => !f.IsFolded).Select(f => Tuple.Create(f.StartOffset, f.EndOffset)).ToList(); - FoldingsChecksum = foldings.Select(f => f.StartOffset * 3 - f.EndOffset).Aggregate((a, b) => a + b); + FoldingsChecksum = unchecked(foldings.Select(f => f.StartOffset * 3 - f.EndOffset).Aggregate((a, b) => a + b)); } internal void RestoreFoldings(List list) { - var checksum = list.Select(f => f.StartOffset * 3 - f.EndOffset).Aggregate((a, b) => a + b); + var checksum = unchecked(list.Select(f => f.StartOffset * 3 - f.EndOffset).Aggregate((a, b) => a + b)); if (FoldingsChecksum == checksum) foreach (var folding in list) folding.DefaultClosed = !ExpandedFoldings.Any(f => f.Item1 == folding.StartOffset && f.Item2 == folding.EndOffset); From 2d42dd5c5740c9fcae7d33a4b8e6cdf0f148b543 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 May 2011 19:01:32 +0200 Subject: [PATCH 45/65] Fixed several issues related to [MarshalAs] attributes. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 39 ++++++++- .../Disassembler/ReflectionDisassembler.cs | 41 +++++++-- .../ILAst/ILAstOptimizer.cs | 1 - .../Tests/ICSharpCode.Decompiler.Tests.csproj | 1 + ICSharpCode.Decompiler/Tests/PInvoke.cs | 87 +++++++++++++++++++ ICSharpCode.Decompiler/Tests/TestRunner.cs | 6 ++ 6 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 ICSharpCode.Decompiler/Tests/PInvoke.cs diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index f941af8b3..e24ecb8e1 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -801,7 +801,13 @@ namespace ICSharpCode.Decompiler.Ast astProp.Setter.Body = CreateMethodBody(propDef.SetMethod); astProp.Setter.AddAnnotation(propDef.SetMethod); ConvertAttributes(astProp.Setter, propDef.SetMethod); - ConvertCustomAttributes(astProp.Setter, propDef.SetMethod.Parameters.Last(), "param"); + ParameterDefinition lastParam = propDef.SetMethod.Parameters.LastOrDefault(); + if (lastParam != null) { + ConvertCustomAttributes(astProp.Setter, lastParam, "param"); + if (lastParam.HasMarshalInfo) { + astProp.Setter.Attributes.Add(new AttributeSection(ConvertMarshalInfo(lastParam, propDef.Module)) { AttributeTarget = "param" }); + } + } if ((setterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask)) astProp.Setter.Modifiers = setterModifiers & Modifiers.VisibilityMask; @@ -1170,6 +1176,37 @@ namespace ICSharpCode.Decompiler.Ast Ast.Attribute attr = CreateNonCustomAttribute(typeof(MarshalAsAttribute), module); var unmanagedType = new TypeReference("System.Runtime.InteropServices", "UnmanagedType", module, module.TypeSystem.Corlib); attr.Arguments.Add(MakePrimitive((int)marshalInfo.NativeType, unmanagedType)); + + FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo; + if (fami != null) { + attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fami.Size)); + if (fami.ElementType != NativeType.None) + attr.AddNamedArgument("ArraySubType", MakePrimitive((int)fami.ElementType, unmanagedType)); + } + SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo; + if (sami != null && sami.ElementType != VariantType.None) { + var varEnum = new TypeReference("System.Runtime.InteropServices", "VarEnum", module, module.TypeSystem.Corlib); + attr.AddNamedArgument("SafeArraySubType", MakePrimitive((int)sami.ElementType, varEnum)); + } + ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo; + if (ami != null) { + if (ami.ElementType != NativeType.Max) + attr.AddNamedArgument("ArraySubType", MakePrimitive((int)ami.ElementType, unmanagedType)); + if (ami.Size >= 0) + attr.AddNamedArgument("SizeConst", new PrimitiveExpression(ami.Size)); + if (ami.SizeParameterMultiplier != 0) + attr.AddNamedArgument("SizeParamIndex", new PrimitiveExpression(ami.SizeParameterIndex)); + } + CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo; + if (cmi != null) { + attr.AddNamedArgument("MarshalType", new PrimitiveExpression(cmi.ManagedType.FullName)); + if (!string.IsNullOrEmpty(cmi.Cookie)) + attr.AddNamedArgument("MarshalCookie", new PrimitiveExpression(cmi.Cookie)); + } + FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo; + if (fssmi != null) { + attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fssmi.Size)); + } return attr; } #endregion diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index 956848a3e..618910fe3 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -269,8 +269,18 @@ namespace ICSharpCode.Decompiler.Disassembler ArrayMarshalInfo ami = (ArrayMarshalInfo)marshalInfo; if (ami == null) goto default; - WriteNativeType(ami.ElementType); - output.Write("[size={0}, sizeParameterIndex={1}, sizeParameterMultiplier={2}]", ami.Size, ami.SizeParameterIndex, ami.SizeParameterMultiplier); + if (ami.ElementType != NativeType.Max) + WriteNativeType(ami.ElementType); + output.Write('['); + if (ami.SizeParameterMultiplier == 0) { + output.Write(ami.Size.ToString()); + } else { + if (ami.Size >= 0) + output.Write(ami.Size.ToString()); + output.Write(" + "); + output.Write(ami.SizeParameterIndex.ToString()); + } + output.Write(']'); break; case NativeType.Currency: output.Write("currency"); @@ -370,10 +380,15 @@ namespace ICSharpCode.Decompiler.Disassembler } break; case NativeType.FixedArray: - output.Write("fixed sysstring"); + output.Write("fixed array"); FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo; - if (fami != null) - output.Write("[{0}]", ((FixedArrayMarshalInfo)marshalInfo).Size); + if (fami != null) { + output.Write("[{0}]", fami.Size); + if (fami.ElementType != NativeType.None) { + output.Write(' '); + WriteNativeType(fami.ElementType); + } + } break; case NativeType.ByValStr: output.Write("byvalstr"); @@ -395,12 +410,19 @@ namespace ICSharpCode.Decompiler.Disassembler break; case NativeType.CustomMarshaler: CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo; - goto default; // ??? + if (cmi == null) + goto default; + output.Write("custom(\"{0}\", \"{1}\"", + NRefactory.CSharp.OutputVisitor.ConvertString(cmi.ManagedType.FullName), + NRefactory.CSharp.OutputVisitor.ConvertString(cmi.Cookie)); + if (cmi.Guid != Guid.Empty || !string.IsNullOrEmpty(cmi.UnmanagedType)) { + output.Write(", \"{0}\", \"{1}\"", cmi.Guid.ToString(), NRefactory.CSharp.OutputVisitor.ConvertString(cmi.UnmanagedType)); + } + output.Write(')'); + break; case NativeType.Error: output.Write("error"); break; - case NativeType.Max: - // ??? default: output.Write(nativeType.ToString()); break; @@ -420,6 +442,9 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write("[opt] "); p.ParameterType.WriteTo(output); output.Write(' '); + if (p.HasMarshalInfo) { + WriteMarshalInfo(p.MarshalInfo); + } output.WriteDefinition(DisassemblerHelpers.Escape(p.Name), p); if (i < parameters.Count - 1) output.Write(','); diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index 8a3cc466f..54db1aea7 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -370,7 +370,6 @@ namespace ICSharpCode.Decompiler.ILAst } else if (expr.Code == ILCode.Newobj && expr.Arguments.Count == 2) { // Might be 'newobj(SomeDelegate, target, ldvirtftn(F, target))'. ILVariable target; - ILExpression ldvirtftnArg; if (expr.Arguments[0].Match(ILCode.Ldloc, out target) && expr.Arguments[1].Code == ILCode.Ldvirtftn && expr.Arguments[1].Arguments.Count == 1 diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index b4906c60f..6023f2aff 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -59,6 +59,7 @@ + diff --git a/ICSharpCode.Decompiler/Tests/PInvoke.cs b/ICSharpCode.Decompiler/Tests/PInvoke.cs new file mode 100644 index 000000000..fe9b9b5bc --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/PInvoke.cs @@ -0,0 +1,87 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Runtime.InteropServices; + +// P/Invoke and marshalling attribute tests +public class PInvoke +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 2)] + public struct MarshalAsTest + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public uint[] FixedArray; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Bool)] + public int[] FixedBoolArray; + + [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] + public string[] SafeBStrArray; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string FixedString; + } + + [StructLayout(LayoutKind.Explicit)] + public struct Rect + { + [FieldOffset(0)] + public int left; + [FieldOffset(4)] + public int top; + [FieldOffset(8)] + public int right; + [FieldOffset(12)] + public int bottom; + } + + public static decimal MarshalAttributesOnPropertyAccessors + { + [return: MarshalAs(UnmanagedType.Currency)] + get + { + return 0m; + } + [param: MarshalAs(UnmanagedType.Currency)] + set + { + } + } + + [DllImport("xyz.dll", CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool Method([MarshalAs(UnmanagedType.LPStr)] string input); + + [DllImport("xyz.dll")] + private static extern void New1(int ElemCnt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] ar); + + [DllImport("xyz.dll")] + private static extern void New2([MarshalAs(UnmanagedType.LPArray, SizeConst = 128)] int[] ar); + + [DllImport("xyz.dll")] + private static extern void New3([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Bool, SizeConst = 64, SizeParamIndex = 1)] int[] ar); + + public void CustomMarshal1([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler")] object o) + { + } + + public void CustomMarshal2([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler", MarshalCookie = "Cookie")] object o) + { + } +} diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs index 998c17370..de06f7d68 100644 --- a/ICSharpCode.Decompiler/Tests/TestRunner.cs +++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs @@ -73,6 +73,12 @@ namespace ICSharpCode.Decompiler.Tests TestFile(@"..\..\Tests\MultidimensionalArray.cs"); } + [Test] + public void PInvoke() + { + TestFile(@"..\..\Tests\PInvoke.cs"); + } + [Test] public void PropertiesAndEvents() { From 32081feb1b8d34148242de4921cae5b47eb740a1 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 May 2011 20:58:55 +0200 Subject: [PATCH 46/65] Decompile security declarations. Closes #189. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 64 +++++++- .../Disassembler/ReflectionDisassembler.cs | 139 ++++++++++++++++++ 2 files changed, 202 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index e24ecb8e1..7a489d07e 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -126,6 +126,7 @@ namespace ICSharpCode.Decompiler.Ast public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false) { ConvertCustomAttributes(astCompileUnit, assemblyDefinition, "assembly"); + ConvertSecurityAttributes(astCompileUnit, assemblyDefinition, "assembly"); ConvertCustomAttributes(astCompileUnit, assemblyDefinition.MainModule, "module"); if (!onlyAssemblyLevel) { @@ -990,6 +991,7 @@ namespace ICSharpCode.Decompiler.Ast void ConvertAttributes(AttributedNode attributedNode, TypeDefinition typeDefinition) { ConvertCustomAttributes(attributedNode, typeDefinition); + ConvertSecurityAttributes(attributedNode, typeDefinition); // Handle the non-custom attributes: #region SerializableAttribute @@ -1040,6 +1042,7 @@ namespace ICSharpCode.Decompiler.Ast void ConvertAttributes(AttributedNode attributedNode, MethodDefinition methodDefinition) { ConvertCustomAttributes(attributedNode, methodDefinition); + ConvertSecurityAttributes(attributedNode, methodDefinition); MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask; @@ -1194,7 +1197,7 @@ namespace ICSharpCode.Decompiler.Ast attr.AddNamedArgument("ArraySubType", MakePrimitive((int)ami.ElementType, unmanagedType)); if (ami.Size >= 0) attr.AddNamedArgument("SizeConst", new PrimitiveExpression(ami.Size)); - if (ami.SizeParameterMultiplier != 0) + if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0) attr.AddNamedArgument("SizeParamIndex", new PrimitiveExpression(ami.SizeParameterIndex)); } CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo; @@ -1296,6 +1299,65 @@ namespace ICSharpCode.Decompiler.Ast } } + static void ConvertSecurityAttributes(AstNode attributedNode, ISecurityDeclarationProvider secDeclProvider, string attributeTarget = null) + { + if (!secDeclProvider.HasSecurityDeclarations) + return; + var attributes = new List(); + foreach (var secDecl in secDeclProvider.SecurityDeclarations) { + foreach (var secAttribute in secDecl.SecurityAttributes) { + var attribute = new ICSharpCode.NRefactory.CSharp.Attribute(); + attribute.AddAnnotation(secAttribute); + attribute.Type = ConvertType(secAttribute.AttributeType); + attributes.Add(attribute); + + SimpleType st = attribute.Type as SimpleType; + if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) { + st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - "Attribute".Length); + } + + var module = secAttribute.AttributeType.Module; + var securityActionType = new TypeReference("System.Security.Permissions", "SecurityAction", module, module.TypeSystem.Corlib); + attribute.Arguments.Add(MakePrimitive((int)secDecl.Action, securityActionType)); + + if (secAttribute.HasProperties) { + TypeDefinition resolvedAttributeType = secAttribute.AttributeType.Resolve(); + foreach (var propertyNamedArg in secAttribute.Properties) { + var propertyReference = resolvedAttributeType != null ? resolvedAttributeType.Properties.FirstOrDefault(pr => pr.Name == propertyNamedArg.Name) : null; + var propertyName = new IdentifierExpression(propertyNamedArg.Name).WithAnnotation(propertyReference); + var argumentValue = ConvertArgumentValue(propertyNamedArg.Argument); + attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue)); + } + } + + if (secAttribute.HasFields) { + TypeDefinition resolvedAttributeType = secAttribute.AttributeType.Resolve(); + foreach (var fieldNamedArg in secAttribute.Fields) { + var fieldReference = resolvedAttributeType != null ? resolvedAttributeType.Fields.FirstOrDefault(f => f.Name == fieldNamedArg.Name) : null; + var fieldName = new IdentifierExpression(fieldNamedArg.Name).WithAnnotation(fieldReference); + var argumentValue = ConvertArgumentValue(fieldNamedArg.Argument); + attribute.Arguments.Add(new AssignmentExpression(fieldName, argumentValue)); + } + } + } + } + if (attributeTarget == "module" || attributeTarget == "assembly") { + // use separate section for each attribute + foreach (var attribute in attributes) { + var section = new AttributeSection(); + section.AttributeTarget = attributeTarget; + section.Attributes.Add(attribute); + attributedNode.AddChild(section, AttributedNode.AttributeRole); + } + } else if (attributes.Count > 0) { + // use single section for all attributes + var section = new AttributeSection(); + section.AttributeTarget = attributeTarget; + section.Attributes.AddRange(attributes); + attributedNode.AddChild(section, AttributedNode.AttributeRole); + } + } + private static Expression ConvertArgumentValue(CustomAttributeArgument argument) { if (argument.Value is CustomAttributeArgument[]) { diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index 618910fe3..be00da59a 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -18,7 +18,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; +using System.Text; using System.Threading; using Mono.Cecil; using Mono.Collections.Generic; @@ -198,6 +200,7 @@ namespace ICSharpCode.Decompiler.Disassembler foreach (var p in method.Parameters) { WriteParameterAttributes(p); } + WriteSecurityDeclarations(method); if (method.HasBody) { // create IL code mappings - used in debugger @@ -208,6 +211,140 @@ namespace ICSharpCode.Decompiler.Disassembler CloseBlock("end of method " + DisassemblerHelpers.Escape(method.DeclaringType.Name) + "::" + DisassemblerHelpers.Escape(method.Name)); } + #region Write Security Declarations + void WriteSecurityDeclarations(ISecurityDeclarationProvider secDeclProvider) + { + if (!secDeclProvider.HasSecurityDeclarations) + return; + foreach (var secdecl in secDeclProvider.SecurityDeclarations) { + output.Write(".permissionset "); + switch (secdecl.Action) { + case SecurityAction.Request: + output.Write("request"); + break; + case SecurityAction.Demand: + output.Write("demand"); + break; + case SecurityAction.Assert: + output.Write("assert"); + break; + case SecurityAction.Deny: + output.Write("deny"); + break; + case SecurityAction.PermitOnly: + output.Write("permitonly"); + break; + case SecurityAction.LinkDemand: + output.Write("linkcheck"); + break; + case SecurityAction.InheritDemand: + output.Write("inheritcheck"); + break; + case SecurityAction.RequestMinimum: + output.Write("reqmin"); + break; + case SecurityAction.RequestOptional: + output.Write("reqopt"); + break; + case SecurityAction.RequestRefuse: + output.Write("reqrefuse"); + break; + case SecurityAction.PreJitGrant: + output.Write("prejitgrant"); + break; + case SecurityAction.PreJitDeny: + output.Write("prejitdeny"); + break; + case SecurityAction.NonCasDemand: + output.Write("noncasdemand"); + break; + case SecurityAction.NonCasLinkDemand: + output.Write("noncaslinkdemand"); + break; + case SecurityAction.NonCasInheritance: + output.Write("noncasinheritance"); + break; + default: + output.Write(secdecl.Action.ToString()); + break; + } + output.WriteLine(" = {"); + output.Indent(); + for (int i = 0; i < secdecl.SecurityAttributes.Count; i++) { + SecurityAttribute sa = secdecl.SecurityAttributes[i]; + if (sa.AttributeType.Scope == sa.AttributeType.Module) { + output.Write("class "); + output.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(sa.AttributeType))); + } else { + sa.AttributeType.WriteTo(output, ILNameSyntax.TypeName); + } + output.Write(" = {"); + if (sa.HasFields || sa.HasProperties) { + output.WriteLine(); + output.Indent(); + + foreach (CustomAttributeNamedArgument na in sa.Fields) { + output.Write("field "); + WriteSecurityDeclarationArgument(na); + output.WriteLine(); + } + + foreach (CustomAttributeNamedArgument na in sa.Properties) { + output.Write("property "); + WriteSecurityDeclarationArgument(na); + output.WriteLine(); + } + + output.Unindent(); + } + output.Write('}'); + + if (i + 1< secdecl.SecurityAttributes.Count) + output.Write(','); + output.WriteLine(); + } + output.Unindent(); + output.WriteLine("}"); + } + } + + void WriteSecurityDeclarationArgument(CustomAttributeNamedArgument na) + { + TypeReference type = na.Argument.Type; + if (type.MetadataType == MetadataType.Class || type.MetadataType == MetadataType.ValueType) { + output.Write("enum "); + if (type.Scope != type.Module) { + output.Write("class "); + output.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(type))); + } else { + type.WriteTo(output, ILNameSyntax.TypeName); + } + } else { + type.WriteTo(output); + } + output.Write(' '); + output.Write(DisassemblerHelpers.Escape(na.Name)); + output.Write(" = "); + WriteConstant(na.Argument.Value); + } + + string GetAssemblyQualifiedName(TypeReference type) + { + AssemblyNameReference anr = type.Scope as AssemblyNameReference; + if (anr == null) { + ModuleDefinition md = type.Scope as ModuleDefinition; + if (md != null) { + anr = md.Assembly.Name; + } + } + if (anr != null) { + return type.FullName + ", " + anr.FullName; + } else { + return type.FullName; + } + } + #endregion + #region WriteMarshalInfo void WriteMarshalInfo(MarshalInfo marshalInfo) { @@ -698,6 +835,7 @@ namespace ICSharpCode.Decompiler.Disassembler bool oldIsInType = isInType; isInType = true; WriteAttributes(type.CustomAttributes); + WriteSecurityDeclarations(type); if (type.HasLayoutInfo) { output.WriteLine(".pack {0}", type.PackingSize); output.WriteLine(".size {0}", type.ClassSize); @@ -917,6 +1055,7 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(".assembly " + DisassemblerHelpers.Escape(asm.Name.Name)); OpenBlock(false); WriteAttributes(asm.CustomAttributes); + WriteSecurityDeclarations(asm); if (asm.Name.PublicKey != null && asm.Name.PublicKey.Length > 0) { output.Write(".publickey = "); WriteBlob(asm.Name.PublicKey); From 3779381796e327191b5702d8afc44cd1ca286153 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 May 2011 21:57:53 +0200 Subject: [PATCH 47/65] Add support for type forwarding declarations ([TypeForwardedToAttribute]). Closes #190. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 68 ++++++++++++++++++- .../Ast/AstMethodBodyBuilder.cs | 31 +-------- .../Disassembler/ReflectionDisassembler.cs | 15 ++++ 3 files changed, 81 insertions(+), 33 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 7a489d07e..397b82030 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -128,6 +128,7 @@ namespace ICSharpCode.Decompiler.Ast ConvertCustomAttributes(astCompileUnit, assemblyDefinition, "assembly"); ConvertSecurityAttributes(astCompileUnit, assemblyDefinition, "assembly"); ConvertCustomAttributes(astCompileUnit, assemblyDefinition.MainModule, "module"); + AddTypeForwarderAttributes(astCompileUnit, assemblyDefinition.MainModule, "assembly"); if (!onlyAssemblyLevel) { foreach (TypeDefinition typeDef in assemblyDefinition.MainModule.Types) { @@ -142,6 +143,30 @@ namespace ICSharpCode.Decompiler.Ast } } + void AddTypeForwarderAttributes(CompilationUnit astCompileUnit, ModuleDefinition module, string target) + { + if (!module.HasExportedTypes) + return; + foreach (ExportedType type in module.ExportedTypes) { + if (type.IsForwarder) { + var forwardedType = CreateTypeOfExpression(new TypeReference(type.Namespace, type.Name, module, type.Scope)); + astCompileUnit.AddChild( + new AttributeSection { + AttributeTarget = target, + Attributes = { + new NRefactory.CSharp.Attribute { + Type = new SimpleType("TypeForwardedTo") + .WithAnnotation(new TypeReference( + "System.Runtime.CompilerServices", "TypeForwardedToAttribute", + module, module.TypeSystem.Corlib)), + Arguments = { forwardedType } + } + } + }, AttributedNode.AttributeRole); + } + } + } + NamespaceDeclaration GetCodeNamespace(string name) { if (string.IsNullOrEmpty(name)) { @@ -306,6 +331,45 @@ namespace ICSharpCode.Decompiler.Ast return name; } + #region Create TypeOf Expression + /// + /// Creates a typeof-expression for the specified type. + /// + public static TypeOfExpression CreateTypeOfExpression(TypeReference type) + { + return new TypeOfExpression(AddEmptyTypeArgumentsForUnboundGenerics(ConvertType(type))); + } + + static AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type) + { + TypeReference typeRef = type.Annotation(); + if (typeRef == null) + return type; + TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters + if (typeDef == null || !typeDef.HasGenericParameters) + return type; + SimpleType sType = type as SimpleType; + MemberType mType = type as MemberType; + if (sType != null) { + while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) { + sType.TypeArguments.Add(new SimpleType("")); + } + } + + if (mType != null) { + AddEmptyTypeArgumentsForUnboundGenerics(mType.Target); + + int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count; + + while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) { + mType.TypeArguments.Add(new SimpleType("")); + } + } + + return type; + } + #endregion + #region Convert Type Reference /// /// Converts a type reference. @@ -1378,9 +1442,7 @@ namespace ICSharpCode.Decompiler.Ast if (type != null && type.IsEnum) { return MakePrimitive(Convert.ToInt64(argument.Value), type); } else if (argument.Value is TypeReference) { - return new TypeOfExpression() { - Type = ConvertType((TypeReference)argument.Value), - }; + return CreateTypeOfExpression((TypeReference)argument.Value); } else { return new PrimitiveExpression(argument.Value); } diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index c8666b73a..b82101562 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -601,7 +601,7 @@ namespace ICSharpCode.Decompiler.Ast case ILCode.Ldstr: return new Ast.PrimitiveExpression(operand); case ILCode.Ldtoken: if (operand is Cecil.TypeReference) { - return new Ast.TypeOfExpression { Type = AddEmptyTypeArgumentsForUnboundGenerics(operandAsTypeRef) }.Member("TypeHandle"); + return AstBuilder.CreateTypeOfExpression((TypeReference)operand).Member("TypeHandle"); } else { return InlineAssembly(byteCode, args); } @@ -749,35 +749,6 @@ namespace ICSharpCode.Decompiler.Ast } } - AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type) - { - TypeReference typeRef = type.Annotation(); - if (typeRef == null) - return type; - TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters - if (typeDef == null || !typeDef.HasGenericParameters) - return type; - SimpleType sType = type as SimpleType; - MemberType mType = type as MemberType; - if (sType != null) { - while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) { - sType.TypeArguments.Add(new SimpleType("")); - } - } - - if (mType != null) { - AddEmptyTypeArgumentsForUnboundGenerics(mType.Target); - - int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count; - - while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) { - mType.TypeArguments.Add(new SimpleType("")); - } - } - - return type; - } - static readonly AstNode objectInitializerPattern = new AssignmentExpression( new MemberReferenceExpression { Target = new InitializedObjectExpression() diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index be00da59a..f4f8dac8a 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -1096,6 +1096,21 @@ namespace ICSharpCode.Decompiler.Disassembler public void WriteModuleHeader(ModuleDefinition module) { + if (module.HasExportedTypes) { + foreach (ExportedType exportedType in module.ExportedTypes) { + output.Write(".class extern "); + if (exportedType.IsForwarder) + output.Write("forwarder "); + output.Write(exportedType.DeclaringType != null ? exportedType.Name : exportedType.FullName); + OpenBlock(false); + if (exportedType.DeclaringType != null) + output.WriteLine(".class extern {0}", DisassemblerHelpers.Escape(exportedType.DeclaringType.FullName)); + else + output.WriteLine(".assembly extern {0}", DisassemblerHelpers.Escape(exportedType.Scope.Name)); + CloseBlock(); + } + } + output.WriteLine(".module {0}", module.Name); output.WriteLine("// MVID: {0}", module.Mvid.ToString("B").ToUpperInvariant()); // TODO: imagebase, file alignment, stackreserve, subsystem From 7d24f683d1ef1705aae3dcfcd6daee64c2d24c07 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 May 2011 22:03:36 +0200 Subject: [PATCH 48/65] Decompile AssemblyVersion attribute. Closes #188. --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 18 ++++++++++++++++++ .../Tests/Helpers/RemoveCompilerAttribute.cs | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 397b82030..c0258db0b 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -125,6 +125,24 @@ namespace ICSharpCode.Decompiler.Ast public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false) { + if (assemblyDefinition.Name.Version != null) { + astCompileUnit.AddChild( + new AttributeSection { + AttributeTarget = "assembly", + Attributes = { + new NRefactory.CSharp.Attribute { + Type = new SimpleType("AssemblyVersion") + .WithAnnotation(new TypeReference( + "System.Reflection", "AssemblyVersionAttribute", + assemblyDefinition.MainModule, assemblyDefinition.MainModule.TypeSystem.Corlib)), + Arguments = { + new PrimitiveExpression(assemblyDefinition.Name.Version.ToString()) + } + } + } + }, AttributedNode.AttributeRole); + } + ConvertCustomAttributes(astCompileUnit, assemblyDefinition, "assembly"); ConvertSecurityAttributes(astCompileUnit, assemblyDefinition, "assembly"); ConvertCustomAttributes(astCompileUnit, assemblyDefinition.MainModule, "module"); diff --git a/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs b/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs index 0076eb2ba..251916557 100644 --- a/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs +++ b/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs @@ -15,7 +15,7 @@ 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 == "CompilationRelaxations" || type.Identifier == "RuntimeCompatibility" || type.Identifier == "SecurityPermission" || type.Identifier == "AssemblyVersion")) { attribute.Remove(); if (section.Attributes.Count == 0) From b74daf8c3259b70ca760ffa8efd952301469dd27 Mon Sep 17 00:00:00 2001 From: KevinCathcart Date: Sat, 21 May 2011 13:12:36 -0700 Subject: [PATCH 49/65] Add support for "instance explicit" calling convention for a MethodReference. --- ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index 555eae487..3c66ef83b 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -110,8 +110,12 @@ namespace ICSharpCode.Decompiler.Disassembler public static void WriteTo(this MethodReference method, ITextOutput writer) { - if (method.HasThis) + if (method.ExplicitThis) { + writer.Write("instance explicit "); + } + else if (method.HasThis) { writer.Write("instance "); + } method.ReturnType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters); writer.Write(' '); if (method.DeclaringType != null) { From 5274fe95c1b54f0aac5744b2c9b7eda9940079f8 Mon Sep 17 00:00:00 2001 From: KevinCathcart Date: Sat, 21 May 2011 13:44:43 -0700 Subject: [PATCH 50/65] Support "instance explicit" method definitions. (The informative metadata validation text indicates that it only applies to function pointers, but that is not enforced except as part of metadata validation.) --- .../Disassembler/ReflectionDisassembler.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index be00da59a..1a79908aa 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -153,9 +153,11 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine(); output.Indent(); - - if (method.HasThis) + if (method.ExplicitThis) { + output.Write("instance explicit "); + } else if (method.HasThis) { output.Write("instance "); + } //call convention WriteEnum(method.CallingConvention & (MethodCallingConvention)0x1f, callingConvention); From e198438a46553f1ae0d3e4504488a18c4d714ede Mon Sep 17 00:00:00 2001 From: KevinCathcart Date: Sat, 21 May 2011 13:48:35 -0700 Subject: [PATCH 51/65] Added support for IL "forwardref" method definitions. --- ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index 1a79908aa..0cffebc18 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -94,6 +94,7 @@ namespace ICSharpCode.Decompiler.Disassembler { MethodImplAttributes.NoOptimization, "nooptimization" }, { MethodImplAttributes.PreserveSig, "preservesig" }, { MethodImplAttributes.InternalCall, "internalcall" }, + { MethodImplAttributes.ForwardRef, "forwardref" }, }; public void DisassembleMethod(MethodDefinition method) From 299bfbe4008a8d08ea4eb9012d3102f6bcfb09dd Mon Sep 17 00:00:00 2001 From: KevinCathcart Date: Sat, 21 May 2011 14:02:25 -0700 Subject: [PATCH 52/65] Added syntax highlighting support for IL's "strict" keyword. --- ILSpy/TextView/ILAsm-Mode.xshd | 1 + 1 file changed, 1 insertion(+) diff --git a/ILSpy/TextView/ILAsm-Mode.xshd b/ILSpy/TextView/ILAsm-Mode.xshd index 5f582d37c..76fbc1afa 100644 --- a/ILSpy/TextView/ILAsm-Mode.xshd +++ b/ILSpy/TextView/ILAsm-Mode.xshd @@ -348,6 +348,7 @@ tls true false + strict .class From 20f9a624f2958fdc649f6167538b041e8b139df2 Mon Sep 17 00:00:00 2001 From: Kevin Cathcart Date: Sat, 21 May 2011 20:08:24 -0400 Subject: [PATCH 53/65] Add support for privatescope. Fixes #186 --- .../Disassembler/DisassemblerHelpers.cs | 7 ++++++- .../Disassembler/ReflectionDisassembler.cs | 9 ++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index 3c66ef83b..97cff7d30 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -122,7 +122,12 @@ namespace ICSharpCode.Decompiler.Disassembler method.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName); writer.Write("::"); } - writer.WriteReference(Escape(method.Name), method); + MethodDefinition md = method as MethodDefinition; + if (md != null && md.IsCompilerControlled) { + writer.WriteReference(Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8")), method); + } else { + writer.WriteReference(Escape(method.Name), method); + } GenericInstanceMethod gim = method as GenericInstanceMethod; if (gim != null) { writer.Write('<'); diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index 0cffebc18..9100faab1 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -113,6 +113,7 @@ namespace ICSharpCode.Decompiler.Disassembler //emit flags WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility); WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags); + if(method.IsCompilerControlled) output.Write("privatescope "); if ((method.Attributes & MethodAttributes.PInvokeImpl) == MethodAttributes.PInvokeImpl) { output.Write("pinvokeimpl"); @@ -170,7 +171,13 @@ namespace ICSharpCode.Decompiler.Disassembler if (method.MethodReturnType.HasMarshalInfo) { WriteMarshalInfo(method.MethodReturnType.MarshalInfo); } - output.Write(DisassemblerHelpers.Escape(method.Name)); + + if (method.IsCompilerControlled) { + output.Write(DisassemblerHelpers.Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8"))); + } else { + output.Write(DisassemblerHelpers.Escape(method.Name)); + } + WriteTypeParameters(output, method); //( params ) From 399a87e5a1f59ef6ed7e3633c297884ae789fec8 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 22 May 2011 02:03:13 +0200 Subject: [PATCH 54/65] Fix #195 IL identfier escaping. --- .../Disassembler/DisassemblerHelpers.cs | 22 ++++++++++++++----- .../Disassembler/ReflectionDisassembler.cs | 7 +++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index 97cff7d30..a88ed7089 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -156,14 +156,21 @@ namespace ICSharpCode.Decompiler.Disassembler writer.WriteReference(Escape(field.Name), field); } + static bool IsValidIdentifierCharacter(char c) + { + return c == '_' || c == '$' || c == '@' || c == '?' || c == '`'; + } + static bool IsValidIdentifier(string identifier) { if (string.IsNullOrEmpty(identifier)) return false; - if (!(char.IsLetter(identifier[0]) || identifier[0] == '_' || identifier[0] == '.')) - return false; + 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++) { - if (!(char.IsLetterOrDigit(identifier[i]) || identifier[i] == '_' || identifier[i] == '.' || identifier[i] == '`')) + if (!(char.IsLetterOrDigit(identifier[i]) || IsValidIdentifierCharacter(identifier[i]) || identifier[i] == '.')) return false; } return true; @@ -196,7 +203,7 @@ namespace ICSharpCode.Decompiler.Disassembler "vararg", "variant", "vector", "virtual", "void", "wchar", "winapi", "with", "wrapper", // These are not listed as keywords in spec, but ILAsm treats them as such - "property", "type", "flags", "callconv" + "property", "type", "flags", "callconv", "strict" ); static HashSet BuildKeywordList(params string[] keywords) @@ -210,10 +217,13 @@ namespace ICSharpCode.Decompiler.Disassembler public static string Escape(string identifier) { - if (IsValidIdentifier(identifier) && !ilKeywords.Contains(identifier)) + if (IsValidIdentifier(identifier) && !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 "'" + NRefactory.CSharp.OutputVisitor.ConvertString(identifier).Replace("'", "\\'") + "'"; + } } public static void WriteTo(this TypeReference type, ITextOutput writer, ILNameSyntax syntax = ILNameSyntax.Signature) diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index 4174f2b11..4e144924e 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -335,7 +335,12 @@ namespace ICSharpCode.Decompiler.Disassembler output.Write(' '); output.Write(DisassemblerHelpers.Escape(na.Name)); output.Write(" = "); - WriteConstant(na.Argument.Value); + if (na.Argument.Value is string) { + // secdecls use special syntax for strings + output.Write("string('{0}')", NRefactory.CSharp.OutputVisitor.ConvertString((string)na.Argument.Value).Replace("'", "\'")); + } else { + WriteConstant(na.Argument.Value); + } } string GetAssemblyQualifiedName(TypeReference type) From 229218174f2d53b5b7915565b5359da4d16c46a7 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 22 May 2011 13:39:29 +0200 Subject: [PATCH 55/65] Inlining: remove the arg_-Variable in catch blocks. --- ICSharpCode.Decompiler/Ast/NameVariables.cs | 2 ++ .../Disassembler/DisassemblerHelpers.cs | 7 ++-- ICSharpCode.Decompiler/ILAst/ILAstTypes.cs | 4 +++ ICSharpCode.Decompiler/ILAst/ILInlining.cs | 32 ++++++++++++++++++- .../Tests/ExceptionHandling.cs | 4 +-- ICSharpCode.Decompiler/Tests/TestRunner.cs | 2 +- 6 files changed, 45 insertions(+), 6 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/NameVariables.cs b/ICSharpCode.Decompiler/Ast/NameVariables.cs index 66f50ff13..c7ac8f385 100644 --- a/ICSharpCode.Decompiler/Ast/NameVariables.cs +++ b/ICSharpCode.Decompiler/Ast/NameVariables.cs @@ -279,6 +279,8 @@ namespace ICSharpCode.Decompiler.Ast name = "array"; } else if (type.IsPointer || type.IsByReference) { name = "ptr"; + } else if (type.Name.EndsWith("Exception", StringComparison.Ordinal)) { + name = "ex"; } else if (!typeNameToVariableNameDict.TryGetValue(type.FullName, out name)) { name = type.Name; // remove the 'I' for interfaces diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index a88ed7089..df66c2650 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.Disassembler /// TypeName, /// - /// Name (even for built-in types) + /// Name (but built-in types use keyword syntax) /// ShortTypeName } @@ -275,7 +275,10 @@ namespace ICSharpCode.Decompiler.Disassembler } else { string name = PrimitiveTypeName(type.FullName); if (syntax == ILNameSyntax.ShortTypeName) { - writer.WriteReference(Escape(type.Name), type); + if (name != null) + writer.Write(name); + else + writer.WriteReference(Escape(type.Name), type); } else if ((syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) && name != null) { writer.Write(name); } else { diff --git a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs index 48312b080..f86225fb8 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs @@ -141,6 +141,10 @@ namespace ICSharpCode.Decompiler.ILAst { output.Write("catch "); output.WriteReference(ExceptionType.FullName, ExceptionType); + if (ExceptionVariable != null) { + output.Write(' '); + output.Write(ExceptionVariable.Name); + } output.WriteLine(" {"); output.Indent(); base.WriteTo(output); diff --git a/ICSharpCode.Decompiler/ILAst/ILInlining.cs b/ICSharpCode.Decompiler/ILAst/ILInlining.cs index 76fde12bf..d839f41ef 100644 --- a/ICSharpCode.Decompiler/ILAst/ILInlining.cs +++ b/ICSharpCode.Decompiler/ILAst/ILInlining.cs @@ -47,7 +47,13 @@ namespace ICSharpCode.Decompiler.ILAst numLdloca.Clear(); // Analyse the whole method - foreach(ILExpression expr in method.GetSelfAndChildrenRecursive()) { + AnalyzeNode(method); + } + + void AnalyzeNode(ILNode node) + { + ILExpression expr = node as ILExpression; + if (expr != null) { ILVariable locVar = expr.Operand as ILVariable; if (locVar != null) { if (expr.Code == ILCode.Stloc) { @@ -60,6 +66,16 @@ namespace ICSharpCode.Decompiler.ILAst throw new NotSupportedException(expr.Code.ToString()); } } + foreach (ILExpression child in expr.Arguments) + AnalyzeNode(child); + } else { + var catchBlock = node as ILTryCatchBlock.CatchBlock; + if (catchBlock != null && catchBlock.ExceptionVariable != null) { + numStloc[catchBlock.ExceptionVariable] = numStloc.GetOrDefault(catchBlock.ExceptionVariable) + 1; + } + + foreach (ILNode child in node.GetChildren()) + AnalyzeNode(child); } } @@ -76,6 +92,20 @@ namespace ICSharpCode.Decompiler.ILAst { bool modified = false; List body = block.Body; + if (block is ILTryCatchBlock.CatchBlock && body.Count > 1) { + ILVariable v = ((ILTryCatchBlock.CatchBlock)block).ExceptionVariable; + if (v != null && v.IsGenerated) { + if (numLdloca.GetOrDefault(v) == 0 && numStloc.GetOrDefault(v) == 1 && numLdloc.GetOrDefault(v) == 1) { + ILVariable v2; + ILExpression ldException; + if (body[0].Match(ILCode.Stloc, out v2, out ldException) && ldException.MatchLdloc(v)) { + body.RemoveAt(0); + ((ILTryCatchBlock.CatchBlock)block).ExceptionVariable = v2; + modified = true; + } + } + } + } for(int i = 0; i < body.Count - 1;) { ILVariable locVar; ILExpression expr; diff --git a/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs b/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs index 9d81936a5..7f6e506ee 100644 --- a/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs +++ b/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs @@ -56,9 +56,9 @@ public class ExceptionHandling { Console.WriteLine(ex.Message); } - catch (Exception ex) + catch (Exception ex2) { - Console.WriteLine(ex.Message); + Console.WriteLine(ex2.Message); } catch { diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs index de06f7d68..87bb31dd4 100644 --- a/ICSharpCode.Decompiler/Tests/TestRunner.cs +++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs @@ -37,7 +37,7 @@ namespace ICSharpCode.Decompiler.Tests TestFile(@"..\..\Tests\DelegateConstruction.cs"); } - [Test, Ignore("arg-Variables in catch clauses")] + [Test] public void ExceptionHandling() { TestFile(@"..\..\Tests\ExceptionHandling.cs"); From a1205d40e9d7d5f091a08b42c46a9a0dc96e7989 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 22 May 2011 13:56:44 +0200 Subject: [PATCH 56/65] Fix #168: ILSpy crashes on close when viewing an obfuscated assembly --- ILSpy/ILSpySettings.cs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/ILSpy/ILSpySettings.cs b/ILSpy/ILSpySettings.cs index 7d0fd19cb..053bee7ce 100644 --- a/ILSpy/ILSpySettings.cs +++ b/ILSpy/ILSpySettings.cs @@ -19,6 +19,7 @@ using System; using System.IO; using System.Linq; +using System.Text; using System.Threading; using System.Xml; using System.Xml.Linq; @@ -58,7 +59,7 @@ namespace ICSharpCode.ILSpy { using (new MutexProtector(ConfigFileMutex)) { try { - XDocument doc = XDocument.Load(GetConfigFile()); + XDocument doc = LoadWithoutCheckingCharacters(GetConfigFile()); return new ILSpySettings(doc.Root); } catch (IOException) { return new ILSpySettings(); @@ -68,6 +69,15 @@ namespace ICSharpCode.ILSpy } } + static XDocument LoadWithoutCheckingCharacters(string fileName) + { + // XDocument.Load(fileName) validates that no invalid characters appear (not even in escaped form), + // but we need those characters for some obfuscated assemblies. + using (XmlTextReader r = new XmlTextReader(fileName)) { + return XDocument.Load(r); + } + } + /// /// Saves a setting section. /// @@ -94,7 +104,7 @@ namespace ICSharpCode.ILSpy string config = GetConfigFile(); XDocument doc; try { - doc = XDocument.Load(config); + doc = LoadWithoutCheckingCharacters(config); } catch (IOException) { // ensure the directory exists Directory.CreateDirectory(Path.GetDirectoryName(config)); @@ -104,7 +114,12 @@ namespace ICSharpCode.ILSpy } doc.Root.SetAttributeValue("version", RevisionClass.Major + "." + RevisionClass.Minor + "." + RevisionClass.Build + "." + RevisionClass.Revision); action(doc.Root); - doc.Save(config); + // We can't use XDocument.Save(filename) because that checks for invalid characters, but those can appear + // in obfuscated assemblies. + using (XmlTextWriter writer = new XmlTextWriter(config, Encoding.UTF8)) { + writer.Formatting = Formatting.Indented; + doc.Save(writer); + } } } From a929decdeb3289939e73fac9c03f8f88c5805f4d Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 22 May 2011 14:35:41 +0200 Subject: [PATCH 57/65] implement basic support for custom short circuit operators + unit test; fixes #193 --- .../ILAst/ILAstOptimizer.cs | 4 + .../ILAst/SimpleControlFlow.cs | 84 ++++++++++++++++++- ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs | 4 + .../Tests/CustomShortCircuitOperators.cs | 43 ++++++++++ .../Tests/ICSharpCode.Decompiler.Tests.csproj | 1 + ICSharpCode.Decompiler/Tests/TestRunner.cs | 6 ++ 6 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index 54db1aea7..ef6ab4e54 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -44,6 +44,7 @@ namespace ICSharpCode.Decompiler.ILAst JoinBasicBlocks, TransformDecimalCtorToConstant, SimplifyLdObjAndStObj, + SimplifyCustomShortCircuit, TransformArrayInitializers, TransformObjectInitializers, MakeAssignmentExpression, @@ -136,6 +137,9 @@ namespace ICSharpCode.Decompiler.ILAst if (abortBeforeStep == ILAstOptimizationStep.SimplifyLdObjAndStObj) return; modified |= block.RunOptimization(SimplifyLdObjAndStObj); + if (abortBeforeStep == ILAstOptimizationStep.SimplifyCustomShortCircuit) return; + modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyCustomShortCircuit); + if (abortBeforeStep == ILAstOptimizationStep.TransformArrayInitializers) return; modified |= block.RunOptimization(TransformArrayInitializers); diff --git a/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs b/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs index e477dbff5..d821f9aae 100644 --- a/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs +++ b/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs @@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler.ILAst newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr); } } else { - // Ternary operator tends to create long complicated return statements + // Ternary operator tends to create long complicated return statements if (opCode == ILCode.Ret) return false; @@ -156,7 +156,7 @@ namespace ICSharpCode.Decompiler.ILAst // ... // v = NullCoalescing(ldloc(leftVar), rightExpr) // br(endBBLabel) - + ILVariable v, v2; ILExpression leftExpr, leftExpr2; ILVariable leftVar; @@ -165,7 +165,7 @@ namespace ICSharpCode.Decompiler.ILAst ILBasicBlock rightBB; ILExpression rightExpr; if (head.Body.Count >= 3 && - head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out v, out leftExpr) && + head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out v, out leftExpr) && leftExpr.Match(ILCode.Ldloc, out leftVar) && head.MatchLastAndBr(ILCode.Brtrue, out endBBLabel, out leftExpr2, out rightBBLabel) && leftExpr2.MatchLdloc(leftVar) && @@ -234,6 +234,84 @@ namespace ICSharpCode.Decompiler.ILAst return false; } + public bool SimplifyCustomShortCircuit(List body, ILBasicBlock head, int pos) + { + Debug.Assert(body.Contains(head)); + + // --- looking for the following pattern --- + // stloc(targetVar, leftVar) + // brtrue(exitLabel, call(op_False, leftVar) + // br(followingBlock) + // + // FollowingBlock: + // stloc(targetVar, call(op_BitwiseAnd, leftVar, rightExpression)) + // br(exitLabel) + // --- + + if (head.Body.Count < 3) + return false; + + // looking for: + // stloc(targetVar, leftVar) + ILVariable targetVar; + ILExpression targetVarInitExpr; + if (!head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out targetVar, out targetVarInitExpr)) + return false; + + // looking for: + // brtrue(exitLabel, call(op_False, leftVar) + // br(followingBlock) + ILExpression callExpr; + ILLabel exitLabel; + ILLabel followingBlock; + if(!head.MatchLastAndBr(ILCode.Brtrue, out exitLabel, out callExpr, out followingBlock)) + return false; + + MethodDefinition opFalse; + ILExpression leftVar; + if (!callExpr.Match(ILCode.Call, out opFalse, out leftVar)) + return false; + + if (!leftVar.MatchLdloc(targetVarInitExpr.Operand as ILVariable)) + return false; + + ILBasicBlock followingBasicBlock = labelToBasicBlock[followingBlock]; + + // FollowingBlock: + // stloc(targetVar, call(op_BitwiseAnd, leftVar, rightExpression)) + // br(exitLabel) + ILVariable _targetVar; + ILExpression opBitwiseCallExpr; + ILLabel _exitLabel; + if (!followingBasicBlock.MatchSingleAndBr(ILCode.Stloc, out _targetVar, out opBitwiseCallExpr, out _exitLabel)) + return false; + + if (_targetVar != targetVar) + return false; + + MethodDefinition opBitwise; + ILExpression leftVarExpression; + ILExpression rightExpression; + if (!opBitwiseCallExpr.Match(ILCode.Call, out opBitwise, out leftVarExpression, out rightExpression)) + return false; + + if (!leftVar.MatchLdloc(leftVarExpression.Operand as ILVariable)) + return false; + + // insert: + // stloc(targetVar, LogicAnd(C::op_BitwiseAnd, leftVar, rightExpression) + // br(exitLabel) + ILExpression shortCircuitExpr = MakeLeftAssociativeShortCircuit(opBitwise.Name == "op_BitwiseAnd" ? ILCode.LogicAnd : ILCode.LogicOr, leftVar, rightExpression); + shortCircuitExpr.Operand = opBitwise; + + head.Body.RemoveTail(ILCode.Stloc, ILCode.Brtrue, ILCode.Br); + head.Body.Add(new ILExpression(ILCode.Stloc, targetVar, shortCircuitExpr)); + head.Body.Add(new ILExpression(ILCode.Br, exitLabel)); + body.Remove(followingBasicBlock); + + return true; + } + ILExpression MakeLeftAssociativeShortCircuit(ILCode code, ILExpression left, ILExpression right) { // Assuming that the inputs are already left associative diff --git a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs index 1aa21a276..3c5c47bf6 100644 --- a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs +++ b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs @@ -267,6 +267,10 @@ namespace ICSharpCode.Decompiler.ILAst return typeSystem.Boolean; case ILCode.LogicAnd: case ILCode.LogicOr: + // if Operand is set the logic and/or expression is a custom operator + // we can deal with it the same as a normal invocation. + if (expr.Operand != null) + goto case ILCode.Call; if (forceInferChildren) { InferTypeForExpression(expr.Arguments[0], typeSystem.Boolean); InferTypeForExpression(expr.Arguments[1], typeSystem.Boolean); diff --git a/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs b/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs new file mode 100644 index 000000000..353e6aea0 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs @@ -0,0 +1,43 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +public static class CustomShortCircuitOperators +{ + private class B + { + public static bool operator true(CustomShortCircuitOperators.B x) + { + return true; + } + + public static bool operator false(CustomShortCircuitOperators.B x) + { + return false; + } + } + + private class C : CustomShortCircuitOperators.B + { + public static CustomShortCircuitOperators.C operator &(CustomShortCircuitOperators.C x, CustomShortCircuitOperators.C y) + { + return null; + } + + public static CustomShortCircuitOperators.C operator |(CustomShortCircuitOperators.C x, CustomShortCircuitOperators.C y) + { + return null; + } + + private static void Main() + { + CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C(); + CustomShortCircuitOperators.C c2 = new CustomShortCircuitOperators.C(); + CustomShortCircuitOperators.C c3 = c && c2; + CustomShortCircuitOperators.C c4 = c || c2; + Console.WriteLine(c3.ToString()); + Console.WriteLine(c4.ToString()); + } + } +} \ No newline at end of file diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index 6023f2aff..33227a313 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -57,6 +57,7 @@ + diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs index 87bb31dd4..a3100391c 100644 --- a/ICSharpCode.Decompiler/Tests/TestRunner.cs +++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs @@ -49,6 +49,12 @@ namespace ICSharpCode.Decompiler.Tests TestFile(@"..\..\Tests\Generics.cs"); } + [Test] + public void CustomShortCircuitOperators() + { + TestFile(@"..\..\Tests\CustomShortCircuitOperators.cs"); + } + [Test] public void IncrementDecrement() { From f86fa5d1dd448bd790cc5a8d5125207de93be1f6 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 22 May 2011 15:28:35 +0200 Subject: [PATCH 58/65] implement support for op_True and extend unit test --- .../ReplaceMethodCallsWithOperators.cs | 7 ++-- .../Tests/CustomShortCircuitOperators.cs | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs b/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs index 7a9eaa365..ba641e77d 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms var arguments = invocationExpression.Arguments.ToArray(); // Reduce "String.Concat(a, b)" to "a + b" - if (methodRef != null && methodRef.Name == "Concat" && methodRef.DeclaringType.FullName == "System.String" && arguments.Length >= 2) + if (methodRef.Name == "Concat" && methodRef.DeclaringType.FullName == "System.String" && arguments.Length >= 2) { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression Expression expr = arguments[0]; @@ -97,7 +97,10 @@ namespace ICSharpCode.Decompiler.Ast.Transforms return null; } if (methodRef.Name == "op_Implicit" && arguments.Length == 1) { - arguments[0].Remove(); // detach argument + invocationExpression.ReplaceWith(arguments[0]); + return null; + } + if (methodRef.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == AstNode.Roles.Condition) { invocationExpression.ReplaceWith(arguments[0]); return null; } diff --git a/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs b/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs index 353e6aea0..30a94a6e6 100644 --- a/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs +++ b/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs @@ -29,6 +29,11 @@ public static class CustomShortCircuitOperators { return null; } + + public static bool operator !(CustomShortCircuitOperators.C x) + { + return false; + } private static void Main() { @@ -39,5 +44,32 @@ public static class CustomShortCircuitOperators Console.WriteLine(c3.ToString()); Console.WriteLine(c4.ToString()); } + + private static void Test2() + { + CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C(); + if (c && c) + { + Console.WriteLine(c.ToString()); + } + + if (!(c && c)) + { + Console.WriteLine(c.ToString()); + } + } + + private static void Test3() + { + CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C(); + if (c) + { + Console.WriteLine(c.ToString()); + } + if (!c) + { + Console.WriteLine(c.ToString()); + } + } } } \ No newline at end of file From 2b366fbb97d40562c8223d96863f1a0cbfab9c0d Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 22 May 2011 16:33:36 +0200 Subject: [PATCH 59/65] make pattern for custom short circuit operator invocations more restrictive --- .../ILAst/SimpleControlFlow.cs | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs b/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs index d821f9aae..319e18bbb 100644 --- a/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs +++ b/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs @@ -258,6 +258,10 @@ namespace ICSharpCode.Decompiler.ILAst if (!head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out targetVar, out targetVarInitExpr)) return false; + ILVariable leftVar; + if (!targetVarInitExpr.Match(ILCode.Ldloc, out leftVar)) + return false; + // looking for: // brtrue(exitLabel, call(op_False, leftVar) // br(followingBlock) @@ -267,12 +271,19 @@ namespace ICSharpCode.Decompiler.ILAst if(!head.MatchLastAndBr(ILCode.Brtrue, out exitLabel, out callExpr, out followingBlock)) return false; - MethodDefinition opFalse; - ILExpression leftVar; - if (!callExpr.Match(ILCode.Call, out opFalse, out leftVar)) + if (labelGlobalRefCount[followingBlock] > 1) + return false; + + MethodReference opFalse; + ILExpression opFalseArg; + if (!callExpr.Match(ILCode.Call, out opFalse, out opFalseArg)) + return false; + + // ignore operators other than op_False and op_True + if (opFalse.Name != "op_False" && opFalse.Name != "op_True") return false; - if (!leftVar.MatchLdloc(targetVarInitExpr.Operand as ILVariable)) + if (!opFalseArg.MatchLdloc(leftVar)) return false; ILBasicBlock followingBasicBlock = labelToBasicBlock[followingBlock]; @@ -286,22 +297,34 @@ namespace ICSharpCode.Decompiler.ILAst if (!followingBasicBlock.MatchSingleAndBr(ILCode.Stloc, out _targetVar, out opBitwiseCallExpr, out _exitLabel)) return false; - if (_targetVar != targetVar) + if (_targetVar != targetVar || exitLabel != _exitLabel) return false; - MethodDefinition opBitwise; + MethodReference opBitwise; ILExpression leftVarExpression; ILExpression rightExpression; if (!opBitwiseCallExpr.Match(ILCode.Call, out opBitwise, out leftVarExpression, out rightExpression)) return false; - if (!leftVar.MatchLdloc(leftVarExpression.Operand as ILVariable)) + if (!opFalseArg.MatchLdloc(leftVarExpression.Operand as ILVariable)) + return false; + + // ignore operators other than op_BitwiseAnd and op_BitwiseOr + if (opBitwise.Name != "op_BitwiseAnd" && opBitwise.Name != "op_BitwiseOr") return false; // insert: // stloc(targetVar, LogicAnd(C::op_BitwiseAnd, leftVar, rightExpression) // br(exitLabel) - ILExpression shortCircuitExpr = MakeLeftAssociativeShortCircuit(opBitwise.Name == "op_BitwiseAnd" ? ILCode.LogicAnd : ILCode.LogicOr, leftVar, rightExpression); + ILCode op = opBitwise.Name == "op_BitwiseAnd" ? ILCode.LogicAnd : ILCode.LogicOr; + + if (op == ILCode.LogicAnd && opFalse.Name != "op_False") + return false; + + if (op == ILCode.LogicOr && opFalse.Name != "op_True") + return false; + + ILExpression shortCircuitExpr = MakeLeftAssociativeShortCircuit(op, opFalseArg, rightExpression); shortCircuitExpr.Operand = opBitwise; head.Body.RemoveTail(ILCode.Stloc, ILCode.Brtrue, ILCode.Br); From 111a6ca29261499c65c36b83dbb0b3b56c292172 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 22 May 2011 18:53:32 +0200 Subject: [PATCH 60/65] do not use primitive type names in TreeNodes; fixes #183 --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 72 +++++++++++++----------- ILSpy/CSharpLanguage.cs | 14 +++++ ILSpy/Language.cs | 7 +++ ILSpy/TreeNodes/TypeTreeNode.cs | 2 +- 4 files changed, 60 insertions(+), 35 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index c0258db0b..17611ffa7 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -28,7 +28,8 @@ namespace ICSharpCode.Decompiler.Ast { None = 0, IncludeNamespace = 1, - IncludeTypeParameterDefinitions = 2 + IncludeTypeParameterDefinitions = 2, + DoNotUsePrimitiveTypeNames = 4 } public class AstBuilder : ICodeMappings @@ -462,39 +463,42 @@ namespace ICSharpCode.Decompiler.Ast return new PrimitiveType("dynamic"); } else { if (ns == "System") { - switch (name) { - case "SByte": - return new PrimitiveType("sbyte"); - case "Int16": - return new PrimitiveType("short"); - case "Int32": - return new PrimitiveType("int"); - case "Int64": - return new PrimitiveType("long"); - case "Byte": - return new PrimitiveType("byte"); - case "UInt16": - return new PrimitiveType("ushort"); - case "UInt32": - return new PrimitiveType("uint"); - case "UInt64": - return new PrimitiveType("ulong"); - case "String": - return new PrimitiveType("string"); - case "Single": - return new PrimitiveType("float"); - case "Double": - return new PrimitiveType("double"); - case "Decimal": - return new PrimitiveType("decimal"); - case "Char": - return new PrimitiveType("char"); - case "Boolean": - return new PrimitiveType("bool"); - case "Void": - return new PrimitiveType("void"); - case "Object": - return new PrimitiveType("object"); + if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) + != ConvertTypeOptions.DoNotUsePrimitiveTypeNames) { + switch (name) { + case "SByte": + return new PrimitiveType("sbyte"); + case "Int16": + return new PrimitiveType("short"); + case "Int32": + return new PrimitiveType("int"); + case "Int64": + return new PrimitiveType("long"); + case "Byte": + return new PrimitiveType("byte"); + case "UInt16": + return new PrimitiveType("ushort"); + case "UInt32": + return new PrimitiveType("uint"); + case "UInt64": + return new PrimitiveType("ulong"); + case "String": + return new PrimitiveType("string"); + case "Single": + return new PrimitiveType("float"); + case "Double": + return new PrimitiveType("double"); + case "Decimal": + return new PrimitiveType("decimal"); + case "Char": + return new PrimitiveType("char"); + case "Boolean": + return new PrimitiveType("bool"); + case "Void": + return new PrimitiveType("void"); + case "Object": + return new PrimitiveType("object"); + } } } diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs index 928e53a37..2408055fc 100644 --- a/ILSpy/CSharpLanguage.cs +++ b/ILSpy/CSharpLanguage.cs @@ -508,6 +508,12 @@ namespace ICSharpCode.ILSpy ConvertTypeOptions options = ConvertTypeOptions.IncludeTypeParameterDefinitions; if (includeNamespace) options |= ConvertTypeOptions.IncludeNamespace; + + return TypeToString(options, type, typeAttributes); + } + + string TypeToString(ConvertTypeOptions options, TypeReference type, ICustomAttributeProvider typeAttributes = null) + { AstType astType = AstBuilder.ConvertType(type, typeAttributes, options); StringWriter w = new StringWriter(); @@ -556,6 +562,14 @@ namespace ICSharpCode.ILSpy } else return property.Name; } + + public override string FormatTypeName(TypeDefinition type) + { + if (type == null) + throw new ArgumentNullException("type"); + + return TypeToString(ConvertTypeOptions.DoNotUsePrimitiveTypeNames | ConvertTypeOptions.IncludeTypeParameterDefinitions, type); + } public override bool ShowMember(MemberReference member) { diff --git a/ILSpy/Language.cs b/ILSpy/Language.cs index c29818621..d9f566013 100644 --- a/ILSpy/Language.cs +++ b/ILSpy/Language.cs @@ -127,6 +127,13 @@ namespace ICSharpCode.ILSpy throw new ArgumentNullException("property"); return property.Name; } + + public virtual string FormatTypeName(TypeDefinition type) + { + if (type == null) + throw new ArgumentNullException("type"); + return type.Name; + } /// /// Used for WPF keyboard navigation. diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index 85568708a..653def410 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -59,7 +59,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } public override object Text { - get { return HighlightSearchMatch(this.Language.TypeToString(type, includeNamespace: false)); } + get { return HighlightSearchMatch(this.Language.FormatTypeName(type)); } } public bool IsPublicAPI { From 51eb00aac724dda67eaf779a86babcc917395b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Mon, 23 May 2011 00:14:59 +0100 Subject: [PATCH 61/65] Remove unreachable code in ILAstBuilder. Closes #134. Closes #151. Closes #171. --- ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs | 44 ++++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index aed211f56..f6edfad85 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -426,13 +426,12 @@ namespace ICSharpCode.Decompiler.ILAst } } - // Occasionally the compiler generates unreachable code - it can be usually just ignored - var reachableBody = body.Where(b => b.StackBefore != null); - var unreachableBody = body.Where(b => b.StackBefore == null); + // Occasionally the compilers or obfuscators generate unreachable code (which migt be intentonally invalid) + // I belive it is safe to just remove it + body.RemoveAll(b => b.StackBefore == null); // Genertate temporary variables to replace stack - // Unrachable code does not need temporary variables - the values are never pushed on the stack for consuption - foreach(ByteCode byteCode in reachableBody) { + foreach(ByteCode byteCode in body) { int argIdx = 0; int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; for (int i = byteCode.StackBefore.Count - popCount; i < byteCode.StackBefore.Count; i++) { @@ -450,19 +449,18 @@ namespace ICSharpCode.Decompiler.ILAst // Try to use single temporary variable insted of several if possilbe (especially useful for dup) // This has to be done after all temporary variables are assigned so we know about all loads - // Unrachable code will not have any StoreTo - foreach(ByteCode byteCode in reachableBody) { + foreach(ByteCode byteCode in body) { if (byteCode.StoreTo != null && byteCode.StoreTo.Count > 1) { var locVars = byteCode.StoreTo; // For each of the variables, find the location where it is loaded - there should be preciesly one - var loadedBy = locVars.Select(locVar => reachableBody.SelectMany(bc => bc.StackBefore).Single(s => s.LoadFrom == locVar)).ToList(); + var loadedBy = locVars.Select(locVar => body.SelectMany(bc => bc.StackBefore).Single(s => s.LoadFrom == locVar)).ToList(); // We now know that all the variables have a single load, // Let's make sure that they have also a single store - us if (loadedBy.All(slot => slot.PushedBy.Length == 1 && slot.PushedBy[0] == byteCode)) { // Great - we can reduce everything into single variable ILVariable tmpVar = new ILVariable() { Name = string.Format("expr_{0:X2}", byteCode.Offset), IsGenerated = true }; byteCode.StoreTo = new List() { tmpVar }; - foreach(ByteCode bc in reachableBody) { + foreach(ByteCode bc in body) { for (int i = 0; i < bc.StackBefore.Count; i++) { // Is it one of the variable to be merged? if (locVars.Contains(bc.StackBefore[i].LoadFrom)) { @@ -658,12 +656,14 @@ namespace ICSharpCode.Decompiler.ILAst // Find the first and widest scope int tryStart = ehs.Min(eh => eh.TryStart.Offset); int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset); - var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList(); + var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).OrderBy(eh => eh.TryStart.Offset).ToList(); + + // Remember that any part of the body migt have been removed due to unreachability // Cut all instructions up to the try block { - int tryStartIdx; - for (tryStartIdx = 0; body[tryStartIdx].Offset != tryStart; tryStartIdx++); + int tryStartIdx = 0; + while (tryStartIdx < body.Count && body[tryStartIdx].Offset < tryStart) tryStartIdx++; ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx))); } @@ -671,24 +671,22 @@ namespace ICSharpCode.Decompiler.ILAst { HashSet nestedEHs = new HashSet(ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd))); ehs.ExceptWith(nestedEHs); - int tryEndIdx; - for (tryEndIdx = 0; tryEndIdx < body.Count && body[tryEndIdx].Offset != tryEnd; tryEndIdx++); + int tryEndIdx = 0; + while (tryEndIdx < body.Count && body[tryEndIdx].Offset < tryEnd) tryEndIdx++; tryCatchBlock.TryBlock = new ILBlock(ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs)); } // Cut all handlers tryCatchBlock.CatchBlocks = new List(); foreach(ExceptionHandler eh in handlers) { - int startIndex; - for (startIndex = 0; body[startIndex].Offset != eh.HandlerStart.Offset; startIndex++); - int endInclusiveIndex; - if (eh.HandlerEnd == null) endInclusiveIndex = body.Count - 1; - // Note that the end(exclusive) instruction may not necessarly be in our body - else for (endInclusiveIndex = 0; body[endInclusiveIndex].Next.Offset != eh.HandlerEnd.Offset; endInclusiveIndex++); - int count = 1 + endInclusiveIndex - startIndex; - HashSet nestedEHs = new HashSet(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < eh.HandlerEnd.Offset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= eh.HandlerEnd.Offset))); + int handlerEndOffset = eh.HandlerEnd == null ? methodDef.Body.CodeSize : eh.HandlerEnd.Offset; + int startIdx = 0; + while (startIdx < body.Count && body[startIdx].Offset < eh.HandlerStart.Offset) startIdx++; + int endIdx = 0; + while (endIdx < body.Count && body[endIdx].Offset < handlerEndOffset) endIdx++; + HashSet nestedEHs = new HashSet(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < handlerEndOffset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= handlerEndOffset))); ehs.ExceptWith(nestedEHs); - List handlerAst = ConvertToAst(body.CutRange(startIndex, count), nestedEHs); + List handlerAst = ConvertToAst(body.CutRange(startIdx, endIdx - startIdx), nestedEHs); if (eh.HandlerType == ExceptionHandlerType.Catch) { ILTryCatchBlock.CatchBlock catchBlock = new ILTryCatchBlock.CatchBlock() { ExceptionType = eh.CatchType, From dd02632a4bad9307d01df5bc3bd94fc4d6732f1b Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 23 May 2011 16:57:39 +0200 Subject: [PATCH 62/65] add ILSpy.BamlDecompiler project --- .../ILSpy.BamlDecompiler.csproj | 48 +++++++++++++++++++ ILSpy.BamlDecompiler/MyClass.cs | 16 +++++++ .../Properties/AssemblyInfo.cs | 31 ++++++++++++ ILSpy.sln | 12 ++++- doc/MS-PL.txt | 31 ++++++++++++ 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj create mode 100644 ILSpy.BamlDecompiler/MyClass.cs create mode 100644 ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs create mode 100644 doc/MS-PL.txt diff --git a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj new file mode 100644 index 000000000..c83e4dc5e --- /dev/null +++ b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj @@ -0,0 +1,48 @@ + + + + {A6BAD2BA-76BA-461C-8B6D-418607591247} + Debug + x86 + Library + ILSpy.BamlDecompiler + ILSpy.BamlDecompiler + v4.0 + Client + Properties + + + x86 + + + bin\Debug\ + True + Full + False + True + DEBUG;TRACE + + + bin\Release\ + False + None + True + False + TRACE + + + + + 3.5 + + + + 3.5 + + + + + + + + \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/MyClass.cs b/ILSpy.BamlDecompiler/MyClass.cs new file mode 100644 index 000000000..f89c0f24e --- /dev/null +++ b/ILSpy.BamlDecompiler/MyClass.cs @@ -0,0 +1,16 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; + +namespace ILSpy.BamlDecompiler +{ + /// + /// Description of MyClass. + /// + public class MyClass + { + + } +} \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs b/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..54a525812 --- /dev/null +++ b/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs @@ -0,0 +1,31 @@ +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ILSpy.BamlDecompiler")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ILSpy.BamlDecompiler")] +[assembly: AssemblyCopyright("Copyright 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all the values or you can use the default the Revision and +// Build Numbers by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.*")] diff --git a/ILSpy.sln b/ILSpy.sln index 7af0dee1b..747fdd135 100644 --- a/ILSpy.sln +++ b/ILSpy.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -# SharpDevelop 4.0.1.7146 +# SharpDevelop 4.1.0.7466-alpha Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E72-4000-B5AD-3A7B485A0896}" ProjectSection(SolutionItems) = postProject doc\Command Line.txt = doc\Command Line.txt @@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestPlugin", "TestPlugin\Te EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "Mono.Cecil\symbols\pdb\Mono.Cecil.Pdb.csproj", "{63E6915C-7EA4-4D76-AB28-0D7191EEA626}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.BamlDecompiler", "ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj", "{A6BAD2BA-76BA-461C-8B6D-418607591247}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -105,6 +107,14 @@ Global {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x86.Build.0 = net_4_0_Debug|Any CPU {63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Release|x86.ActiveCfg = net_4_0_Release|Any CPU + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.Build.0 = Debug|x86 + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.ActiveCfg = Debug|x86 + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|x86.Build.0 = Debug|x86 + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|x86.ActiveCfg = Debug|x86 + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.Build.0 = Release|x86 + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.ActiveCfg = Release|x86 + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|x86.Build.0 = Release|x86 + {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|x86.ActiveCfg = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/doc/MS-PL.txt b/doc/MS-PL.txt new file mode 100644 index 000000000..622a544b7 --- /dev/null +++ b/doc/MS-PL.txt @@ -0,0 +1,31 @@ +Microsoft Public License (Ms-PL) + +This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. + +1. Definitions + +The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. + +A "contribution" is the original software, or any additions or changes to the software. + +A "contributor" is any person that distributes its contribution under this license. + +"Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights + +(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. + +(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations + +(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. + +(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. + +(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. + +(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. + +(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. \ No newline at end of file From 71c8fb1446e9f0dd96449fa4265d2b38ae609c3e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 23 May 2011 17:20:55 +0200 Subject: [PATCH 63/65] add source of Ricciolo.StylesExplorer.MarkupReflection by Cristian Civera --- .../ILSpy.BamlDecompiler.csproj | 25 + .../AppDomainTypeResolver.cs | 172 ++ .../BamlAssembly.cs | 112 + .../BamlBinaryReader.cs | 47 + .../BamlFile.cs | 80 + .../BamlRecordType.cs | 72 + .../DotNetType.cs | 58 + .../IDependencyPropertyDescriptor.cs | 14 + .../IType.cs | 19 + .../ITypeResolver.cs | 15 + .../KnownInfo.cs | 1319 +++++++++++ .../PropertyDeclaration.cs | 58 + .../ResourceName.cs | 32 + .../TypeDeclaration.cs | 137 ++ .../WpfDependencyPropertyDescriptor.cs | 35 + .../XmlBamlElement.cs | 193 ++ .../XmlBamlNode.cs | 21 + .../XmlBamlProperty.cs | 86 + .../XmlBamlPropertyElement.cs | 48 + .../XmlBamlReader.cs | 1939 +++++++++++++++++ .../XmlBamlText.cs | 33 + .../XmlNamespace.cs | 47 + .../XmlPIMapping.cs | 63 + 23 files changed, 4625 insertions(+) create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlAssembly.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlBinaryReader.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlFile.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlRecordType.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IDependencyPropertyDescriptor.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/PropertyDeclaration.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ResourceName.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/WpfDependencyPropertyDescriptor.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlNode.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlProperty.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlPropertyElement.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlText.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlNamespace.cs create mode 100644 ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlPIMapping.cs diff --git a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj index c83e4dc5e..7424fec6f 100644 --- a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj +++ b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj @@ -43,6 +43,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs new file mode 100644 index 000000000..9cc329459 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs @@ -0,0 +1,172 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reflection; +using System.Text; +using System.IO; +using System.Linq; +using Microsoft.Win32; +using System.Threading; +using System.Security.Permissions; +using System.Security; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + public delegate void AssemblyResolveEventHandler(object s, AssemblyResolveEventArgs e); + + public class AppDomainTypeResolver : MarshalByRefObject, ITypeResolver + { + private readonly AppDomain _domain; + private string baseDir; + + public event AssemblyResolveEventHandler AssemblyResolve; + + public static AppDomainTypeResolver GetIntoNewAppDomain(string baseDir) + { + AppDomainSetup info = new AppDomainSetup(); + info.ApplicationBase = Environment.CurrentDirectory; + AppDomain domain = AppDomain.CreateDomain("AppDomainTypeResolver", null, info, new PermissionSet(PermissionState.Unrestricted)); + AppDomainTypeResolver resolver = (AppDomainTypeResolver)domain.CreateInstanceAndUnwrap(typeof(AppDomainTypeResolver).Assembly.FullName, + typeof(AppDomainTypeResolver).FullName, false, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, new object[] { domain, baseDir }, null, null, null); + + return resolver; + } + + Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args) + { + // Cerco di risolvere automaticamente + AssemblyName name = new AssemblyName(args.Name); + string fileName = Path.Combine(this.baseDir, name.Name + ".exe"); + if (!File.Exists(fileName)) + fileName = Path.Combine(this.baseDir, name.Name + ".dll"); + + // Carico il percorso autocalcolato + if (File.Exists(fileName)) + return Assembly.LoadFile(fileName); + + if (AssemblyResolve != null) + { + AssemblyResolveEventArgs e = new AssemblyResolveEventArgs(args.Name, this.baseDir); + AssemblyResolve(this, e); + if (!String.IsNullOrEmpty(e.Location) && File.Exists(e.Location)) + return Assembly.LoadFile(e.Location); + } + + return null; + } + + public static void DestroyResolver(AppDomainTypeResolver resolver) + { + if (resolver == null) throw new ArgumentNullException("resolver"); + + ThreadPool.QueueUserWorkItem(delegate + { + AppDomain.Unload(resolver.Domain); + }); + } + + protected AppDomainTypeResolver(AppDomain domain, string baseDir) + { + _domain = domain; + this.baseDir = baseDir; + + domain.AssemblyResolve += new ResolveEventHandler(domain_AssemblyResolve); + } + + public BamlAssembly LoadAssembly(AssemblyName asm) + { + //return new BamlAssembly(Assembly.Load(asm)); + return new BamlAssembly(_domain.Load(asm)); + } + + public BamlAssembly LoadAssembly(string location) + { + Assembly asm = Assembly.LoadFile(location); + return new BamlAssembly(asm); + //return _domain.Load(System.IO.File.ReadAllBytes(location)); + //return Assembly.LoadFrom(location); + } + + public BamlAssembly[] GetReferencedAssemblies(BamlAssembly asm) + { + AssemblyName[] list = asm.Assembly.GetReferencedAssemblies(); + + return (from an in list + select this.LoadAssembly(an)).ToArray(); + } + + public AppDomain Domain + { + get { return _domain; } + } + + #region ITypeResolver Members + + public IType GetTypeByAssemblyQualifiedName(string name) + { + return new DotNetType(name); + } + + public IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IType ownerType, IType targetType) + { + if (name == null) throw new ArgumentNullException("name"); + if (ownerType == null) throw new ArgumentNullException("ownerType"); + if (targetType == null) throw new ArgumentNullException("targetType"); + + Type dOwnerType = ((DotNetType)ownerType).Type; + Type dTargetType = ((DotNetType)targetType).Type; + + try + { + DependencyPropertyDescriptor propertyDescriptor = DependencyPropertyDescriptor.FromName(name, dOwnerType, dTargetType); + if (propertyDescriptor != null) + return new WpfDependencyPropertyDescriptor(propertyDescriptor); + return null; + } + catch (Exception) + { + return null; + } + } + + #endregion + + public override object InitializeLifetimeService() + { + return null; + } + } + + public class AssemblyResolveEventArgs : MarshalByRefObject + { + + private string _location; + private string _name; + private string _baseDir; + + public AssemblyResolveEventArgs(string name, string baseDir) + { + _name = name; + _baseDir = baseDir; + } + + public string Location + { + get { return _location; } + set { _location = value; } + } + + public string Name + { + get { return _name; } + } + + public string BaseDir + { + get { return _baseDir; } + } + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlAssembly.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlAssembly.cs new file mode 100644 index 000000000..d9d71860f --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlAssembly.cs @@ -0,0 +1,112 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Reflection; +using System.Resources; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + public class BamlAssembly : MarshalByRefObject + { + private readonly string _filePath; + private Assembly _assembly; + private BamlFileList _bamlFile; + + public BamlAssembly(Assembly assembly) + { + _assembly = assembly; + _filePath = assembly.CodeBase; + + ReadBaml(); + } + + public BamlAssembly(string filePath) + { + this._filePath = Path.GetFullPath(filePath); + this._assembly = Assembly.LoadFile(this.FilePath); + if (String.Compare(this.Assembly.CodeBase, this.FilePath, true) != 0) + throw new ArgumentException("Cannot load filePath because Assembly is already loaded", "filePath"); + + ReadBaml(); + } + + private void ReadBaml() + { + // Get available names + string[] resources = this.Assembly.GetManifestResourceNames(); + foreach (string res in resources) + { + // Solo le risorse + if (String.Compare(Path.GetExtension(res), ".resources", true) != 0) continue; + + // Get stream + using (Stream stream = this.Assembly.GetManifestResourceStream(res)) + { + try + { + ResourceReader reader = new ResourceReader(stream); + foreach (DictionaryEntry entry in reader) + { + if (String.Compare(Path.GetExtension(entry.Key.ToString()), ".baml", true) == 0 && entry.Value is Stream) + { + BamlFile bm = new BamlFile(GetAssemblyResourceUri(entry.Key.ToString()), (Stream)entry.Value); + this.BamlFiles.Add(bm); + } + } + } + catch (ArgumentException) + {} + } + } + } + + private Uri GetAssemblyResourceUri(string resourceName) + { + AssemblyName asm = this.Assembly.GetName(); + byte[] data = asm.GetPublicKeyToken(); + StringBuilder token = new StringBuilder(data.Length * 2); + for (int x = 0; x < data.Length; x++) + { + token.Append(data[x].ToString("x", System.Globalization.CultureInfo.InvariantCulture)); + } + + return new Uri(String.Format(@"{0};V{1};{2};component\{3}", asm.Name, asm.Version, token, Path.ChangeExtension(resourceName, ".xaml")), UriKind.RelativeOrAbsolute); + } + + public string FilePath + { + get { return _filePath; } + } + + public Assembly Assembly + { + get { return _assembly; } + } + + public BamlFileList BamlFiles + { + get + { + if (_bamlFile == null) + _bamlFile = new BamlFileList(); + return _bamlFile; + } + } + + public override object InitializeLifetimeService() + { + return null; + } + } + + [Serializable()] + public class BamlFileList : Collection + {} + +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlBinaryReader.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlBinaryReader.cs new file mode 100644 index 000000000..6df206561 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlBinaryReader.cs @@ -0,0 +1,47 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.IO; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + internal class BamlBinaryReader : BinaryReader + { + // Methods + public BamlBinaryReader(Stream stream) + : base(stream) + { + } + + public virtual double ReadCompressedDouble() + { + switch (this.ReadByte()) + { + case 1: + return 0; + + case 2: + return 1; + + case 3: + return -1; + + case 4: + { + double num = this.ReadInt32(); + return (num * 1E-06); + } + case 5: + return this.ReadDouble(); + } + throw new NotSupportedException(); + } + + public int ReadCompressedInt32() + { + return base.Read7BitEncodedInt(); + } + } +} \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlFile.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlFile.cs new file mode 100644 index 000000000..d4af6bb81 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlFile.cs @@ -0,0 +1,80 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Resources; +using System.Text; +using System.Windows; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + /// + /// Rappresenta un singole file Baml all'interno di un assembly + /// + public class BamlFile : Component + { + private Uri _uri; + private readonly Stream _stream; + + public BamlFile(Uri uri, Stream stream) + { + if (uri == null) + new ArgumentNullException("uri"); + if (stream == null) + throw new ArgumentNullException("stream"); + + _uri = uri; + _stream = stream; + } + + /// + /// Carica il Baml attraverso il motore di WPF con Application.LoadComponent + /// + /// + public object LoadContent() + { + try + { + return Application.LoadComponent(this.Uri); + } + catch (Exception e) + { + throw new InvalidOperationException("Invalid baml file.", e); + } + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + this.Stream.Dispose(); + } + + public override object InitializeLifetimeService() + { + return null; + } + + /// + /// Restituisce lo stream originale contenente il Baml + /// + public Stream Stream + { + get { return _stream; } + } + + /// + /// Restituisce l'indirizzo secondo lo schema pack:// + /// + public Uri Uri + { + get { return _uri; } + } + + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlRecordType.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlRecordType.cs new file mode 100644 index 000000000..50ca01ddb --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlRecordType.cs @@ -0,0 +1,72 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + internal enum BamlRecordType : byte + { + AssemblyInfo = 0x1c, + AttributeInfo = 0x1f, + ClrEvent = 0x13, + Comment = 0x17, + ConnectionId = 0x2d, + ConstructorParametersEnd = 0x2b, + ConstructorParametersStart = 0x2a, + ConstructorParameterType = 0x2c, + ContentProperty = 0x2e, + DefAttribute = 0x19, + DefAttributeKeyString = 0x26, + DefAttributeKeyType = 0x27, + DeferableContentStart = 0x25, + DefTag = 0x18, + DocumentEnd = 2, + DocumentStart = 1, + ElementEnd = 4, + ElementStart = 3, + EndAttributes = 0x1a, + KeyElementEnd = 0x29, + KeyElementStart = 40, + LastRecordType = 0x39, + LineNumberAndPosition = 0x35, + LinePosition = 0x36, + LiteralContent = 15, + NamedElementStart = 0x2f, + OptimizedStaticResource = 0x37, + PIMapping = 0x1b, + PresentationOptionsAttribute = 0x34, + ProcessingInstruction = 0x16, + Property = 5, + PropertyArrayEnd = 10, + PropertyArrayStart = 9, + PropertyComplexEnd = 8, + PropertyComplexStart = 7, + PropertyCustom = 6, + PropertyDictionaryEnd = 14, + PropertyDictionaryStart = 13, + PropertyListEnd = 12, + PropertyListStart = 11, + PropertyStringReference = 0x21, + PropertyTypeReference = 0x22, + PropertyWithConverter = 0x24, + PropertyWithExtension = 0x23, + PropertyWithStaticResourceId = 0x38, + RoutedEvent = 0x12, + StaticResourceEnd = 0x31, + StaticResourceId = 50, + StaticResourceStart = 0x30, + StringInfo = 0x20, + Text = 0x10, + TextWithConverter = 0x11, + TextWithId = 0x33, + TypeInfo = 0x1d, + TypeSerializerInfo = 30, + Unknown = 0, + XmlAttribute = 0x15, + XmlnsProperty = 20 + } + +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs new file mode 100644 index 000000000..1dbf1b21a --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs @@ -0,0 +1,58 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + public class DotNetType : MarshalByRefObject, IType + { + private readonly string _assemblyQualifiedName; + private Type _type; + + public DotNetType(string assemblyQualifiedName) + { + if (assemblyQualifiedName == null) throw new ArgumentNullException("assemblyQualifiedName"); + + _assemblyQualifiedName = assemblyQualifiedName; + _type = Type.GetType(assemblyQualifiedName, false, true); + } + + #region IType Members + + public string AssemblyQualifiedName + { + get { return _assemblyQualifiedName; } + } + + public bool IsSubclassOf(IType type) + { + if (type == null) throw new ArgumentNullException("type"); + if (!(type is DotNetType)) throw new ArgumentException("type"); + if (_type == null) return false; + return this._type.IsSubclassOf(((DotNetType)type).Type); + } + + public bool Equals(IType type) + { + if (type == null) throw new ArgumentNullException("type"); + if (!(type is DotNetType)) throw new ArgumentException("type"); + if (_type == null) return false; + return this._type.Equals(((DotNetType)type).Type); + } + + #endregion + + public Type Type + { + get { return _type; } + } + + public override object InitializeLifetimeService() + { + return null; + } + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IDependencyPropertyDescriptor.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IDependencyPropertyDescriptor.cs new file mode 100644 index 000000000..0005efa52 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IDependencyPropertyDescriptor.cs @@ -0,0 +1,14 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + public interface IDependencyPropertyDescriptor + { + bool IsAttached { get; } + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs new file mode 100644 index 000000000..7ec8c79e4 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs @@ -0,0 +1,19 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + /// + /// Interface rappresenting a DotNet type + /// + public interface IType + { + string AssemblyQualifiedName { get; } + bool IsSubclassOf(IType type); + bool Equals(IType type); + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs new file mode 100644 index 000000000..71e802a61 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs @@ -0,0 +1,15 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + public interface ITypeResolver + { + IType GetTypeByAssemblyQualifiedName(string name); + IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IType ownerType, IType targetType); + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs new file mode 100644 index 000000000..e58762f41 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs @@ -0,0 +1,1319 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + public class KnownInfo + { + internal TypeDeclaration[] KnownTypeTable = null; + internal PropertyDeclaration[] KnownPropertyTable = null; + internal static String[] KnownAssemblyTable = null; + internal Hashtable KnownResourceTable = new Hashtable(); + + #region Initialize + + static KnownInfo() + { + KnownAssemblyTable = new string[5]; + KnownAssemblyTable[0] = + "PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + KnownAssemblyTable[1] = + "PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + KnownAssemblyTable[2] = "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + KnownAssemblyTable[3] = "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + KnownAssemblyTable[4] = "WindowBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + } + + public KnownInfo() : this(null) + { + } + + public KnownInfo(ITypeResolver resolver) + { + KnownAssemblyTable = new string[5]; + KnownAssemblyTable[0] = "PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + KnownAssemblyTable[1] = "PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + KnownAssemblyTable[2] = "mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + KnownAssemblyTable[3] = "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + KnownAssemblyTable[4] = "WindowBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + + KnownTypeTable = new TypeDeclaration[760]; + KnownTypeTable[0] = new TypeDeclaration(resolver, string.Empty, string.Empty, 0); + KnownTypeTable[1] = new TypeDeclaration(resolver, "AccessText", "System.Windows.Controls", 0); + KnownTypeTable[2] = new TypeDeclaration(resolver, "AdornedElementPlaceholder", "System.Windows.Controls", 0); + KnownTypeTable[3] = new TypeDeclaration(resolver, "Adorner", "System.Windows.Documents", 0); + KnownTypeTable[4] = new TypeDeclaration(resolver, "AdornerDecorator", "System.Windows.Documents", 0); + KnownTypeTable[5] = new TypeDeclaration(resolver, "AdornerLayer", "System.Windows.Documents", 0); + KnownTypeTable[6] = new TypeDeclaration(resolver, "AffineTransform3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[7] = new TypeDeclaration(resolver, "AmbientLight", "System.Windows.Media.Media3D", 1); + KnownTypeTable[8] = new TypeDeclaration(resolver, "AnchoredBlock", "System.Windows.Documents", 0); + KnownTypeTable[9] = new TypeDeclaration(resolver, "Animatable", "System.Windows.Media.Animaton", 1); + KnownTypeTable[10] = new TypeDeclaration(resolver, "AnimationClock", "System.Windows.Media.Animation", 1); + KnownTypeTable[11] = new TypeDeclaration(resolver, "AnimationTimeline", "System.Windows.Media.Animation", 1); + KnownTypeTable[12] = new TypeDeclaration(resolver, "Application", "System.Net.Mime", 3); + KnownTypeTable[13] = new TypeDeclaration(resolver, "ArcSegment", "System.Windows.Media", 1); + KnownTypeTable[14] = new TypeDeclaration(resolver, "ArrayExtension", "System.Windows.Markup", 0); + KnownTypeTable[15] = new TypeDeclaration(resolver, "AxisAngleRotation3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x10] = new TypeDeclaration(resolver, "BaseIListConverter", "System.Windows.Media.Converters", 1); + KnownTypeTable[0x11] = new TypeDeclaration(resolver, "BeginStoryboard", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x12] = new TypeDeclaration(resolver, "BevelBitmapEffect", "System.Windows.Media.Effects", 1); + KnownTypeTable[0x13] = new TypeDeclaration(resolver, "BezierSegment", "System.Windows.Media", 1); + KnownTypeTable[20] = new TypeDeclaration(resolver, "Binding", "System.Windows.Data", 0, true); + KnownTypeTable[0x15] = new TypeDeclaration(resolver, "BindingBase", "System.Windows.Data", 0); + KnownTypeTable[0x16] = new TypeDeclaration(resolver, "BindingExpression", "System.Windows.Data", 0); + KnownTypeTable[0x17] = new TypeDeclaration(resolver, "BindingExpressionBase", "System.Windows.Data", 0); + KnownTypeTable[0x18] = new TypeDeclaration(resolver, "BindingListCollectionView", "System.Windows.Data", 0); + KnownTypeTable[0x19] = new TypeDeclaration(resolver, "BitmapDecoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x1a] = new TypeDeclaration(resolver, "BitmapEffect", "System.Windows.Media.Effects", 1); + KnownTypeTable[0x1b] = new TypeDeclaration(resolver, "BitmapEffectCollection", "System.Windows.Media.Effects", 1); + KnownTypeTable[0x1c] = new TypeDeclaration(resolver, "BitmapEffectGroup", "System.Windows.Media.Effects", 1); + KnownTypeTable[0x1d] = new TypeDeclaration(resolver, "BitmapEffectInput", "System.Windows.Media.Effects", 1); + KnownTypeTable[30] = new TypeDeclaration(resolver, "BitmapEncoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x1f] = new TypeDeclaration(resolver, "BitmapFrame", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x20] = new TypeDeclaration(resolver, "BitmapImage", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x21] = new TypeDeclaration(resolver, "BitmapMetadata", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x22] = new TypeDeclaration(resolver, "BitmapPalette", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x23] = new TypeDeclaration(resolver, "BitmapSource", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x24] = new TypeDeclaration(resolver, "Block", "System.Windows.Documents", 0); + KnownTypeTable[0x25] = new TypeDeclaration(resolver, "BlockUIContainer", "System.Windows.Documents", 0); + KnownTypeTable[0x26] = new TypeDeclaration(resolver, "BlurBitmapEffect", "System.Windows.Media.Effects", 1); + KnownTypeTable[0x27] = new TypeDeclaration(resolver, "BmpBitmapDecoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[40] = new TypeDeclaration(resolver, "BmpBitmapEncoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x29] = new TypeDeclaration(resolver, "Bold", "System.Windows.Documents", 0); + KnownTypeTable[0x2b] = new TypeDeclaration(resolver, "Boolean", "System", 2); + KnownTypeTable[0x2c] = new TypeDeclaration(resolver, "BooleanAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2d] = new TypeDeclaration(resolver, "BooleanAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2e] = new TypeDeclaration(resolver, "BooleanConverter", "System.ComponentModel", 3); + KnownTypeTable[0x2f] = new TypeDeclaration(resolver, "BooleanKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x30] = new TypeDeclaration(resolver, "BooleanKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x31] = new TypeDeclaration(resolver, "BooleanToVisibilityConverter", "System.Windows.Controls", 0); + KnownTypeTable[0x2a] = new TypeDeclaration(resolver, "BoolIListConverter", "System.Windows.Media.Converters", 1); + KnownTypeTable[50] = new TypeDeclaration(resolver, "Border", "System.Windows.Controls", 0); + KnownTypeTable[0x33] = new TypeDeclaration(resolver, "BorderGapMaskConverter", "System.Windows.Controls", 0); + KnownTypeTable[0x34] = new TypeDeclaration(resolver, "Brush", "System.Windows.Media", 1); + KnownTypeTable[0x35] = new TypeDeclaration(resolver, "BrushConverter", "System.Windows.Media", 1); + KnownTypeTable[0x36] = new TypeDeclaration(resolver, "BulletDecorator", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x37] = new TypeDeclaration(resolver, "Button", "System.Windows.Controls", 0); + KnownTypeTable[0x38] = new TypeDeclaration(resolver, "ButtonBase", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x39] = new TypeDeclaration(resolver, "Byte", "System", 2); + KnownTypeTable[0x3a] = new TypeDeclaration(resolver, "ByteAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x3b] = new TypeDeclaration(resolver, "ByteAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[60] = new TypeDeclaration(resolver, "ByteAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x3d] = new TypeDeclaration(resolver, "ByteConverter", "System.ComponentModel", 3); + KnownTypeTable[0x3e] = new TypeDeclaration(resolver, "ByteKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x3f] = new TypeDeclaration(resolver, "ByteKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x40] = new TypeDeclaration(resolver, "CachedBitmap", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x41] = new TypeDeclaration(resolver, "Camera", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x42] = new TypeDeclaration(resolver, "Canvas", "System.Windows.Controls", 0); + KnownTypeTable[0x43] = new TypeDeclaration(resolver, "Char", "System", 2); + KnownTypeTable[0x44] = new TypeDeclaration(resolver, "CharAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x45] = new TypeDeclaration(resolver, "CharAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[70] = new TypeDeclaration(resolver, "CharConverter", "System.ComponentModel", 3); + KnownTypeTable[0x47] = new TypeDeclaration(resolver, "CharIListConverter", "System.Windows.Media.Converters", 1); + KnownTypeTable[0x48] = new TypeDeclaration(resolver, "CharKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x49] = new TypeDeclaration(resolver, "CharKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x4a] = new TypeDeclaration(resolver, "CheckBox", "System.Windows.Controls", 0); + KnownTypeTable[0x4b] = new TypeDeclaration(resolver, "Clock", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x4c] = new TypeDeclaration(resolver, "ClockController", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x4d] = new TypeDeclaration(resolver, "ClockGroup", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x4e] = new TypeDeclaration(resolver, "CollectionContainer", "System.Windows.Data", 0); + KnownTypeTable[0x4f] = new TypeDeclaration(resolver, "CollectionView", "System.Windows.Data", 0); + KnownTypeTable[80] = new TypeDeclaration(resolver, "CollectionViewSource", "System.Windows.Data", 0); + KnownTypeTable[0x51] = new TypeDeclaration(resolver, "Color", "Microsoft.Win32", 2); + KnownTypeTable[0x52] = new TypeDeclaration(resolver, "ColorAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x53] = new TypeDeclaration(resolver, "ColorAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x54] = new TypeDeclaration(resolver, "ColorAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x55] = new TypeDeclaration(resolver, "ColorConvertedBitmap", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x56] = new TypeDeclaration(resolver, "ColorConvertedBitmapExtension", "System.Windows", 0); + KnownTypeTable[0x57] = new TypeDeclaration(resolver, "ColorConverter", "System.Windows.Media", 1); + KnownTypeTable[0x58] = new TypeDeclaration(resolver, "ColorKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x59] = new TypeDeclaration(resolver, "ColorKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[90] = new TypeDeclaration(resolver, "ColumnDefinition", "System.Windows.Controls", 0); + KnownTypeTable[0x5b] = new TypeDeclaration(resolver, "CombinedGeometry", "System.Windows.Media", 1); + KnownTypeTable[0x5c] = new TypeDeclaration(resolver, "ComboBox", "System.Windows.Controls", 0); + KnownTypeTable[0x5d] = new TypeDeclaration(resolver, "ComboBoxItem", "System.Windows.Controls", 0); + KnownTypeTable[0x5e] = new TypeDeclaration(resolver, "CommandConverter", "System.Windows.Input", 0); + KnownTypeTable[0x5f] = new TypeDeclaration(resolver, "ComponentResourceKey", "System.Windows", 0, true); + KnownTypeTable[0x60] = new TypeDeclaration(resolver, "ComponentResourceKeyConverter", "System.Windows.Markup", 0); + KnownTypeTable[0x61] = new TypeDeclaration(resolver, "CompositionTarget", "System.Windows.Media", 1); + KnownTypeTable[0x62] = new TypeDeclaration(resolver, "Condition", "System.Windows", 0); + KnownTypeTable[0x63] = new TypeDeclaration(resolver, "ContainerVisual", "System.Windows.Media", 1); + KnownTypeTable[100] = new TypeDeclaration(resolver, "ContentControl", "System.Windows.Controls", 0); + KnownTypeTable[0x65] = new TypeDeclaration(resolver, "ContentElement", "System.Windows", 1); + KnownTypeTable[0x66] = new TypeDeclaration(resolver, "ContentPresenter", "System.Windows.Controls", 0); + KnownTypeTable[0x67] = new TypeDeclaration(resolver, "ContentPropertyAttribute", "System.Windows.Markup", 4); + KnownTypeTable[0x68] = new TypeDeclaration(resolver, "ContentWrapperAttribute", "System.Windows.Markup", 4); + KnownTypeTable[0x69] = new TypeDeclaration(resolver, "ContextMenu", "System.Windows.Controls", 0); + KnownTypeTable[0x6a] = new TypeDeclaration(resolver, "ContextMenuService", "System.Windows.Controls", 0); + KnownTypeTable[0x6b] = new TypeDeclaration(resolver, "Control", "System.Windows.Controls", 0); + KnownTypeTable[0x6d] = new TypeDeclaration(resolver, "ControllableStoryboardAction", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x6c] = new TypeDeclaration(resolver, "ControlTemplate", "System.Windows.Controls", 0); + KnownTypeTable[110] = new TypeDeclaration(resolver, "CornerRadius", "System.Windows", 0); + KnownTypeTable[0x6f] = new TypeDeclaration(resolver, "CornerRadiusConverter", "System.Windows", 0); + KnownTypeTable[0x70] = new TypeDeclaration(resolver, "CroppedBitmap", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x71] = new TypeDeclaration(resolver, "CultureInfo", "System.Globalization", 2); + KnownTypeTable[0x72] = new TypeDeclaration(resolver, "CultureInfoConverter", "System.ComponentModel", 3); + KnownTypeTable[0x73] = new TypeDeclaration(resolver, "CultureInfoIetfLanguageTagConverter", "System.Windows", 1); + KnownTypeTable[0x74] = new TypeDeclaration(resolver, "Cursor", "System.Windows.Input", 1); + KnownTypeTable[0x75] = new TypeDeclaration(resolver, "CursorConverter", "System.Windows.Input", 1); + KnownTypeTable[0x76] = new TypeDeclaration(resolver, "DashStyle", "System.Windows.Media", 1); + KnownTypeTable[0x77] = new TypeDeclaration(resolver, "DataChangedEventManager", "System.Windows.Data", 0); + KnownTypeTable[120] = new TypeDeclaration(resolver, "DataTemplate", "System.Windows", 0); + KnownTypeTable[0x79] = new TypeDeclaration(resolver, "DataTemplateKey", "System.Windows", 0, true); + KnownTypeTable[0x7a] = new TypeDeclaration(resolver, "DataTrigger", "System.Windows", 0); + KnownTypeTable[0x7b] = new TypeDeclaration(resolver, "DateTime", "System", 2); + KnownTypeTable[0x7c] = new TypeDeclaration(resolver, "DateTimeConverter", "System.ComponentModel", 3); + KnownTypeTable[0x7d] = new TypeDeclaration(resolver, "DateTimeConverter2", "System.Windows.Markup", 4); + KnownTypeTable[0x7e] = new TypeDeclaration(resolver, "Decimal", "System", 2); + KnownTypeTable[0x7f] = new TypeDeclaration(resolver, "DecimalAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x80] = new TypeDeclaration(resolver, "DecimalAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x81] = new TypeDeclaration(resolver, "DecimalAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[130] = new TypeDeclaration(resolver, "DecimalConverter", "System.ComponentModel", 3); + KnownTypeTable[0x83] = new TypeDeclaration(resolver, "DecimalKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x84] = new TypeDeclaration(resolver, "DecimalKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x85] = new TypeDeclaration(resolver, "Decorator", "System.Windows.Controls", 0); + KnownTypeTable[0x86] = new TypeDeclaration(resolver, "DefinitionBase", "System.Windows.Controls", 0); + KnownTypeTable[0x87] = new TypeDeclaration(resolver, "DependencyObject", "System.Windows", 4); + KnownTypeTable[0x88] = new TypeDeclaration(resolver, "DependencyProperty", "System.Windows", 4); + KnownTypeTable[0x89] = new TypeDeclaration(resolver, "DependencyPropertyConverter", "System.Windows.Markup", 0); + KnownTypeTable[0x8a] = new TypeDeclaration(resolver, "DialogResultConverter", "System.Windows", 0); + KnownTypeTable[0x8b] = new TypeDeclaration(resolver, "DiffuseMaterial", "System.Windows.Media.Media3D", 1); + KnownTypeTable[140] = new TypeDeclaration(resolver, "DirectionalLight", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x8d] = new TypeDeclaration(resolver, "DiscreteBooleanKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x8e] = new TypeDeclaration(resolver, "DiscreteByteKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x8f] = new TypeDeclaration(resolver, "DiscreteCharKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x90] = new TypeDeclaration(resolver, "DiscreteColorKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x91] = new TypeDeclaration(resolver, "DiscreteDecimalKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x92] = new TypeDeclaration(resolver, "DiscreteDoubleKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x93] = new TypeDeclaration(resolver, "DiscreteInt16KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x94] = new TypeDeclaration(resolver, "DiscreteInt32KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x95] = new TypeDeclaration(resolver, "DiscreteInt64KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[150] = new TypeDeclaration(resolver, "DiscreteMatrixKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x97] = new TypeDeclaration(resolver, "DiscreteObjectKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x98] = new TypeDeclaration(resolver, "DiscretePoint3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x99] = new TypeDeclaration(resolver, "DiscretePointKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x9a] = new TypeDeclaration(resolver, "DiscreteQuaternionKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x9b] = new TypeDeclaration(resolver, "DiscreteRectKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x9c] = new TypeDeclaration(resolver, "DiscreteRotation3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x9d] = new TypeDeclaration(resolver, "DiscreteSingleKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x9e] = new TypeDeclaration(resolver, "DiscreteSizeKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x9f] = new TypeDeclaration(resolver, "DiscreteStringKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[160] = new TypeDeclaration(resolver, "DiscreteThicknessKeyFrame", "System.Windows.Media.Animation", 0); + KnownTypeTable[0xa1] = new TypeDeclaration(resolver, "DiscreteVector3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0xa2] = new TypeDeclaration(resolver, "DiscreteVectorKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0xa3] = new TypeDeclaration(resolver, "DockPanel", "System.Windows.Controls", 0); + KnownTypeTable[0xa4] = new TypeDeclaration(resolver, "DocumentPageView", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0xa5] = new TypeDeclaration(resolver, "DocumentReference", "System.Windows.Documents", 0); + KnownTypeTable[0xa6] = new TypeDeclaration(resolver, "DocumentViewer", "System.Windows.Controls", 0); + KnownTypeTable[0xa7] = new TypeDeclaration(resolver, "DocumentViewerBase", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0xa8] = new TypeDeclaration(resolver, "Double", "System", 2); + KnownTypeTable[0xa9] = new TypeDeclaration(resolver, "DoubleAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[170] = new TypeDeclaration(resolver, "DoubleAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0xab] = new TypeDeclaration(resolver, "DoubleAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0xac] = new TypeDeclaration(resolver, "DoubleAnimationUsingPath", "System.Windows.Media.Animation", 1); + KnownTypeTable[0xad] = new TypeDeclaration(resolver, "DoubleCollection", "System.Windows.Media", 1); + KnownTypeTable[0xae] = new TypeDeclaration(resolver, "DoubleCollectionConverter", "System.Windows.Media", 1); + KnownTypeTable[0xaf] = new TypeDeclaration(resolver, "DoubleConverter", "System.ComponentModel", 3); + KnownTypeTable[0xb0] = new TypeDeclaration(resolver, "DoubleIListConverter", "System.Windows.Media.Converters", 1); + KnownTypeTable[0xb1] = new TypeDeclaration(resolver, "DoubleKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0xb2] = new TypeDeclaration(resolver, "DoubleKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0xb3] = new TypeDeclaration(resolver, "Drawing", "System.Windows.Media", 1); + KnownTypeTable[180] = new TypeDeclaration(resolver, "DrawingBrush", "System.Windows.Media", 1); + KnownTypeTable[0xb5] = new TypeDeclaration(resolver, "DrawingCollection", "System.Windows.Media", 1); + KnownTypeTable[0xb6] = new TypeDeclaration(resolver, "DrawingContext", "System.Windows.Media", 1); + KnownTypeTable[0xb7] = new TypeDeclaration(resolver, "DrawingGroup", "System.Windows.Media", 1); + KnownTypeTable[0xb8] = new TypeDeclaration(resolver, "DrawingImage", "System.Windows.Media", 1); + KnownTypeTable[0xb9] = new TypeDeclaration(resolver, "DrawingVisual", "System.Windows.Media", 1); + KnownTypeTable[0xba] = new TypeDeclaration(resolver, "DropShadowBitmapEffect", "System.Windows.Media.Effects", 1); + KnownTypeTable[0xbb] = new TypeDeclaration(resolver, "Duration", "System.Windows", 1); + KnownTypeTable[0xbc] = new TypeDeclaration(resolver, "DurationConverter", "System.Windows", 1); + KnownTypeTable[0xbd] = new TypeDeclaration(resolver, "DynamicResourceExtension", "System.Windows", 0, true); + KnownTypeTable[190] = new TypeDeclaration(resolver, "DynamicResourceExtensionConverter", "System.Windows", 0); + KnownTypeTable[0xbf] = new TypeDeclaration(resolver, "Ellipse", "System.Windows.Shapes", 0); + KnownTypeTable[0xc0] = new TypeDeclaration(resolver, "EllipseGeometry", "System.Windows.Media", 1); + KnownTypeTable[0xc1] = new TypeDeclaration(resolver, "EmbossBitmapEffect", "System.Windows.Media.Effects", 1); + KnownTypeTable[0xc2] = new TypeDeclaration(resolver, "EmissiveMaterial", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0xc3] = new TypeDeclaration(resolver, "EnumConverter", "System.ComponentModel", 3); + KnownTypeTable[0xc4] = new TypeDeclaration(resolver, "EventManager", "System.Windows", 1); + KnownTypeTable[0xc5] = new TypeDeclaration(resolver, "EventSetter", "System.Windows", 0); + KnownTypeTable[0xc6] = new TypeDeclaration(resolver, "EventTrigger", "System.Windows", 0); + KnownTypeTable[0xc7] = new TypeDeclaration(resolver, "Expander", "System.Windows.Controls", 0); + KnownTypeTable[200] = new TypeDeclaration(resolver, "Expression", "System.Windows", 4); + KnownTypeTable[0xc9] = new TypeDeclaration(resolver, "ExpressionConverter", "System.Windows", 4); + KnownTypeTable[0xca] = new TypeDeclaration(resolver, "Figure", "System.Windows.Documents", 0); + KnownTypeTable[0xcb] = new TypeDeclaration(resolver, "FigureLength", "System.Windows", 0); + KnownTypeTable[0xcc] = new TypeDeclaration(resolver, "FigureLengthConverter", "System.Windows", 0); + KnownTypeTable[0xcd] = new TypeDeclaration(resolver, "FixedDocument", "System.Windows.Documents", 0); + KnownTypeTable[0xce] = new TypeDeclaration(resolver, "FixedDocumentSequence", "System.Windows.Documents", 0); + KnownTypeTable[0xcf] = new TypeDeclaration(resolver, "FixedPage", "System.Windows.Documents", 0); + KnownTypeTable[0xd0] = new TypeDeclaration(resolver, "Floater", "System.Windows.Documents", 0); + KnownTypeTable[0xd1] = new TypeDeclaration(resolver, "FlowDocument", "System.Windows.Documents", 0); + KnownTypeTable[210] = new TypeDeclaration(resolver, "FlowDocumentPageViewer", "System.Windows.Controls", 0); + KnownTypeTable[0xd3] = new TypeDeclaration(resolver, "FlowDocumentReader", "System.Windows.Controls", 0); + KnownTypeTable[0xd4] = new TypeDeclaration(resolver, "FlowDocumentScrollViewer", "System.Windows.Controls", 0); + KnownTypeTable[0xd5] = new TypeDeclaration(resolver, "FocusManager", "System.Windows.Input", 1); + KnownTypeTable[0xd6] = new TypeDeclaration(resolver, "FontFamily", "System.Windows.Media", 1); + KnownTypeTable[0xd7] = new TypeDeclaration(resolver, "FontFamilyConverter", "System.Windows.Media", 1); + KnownTypeTable[0xd8] = new TypeDeclaration(resolver, "FontSizeConverter", "System.Windows", 0); + KnownTypeTable[0xd9] = new TypeDeclaration(resolver, "FontStretch", "System.Windows", 1); + KnownTypeTable[0xda] = new TypeDeclaration(resolver, "FontStretchConverter", "System.Windows", 1); + KnownTypeTable[0xdb] = new TypeDeclaration(resolver, "FontStyle", "System.Windows", 1); + KnownTypeTable[220] = new TypeDeclaration(resolver, "FontStyleConverter", "System.Windows", 1); + KnownTypeTable[0xdd] = new TypeDeclaration(resolver, "FontWeight", "System.Windows", 1); + KnownTypeTable[0xde] = new TypeDeclaration(resolver, "FontWeightConverter", "System.Windows", 1); + KnownTypeTable[0xdf] = new TypeDeclaration(resolver, "FormatConvertedBitmap", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0xe0] = new TypeDeclaration(resolver, "Frame", "System.Windows.Controls", 0); + KnownTypeTable[0xe1] = new TypeDeclaration(resolver, "FrameworkContentElement", "System.Windows", 0); + KnownTypeTable[0xe2] = new TypeDeclaration(resolver, "FrameworkElement", "System.Windows", 0); + KnownTypeTable[0xe3] = new TypeDeclaration(resolver, "FrameworkElementFactory", "System.Windows", 0); + KnownTypeTable[0xe4] = new TypeDeclaration(resolver, "FrameworkPropertyMetadata", "System.Windows", 0); + KnownTypeTable[0xe5] = new TypeDeclaration(resolver, "FrameworkPropertyMetadataOptions", "System.Windows", 0); + KnownTypeTable[230] = new TypeDeclaration(resolver, "FrameworkRichTextComposition", "System.Windows.Documents", 0); + KnownTypeTable[0xe7] = new TypeDeclaration(resolver, "FrameworkTemplate", "System.Windows", 0); + KnownTypeTable[0xe8] = new TypeDeclaration(resolver, "FrameworkTextComposition", "System.Windows.Documents", 0); + KnownTypeTable[0xe9] = new TypeDeclaration(resolver, "Freezable", "System.Windows", 4); + KnownTypeTable[0xea] = new TypeDeclaration(resolver, "GeneralTransform", "System.Windows.Media", 1); + KnownTypeTable[0xeb] = new TypeDeclaration(resolver, "GeneralTransformCollection", "System.Windows.Media", 1); + KnownTypeTable[0xec] = new TypeDeclaration(resolver, "GeneralTransformGroup", "System.Windows.Media", 1); + KnownTypeTable[0xed] = new TypeDeclaration(resolver, "Geometry", "System.Windows.Media", 1); + KnownTypeTable[0xee] = new TypeDeclaration(resolver, "Geometry3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0xef] = new TypeDeclaration(resolver, "GeometryCollection", "System.Windows.Media", 1); + KnownTypeTable[240] = new TypeDeclaration(resolver, "GeometryConverter", "System.Windows.Media", 1); + KnownTypeTable[0xf1] = new TypeDeclaration(resolver, "GeometryDrawing", "System.Windows.Media", 1); + KnownTypeTable[0xf2] = new TypeDeclaration(resolver, "GeometryGroup", "System.Windows.Media", 1); + KnownTypeTable[0xf3] = new TypeDeclaration(resolver, "GeometryModel3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0xf4] = new TypeDeclaration(resolver, "GestureRecognizer", "System.Windows.Ink", 1); + KnownTypeTable[0xf5] = new TypeDeclaration(resolver, "GifBitmapDecoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0xf6] = new TypeDeclaration(resolver, "GifBitmapEncoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0xf7] = new TypeDeclaration(resolver, "GlyphRun", "System.Windows.Media", 1); + KnownTypeTable[0xf8] = new TypeDeclaration(resolver, "GlyphRunDrawing", "System.Windows.Media", 1); + KnownTypeTable[250] = new TypeDeclaration(resolver, "Glyphs", "System.Windows.Documents", 0); + KnownTypeTable[0xf9] = new TypeDeclaration(resolver, "GlyphTypeface", "System.Windows.Media", 1); + KnownTypeTable[0xfb] = new TypeDeclaration(resolver, "GradientBrush", "System.Windows.Media", 1); + KnownTypeTable[0xfc] = new TypeDeclaration(resolver, "GradientStop", "System.Windows.Media", 1); + KnownTypeTable[0xfd] = new TypeDeclaration(resolver, "GradientStopCollection", "System.Windows.Media", 1); + KnownTypeTable[0xfe] = new TypeDeclaration(resolver, "Grid", "System.Windows.Controls", 0); + KnownTypeTable[0xff] = new TypeDeclaration(resolver, "GridLength", "System.Windows", 0); + KnownTypeTable[0x100] = new TypeDeclaration(resolver, "GridLengthConverter", "System.Windows", 0); + KnownTypeTable[0x101] = new TypeDeclaration(resolver, "GridSplitter", "System.Windows.Controls", 0); + KnownTypeTable[0x102] = new TypeDeclaration(resolver, "GridView", "System.Windows.Controls", 0); + KnownTypeTable[0x103] = new TypeDeclaration(resolver, "GridViewColumn", "System.Windows.Controls", 0); + KnownTypeTable[260] = new TypeDeclaration(resolver, "GridViewColumnHeader", "System.Windows.Controls", 0); + KnownTypeTable[0x105] = new TypeDeclaration(resolver, "GridViewHeaderRowPresenter", "System.Windows.Controls", 0); + KnownTypeTable[0x106] = new TypeDeclaration(resolver, "GridViewRowPresenter", "System.Windows.Controls", 0); + KnownTypeTable[0x107] = new TypeDeclaration(resolver, "GridViewRowPresenterBase", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x108] = new TypeDeclaration(resolver, "GroupBox", "System.Windows.Controls", 0); + KnownTypeTable[0x109] = new TypeDeclaration(resolver, "GroupItem", "System.Windows.Controls", 0); + KnownTypeTable[0x10a] = new TypeDeclaration(resolver, "Guid", "System", 2); + KnownTypeTable[0x10b] = new TypeDeclaration(resolver, "GuidConverter", "System.ComponentModel", 3); + KnownTypeTable[0x10c] = new TypeDeclaration(resolver, "GuidelineSet", "System.Windows.Media", 1); + KnownTypeTable[0x10d] = new TypeDeclaration(resolver, "HeaderedContentControl", "System.Windows.Controls", 0); + KnownTypeTable[270] = new TypeDeclaration(resolver, "HeaderedItemsControl", "System.Windows.Controls", 0); + KnownTypeTable[0x10f] = new TypeDeclaration(resolver, "HierarchicalDataTemplate", "System.Windows", 0); + KnownTypeTable[0x110] = new TypeDeclaration(resolver, "HostVisual", "System.Windows.Media", 1); + KnownTypeTable[0x111] = new TypeDeclaration(resolver, "Hyperlink", "System.Windows.Documents", 0); + KnownTypeTable[0x112] = new TypeDeclaration(resolver, "IAddChild", "System.Windows.Markup", 1); + KnownTypeTable[0x113] = new TypeDeclaration(resolver, "IAddChildInternal", "System.Windows.Markup", 1); + KnownTypeTable[0x114] = new TypeDeclaration(resolver, "ICommand", "System.Windows.Input", 1); + KnownTypeTable[0x115] = new TypeDeclaration(resolver, "IComponentConnector", "System.Windows.Markup", 4); + KnownTypeTable[280] = new TypeDeclaration(resolver, "IconBitmapDecoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x119] = new TypeDeclaration(resolver, "Image", "System.Windows.Controls", 0); + KnownTypeTable[0x11a] = new TypeDeclaration(resolver, "ImageBrush", "System.Windows.Media", 1); + KnownTypeTable[0x11b] = new TypeDeclaration(resolver, "ImageDrawing", "System.Windows.Media", 1); + KnownTypeTable[0x11c] = new TypeDeclaration(resolver, "ImageMetadata", "System.Windows.Media", 1); + KnownTypeTable[0x11d] = new TypeDeclaration(resolver, "ImageSource", "System.Windows.Media", 1); + KnownTypeTable[0x11e] = new TypeDeclaration(resolver, "ImageSourceConverter", "System.Windows.Media", 1); + KnownTypeTable[0x116] = new TypeDeclaration(resolver, "INameScope", "System.Windows.Markup", 4); + KnownTypeTable[0x120] = new TypeDeclaration(resolver, "InkCanvas", "System.Windows.Controls", 0); + KnownTypeTable[0x121] = new TypeDeclaration(resolver, "InkPresenter", "System.Windows.Controls", 0); + KnownTypeTable[290] = new TypeDeclaration(resolver, "Inline", "System.Windows.Documents", 0); + KnownTypeTable[0x123] = new TypeDeclaration(resolver, "InlineCollection", "System.Windows.Documents", 0); + KnownTypeTable[0x124] = new TypeDeclaration(resolver, "InlineUIContainer", "System.Windows.Documents", 0); + KnownTypeTable[0x11f] = new TypeDeclaration(resolver, "InPlaceBitmapMetadataWriter", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x125] = new TypeDeclaration(resolver, "InputBinding", "System.Windows.Input", 1); + KnownTypeTable[0x126] = new TypeDeclaration(resolver, "InputDevice", "System.Windows.Input", 1); + KnownTypeTable[0x127] = new TypeDeclaration(resolver, "InputLanguageManager", "System.Windows.Input", 1); + KnownTypeTable[0x128] = new TypeDeclaration(resolver, "InputManager", "System.Windows.Input", 1); + KnownTypeTable[0x129] = new TypeDeclaration(resolver, "InputMethod", "System.Windows.Input", 1); + KnownTypeTable[0x12a] = new TypeDeclaration(resolver, "InputScope", "System.Windows.Input", 1); + KnownTypeTable[0x12b] = new TypeDeclaration(resolver, "InputScopeConverter", "System.Windows.Input", 1); + KnownTypeTable[300] = new TypeDeclaration(resolver, "InputScopeName", "System.Windows.Input", 1); + KnownTypeTable[0x12d] = new TypeDeclaration(resolver, "InputScopeNameConverter", "System.Windows.Input", 1); + KnownTypeTable[0x12e] = new TypeDeclaration(resolver, "Int16", "System", 2); + KnownTypeTable[0x12f] = new TypeDeclaration(resolver, "Int16Animation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x130] = new TypeDeclaration(resolver, "Int16AnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x131] = new TypeDeclaration(resolver, "Int16AnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x132] = new TypeDeclaration(resolver, "Int16Converter", "System.ComponentModel", 3); + KnownTypeTable[0x133] = new TypeDeclaration(resolver, "Int16KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x134] = new TypeDeclaration(resolver, "Int16KeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x135] = new TypeDeclaration(resolver, "Int32", "System", 2); + KnownTypeTable[310] = new TypeDeclaration(resolver, "Int32Animation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x137] = new TypeDeclaration(resolver, "Int32AnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x138] = new TypeDeclaration(resolver, "Int32AnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x139] = new TypeDeclaration(resolver, "Int32Collection", "System.Windows.Media", 1); + KnownTypeTable[0x13a] = new TypeDeclaration(resolver, "Int32CollectionConverter", "System.Windows.Media", 1); + KnownTypeTable[0x13b] = new TypeDeclaration(resolver, "Int32Converter", "System.ComponentModel", 3); + KnownTypeTable[0x13c] = new TypeDeclaration(resolver, "Int32KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x13d] = new TypeDeclaration(resolver, "Int32KeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x13e] = new TypeDeclaration(resolver, "Int32Rect", "System.Windows", 4); + KnownTypeTable[0x13f] = new TypeDeclaration(resolver, "Int32RectConverter", "System.Windows", 4); + KnownTypeTable[320] = new TypeDeclaration(resolver, "Int64", "System", 2); + KnownTypeTable[0x141] = new TypeDeclaration(resolver, "Int64Animation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x142] = new TypeDeclaration(resolver, "Int64AnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x143] = new TypeDeclaration(resolver, "Int64AnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x144] = new TypeDeclaration(resolver, "Int64Converter", "System.ComponentModel", 3); + KnownTypeTable[0x145] = new TypeDeclaration(resolver, "Int64KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x146] = new TypeDeclaration(resolver, "Int64KeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x117] = new TypeDeclaration(resolver, "IStyleConnector", "System.Windows.Markup", 0); + KnownTypeTable[0x147] = new TypeDeclaration(resolver, "Italic", "System.Windows.Documents", 0); + KnownTypeTable[0x148] = new TypeDeclaration(resolver, "ItemCollection", "System.Windows.Controls", 0); + KnownTypeTable[0x149] = new TypeDeclaration(resolver, "ItemsControl", "System.Windows.Controls", 0); + KnownTypeTable[330] = new TypeDeclaration(resolver, "ItemsPanelTemplate", "System.Windows.Controls", 0); + KnownTypeTable[0x14b] = new TypeDeclaration(resolver, "ItemsPresenter", "System.Windows.Controls", 0); + KnownTypeTable[0x14c] = new TypeDeclaration(resolver, "JournalEntry", "System.Windows.Navigation", 0); + KnownTypeTable[0x14d] = new TypeDeclaration(resolver, "JournalEntryListConverter", "System.Windows.Navigation", 0); + KnownTypeTable[0x14e] = new TypeDeclaration(resolver, "JournalEntryUnifiedViewConverter", "System.Windows.Navigation", 0); + KnownTypeTable[0x14f] = new TypeDeclaration(resolver, "JpegBitmapDecoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x150] = new TypeDeclaration(resolver, "JpegBitmapEncoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x151] = new TypeDeclaration(resolver, "KeyBinding", "System.Windows.Input", 1); + KnownTypeTable[0x159] = new TypeDeclaration(resolver, "KeyboardDevice", "System.Windows.Input", 1); + KnownTypeTable[0x152] = new TypeDeclaration(resolver, "KeyConverter", "System.Windows.Input", 4); + KnownTypeTable[0x153] = new TypeDeclaration(resolver, "KeyGesture", "System.Windows.Input", 1); + KnownTypeTable[340] = new TypeDeclaration(resolver, "KeyGestureConverter", "System.Windows.Input", 1); + KnownTypeTable[0x155] = new TypeDeclaration(resolver, "KeySpline", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x156] = new TypeDeclaration(resolver, "KeySplineConverter", "System.Windows", 1); + KnownTypeTable[0x157] = new TypeDeclaration(resolver, "KeyTime", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x158] = new TypeDeclaration(resolver, "KeyTimeConverter", "System.Windows", 1); + KnownTypeTable[0x15a] = new TypeDeclaration(resolver, "Label", "System.Windows.Controls", 0); + KnownTypeTable[0x15b] = new TypeDeclaration(resolver, "LateBoundBitmapDecoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x15c] = new TypeDeclaration(resolver, "LengthConverter", "System.Windows", 0); + KnownTypeTable[0x15d] = new TypeDeclaration(resolver, "Light", "System.Windows.Media.Media3D", 1); + KnownTypeTable[350] = new TypeDeclaration(resolver, "Line", "System.Windows.Shapes", 0); + KnownTypeTable[0x162] = new TypeDeclaration(resolver, "LinearByteKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x163] = new TypeDeclaration(resolver, "LinearColorKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x164] = new TypeDeclaration(resolver, "LinearDecimalKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x165] = new TypeDeclaration(resolver, "LinearDoubleKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x166] = new TypeDeclaration(resolver, "LinearGradientBrush", "System.Windows.Media", 1); + KnownTypeTable[0x167] = new TypeDeclaration(resolver, "LinearInt16KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[360] = new TypeDeclaration(resolver, "LinearInt32KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x169] = new TypeDeclaration(resolver, "LinearInt64KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x16a] = new TypeDeclaration(resolver, "LinearPoint3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x16b] = new TypeDeclaration(resolver, "LinearPointKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x16c] = new TypeDeclaration(resolver, "LinearQuaternionKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x16d] = new TypeDeclaration(resolver, "LinearRectKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x16e] = new TypeDeclaration(resolver, "LinearRotation3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x16f] = new TypeDeclaration(resolver, "LinearSingleKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x170] = new TypeDeclaration(resolver, "LinearSizeKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x171] = new TypeDeclaration(resolver, "LinearThicknessKeyFrame", "System.Windows.Media.Animation", 0); + KnownTypeTable[370] = new TypeDeclaration(resolver, "LinearVector3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x173] = new TypeDeclaration(resolver, "LinearVectorKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x15f] = new TypeDeclaration(resolver, "LineBreak", "System.Windows.Documents", 0); + KnownTypeTable[0x160] = new TypeDeclaration(resolver, "LineGeometry", "System.Windows.Media", 1); + KnownTypeTable[0x161] = new TypeDeclaration(resolver, "LineSegment", "System.Windows.Media", 1); + KnownTypeTable[0x174] = new TypeDeclaration(resolver, "List", "System.Windows.Documents", 0); + KnownTypeTable[0x175] = new TypeDeclaration(resolver, "ListBox", "System.Windows.Controls", 0); + KnownTypeTable[0x176] = new TypeDeclaration(resolver, "ListBoxItem", "System.Windows.Controls", 0); + KnownTypeTable[0x177] = new TypeDeclaration(resolver, "ListCollectionView", "System.Windows.Data", 0); + KnownTypeTable[0x178] = new TypeDeclaration(resolver, "ListItem", "System.Windows.Documents", 0); + KnownTypeTable[0x179] = new TypeDeclaration(resolver, "ListView", "System.Windows.Controls", 0); + KnownTypeTable[0x17a] = new TypeDeclaration(resolver, "ListViewItem", "System.Windows.Controls", 0); + KnownTypeTable[0x17b] = new TypeDeclaration(resolver, "Localization", "System.Windows", 0); + KnownTypeTable[380] = new TypeDeclaration(resolver, "LostFocusEventManager", "System.Windows", 0); + KnownTypeTable[0x17d] = new TypeDeclaration(resolver, "MarkupExtension", "System.Windows.Markup", 4); + KnownTypeTable[0x17e] = new TypeDeclaration(resolver, "Material", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x17f] = new TypeDeclaration(resolver, "MaterialCollection", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x180] = new TypeDeclaration(resolver, "MaterialGroup", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x181] = new TypeDeclaration(resolver, "Matrix", "System.Windows.Media", 4); + KnownTypeTable[0x182] = new TypeDeclaration(resolver, "Matrix3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x183] = new TypeDeclaration(resolver, "Matrix3DConverter", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x184] = new TypeDeclaration(resolver, "MatrixAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x185] = new TypeDeclaration(resolver, "MatrixAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[390] = new TypeDeclaration(resolver, "MatrixAnimationUsingPath", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x187] = new TypeDeclaration(resolver, "MatrixCamera", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x188] = new TypeDeclaration(resolver, "MatrixConverter", "System.Windows.Media", 4); + KnownTypeTable[0x189] = new TypeDeclaration(resolver, "MatrixKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x18a] = new TypeDeclaration(resolver, "MatrixKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x18b] = new TypeDeclaration(resolver, "MatrixTransform", "System.Windows.Media", 1); + KnownTypeTable[0x18c] = new TypeDeclaration(resolver, "MatrixTransform3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x18d] = new TypeDeclaration(resolver, "MediaClock", "System.Windows.Media", 1); + KnownTypeTable[0x18e] = new TypeDeclaration(resolver, "MediaElement", "System.Windows.Controls", 0); + KnownTypeTable[0x18f] = new TypeDeclaration(resolver, "MediaPlayer", "System.Windows.Media", 1); + KnownTypeTable[400] = new TypeDeclaration(resolver, "MediaTimeline", "System.Windows.Media", 1); + KnownTypeTable[0x191] = new TypeDeclaration(resolver, "Menu", "System.Windows.Controls", 0); + KnownTypeTable[0x192] = new TypeDeclaration(resolver, "MenuBase", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x193] = new TypeDeclaration(resolver, "MenuItem", "System.Windows.Controls", 0); + KnownTypeTable[0x194] = new TypeDeclaration(resolver, "MenuScrollingVisibilityConverter", "System.Windows.Controls", 0); + KnownTypeTable[0x195] = new TypeDeclaration(resolver, "MeshGeometry3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x196] = new TypeDeclaration(resolver, "Model3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x197] = new TypeDeclaration(resolver, "Model3DCollection", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x198] = new TypeDeclaration(resolver, "Model3DGroup", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x199] = new TypeDeclaration(resolver, "ModelVisual3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[410] = new TypeDeclaration(resolver, "ModifierKeysConverter", "System.Windows.Input", 4); + KnownTypeTable[0x19b] = new TypeDeclaration(resolver, "MouseActionConverter", "System.Windows.Input", 1); + KnownTypeTable[0x19c] = new TypeDeclaration(resolver, "MouseBinding", "System.Windows.Input", 1); + KnownTypeTable[0x19d] = new TypeDeclaration(resolver, "MouseDevice", "System.Windows.Input", 1); + KnownTypeTable[0x19e] = new TypeDeclaration(resolver, "MouseGesture", "System.Windows.Input", 1); + KnownTypeTable[0x19f] = new TypeDeclaration(resolver, "MouseGestureConverter", "System.Windows.Input", 1); + KnownTypeTable[0x1a0] = new TypeDeclaration(resolver, "MultiBinding", "System.Windows.Data", 0, false); + KnownTypeTable[0x1a1] = new TypeDeclaration(resolver, "MultiBindingExpression", "System.Windows.Data", 0); + KnownTypeTable[0x1a2] = new TypeDeclaration(resolver, "MultiDataTrigger", "System.Windows", 0); + KnownTypeTable[0x1a3] = new TypeDeclaration(resolver, "MultiTrigger", "System.Windows", 0); + KnownTypeTable[420] = new TypeDeclaration(resolver, "NameScope", "System.Windows", 0); + KnownTypeTable[0x1a5] = new TypeDeclaration(resolver, "NavigationWindow", "System.Windows.Navigation", 0); + KnownTypeTable[0x1a7] = new TypeDeclaration(resolver, "NullableBoolConverter", "System.Windows", 0); + KnownTypeTable[0x1a8] = new TypeDeclaration(resolver, "NullableConverter", "System.ComponentModel", 3); + KnownTypeTable[0x1a6] = new TypeDeclaration(resolver, "NullExtension", "System.Windows.Markup", 0, true); + KnownTypeTable[0x1a9] = new TypeDeclaration(resolver, "NumberSubstitution", "System.Windows.Media", 1); + KnownTypeTable[0x1aa] = new TypeDeclaration(resolver, "Object", "System", 2); + KnownTypeTable[0x1ab] = new TypeDeclaration(resolver, "ObjectAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1ac] = new TypeDeclaration(resolver, "ObjectAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1ad] = new TypeDeclaration(resolver, "ObjectDataProvider", "System.Windows.Data", 0); + KnownTypeTable[430] = new TypeDeclaration(resolver, "ObjectKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1af] = new TypeDeclaration(resolver, "ObjectKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1b0] = new TypeDeclaration(resolver, "OrthographicCamera", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1b1] = new TypeDeclaration(resolver, "OuterGlowBitmapEffect", "System.Windows.Media.Effects", 1); + KnownTypeTable[0x1b2] = new TypeDeclaration(resolver, "Page", "System.Windows.Controls", 0); + KnownTypeTable[0x1b3] = new TypeDeclaration(resolver, "PageContent", "System.Windows.Documents", 0); + KnownTypeTable[0x1b4] = new TypeDeclaration(resolver, "PageFunctionBase", "System.Windows.Navigation", 0); + KnownTypeTable[0x1b5] = new TypeDeclaration(resolver, "Panel", "System.Windows.Controls", 0); + KnownTypeTable[0x1b6] = new TypeDeclaration(resolver, "Paragraph", "System.Windows.Documents", 0); + KnownTypeTable[0x1b7] = new TypeDeclaration(resolver, "ParallelTimeline", "System.Windows.Media.Animation", 1); + KnownTypeTable[440] = new TypeDeclaration(resolver, "ParserContext", "System.Windows.Markup", 0); + KnownTypeTable[0x1b9] = new TypeDeclaration(resolver, "PasswordBox", "System.Windows.Controls", 0); + KnownTypeTable[0x1ba] = new TypeDeclaration(resolver, "Path", "System.Windows.Shapes", 0); + KnownTypeTable[0x1bb] = new TypeDeclaration(resolver, "PathFigure", "System.Windows.Media", 1); + KnownTypeTable[0x1bc] = new TypeDeclaration(resolver, "PathFigureCollection", "System.Windows.Media", 1); + KnownTypeTable[0x1bd] = new TypeDeclaration(resolver, "PathFigureCollectionConverter", "System.Windows.Media", 1); + KnownTypeTable[0x1be] = new TypeDeclaration(resolver, "PathGeometry", "System.Windows.Media", 1); + KnownTypeTable[0x1bf] = new TypeDeclaration(resolver, "PathSegment", "System.Windows.Media", 1); + KnownTypeTable[0x1c0] = new TypeDeclaration(resolver, "PathSegmentCollection", "System.Windows.Media", 1); + KnownTypeTable[0x1c1] = new TypeDeclaration(resolver, "PauseStoryboard", "System.Windows.Media.Animation", 0); + KnownTypeTable[450] = new TypeDeclaration(resolver, "Pen", "System.Windows.Media", 1); + KnownTypeTable[0x1c3] = new TypeDeclaration(resolver, "PerspectiveCamera", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1c4] = new TypeDeclaration(resolver, "PixelFormat", "System.Windows.Media", 1); + KnownTypeTable[0x1c5] = new TypeDeclaration(resolver, "PixelFormatConverter", "System.Windows.Media", 1); + KnownTypeTable[0x1c6] = new TypeDeclaration(resolver, "PngBitmapDecoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x1c7] = new TypeDeclaration(resolver, "PngBitmapEncoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x1c8] = new TypeDeclaration(resolver, "Point", "System.Windows", 4); + KnownTypeTable[0x1c9] = new TypeDeclaration(resolver, "Point3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1ca] = new TypeDeclaration(resolver, "Point3DAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1cb] = new TypeDeclaration(resolver, "Point3DAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[460] = new TypeDeclaration(resolver, "Point3DAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1cd] = new TypeDeclaration(resolver, "Point3DCollection", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1ce] = new TypeDeclaration(resolver, "Point3DCollectionConverter", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1cf] = new TypeDeclaration(resolver, "Point3DConverter", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1d0] = new TypeDeclaration(resolver, "Point3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1d1] = new TypeDeclaration(resolver, "Point3DKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1d2] = new TypeDeclaration(resolver, "Point4D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1d3] = new TypeDeclaration(resolver, "Point4DConverter", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1d4] = new TypeDeclaration(resolver, "PointAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1d5] = new TypeDeclaration(resolver, "PointAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[470] = new TypeDeclaration(resolver, "PointAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1d7] = new TypeDeclaration(resolver, "PointAnimationUsingPath", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1d8] = new TypeDeclaration(resolver, "PointCollection", "System.Windows.Media", 1); + KnownTypeTable[0x1d9] = new TypeDeclaration(resolver, "PointCollectionConverter", "System.Windows.Media", 1); + KnownTypeTable[0x1da] = new TypeDeclaration(resolver, "PointConverter", "System.Windows", 4); + KnownTypeTable[0x1db] = new TypeDeclaration(resolver, "PointIListConverter", "System.Windows.Media.Converters", 1); + KnownTypeTable[0x1dc] = new TypeDeclaration(resolver, "PointKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1dd] = new TypeDeclaration(resolver, "PointKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1de] = new TypeDeclaration(resolver, "PointLight", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1df] = new TypeDeclaration(resolver, "PointLightBase", "System.Windows.Media.Media3D", 1); + KnownTypeTable[480] = new TypeDeclaration(resolver, "PolyBezierSegment", "System.Windows.Media", 1); + KnownTypeTable[0x1e3] = new TypeDeclaration(resolver, "Polygon", "System.Windows.Shapes", 0); + KnownTypeTable[0x1e4] = new TypeDeclaration(resolver, "Polyline", "System.Windows.Shapes", 0); + KnownTypeTable[0x1e1] = new TypeDeclaration(resolver, "PolyLineSegment", "System.Windows.Media", 1); + KnownTypeTable[0x1e2] = new TypeDeclaration(resolver, "PolyQuadraticBezierSegment", "System.Windows.Media", 1); + KnownTypeTable[0x1e5] = new TypeDeclaration(resolver, "Popup", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x1e6] = new TypeDeclaration(resolver, "PresentationSource", "System.Windows", 1); + KnownTypeTable[0x1e7] = new TypeDeclaration(resolver, "PriorityBinding", "System.Windows.Data", 0, true); + KnownTypeTable[0x1e8] = new TypeDeclaration(resolver, "PriorityBindingExpression", "System.Windows.Data", 0); + KnownTypeTable[0x1e9] = new TypeDeclaration(resolver, "ProgressBar", "System.Windows.Controls", 0); + KnownTypeTable[490] = new TypeDeclaration(resolver, "ProjectionCamera", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1eb] = new TypeDeclaration(resolver, "PropertyPath", "System.Windows", 0); + KnownTypeTable[0x1ec] = new TypeDeclaration(resolver, "PropertyPathConverter", "System.Windows", 0); + KnownTypeTable[0x1ed] = new TypeDeclaration(resolver, "QuadraticBezierSegment", "System.Windows.Media", 1); + KnownTypeTable[0x1ee] = new TypeDeclaration(resolver, "Quaternion", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1ef] = new TypeDeclaration(resolver, "QuaternionAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1f0] = new TypeDeclaration(resolver, "QuaternionAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1f1] = new TypeDeclaration(resolver, "QuaternionAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1f2] = new TypeDeclaration(resolver, "QuaternionConverter", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1f3] = new TypeDeclaration(resolver, "QuaternionKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[500] = new TypeDeclaration(resolver, "QuaternionKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1f5] = new TypeDeclaration(resolver, "QuaternionRotation3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1f6] = new TypeDeclaration(resolver, "RadialGradientBrush", "System.Windows.Media", 1); + KnownTypeTable[0x1f7] = new TypeDeclaration(resolver, "RadioButton", "System.Windows.Controls", 0); + KnownTypeTable[0x1f8] = new TypeDeclaration(resolver, "RangeBase", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x1f9] = new TypeDeclaration(resolver, "Rect", "System.Windows", 1); + KnownTypeTable[0x1fa] = new TypeDeclaration(resolver, "Rect3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x1fb] = new TypeDeclaration(resolver, "Rect3DConverter", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x202] = new TypeDeclaration(resolver, "Rectangle", "System.Windows.Shapes", 0); + KnownTypeTable[0x203] = new TypeDeclaration(resolver, "RectangleGeometry", "System.Windows.Media", 1); + KnownTypeTable[0x1fc] = new TypeDeclaration(resolver, "RectAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1fd] = new TypeDeclaration(resolver, "RectAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[510] = new TypeDeclaration(resolver, "RectAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x1ff] = new TypeDeclaration(resolver, "RectConverter", "System.Windows", 4); + KnownTypeTable[0x200] = new TypeDeclaration(resolver, "RectKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x201] = new TypeDeclaration(resolver, "RectKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x204] = new TypeDeclaration(resolver, "RelativeSource", "System.Windows.Data", 0, true); + KnownTypeTable[0x205] = new TypeDeclaration(resolver, "RemoveStoryboard", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x206] = new TypeDeclaration(resolver, "RenderOptions", "System.Windows.Media", 1); + KnownTypeTable[0x207] = new TypeDeclaration(resolver, "RenderTargetBitmap", "System.Windows.Media.Imaging", 1); + KnownTypeTable[520] = new TypeDeclaration(resolver, "RepeatBehavior", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x209] = new TypeDeclaration(resolver, "RepeatBehaviorConverter", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x20a] = new TypeDeclaration(resolver, "RepeatButton", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x20b] = new TypeDeclaration(resolver, "ResizeGrip", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x20c] = new TypeDeclaration(resolver, "ResourceDictionary", "System.Windows", 0); + KnownTypeTable[0x20d] = new TypeDeclaration(resolver, "ResourceKey", "System.Windows", 0, true); + KnownTypeTable[0x20e] = new TypeDeclaration(resolver, "ResumeStoryboard", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x20f] = new TypeDeclaration(resolver, "RichTextBox", "System.Windows.Controls", 0); + KnownTypeTable[0x210] = new TypeDeclaration(resolver, "RotateTransform", "System.Windows.Media", 1); + KnownTypeTable[0x211] = new TypeDeclaration(resolver, "RotateTransform3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[530] = new TypeDeclaration(resolver, "Rotation3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x213] = new TypeDeclaration(resolver, "Rotation3DAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x214] = new TypeDeclaration(resolver, "Rotation3DAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x215] = new TypeDeclaration(resolver, "Rotation3DAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x216] = new TypeDeclaration(resolver, "Rotation3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x217] = new TypeDeclaration(resolver, "Rotation3DKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x218] = new TypeDeclaration(resolver, "RoutedCommand", "System.Windows.Input", 1); + KnownTypeTable[0x219] = new TypeDeclaration(resolver, "RoutedEvent", "System.Windows", 1); + KnownTypeTable[0x21a] = new TypeDeclaration(resolver, "RoutedEventConverter", "System.Windows.Markup", 0); + KnownTypeTable[0x21b] = new TypeDeclaration(resolver, "RoutedUICommand", "System.Windows.Input", 1); + KnownTypeTable[540] = new TypeDeclaration(resolver, "RoutingStrategy", "System.Windows", 1); + KnownTypeTable[0x21d] = new TypeDeclaration(resolver, "RowDefinition", "System.Windows.Controls", 0); + KnownTypeTable[0x21e] = new TypeDeclaration(resolver, "Run", "System.Windows.Documents", 0); + KnownTypeTable[0x21f] = new TypeDeclaration(resolver, "RuntimeNamePropertyAttribute", "System.Windows.Markup", 4); + KnownTypeTable[0x220] = new TypeDeclaration(resolver, "SByte", "System", 2); + KnownTypeTable[0x221] = new TypeDeclaration(resolver, "SByteConverter", "System.ComponentModel", 3); + KnownTypeTable[0x222] = new TypeDeclaration(resolver, "ScaleTransform", "System.Windows.Media", 1); + KnownTypeTable[0x223] = new TypeDeclaration(resolver, "ScaleTransform3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x224] = new TypeDeclaration(resolver, "ScrollBar", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x225] = new TypeDeclaration(resolver, "ScrollContentPresenter", "System.Windows.Controls", 0); + KnownTypeTable[550] = new TypeDeclaration(resolver, "ScrollViewer", "System.Windows.Controls", 0); + KnownTypeTable[0x227] = new TypeDeclaration(resolver, "Section", "System.Windows.Documents", 0); + KnownTypeTable[0x228] = new TypeDeclaration(resolver, "SeekStoryboard", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x229] = new TypeDeclaration(resolver, "Selector", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x22a] = new TypeDeclaration(resolver, "Separator", "System.Windows.Controls", 0); + KnownTypeTable[0x22b] = new TypeDeclaration(resolver, "SetStoryboardSpeedRatio", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x22c] = new TypeDeclaration(resolver, "Setter", "System.Windows", 0); + KnownTypeTable[0x22d] = new TypeDeclaration(resolver, "SetterBase", "System.Windows", 0); + KnownTypeTable[0x22e] = new TypeDeclaration(resolver, "Shape", "System.Windows.Shapes", 0); + KnownTypeTable[0x22f] = new TypeDeclaration(resolver, "Single", "System", 2); + KnownTypeTable[560] = new TypeDeclaration(resolver, "SingleAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x231] = new TypeDeclaration(resolver, "SingleAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x232] = new TypeDeclaration(resolver, "SingleAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x233] = new TypeDeclaration(resolver, "SingleConverter", "System.ComponentModel", 3); + KnownTypeTable[0x234] = new TypeDeclaration(resolver, "SingleKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x235] = new TypeDeclaration(resolver, "SingleKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x236] = new TypeDeclaration(resolver, "Size", "System.Windows", 4); + KnownTypeTable[0x237] = new TypeDeclaration(resolver, "Size3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x238] = new TypeDeclaration(resolver, "Size3DConverter", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x239] = new TypeDeclaration(resolver, "SizeAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[570] = new TypeDeclaration(resolver, "SizeAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x23b] = new TypeDeclaration(resolver, "SizeAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x23c] = new TypeDeclaration(resolver, "SizeConverter", "System.Windows", 4); + KnownTypeTable[0x23d] = new TypeDeclaration(resolver, "SizeKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x23e] = new TypeDeclaration(resolver, "SizeKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x23f] = new TypeDeclaration(resolver, "SkewTransform", "System.Windows.Media", 1); + KnownTypeTable[0x240] = new TypeDeclaration(resolver, "SkipStoryboardToFill", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x241] = new TypeDeclaration(resolver, "Slider", "System.Windows.Controls", 0); + KnownTypeTable[0x242] = new TypeDeclaration(resolver, "SolidColorBrush", "System.Windows.Media", 1); + KnownTypeTable[0x243] = new TypeDeclaration(resolver, "SoundPlayerAction", "System.Windows.Controls", 0); + KnownTypeTable[580] = new TypeDeclaration(resolver, "Span", "System.Windows.Documents", 0); + KnownTypeTable[0x245] = new TypeDeclaration(resolver, "SpecularMaterial", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x246] = new TypeDeclaration(resolver, "SpellCheck", "System.Windows.Controls", 0); + KnownTypeTable[0x247] = new TypeDeclaration(resolver, "SplineByteKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x248] = new TypeDeclaration(resolver, "SplineColorKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x249] = new TypeDeclaration(resolver, "SplineDecimalKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x24a] = new TypeDeclaration(resolver, "SplineDoubleKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x24b] = new TypeDeclaration(resolver, "SplineInt16KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x24c] = new TypeDeclaration(resolver, "SplineInt32KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x24d] = new TypeDeclaration(resolver, "SplineInt64KeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[590] = new TypeDeclaration(resolver, "SplinePoint3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x24f] = new TypeDeclaration(resolver, "SplinePointKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x250] = new TypeDeclaration(resolver, "SplineQuaternionKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x251] = new TypeDeclaration(resolver, "SplineRectKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x252] = new TypeDeclaration(resolver, "SplineRotation3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x253] = new TypeDeclaration(resolver, "SplineSingleKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x254] = new TypeDeclaration(resolver, "SplineSizeKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x255] = new TypeDeclaration(resolver, "SplineThicknessKeyFrame", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x256] = new TypeDeclaration(resolver, "SplineVector3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x257] = new TypeDeclaration(resolver, "SplineVectorKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[600] = new TypeDeclaration(resolver, "SpotLight", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x259] = new TypeDeclaration(resolver, "StackPanel", "System.Windows.Controls", 0); + KnownTypeTable[0x25a] = new TypeDeclaration(resolver, "StaticExtension", "System.Windows.Markup", 0); + KnownTypeTable[0x25b] = new TypeDeclaration(resolver, "StaticResourceExtension", "System.Windows", 0, true); + KnownTypeTable[0x25c] = new TypeDeclaration(resolver, "StatusBar", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x25d] = new TypeDeclaration(resolver, "StatusBarItem", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x25e] = new TypeDeclaration(resolver, "StickyNoteControl", "System.Windows.Controls", 0); + KnownTypeTable[0x25f] = new TypeDeclaration(resolver, "StopStoryboard", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x260] = new TypeDeclaration(resolver, "Storyboard", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x261] = new TypeDeclaration(resolver, "StreamGeometry", "System.Windows.Media", 1); + KnownTypeTable[610] = new TypeDeclaration(resolver, "StreamGeometryContext", "System.Windows.Media", 1); + KnownTypeTable[0x263] = new TypeDeclaration(resolver, "StreamResourceInfo", "System.Windows.Resources", 0); + KnownTypeTable[0x264] = new TypeDeclaration(resolver, "String", "System", 2); + KnownTypeTable[0x265] = new TypeDeclaration(resolver, "StringAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x266] = new TypeDeclaration(resolver, "StringAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x267] = new TypeDeclaration(resolver, "StringConverter", "System.ComponentModel", 3); + KnownTypeTable[0x268] = new TypeDeclaration(resolver, "StringKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x269] = new TypeDeclaration(resolver, "StringKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x26a] = new TypeDeclaration(resolver, "StrokeCollection", "System.Windows.Ink", 1); + KnownTypeTable[0x26b] = new TypeDeclaration(resolver, "StrokeCollectionConverter", "System.Windows", 1); + KnownTypeTable[620] = new TypeDeclaration(resolver, "Style", "System.Windows", 0); + KnownTypeTable[0x26d] = new TypeDeclaration(resolver, "Stylus", "System.Windows.Input", 1); + KnownTypeTable[0x26e] = new TypeDeclaration(resolver, "StylusDevice", "System.Windows.Input", 1); + KnownTypeTable[0x26f] = new TypeDeclaration(resolver, "TabControl", "System.Windows.Controls", 0); + KnownTypeTable[0x270] = new TypeDeclaration(resolver, "TabItem", "System.Windows.Controls", 0); + KnownTypeTable[0x272] = new TypeDeclaration(resolver, "Table", "System.Windows.Documents", 0); + KnownTypeTable[0x273] = new TypeDeclaration(resolver, "TableCell", "System.Windows.Documents", 0); + KnownTypeTable[0x274] = new TypeDeclaration(resolver, "TableColumn", "System.Windows.Documents", 0); + KnownTypeTable[0x275] = new TypeDeclaration(resolver, "TableRow", "System.Windows.Documents", 0); + KnownTypeTable[630] = new TypeDeclaration(resolver, "TableRowGroup", "System.Windows.Documents", 0); + KnownTypeTable[0x277] = new TypeDeclaration(resolver, "TabletDevice", "System.Windows.Input", 1); + KnownTypeTable[0x271] = new TypeDeclaration(resolver, "TabPanel", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x278] = new TypeDeclaration(resolver, "TemplateBindingExpression", "System.Windows", 0); + KnownTypeTable[0x279] = new TypeDeclaration(resolver, "TemplateBindingExpressionConverter", "System.Windows", 0); + KnownTypeTable[0x27a] = new TypeDeclaration(resolver, "TemplateBindingExtension", "System.Windows", 0); + KnownTypeTable[0x27b] = new TypeDeclaration(resolver, "TemplateBindingExtensionConverter", "System.Windows", 0); + KnownTypeTable[0x27c] = new TypeDeclaration(resolver, "TemplateKey", "System.Windows", 0, true); + KnownTypeTable[0x27d] = new TypeDeclaration(resolver, "TemplateKeyConverter", "System.Windows.Markup", 0); + KnownTypeTable[0x27e] = new TypeDeclaration(resolver, "TextBlock", "System.Windows.Controls", 0); + KnownTypeTable[0x27f] = new TypeDeclaration(resolver, "TextBox", "System.Windows.Controls", 0); + KnownTypeTable[640] = new TypeDeclaration(resolver, "TextBoxBase", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x281] = new TypeDeclaration(resolver, "TextComposition", "System.Windows.Input", 1); + KnownTypeTable[0x282] = new TypeDeclaration(resolver, "TextCompositionManager", "System.Windows.Input", 1); + KnownTypeTable[0x283] = new TypeDeclaration(resolver, "TextDecoration", "System.Windows", 1); + KnownTypeTable[0x284] = new TypeDeclaration(resolver, "TextDecorationCollection", "System.Windows", 1); + KnownTypeTable[0x285] = new TypeDeclaration(resolver, "TextDecorationCollectionConverter", "System.Windows", 1); + KnownTypeTable[0x286] = new TypeDeclaration(resolver, "TextEffect", "System.Windows.Media", 1); + KnownTypeTable[0x287] = new TypeDeclaration(resolver, "TextEffectCollection", "System.Windows.Media", 1); + KnownTypeTable[0x288] = new TypeDeclaration(resolver, "TextElement", "System.Windows.Documents", 0); + KnownTypeTable[0x289] = new TypeDeclaration(resolver, "TextSearch", "System.Windows.Controls", 0); + KnownTypeTable[650] = new TypeDeclaration(resolver, "ThemeDictionaryExtension", "System.Windows", 0, true); + KnownTypeTable[0x28b] = new TypeDeclaration(resolver, "Thickness", "System.Windows", 0); + KnownTypeTable[0x28c] = new TypeDeclaration(resolver, "ThicknessAnimation", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x28d] = new TypeDeclaration(resolver, "ThicknessAnimationBase", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x28e] = new TypeDeclaration(resolver, "ThicknessAnimationUsingKeyFrames", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x28f] = new TypeDeclaration(resolver, "ThicknessConverter", "System.Windows", 0); + KnownTypeTable[0x290] = new TypeDeclaration(resolver, "ThicknessKeyFrame", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x291] = new TypeDeclaration(resolver, "ThicknessKeyFrameCollection", "System.Windows.Media.Animation", 0); + KnownTypeTable[0x292] = new TypeDeclaration(resolver, "Thumb", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x293] = new TypeDeclaration(resolver, "TickBar", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[660] = new TypeDeclaration(resolver, "TiffBitmapDecoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x295] = new TypeDeclaration(resolver, "TiffBitmapEncoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x296] = new TypeDeclaration(resolver, "TileBrush", "System.Windows.Media", 1); + KnownTypeTable[0x299] = new TypeDeclaration(resolver, "Timeline", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x29a] = new TypeDeclaration(resolver, "TimelineCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x29b] = new TypeDeclaration(resolver, "TimelineGroup", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x297] = new TypeDeclaration(resolver, "TimeSpan", "System", 2); + KnownTypeTable[0x298] = new TypeDeclaration(resolver, "TimeSpanConverter", "System.ComponentModel", 3); + KnownTypeTable[0x29c] = new TypeDeclaration(resolver, "ToggleButton", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x29d] = new TypeDeclaration(resolver, "ToolBar", "System.Windows.Controls", 0); + KnownTypeTable[670] = new TypeDeclaration(resolver, "ToolBarOverflowPanel", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x29f] = new TypeDeclaration(resolver, "ToolBarPanel", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x2a0] = new TypeDeclaration(resolver, "ToolBarTray", "System.Windows.Controls", 0); + KnownTypeTable[0x2a1] = new TypeDeclaration(resolver, "ToolTip", "System.Windows.Controls", 0); + KnownTypeTable[0x2a2] = new TypeDeclaration(resolver, "ToolTipService", "System.Windows.Controls", 0); + KnownTypeTable[0x2a3] = new TypeDeclaration(resolver, "Track", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x2a4] = new TypeDeclaration(resolver, "Transform", "System.Windows.Media", 1); + KnownTypeTable[0x2a5] = new TypeDeclaration(resolver, "Transform3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x2a6] = new TypeDeclaration(resolver, "Transform3DCollection", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x2a7] = new TypeDeclaration(resolver, "Transform3DGroup", "System.Windows.Media.Media3D", 1); + KnownTypeTable[680] = new TypeDeclaration(resolver, "TransformCollection", "System.Windows.Media", 1); + KnownTypeTable[0x2a9] = new TypeDeclaration(resolver, "TransformConverter", "System.Windows.Media", 1); + KnownTypeTable[0x2ab] = new TypeDeclaration(resolver, "TransformedBitmap", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x2aa] = new TypeDeclaration(resolver, "TransformGroup", "System.Windows.Media", 1); + KnownTypeTable[0x2ac] = new TypeDeclaration(resolver, "TranslateTransform", "System.Windows.Media", 1); + KnownTypeTable[0x2ad] = new TypeDeclaration(resolver, "TranslateTransform3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x2ae] = new TypeDeclaration(resolver, "TreeView", "System.Windows.Controls", 0); + KnownTypeTable[0x2af] = new TypeDeclaration(resolver, "TreeViewItem", "System.Windows.Controls", 0); + KnownTypeTable[0x2b0] = new TypeDeclaration(resolver, "Trigger", "System.Windows", 0); + KnownTypeTable[0x2b1] = new TypeDeclaration(resolver, "TriggerAction", "System.Windows", 0); + KnownTypeTable[690] = new TypeDeclaration(resolver, "TriggerBase", "System.Windows", 0); + KnownTypeTable[0x2b3] = new TypeDeclaration(resolver, "TypeExtension", "System.Windows.Markup", 0, true); + KnownTypeTable[0x2b4] = new TypeDeclaration(resolver, "TypeTypeConverter", "System.Net.Configuration", 3); + KnownTypeTable[0x2b5] = new TypeDeclaration(resolver, "Typography", "System.Windows.Documents", 0); + KnownTypeTable[0x2b6] = new TypeDeclaration(resolver, "UIElement", "System.Windows", 1); + KnownTypeTable[0x2b7] = new TypeDeclaration(resolver, "UInt16", "System", 2); + KnownTypeTable[0x2b8] = new TypeDeclaration(resolver, "UInt16Converter", "System.ComponentModel", 3); + KnownTypeTable[0x2b9] = new TypeDeclaration(resolver, "UInt32", "System", 2); + KnownTypeTable[0x2ba] = new TypeDeclaration(resolver, "UInt32Converter", "System.ComponentModel", 3); + KnownTypeTable[0x2bb] = new TypeDeclaration(resolver, "UInt64", "System", 2); + KnownTypeTable[700] = new TypeDeclaration(resolver, "UInt64Converter", "System.ComponentModel", 3); + KnownTypeTable[0x2be] = new TypeDeclaration(resolver, "Underline", "System.Windows.Documents", 0); + KnownTypeTable[0x2bf] = new TypeDeclaration(resolver, "UniformGrid", "System.Windows.Controls.Primitives", 0); + KnownTypeTable[0x2c0] = new TypeDeclaration(resolver, "Uri", "System", 3); + KnownTypeTable[0x2c1] = new TypeDeclaration(resolver, "UriTypeConverter", "System", 3); + KnownTypeTable[0x2c2] = new TypeDeclaration(resolver, "UserControl", "System.Windows.Controls", 0); + KnownTypeTable[0x2bd] = new TypeDeclaration(resolver, "UShortIListConverter", "System.Windows.Media.Converters", 1); + KnownTypeTable[0x2c3] = new TypeDeclaration(resolver, "Validation", "System.Windows.Controls", 0); + KnownTypeTable[0x2c4] = new TypeDeclaration(resolver, "Vector", "System.Windows", 1); + KnownTypeTable[0x2c5] = new TypeDeclaration(resolver, "Vector3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[710] = new TypeDeclaration(resolver, "Vector3DAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2c7] = new TypeDeclaration(resolver, "Vector3DAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2c8] = new TypeDeclaration(resolver, "Vector3DAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2c9] = new TypeDeclaration(resolver, "Vector3DCollection", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x2ca] = new TypeDeclaration(resolver, "Vector3DCollectionConverter", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x2cb] = new TypeDeclaration(resolver, "Vector3DConverter", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x2cc] = new TypeDeclaration(resolver, "Vector3DKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2cd] = new TypeDeclaration(resolver, "Vector3DKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2ce] = new TypeDeclaration(resolver, "VectorAnimation", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2cf] = new TypeDeclaration(resolver, "VectorAnimationBase", "System.Windows.Media.Animation", 1); + KnownTypeTable[720] = new TypeDeclaration(resolver, "VectorAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2d1] = new TypeDeclaration(resolver, "VectorCollection", "System.Windows.Media", 1); + KnownTypeTable[0x2d2] = new TypeDeclaration(resolver, "VectorCollectionConverter", "System.Windows.Media", 1); + KnownTypeTable[0x2d3] = new TypeDeclaration(resolver, "VectorConverter", "System.Windows", 4); + KnownTypeTable[0x2d4] = new TypeDeclaration(resolver, "VectorKeyFrame", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2d5] = new TypeDeclaration(resolver, "VectorKeyFrameCollection", "System.Windows.Media.Animation", 1); + KnownTypeTable[0x2d6] = new TypeDeclaration(resolver, "VideoDrawing", "System.Windows.Media", 1); + KnownTypeTable[0x2d7] = new TypeDeclaration(resolver, "ViewBase", "System.Windows.Controls", 0); + KnownTypeTable[0x2d8] = new TypeDeclaration(resolver, "Viewbox", "System.Windows.Controls", 0); + KnownTypeTable[0x2d9] = new TypeDeclaration(resolver, "Viewport3D", "System.Windows.Controls", 0); + KnownTypeTable[730] = new TypeDeclaration(resolver, "Viewport3DVisual", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x2db] = new TypeDeclaration(resolver, "VirtualizingPanel", "System.Windows.Controls", 0); + KnownTypeTable[0x2dc] = new TypeDeclaration(resolver, "VirtualizingStackPanel", "System.Windows.Controls", 0); + KnownTypeTable[0x2dd] = new TypeDeclaration(resolver, "Visual", "System.Windows.Media", 1); + KnownTypeTable[0x2de] = new TypeDeclaration(resolver, "Visual3D", "System.Windows.Media.Media3D", 1); + KnownTypeTable[0x2df] = new TypeDeclaration(resolver, "VisualBrush", "System.Windows.Media", 1); + KnownTypeTable[0x2e0] = new TypeDeclaration(resolver, "VisualTarget", "System.Windows.Media", 1); + KnownTypeTable[0x2e1] = new TypeDeclaration(resolver, "WeakEventManager", "System.Windows", 4); + KnownTypeTable[0x2e2] = new TypeDeclaration(resolver, "WhitespaceSignificantCollectionAttribute", "System.Windows.Markup", 4); + KnownTypeTable[0x2e3] = new TypeDeclaration(resolver, "Window", "System.Windows", 0); + KnownTypeTable[740] = new TypeDeclaration(resolver, "WmpBitmapDecoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x2e5] = new TypeDeclaration(resolver, "WmpBitmapEncoder", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x2e6] = new TypeDeclaration(resolver, "WrapPanel", "System.Windows.Controls", 0); + KnownTypeTable[0x2e7] = new TypeDeclaration(resolver, "WriteableBitmap", "System.Windows.Media.Imaging", 1); + KnownTypeTable[0x2e8] = new TypeDeclaration(resolver, "XamlBrushSerializer", "System.Windows.Markup", 0); + KnownTypeTable[0x2e9] = new TypeDeclaration(resolver, "XamlInt32CollectionSerializer", "System.Windows.Markup", 0); + KnownTypeTable[0x2ea] = new TypeDeclaration(resolver, "XamlPathDataSerializer", "System.Windows.Markup", 0); + KnownTypeTable[0x2eb] = new TypeDeclaration(resolver, "XamlPoint3DCollectionSerializer", "System.Windows.Markup", 0); + KnownTypeTable[0x2ec] = new TypeDeclaration(resolver, "XamlPointCollectionSerializer", "System.Windows.Markup", 0); + KnownTypeTable[0x2ed] = new TypeDeclaration(resolver, "XamlReader", "System.Windows.Markup", 0); + KnownTypeTable[750] = new TypeDeclaration(resolver, "XamlStyleSerializer", "System.Windows.Markup", 0); + KnownTypeTable[0x2ef] = new TypeDeclaration(resolver, "XamlTemplateSerializer", "System.Windows.Markup", 0); + KnownTypeTable[0x2f0] = new TypeDeclaration(resolver, "XamlVector3DCollectionSerializer", "System.Windows.Markup", 0); + KnownTypeTable[0x2f1] = new TypeDeclaration(resolver, "XamlWriter", "System.Windows.Markup", 0); + KnownTypeTable[0x2f2] = new TypeDeclaration(resolver, "XmlDataProvider", "System.Windows.Data", 0); + KnownTypeTable[0x2f3] = new TypeDeclaration(resolver, "XmlLangPropertyAttribute", "System.Windows.Markup", 4); + KnownTypeTable[0x2f4] = new TypeDeclaration(resolver, "XmlLanguage", "System.Windows.Markup", 1); + KnownTypeTable[0x2f5] = new TypeDeclaration(resolver, "XmlLanguageConverter", "System.Windows.Markup", 1); + KnownTypeTable[0x2f6] = new TypeDeclaration(resolver, "XmlNamespaceMapping", "System.Windows.Data", 0); + KnownTypeTable[0x2f7] = new TypeDeclaration(resolver, "ZoomPercentageConverter", "System.Windows.Documents", 0); + KnownPropertyTable = new PropertyDeclaration[0x10d]; + KnownPropertyTable[1] = new PropertyDeclaration("Text", KnownTypeTable[1]); + KnownPropertyTable[2] = new PropertyDeclaration("Storyboard", KnownTypeTable[0x11]); + KnownPropertyTable[3] = new PropertyDeclaration("Children", KnownTypeTable[0x1c]); + KnownPropertyTable[4] = new PropertyDeclaration("Background", KnownTypeTable[50]); + KnownPropertyTable[5] = new PropertyDeclaration("BorderBrush", KnownTypeTable[50]); + KnownPropertyTable[6] = new PropertyDeclaration("BorderThickness", KnownTypeTable[50]); + KnownPropertyTable[7] = new PropertyDeclaration("Command", KnownTypeTable[0x38]); + KnownPropertyTable[8] = new PropertyDeclaration("CommandParameter", KnownTypeTable[0x38]); + KnownPropertyTable[9] = new PropertyDeclaration("CommandTarget", KnownTypeTable[0x38]); + KnownPropertyTable[10] = new PropertyDeclaration("IsPressed", KnownTypeTable[0x38]); + KnownPropertyTable[11] = new PropertyDeclaration("MaxWidth", KnownTypeTable[90]); + KnownPropertyTable[12] = new PropertyDeclaration("MinWidth", KnownTypeTable[90]); + KnownPropertyTable[13] = new PropertyDeclaration("Width", KnownTypeTable[90]); + KnownPropertyTable[14] = new PropertyDeclaration("Content", KnownTypeTable[100]); + KnownPropertyTable[15] = new PropertyDeclaration("ContentTemplate", KnownTypeTable[100]); + KnownPropertyTable[0x10] = new PropertyDeclaration("ContentTemplateSelector", KnownTypeTable[100]); + KnownPropertyTable[0x11] = new PropertyDeclaration("HasContent", KnownTypeTable[100]); + KnownPropertyTable[0x12] = new PropertyDeclaration("Focusable", KnownTypeTable[0x65]); + KnownPropertyTable[0x13] = new PropertyDeclaration("Content", KnownTypeTable[0x66]); + KnownPropertyTable[20] = new PropertyDeclaration("ContentSource", KnownTypeTable[0x66]); + KnownPropertyTable[0x15] = new PropertyDeclaration("ContentTemplate", KnownTypeTable[0x66]); + KnownPropertyTable[0x16] = new PropertyDeclaration("ContentTemplateSelector", KnownTypeTable[0x66]); + KnownPropertyTable[0x17] = new PropertyDeclaration("RecognizesAccessKey", KnownTypeTable[0x66]); + KnownPropertyTable[0x18] = new PropertyDeclaration("Background", KnownTypeTable[0x6b]); + KnownPropertyTable[0x19] = new PropertyDeclaration("BorderBrush", KnownTypeTable[0x6b]); + KnownPropertyTable[0x1a] = new PropertyDeclaration("BorderThickness", KnownTypeTable[0x6b]); + KnownPropertyTable[0x1b] = new PropertyDeclaration("FontFamily", KnownTypeTable[0x6b]); + KnownPropertyTable[0x1c] = new PropertyDeclaration("FontSize", KnownTypeTable[0x6b]); + KnownPropertyTable[0x1d] = new PropertyDeclaration("FontStretch", KnownTypeTable[0x6b]); + KnownPropertyTable[30] = new PropertyDeclaration("FontStyle", KnownTypeTable[0x6b]); + KnownPropertyTable[0x1f] = new PropertyDeclaration("FontWeight", KnownTypeTable[0x6b]); + KnownPropertyTable[0x20] = new PropertyDeclaration("Foreground", KnownTypeTable[0x6b]); + KnownPropertyTable[0x21] = new PropertyDeclaration("HorizontalContentAlignment", KnownTypeTable[0x6b]); + KnownPropertyTable[0x22] = new PropertyDeclaration("IsTabStop", KnownTypeTable[0x6b]); + KnownPropertyTable[0x23] = new PropertyDeclaration("Padding", KnownTypeTable[0x6b]); + KnownPropertyTable[0x24] = new PropertyDeclaration("TabIndex", KnownTypeTable[0x6b]); + KnownPropertyTable[0x25] = new PropertyDeclaration("Template", KnownTypeTable[0x6b]); + KnownPropertyTable[0x26] = new PropertyDeclaration("VerticalContentAlignment", KnownTypeTable[0x6b]); + KnownPropertyTable[0x27] = new PropertyDeclaration("Dock", KnownTypeTable[0xa3]); + KnownPropertyTable[40] = new PropertyDeclaration("LastChildFill", KnownTypeTable[0xa3]); + KnownPropertyTable[0x29] = new PropertyDeclaration("Document", KnownTypeTable[0xa7]); + KnownPropertyTable[0x2a] = new PropertyDeclaration("Children", KnownTypeTable[0xb7]); + KnownPropertyTable[0x2b] = new PropertyDeclaration("Document", KnownTypeTable[0xd3]); + KnownPropertyTable[0x2c] = new PropertyDeclaration("Document", KnownTypeTable[0xd4]); + KnownPropertyTable[0x2d] = new PropertyDeclaration("Style", KnownTypeTable[0xe1]); + KnownPropertyTable[0x2e] = new PropertyDeclaration("FlowDirection", KnownTypeTable[0xe2]); + KnownPropertyTable[0x2f] = new PropertyDeclaration("Height", KnownTypeTable[0xe2]); + KnownPropertyTable[0x30] = new PropertyDeclaration("HorizontalAlignment", KnownTypeTable[0xe2]); + KnownPropertyTable[0x31] = new PropertyDeclaration("Margin", KnownTypeTable[0xe2]); + KnownPropertyTable[50] = new PropertyDeclaration("MaxHeight", KnownTypeTable[0xe2]); + KnownPropertyTable[0x33] = new PropertyDeclaration("MaxWidth", KnownTypeTable[0xe2]); + KnownPropertyTable[0x34] = new PropertyDeclaration("MinHeight", KnownTypeTable[0xe2]); + KnownPropertyTable[0x35] = new PropertyDeclaration("MinWidth", KnownTypeTable[0xe2]); + KnownPropertyTable[0x36] = new PropertyDeclaration("Name", KnownTypeTable[0xe2]); + KnownPropertyTable[0x37] = new PropertyDeclaration("Style", KnownTypeTable[0xe2]); + KnownPropertyTable[0x38] = new PropertyDeclaration("VerticalAlignment", KnownTypeTable[0xe2]); + KnownPropertyTable[0x39] = new PropertyDeclaration("Width", KnownTypeTable[0xe2]); + KnownPropertyTable[0x3a] = new PropertyDeclaration("Children", KnownTypeTable[0xec]); + KnownPropertyTable[0x3b] = new PropertyDeclaration("Children", KnownTypeTable[0xf2]); + KnownPropertyTable[60] = new PropertyDeclaration("GradientStops", KnownTypeTable[0xfb]); + KnownPropertyTable[0x3d] = new PropertyDeclaration("Column", KnownTypeTable[0xfe]); + KnownPropertyTable[0x3e] = new PropertyDeclaration("ColumnSpan", KnownTypeTable[0xfe]); + KnownPropertyTable[0x3f] = new PropertyDeclaration("Row", KnownTypeTable[0xfe]); + KnownPropertyTable[0x40] = new PropertyDeclaration("RowSpan", KnownTypeTable[0xfe]); + KnownPropertyTable[0x41] = new PropertyDeclaration("Header", KnownTypeTable[0x103]); + KnownPropertyTable[0x42] = new PropertyDeclaration("HasHeader", KnownTypeTable[0x10d]); + KnownPropertyTable[0x43] = new PropertyDeclaration("Header", KnownTypeTable[0x10d]); + KnownPropertyTable[0x44] = new PropertyDeclaration("HeaderTemplate", KnownTypeTable[0x10d]); + KnownPropertyTable[0x45] = new PropertyDeclaration("HeaderTemplateSelector", KnownTypeTable[0x10d]); + KnownPropertyTable[70] = new PropertyDeclaration("HasHeader", KnownTypeTable[270]); + KnownPropertyTable[0x47] = new PropertyDeclaration("Header", KnownTypeTable[270]); + KnownPropertyTable[0x48] = new PropertyDeclaration("HeaderTemplate", KnownTypeTable[270]); + KnownPropertyTable[0x49] = new PropertyDeclaration("HeaderTemplateSelector", KnownTypeTable[270]); + KnownPropertyTable[0x4a] = new PropertyDeclaration("NavigateUri", KnownTypeTable[0x111]); + KnownPropertyTable[0x4b] = new PropertyDeclaration("Source", KnownTypeTable[0x119]); + KnownPropertyTable[0x4c] = new PropertyDeclaration("Stretch", KnownTypeTable[0x119]); + KnownPropertyTable[0x4d] = new PropertyDeclaration("ItemContainerStyle", KnownTypeTable[0x149]); + KnownPropertyTable[0x4e] = new PropertyDeclaration("ItemContainerStyleSelector", KnownTypeTable[0x149]); + KnownPropertyTable[0x4f] = new PropertyDeclaration("ItemTemplate", KnownTypeTable[0x149]); + KnownPropertyTable[80] = new PropertyDeclaration("ItemTemplateSelector", KnownTypeTable[0x149]); + KnownPropertyTable[0x51] = new PropertyDeclaration("ItemsPanel", KnownTypeTable[0x149]); + KnownPropertyTable[0x52] = new PropertyDeclaration("ItemsSource", KnownTypeTable[0x149]); + KnownPropertyTable[0x53] = new PropertyDeclaration("Children", KnownTypeTable[0x180]); + KnownPropertyTable[0x54] = new PropertyDeclaration("Children", KnownTypeTable[0x198]); + KnownPropertyTable[0x55] = new PropertyDeclaration("Content", KnownTypeTable[0x1b2]); + KnownPropertyTable[0x56] = new PropertyDeclaration("Background", KnownTypeTable[0x1b5]); + KnownPropertyTable[0x57] = new PropertyDeclaration("Data", KnownTypeTable[0x1ba]); + KnownPropertyTable[0x58] = new PropertyDeclaration("Segments", KnownTypeTable[0x1bb]); + KnownPropertyTable[0x59] = new PropertyDeclaration("Figures", KnownTypeTable[0x1be]); + KnownPropertyTable[90] = new PropertyDeclaration("Child", KnownTypeTable[0x1e5]); + KnownPropertyTable[0x5b] = new PropertyDeclaration("IsOpen", KnownTypeTable[0x1e5]); + KnownPropertyTable[0x5c] = new PropertyDeclaration("Placement", KnownTypeTable[0x1e5]); + KnownPropertyTable[0x5d] = new PropertyDeclaration("PopupAnimation", KnownTypeTable[0x1e5]); + KnownPropertyTable[0x5e] = new PropertyDeclaration("Height", KnownTypeTable[0x21d]); + KnownPropertyTable[0x5f] = new PropertyDeclaration("MaxHeight", KnownTypeTable[0x21d]); + KnownPropertyTable[0x60] = new PropertyDeclaration("MinHeight", KnownTypeTable[0x21d]); + KnownPropertyTable[0x61] = new PropertyDeclaration("CanContentScroll", KnownTypeTable[550]); + KnownPropertyTable[0x62] = new PropertyDeclaration("HorizontalScrollBarVisibility", KnownTypeTable[550]); + KnownPropertyTable[0x63] = new PropertyDeclaration("VerticalScrollBarVisibility", KnownTypeTable[550]); + KnownPropertyTable[100] = new PropertyDeclaration("Fill", KnownTypeTable[0x22e]); + KnownPropertyTable[0x65] = new PropertyDeclaration("Stroke", KnownTypeTable[0x22e]); + KnownPropertyTable[0x66] = new PropertyDeclaration("StrokeThickness", KnownTypeTable[0x22e]); + KnownPropertyTable[0x67] = new PropertyDeclaration("Background", KnownTypeTable[0x27e]); + KnownPropertyTable[0x68] = new PropertyDeclaration("FontFamily", KnownTypeTable[0x27e]); + KnownPropertyTable[0x69] = new PropertyDeclaration("FontSize", KnownTypeTable[0x27e]); + KnownPropertyTable[0x6a] = new PropertyDeclaration("FontStretch", KnownTypeTable[0x27e]); + KnownPropertyTable[0x6b] = new PropertyDeclaration("FontStyle", KnownTypeTable[0x27e]); + KnownPropertyTable[0x6c] = new PropertyDeclaration("FontWeight", KnownTypeTable[0x27e]); + KnownPropertyTable[0x6d] = new PropertyDeclaration("Foreground", KnownTypeTable[0x27e]); + KnownPropertyTable[110] = new PropertyDeclaration("Text", KnownTypeTable[0x27e]); + KnownPropertyTable[0x6f] = new PropertyDeclaration("TextDecorations", KnownTypeTable[0x27e]); + KnownPropertyTable[0x70] = new PropertyDeclaration("TextTrimming", KnownTypeTable[0x27e]); + KnownPropertyTable[0x71] = new PropertyDeclaration("TextWrapping", KnownTypeTable[0x27e]); + KnownPropertyTable[0x72] = new PropertyDeclaration("Text", KnownTypeTable[0x27f]); + KnownPropertyTable[0x73] = new PropertyDeclaration("Background", KnownTypeTable[0x288]); + KnownPropertyTable[0x74] = new PropertyDeclaration("FontFamily", KnownTypeTable[0x288]); + KnownPropertyTable[0x75] = new PropertyDeclaration("FontSize", KnownTypeTable[0x288]); + KnownPropertyTable[0x76] = new PropertyDeclaration("FontStretch", KnownTypeTable[0x288]); + KnownPropertyTable[0x77] = new PropertyDeclaration("FontStyle", KnownTypeTable[0x288]); + KnownPropertyTable[120] = new PropertyDeclaration("FontWeight", KnownTypeTable[0x288]); + KnownPropertyTable[0x79] = new PropertyDeclaration("Foreground", KnownTypeTable[0x288]); + KnownPropertyTable[0x7a] = new PropertyDeclaration("Children", KnownTypeTable[0x29b]); + KnownPropertyTable[0x7b] = new PropertyDeclaration("IsDirectionReversed", KnownTypeTable[0x2a3]); + KnownPropertyTable[0x7c] = new PropertyDeclaration("Maximum", KnownTypeTable[0x2a3]); + KnownPropertyTable[0x7d] = new PropertyDeclaration("Minimum", KnownTypeTable[0x2a3]); + KnownPropertyTable[0x7e] = new PropertyDeclaration("Orientation", KnownTypeTable[0x2a3]); + KnownPropertyTable[0x7f] = new PropertyDeclaration("Value", KnownTypeTable[0x2a3]); + KnownPropertyTable[0x80] = new PropertyDeclaration("ViewportSize", KnownTypeTable[0x2a3]); + KnownPropertyTable[0x81] = new PropertyDeclaration("Children", KnownTypeTable[0x2a7]); + KnownPropertyTable[130] = new PropertyDeclaration("Children", KnownTypeTable[0x2aa]); + KnownPropertyTable[0x83] = new PropertyDeclaration("ClipToBounds", KnownTypeTable[0x2b6]); + KnownPropertyTable[0x84] = new PropertyDeclaration("Focusable", KnownTypeTable[0x2b6]); + KnownPropertyTable[0x85] = new PropertyDeclaration("IsEnabled", KnownTypeTable[0x2b6]); + KnownPropertyTable[0x86] = new PropertyDeclaration("RenderTransform", KnownTypeTable[0x2b6]); + KnownPropertyTable[0x87] = new PropertyDeclaration("Visibility", KnownTypeTable[0x2b6]); + KnownPropertyTable[0x88] = new PropertyDeclaration("Children", KnownTypeTable[0x2d9]); + KnownPropertyTable[0x8a] = new PropertyDeclaration("Child", KnownTypeTable[2]); + KnownPropertyTable[0x8b] = new PropertyDeclaration("Child", KnownTypeTable[4]); + KnownPropertyTable[140] = new PropertyDeclaration("Blocks", KnownTypeTable[8]); + KnownPropertyTable[0x8d] = new PropertyDeclaration("Items", KnownTypeTable[14]); + KnownPropertyTable[0x8e] = new PropertyDeclaration("Child", KnownTypeTable[0x25]); + KnownPropertyTable[0x8f] = new PropertyDeclaration("Inlines", KnownTypeTable[0x29]); + KnownPropertyTable[0x90] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x2d]); + KnownPropertyTable[0x91] = new PropertyDeclaration("Child", KnownTypeTable[50]); + KnownPropertyTable[0x92] = new PropertyDeclaration("Child", KnownTypeTable[0x36]); + KnownPropertyTable[0x93] = new PropertyDeclaration("Content", KnownTypeTable[0x37]); + KnownPropertyTable[0x94] = new PropertyDeclaration("Content", KnownTypeTable[0x38]); + KnownPropertyTable[0x95] = new PropertyDeclaration("KeyFrames", KnownTypeTable[60]); + KnownPropertyTable[150] = new PropertyDeclaration("Children", KnownTypeTable[0x42]); + KnownPropertyTable[0x97] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x45]); + KnownPropertyTable[0x98] = new PropertyDeclaration("Content", KnownTypeTable[0x4a]); + KnownPropertyTable[0x99] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x54]); + KnownPropertyTable[0x9a] = new PropertyDeclaration("Items", KnownTypeTable[0x5c]); + KnownPropertyTable[0x9b] = new PropertyDeclaration("Content", KnownTypeTable[0x5d]); + KnownPropertyTable[0x9c] = new PropertyDeclaration("Items", KnownTypeTable[0x69]); + KnownPropertyTable[0x9d] = new PropertyDeclaration("VisualTree", KnownTypeTable[0x6c]); + KnownPropertyTable[0x9e] = new PropertyDeclaration("VisualTree", KnownTypeTable[120]); + KnownPropertyTable[0x9f] = new PropertyDeclaration("Setters", KnownTypeTable[0x7a]); + KnownPropertyTable[160] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x81]); + KnownPropertyTable[0xa1] = new PropertyDeclaration("Child", KnownTypeTable[0x85]); + KnownPropertyTable[0xa2] = new PropertyDeclaration("Children", KnownTypeTable[0xa3]); + KnownPropertyTable[0xa3] = new PropertyDeclaration("Document", KnownTypeTable[0xa6]); + KnownPropertyTable[0xa4] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0xab]); + KnownPropertyTable[0xa5] = new PropertyDeclaration("Actions", KnownTypeTable[0xc6]); + KnownPropertyTable[0xa6] = new PropertyDeclaration("Content", KnownTypeTable[0xc7]); + KnownPropertyTable[0xa7] = new PropertyDeclaration("Blocks", KnownTypeTable[0xca]); + KnownPropertyTable[0xa8] = new PropertyDeclaration("Pages", KnownTypeTable[0xcd]); + KnownPropertyTable[0xa9] = new PropertyDeclaration("References", KnownTypeTable[0xce]); + KnownPropertyTable[170] = new PropertyDeclaration("Children", KnownTypeTable[0xcf]); + KnownPropertyTable[0xab] = new PropertyDeclaration("Blocks", KnownTypeTable[0xd0]); + KnownPropertyTable[0xac] = new PropertyDeclaration("Blocks", KnownTypeTable[0xd1]); + KnownPropertyTable[0xad] = new PropertyDeclaration("Document", KnownTypeTable[210]); + KnownPropertyTable[0xae] = new PropertyDeclaration("VisualTree", KnownTypeTable[0xe7]); + KnownPropertyTable[0xaf] = new PropertyDeclaration("Children", KnownTypeTable[0xfe]); + KnownPropertyTable[0xb0] = new PropertyDeclaration("Columns", KnownTypeTable[0x102]); + KnownPropertyTable[0xb1] = new PropertyDeclaration("Content", KnownTypeTable[260]); + KnownPropertyTable[0xb2] = new PropertyDeclaration("Content", KnownTypeTable[0x108]); + KnownPropertyTable[0xb3] = new PropertyDeclaration("Content", KnownTypeTable[0x109]); + KnownPropertyTable[180] = new PropertyDeclaration("Content", KnownTypeTable[0x10d]); + KnownPropertyTable[0xb5] = new PropertyDeclaration("Items", KnownTypeTable[270]); + KnownPropertyTable[0xb6] = new PropertyDeclaration("VisualTree", KnownTypeTable[0x10f]); + KnownPropertyTable[0xb7] = new PropertyDeclaration("Inlines", KnownTypeTable[0x111]); + KnownPropertyTable[0xb8] = new PropertyDeclaration("Children", KnownTypeTable[0x120]); + KnownPropertyTable[0xb9] = new PropertyDeclaration("Child", KnownTypeTable[0x121]); + KnownPropertyTable[0xba] = new PropertyDeclaration("Child", KnownTypeTable[0x124]); + KnownPropertyTable[0xbb] = new PropertyDeclaration("NameValue", KnownTypeTable[300]); + KnownPropertyTable[0xbc] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x131]); + KnownPropertyTable[0xbd] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x138]); + KnownPropertyTable[190] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x143]); + KnownPropertyTable[0xbf] = new PropertyDeclaration("Inlines", KnownTypeTable[0x147]); + KnownPropertyTable[0xc0] = new PropertyDeclaration("Items", KnownTypeTable[0x149]); + KnownPropertyTable[0xc1] = new PropertyDeclaration("VisualTree", KnownTypeTable[330]); + KnownPropertyTable[0xc2] = new PropertyDeclaration("Content", KnownTypeTable[0x15a]); + KnownPropertyTable[0xc3] = new PropertyDeclaration("GradientStops", KnownTypeTable[0x166]); + KnownPropertyTable[0xc4] = new PropertyDeclaration("ListItems", KnownTypeTable[0x174]); + KnownPropertyTable[0xc5] = new PropertyDeclaration("Items", KnownTypeTable[0x175]); + KnownPropertyTable[0xc6] = new PropertyDeclaration("Content", KnownTypeTable[0x176]); + KnownPropertyTable[0xc7] = new PropertyDeclaration("Blocks", KnownTypeTable[0x178]); + KnownPropertyTable[200] = new PropertyDeclaration("Items", KnownTypeTable[0x179]); + KnownPropertyTable[0xc9] = new PropertyDeclaration("Content", KnownTypeTable[0x17a]); + KnownPropertyTable[0xca] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x185]); + KnownPropertyTable[0xcb] = new PropertyDeclaration("Items", KnownTypeTable[0x191]); + KnownPropertyTable[0xcc] = new PropertyDeclaration("Items", KnownTypeTable[0x192]); + KnownPropertyTable[0xcd] = new PropertyDeclaration("Items", KnownTypeTable[0x193]); + KnownPropertyTable[0xce] = new PropertyDeclaration("Children", KnownTypeTable[0x199]); + KnownPropertyTable[0xcf] = new PropertyDeclaration("Bindings", KnownTypeTable[0x1a0]); + KnownPropertyTable[0xd0] = new PropertyDeclaration("Setters", KnownTypeTable[0x1a2]); + KnownPropertyTable[0xd1] = new PropertyDeclaration("Setters", KnownTypeTable[0x1a3]); + KnownPropertyTable[210] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x1ac]); + KnownPropertyTable[0xd3] = new PropertyDeclaration("Child", KnownTypeTable[0x1b3]); + KnownPropertyTable[0xd4] = new PropertyDeclaration("Content", KnownTypeTable[0x1b4]); + KnownPropertyTable[0xd5] = new PropertyDeclaration("Children", KnownTypeTable[0x1b5]); + KnownPropertyTable[0xd6] = new PropertyDeclaration("Inlines", KnownTypeTable[0x1b6]); + KnownPropertyTable[0xd7] = new PropertyDeclaration("Children", KnownTypeTable[0x1b7]); + KnownPropertyTable[0xd8] = new PropertyDeclaration("KeyFrames", KnownTypeTable[460]); + KnownPropertyTable[0xd9] = new PropertyDeclaration("KeyFrames", KnownTypeTable[470]); + KnownPropertyTable[0xda] = new PropertyDeclaration("Bindings", KnownTypeTable[0x1e7]); + KnownPropertyTable[0xdb] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x1f1]); + KnownPropertyTable[220] = new PropertyDeclaration("GradientStops", KnownTypeTable[0x1f6]); + KnownPropertyTable[0xdd] = new PropertyDeclaration("Content", KnownTypeTable[0x1f7]); + KnownPropertyTable[0xde] = new PropertyDeclaration("KeyFrames", KnownTypeTable[510]); + KnownPropertyTable[0xdf] = new PropertyDeclaration("Content", KnownTypeTable[0x20a]); + KnownPropertyTable[0xe0] = new PropertyDeclaration("Document", KnownTypeTable[0x20f]); + KnownPropertyTable[0xe1] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x215]); + KnownPropertyTable[0xe2] = new PropertyDeclaration("Text", KnownTypeTable[0x21e]); + KnownPropertyTable[0xe3] = new PropertyDeclaration("Content", KnownTypeTable[550]); + KnownPropertyTable[0xe4] = new PropertyDeclaration("Blocks", KnownTypeTable[0x227]); + KnownPropertyTable[0xe5] = new PropertyDeclaration("Items", KnownTypeTable[0x229]); + KnownPropertyTable[230] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x232]); + KnownPropertyTable[0xe7] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x23b]); + KnownPropertyTable[0xe8] = new PropertyDeclaration("Inlines", KnownTypeTable[580]); + KnownPropertyTable[0xe9] = new PropertyDeclaration("Children", KnownTypeTable[0x259]); + KnownPropertyTable[0xea] = new PropertyDeclaration("Items", KnownTypeTable[0x25c]); + KnownPropertyTable[0xeb] = new PropertyDeclaration("Content", KnownTypeTable[0x25d]); + KnownPropertyTable[0xec] = new PropertyDeclaration("Children", KnownTypeTable[0x260]); + KnownPropertyTable[0xed] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x266]); + KnownPropertyTable[0xee] = new PropertyDeclaration("Setters", KnownTypeTable[620]); + KnownPropertyTable[0xef] = new PropertyDeclaration("Items", KnownTypeTable[0x26f]); + KnownPropertyTable[240] = new PropertyDeclaration("Content", KnownTypeTable[0x270]); + KnownPropertyTable[0xf1] = new PropertyDeclaration("Children", KnownTypeTable[0x271]); + KnownPropertyTable[0xf2] = new PropertyDeclaration("RowGroups", KnownTypeTable[0x272]); + KnownPropertyTable[0xf3] = new PropertyDeclaration("Blocks", KnownTypeTable[0x273]); + KnownPropertyTable[0xf4] = new PropertyDeclaration("Cells", KnownTypeTable[0x275]); + KnownPropertyTable[0xf5] = new PropertyDeclaration("Rows", KnownTypeTable[630]); + KnownPropertyTable[0xf6] = new PropertyDeclaration("Inlines", KnownTypeTable[0x27e]); + KnownPropertyTable[0xf7] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x28e]); + KnownPropertyTable[0xf8] = new PropertyDeclaration("Content", KnownTypeTable[0x29c]); + KnownPropertyTable[0xf9] = new PropertyDeclaration("Items", KnownTypeTable[0x29d]); + KnownPropertyTable[250] = new PropertyDeclaration("Children", KnownTypeTable[670]); + KnownPropertyTable[0xfb] = new PropertyDeclaration("Children", KnownTypeTable[0x29f]); + KnownPropertyTable[0xfc] = new PropertyDeclaration("ToolBars", KnownTypeTable[0x2a0]); + KnownPropertyTable[0xfd] = new PropertyDeclaration("Content", KnownTypeTable[0x2a1]); + KnownPropertyTable[0xfe] = new PropertyDeclaration("Items", KnownTypeTable[0x2ae]); + KnownPropertyTable[0xff] = new PropertyDeclaration("Items", KnownTypeTable[0x2af]); + KnownPropertyTable[0x100] = new PropertyDeclaration("Setters", KnownTypeTable[0x2b0]); + KnownPropertyTable[0x101] = new PropertyDeclaration("Inlines", KnownTypeTable[0x2be]); + KnownPropertyTable[0x102] = new PropertyDeclaration("Children", KnownTypeTable[0x2bf]); + KnownPropertyTable[0x103] = new PropertyDeclaration("Content", KnownTypeTable[0x2c2]); + KnownPropertyTable[260] = new PropertyDeclaration("KeyFrames", KnownTypeTable[0x2c8]); + KnownPropertyTable[0x105] = new PropertyDeclaration("KeyFrames", KnownTypeTable[720]); + KnownPropertyTable[0x106] = new PropertyDeclaration("Child", KnownTypeTable[0x2d8]); + KnownPropertyTable[0x107] = new PropertyDeclaration("Children", KnownTypeTable[730]); + KnownPropertyTable[0x108] = new PropertyDeclaration("Children", KnownTypeTable[0x2db]); + KnownPropertyTable[0x109] = new PropertyDeclaration("Children", KnownTypeTable[0x2dc]); + KnownPropertyTable[0x10a] = new PropertyDeclaration("Content", KnownTypeTable[0x2e3]); + KnownPropertyTable[0x10b] = new PropertyDeclaration("Children", KnownTypeTable[0x2e6]); + KnownPropertyTable[0x10c] = new PropertyDeclaration("XmlSerializer", KnownTypeTable[0x2f2]); + KnownResourceTable.Add(1, new ResourceName("SystemColors.ActiveBorderBrush")); + KnownResourceTable.Add(0x1f, new ResourceName("SystemColors.ActiveBorderColor")); + KnownResourceTable.Add(2, new ResourceName("SystemColors.ActiveCaptionBrush")); + KnownResourceTable.Add(0x20, new ResourceName("SystemColors.ActiveCaptionColor")); + KnownResourceTable.Add(3, new ResourceName("SystemColors.ActiveCaptionTextBrush")); + KnownResourceTable.Add(0x21, new ResourceName("SystemColors.ActiveCaptionTextColor")); + KnownResourceTable.Add(4, new ResourceName("SystemColors.AppWorkspaceBrush")); + KnownResourceTable.Add(0x22, new ResourceName("SystemParameters.AppWorkspaceColor")); + KnownResourceTable.Add(0xc6, new ResourceName("SystemParameters.Border")); + KnownResourceTable.Add(0xca, new ResourceName("SystemParameters.BorderWidth")); + KnownResourceTable.Add(0x40, new ResourceName("SystemFonts.CaptionFontFamily")); + KnownResourceTable.Add(0x3f, new ResourceName("SystemFonts.CaptionFontSize")); + KnownResourceTable.Add(0x41, new ResourceName("SystemFonts.CaptionFontStyle")); + KnownResourceTable.Add(0x43, new ResourceName("SystemFonts.CaptionFontTextDecorations")); + KnownResourceTable.Add(0x42, new ResourceName("SystemFonts.CaptionFontWeight")); + KnownResourceTable.Add(0xce, new ResourceName("SystemParameters.CaptionHeight")); + KnownResourceTable.Add(0xcd, new ResourceName("SystemParameters.CaptionWidth")); + KnownResourceTable.Add(0xc7, new ResourceName("SystemParameters.CaretWidth")); + KnownResourceTable.Add(0xba, new ResourceName("SystemParameters.ClientAreaAnimation")); + KnownResourceTable.Add(0xb9, new ResourceName("SystemParameters.ComboBoxAnimation")); + KnownResourceTable.Add(210, new ResourceName("SystemParameters.ComboBoxPopupAnimation")); + KnownResourceTable.Add(5, new ResourceName("SystemColors.ControlBrush")); + KnownResourceTable.Add(0x23, new ResourceName("SystemColors.ControlColor")); + KnownResourceTable.Add(6, new ResourceName("SystemColors.ControlDarkBrush")); + KnownResourceTable.Add(0x24, new ResourceName("SystemColors.ControlDarkColor")); + KnownResourceTable.Add(7, new ResourceName("SystemColors.ControlDarkDarkBrush")); + KnownResourceTable.Add(0x25, new ResourceName("SystemColors.ControlDarkDarkColor")); + KnownResourceTable.Add(8, new ResourceName("SystemColors.ControlLightBrush")); + KnownResourceTable.Add(0x26, new ResourceName("SystemColors.ControlLightColor")); + KnownResourceTable.Add(9, new ResourceName("SystemColors.ControlLightLightBrush")); + KnownResourceTable.Add(0x27, new ResourceName("SystemColors.ControlLightLightColor")); + KnownResourceTable.Add(10, new ResourceName("SystemColors.ControlTextBrush")); + KnownResourceTable.Add(40, new ResourceName("SystemColors.ControlTextColor")); + KnownResourceTable.Add(0x62, new ResourceName("SystemParameters.CursorHeight")); + KnownResourceTable.Add(0xbb, new ResourceName("SystemParameters.CursorShadow")); + KnownResourceTable.Add(0x61, new ResourceName("SystemParameters.CursorWidth")); + KnownResourceTable.Add(11, new ResourceName("SystemColors.DesktopBrush")); + KnownResourceTable.Add(0x29, new ResourceName("SystemColors.DesktopColor")); + KnownResourceTable.Add(0xc9, new ResourceName("SystemParameters.DragFullWindows")); + KnownResourceTable.Add(0xa7, new ResourceName("SystemParameters.DropShadow")); + KnownResourceTable.Add(0x65, new ResourceName("SystemParameters.FixedFrameHorizontalBorderHeight")); + KnownResourceTable.Add(0x66, new ResourceName("SystemParameters.FixedFrameVerticalBorderWidth")); + KnownResourceTable.Add(0xa8, new ResourceName("SystemParameters.FlatMenu")); + KnownResourceTable.Add(0xa5, new ResourceName("SystemParameters.FocusBorderHeight")); + KnownResourceTable.Add(0xa4, new ResourceName("SystemParameters.FocusBorderWidth")); + KnownResourceTable.Add(0x67, new ResourceName("SystemParameters.FocusHorizontalBorderHeight")); + KnownResourceTable.Add(0x68, new ResourceName("SystemParameters.FocusVerticalBorderWidth")); + KnownResourceTable.Add(0xd7, new ResourceName("SystemParameters.FocusVisualStyle")); + KnownResourceTable.Add(200, new ResourceName("SystemParameters.ForegroundFlashCount")); + KnownResourceTable.Add(0x6a, new ResourceName("SystemParameters.FullPrimaryScreenHeight")); + KnownResourceTable.Add(0x69, new ResourceName("SystemParameters.FullPrimaryScreenWidth")); + KnownResourceTable.Add(12, new ResourceName("SystemColors.GradientActiveCaptionBrush")); + KnownResourceTable.Add(0x2a, new ResourceName("SystemColors.GradientActiveCaptionColor")); + KnownResourceTable.Add(0xbc, new ResourceName("SystemColors.GradientCaptions")); + KnownResourceTable.Add(13, new ResourceName("SystemColors.GradientInactiveCaptionBrush")); + KnownResourceTable.Add(0x2b, new ResourceName("SystemColors.GradientInactiveCaptionColor")); + KnownResourceTable.Add(14, new ResourceName("SystemColors.GrayTextBrush")); + KnownResourceTable.Add(0x2c, new ResourceName("SystemColors.GrayTextColor")); + KnownResourceTable.Add(0xde, new ResourceName("GridView.GridViewItemContainerStyle")); + KnownResourceTable.Add(220, new ResourceName("GridView.GridViewScrollViewerStyle")); + KnownResourceTable.Add(0xdd, new ResourceName("GridView.GridViewStyle")); + KnownResourceTable.Add(0xa6, new ResourceName("SystemParameters.HighContrast")); + KnownResourceTable.Add(15, new ResourceName("SystemColors.HighlightBrush")); + KnownResourceTable.Add(0x2d, new ResourceName("SystemColors.HighlightColor")); + KnownResourceTable.Add(0x10, new ResourceName("SystemColors.HighlightTextBrush")); + KnownResourceTable.Add(0x2e, new ResourceName("SystemColors.HighlightTextColor")); + KnownResourceTable.Add(0x6b, new ResourceName("SystemParameters.HorizontalScrollBarButtonWidth")); + KnownResourceTable.Add(0x6c, new ResourceName("SystemParameters.HorizontalScrollBarHeight")); + KnownResourceTable.Add(0x6d, new ResourceName("SystemParameters.HorizontalScrollBarThumbWidth")); + KnownResourceTable.Add(0x11, new ResourceName("SystemColors.HotTrackBrush")); + KnownResourceTable.Add(0x2f, new ResourceName("SystemColors.HotTrackColor")); + KnownResourceTable.Add(0xbd, new ResourceName("SystemParameters.HotTracking")); + KnownResourceTable.Add(0x59, new ResourceName("SystemParameters.IconFontFamily")); + KnownResourceTable.Add(0x58, new ResourceName("SystemParameters.IconFontSize")); + KnownResourceTable.Add(90, new ResourceName("SystemParameters.IconFontStyle")); + KnownResourceTable.Add(0x5c, new ResourceName("SystemParameters.IconFontTextDecorations")); + KnownResourceTable.Add(0x5b, new ResourceName("SystemParameters.IconFontWeight")); + KnownResourceTable.Add(0x71, new ResourceName("SystemParameters.IconGridHeight")); + KnownResourceTable.Add(0x70, new ResourceName("SystemParameters.IconGridWidth")); + KnownResourceTable.Add(0x6f, new ResourceName("SystemParameters.IconHeight")); + KnownResourceTable.Add(170, new ResourceName("SystemParameters.IconHorizontalSpacing")); + KnownResourceTable.Add(0xac, new ResourceName("SystemParameters.IconTitleWrap")); + KnownResourceTable.Add(0xab, new ResourceName("SystemParameters.IconVerticalSpacing")); + KnownResourceTable.Add(110, new ResourceName("SystemParameters.IconWidth")); + KnownResourceTable.Add(0x12, new ResourceName("SystemColors.InactiveBorderBrush")); + KnownResourceTable.Add(0x30, new ResourceName("SystemColors.InactiveBorderColor")); + KnownResourceTable.Add(0x13, new ResourceName("SystemColors.InactiveCaptionBrush")); + KnownResourceTable.Add(0x31, new ResourceName("SystemColors.InactiveCaptionColor")); + KnownResourceTable.Add(20, new ResourceName("SystemColors.InactiveCaptionTextBrush")); + KnownResourceTable.Add(50, new ResourceName("SystemColors.InactiveCaptionTextColor")); + KnownResourceTable.Add(0x15, new ResourceName("SystemColors.InfoBrush")); + KnownResourceTable.Add(0x33, new ResourceName("SystemColors.InfoColor")); + KnownResourceTable.Add(0x16, new ResourceName("SystemColors.InfoTextBrush")); + KnownResourceTable.Add(0x34, new ResourceName("SystemColors.InfoTextColor")); + KnownResourceTable.Add(0x3d, new ResourceName("SystemColors.InternalSystemColorsEnd")); + KnownResourceTable.Add(0, new ResourceName("InternalSystemColorsStart")); + KnownResourceTable.Add(0x5d, new ResourceName("InternalSystemFontsEnd")); + KnownResourceTable.Add(0x3e, new ResourceName("InternalSystemFontsStart")); + KnownResourceTable.Add(0xda, new ResourceName("InternalSystemParametersEnd")); + KnownResourceTable.Add(0x5e, new ResourceName("InternalSystemParametersStart")); + KnownResourceTable.Add(0xe8, new ResourceName("InternalSystemThemeStylesEnd")); + KnownResourceTable.Add(0xd6, new ResourceName("InternalSystemThemeStylesStart")); + KnownResourceTable.Add(0x95, new ResourceName("SystemParameters.IsImmEnabled")); + KnownResourceTable.Add(150, new ResourceName("SystemParameters.IsMediaCenter")); + KnownResourceTable.Add(0x97, new ResourceName("SystemParameters.IsMenuDropRightAligned")); + KnownResourceTable.Add(0x98, new ResourceName("SystemParameters.IsMiddleEastEnabled")); + KnownResourceTable.Add(0x99, new ResourceName("SystemParameters.IsMousePresent")); + KnownResourceTable.Add(0x9a, new ResourceName("SystemParameters.IsMouseWheelPresent")); + KnownResourceTable.Add(0x9b, new ResourceName("SystemParameters.IsPenWindows")); + KnownResourceTable.Add(0x9c, new ResourceName("SystemParameters.IsRemotelyControlled")); + KnownResourceTable.Add(0x9d, new ResourceName("SystemParameters.IsRemoteSession")); + KnownResourceTable.Add(0x9f, new ResourceName("SystemParameters.IsSlowMachine")); + KnownResourceTable.Add(0xa1, new ResourceName("SystemParameters.IsTabletPC")); + KnownResourceTable.Add(0x91, new ResourceName("SystemParameters.KanjiWindowHeight")); + KnownResourceTable.Add(0xad, new ResourceName("SystemParameters.KeyboardCues")); + KnownResourceTable.Add(0xae, new ResourceName("SystemParameters.KeyboardDelay")); + KnownResourceTable.Add(0xaf, new ResourceName("SystemParameters.KeyboardPreference")); + KnownResourceTable.Add(0xb0, new ResourceName("SystemParameters.KeyboardSpeed")); + KnownResourceTable.Add(190, new ResourceName("SystemParameters.ListBoxSmoothScrolling")); + KnownResourceTable.Add(0x73, new ResourceName("SystemParameters.MaximizedPrimaryScreenHeight")); + KnownResourceTable.Add(0x72, new ResourceName("SystemParameters.MaximizedPrimaryScreenWidth")); + KnownResourceTable.Add(0x75, new ResourceName("SystemParameters.MaximumWindowTrackHeight")); + KnownResourceTable.Add(0x74, new ResourceName("SystemParameters.MaximumWindowTrackWidth")); + KnownResourceTable.Add(0xbf, new ResourceName("SystemParameters.MenuAnimation")); + KnownResourceTable.Add(0x18, new ResourceName("SystemColors.MenuBarBrush")); + KnownResourceTable.Add(0x36, new ResourceName("SystemColors.MenuBarColor")); + KnownResourceTable.Add(0x92, new ResourceName("SystemParameters.MenuBarHeight")); + KnownResourceTable.Add(0x17, new ResourceName("SystemColors.MenuBrush")); + KnownResourceTable.Add(0x79, new ResourceName("SystemParameters.MenuButtonHeight")); + KnownResourceTable.Add(120, new ResourceName("SystemParameters.MenuButtonWidth")); + KnownResourceTable.Add(0x77, new ResourceName("SystemParameters.MenuCheckmarkHeight")); + KnownResourceTable.Add(0x76, new ResourceName("SystemParameters.MenuCheckmarkWidth")); + KnownResourceTable.Add(0x35, new ResourceName("SystemColors.MenuColor")); + KnownResourceTable.Add(0xb6, new ResourceName("SystemParameters.MenuDropAlignment")); + KnownResourceTable.Add(0xb7, new ResourceName("SystemParameters.MenuFade")); + KnownResourceTable.Add(0x4a, new ResourceName("SystemFonts.MenuFontFamily")); + KnownResourceTable.Add(0x49, new ResourceName("SystemFonts.MenuFontSize")); + KnownResourceTable.Add(0x4b, new ResourceName("SystemFonts.MenuFontStyle")); + KnownResourceTable.Add(0x4d, new ResourceName("SystemFonts.MenuFontTextDecorations")); + KnownResourceTable.Add(0x4c, new ResourceName("SystemFonts.MenuFontWeight")); + KnownResourceTable.Add(0xd1, new ResourceName("SystemParameters.MenuHeight")); + KnownResourceTable.Add(0x19, new ResourceName("SystemColors.MenuHighlightBrush")); + KnownResourceTable.Add(0x37, new ResourceName("SystemColors.MenuHighlightColor")); + KnownResourceTable.Add(0xdb, new ResourceName("MenuItem.MenuItemSeparatorStyle")); + KnownResourceTable.Add(0xd3, new ResourceName("SystemParameters.MenuPopupAnimation")); + KnownResourceTable.Add(0xb8, new ResourceName("SystemParameters.MenuShowDelay")); + KnownResourceTable.Add(0x1a, new ResourceName("SystemColors.MenuTextBrush")); + KnownResourceTable.Add(0x38, new ResourceName("SystemColors.MenuTextColor")); + KnownResourceTable.Add(0xd0, new ResourceName("SystemParameters.MenuWidth")); + KnownResourceTable.Add(0x54, new ResourceName("SystemFonts.MessageFontFamily")); + KnownResourceTable.Add(0x53, new ResourceName("SystemFonts..MessageFontSize")); + KnownResourceTable.Add(0x55, new ResourceName("SystemFonts.MessageFontStyle")); + KnownResourceTable.Add(0x57, new ResourceName("SystemFonts.MessageFontTextDecorations")); + KnownResourceTable.Add(0x56, new ResourceName("SystemFonts.MessageFontWeight")); + KnownResourceTable.Add(0xc5, new ResourceName("SystemParameters.MinimizeAnimation")); + KnownResourceTable.Add(0x7f, new ResourceName("SystemParameters.MinimizedGridHeight")); + KnownResourceTable.Add(0x7e, new ResourceName("SystemParameters.MinimizedGridWidth")); + KnownResourceTable.Add(0x7d, new ResourceName("SystemParameters.MinimizedWindowHeight")); + KnownResourceTable.Add(0x7c, new ResourceName("SystemParameters.MinimizedWindowWidth")); + KnownResourceTable.Add(0x7b, new ResourceName("SystemParameters.MinimumWindowHeight")); + KnownResourceTable.Add(0x81, new ResourceName("SystemParameters.MinimumWindowTrackHeight")); + KnownResourceTable.Add(0x80, new ResourceName("SystemParameters.MinimumWindowTrackWidth")); + KnownResourceTable.Add(0x7a, new ResourceName("SystemParameters.MinimumWindowWidth")); + KnownResourceTable.Add(180, new ResourceName("SystemParameters.MouseHoverHeight")); + KnownResourceTable.Add(0xb3, new ResourceName("SystemParameters.MouseHoverTime")); + KnownResourceTable.Add(0xb5, new ResourceName("SystemParameters.MouseHoverWidth")); + KnownResourceTable.Add(0xd8, new ResourceName("SystemParameters.NavigationChromeDownLevelStyle")); + KnownResourceTable.Add(0xd9, new ResourceName("SystemParameters.NavigationChromeStyle")); + KnownResourceTable.Add(0xd5, new ResourceName("SystemParameters.PowerLineStatus")); + KnownResourceTable.Add(0x83, new ResourceName("SystemParameters.PrimaryScreenHeight")); + KnownResourceTable.Add(130, new ResourceName("SystemParameters.PrimaryScreenWidth")); + KnownResourceTable.Add(0x86, new ResourceName("SystemParameters.ResizeFrameHorizontalBorderHeight")); + KnownResourceTable.Add(0x87, new ResourceName("SystemParameters.ResizeFrameVerticalBorderWidth")); + KnownResourceTable.Add(0x1b, new ResourceName("SystemColors.ScrollBarBrush")); + KnownResourceTable.Add(0x39, new ResourceName("SystemColors.ScrollBarColor")); + KnownResourceTable.Add(0xcc, new ResourceName("SystemParameters.ScrollHeight")); + KnownResourceTable.Add(0xcb, new ResourceName("SystemParameters.ScrollWidth")); + KnownResourceTable.Add(0xc0, new ResourceName("SystemParameters.SelectionFade")); + KnownResourceTable.Add(0x9e, new ResourceName("SystemParameters.ShowSounds")); + KnownResourceTable.Add(0x45, new ResourceName("SystemFonts.SmallCaptionFontFamily")); + KnownResourceTable.Add(0x44, new ResourceName("SystemFonts.SmallCaptionFontSize")); + KnownResourceTable.Add(70, new ResourceName("SystemFonts.SmallCaptionFontStyle")); + KnownResourceTable.Add(0x48, new ResourceName("SystemFonts.SmallCaptionFontTextDecorations")); + KnownResourceTable.Add(0x47, new ResourceName("SystemFonts.SmallCaptionFontWeight")); + KnownResourceTable.Add(0x93, new ResourceName("SystemParameters.SmallCaptionHeight")); + KnownResourceTable.Add(0xcf, new ResourceName("SystemParameters.SmallCaptionWidth")); + KnownResourceTable.Add(0x89, new ResourceName("SystemParameters.SmallIconHeight")); + KnownResourceTable.Add(0x88, new ResourceName("SystemParameters.SmallIconWidth")); + KnownResourceTable.Add(0x8b, new ResourceName("SystemParameters.SmallWindowCaptionButtonHeight")); + KnownResourceTable.Add(0x8a, new ResourceName("SystemParameters.SmallWindowCaptionButtonWidth")); + KnownResourceTable.Add(0xb1, new ResourceName("SystemParameters.SnapToDefaultButton")); + KnownResourceTable.Add(0xdf, new ResourceName("StatusBar.StatusBarSeparatorStyle")); + KnownResourceTable.Add(0x4f, new ResourceName("SystemFonts.StatusFontFamily")); + KnownResourceTable.Add(0x4e, new ResourceName("SystemFonts.StatusFontSize")); + KnownResourceTable.Add(80, new ResourceName("SystemFonts.StatusFontStyle")); + KnownResourceTable.Add(0x52, new ResourceName("SystemFonts.StatusFontTextDecorations")); + KnownResourceTable.Add(0x51, new ResourceName("SystemFonts.StatusFontWeight")); + KnownResourceTable.Add(0xc1, new ResourceName("SystemParameters.StylusHotTracking")); + KnownResourceTable.Add(160, new ResourceName("SystemParameters.SwapButtons")); + KnownResourceTable.Add(0x63, new ResourceName("SystemParameters.ThickHorizontalBorderHeight")); + KnownResourceTable.Add(100, new ResourceName("SystemParameters.ThickVerticalBorderWidth")); + KnownResourceTable.Add(0x5f, new ResourceName("SystemParameters.ThinHorizontalBorderHeight")); + KnownResourceTable.Add(0x60, new ResourceName("SystemParameters.ThinVerticalBorderWidth")); + KnownResourceTable.Add(0xe0, new ResourceName("ToolBar.ButtonStyle")); + KnownResourceTable.Add(0xe3, new ResourceName("ToolBar.CheckBoxStyle")); + KnownResourceTable.Add(0xe5, new ResourceName("ToolBar.ComboBoxStyle")); + KnownResourceTable.Add(0xe7, new ResourceName("ToolBar.MenuStyle")); + KnownResourceTable.Add(0xe4, new ResourceName("ToolBar.RadioButtonStyle")); + KnownResourceTable.Add(0xe2, new ResourceName("ToolBar.SeparatorStyle")); + KnownResourceTable.Add(230, new ResourceName("ToolBar.TextBoxStyle")); + KnownResourceTable.Add(0xe1, new ResourceName("ToolBar.ToggleButtonStyle")); + KnownResourceTable.Add(0xc2, new ResourceName("SystemParameters.ToolTipAnimation")); + KnownResourceTable.Add(0xc3, new ResourceName("SystemParameters.ToolTipFade")); + KnownResourceTable.Add(0xd4, new ResourceName("SystemParameters.ToolTipPopupAnimation")); + KnownResourceTable.Add(0xc4, new ResourceName("SystemParameters.UIEffects")); + KnownResourceTable.Add(0x8f, new ResourceName("SystemParameters.VerticalScrollBarButtonHeight")); + KnownResourceTable.Add(0x94, new ResourceName("SystemParameters.VerticalScrollBarThumbHeight")); + KnownResourceTable.Add(0x8e, new ResourceName("SystemParameters.VerticalScrollBarWidth")); + KnownResourceTable.Add(0x8d, new ResourceName("SystemParameters.VirtualScreenHeight")); + KnownResourceTable.Add(0xa2, new ResourceName("SystemParameters.VirtualScreenLeft")); + KnownResourceTable.Add(0xa3, new ResourceName("SystemParameters.VirtualScreenTop")); + KnownResourceTable.Add(140, new ResourceName("SystemParameters.VirtualScreenWidth")); + KnownResourceTable.Add(0xb2, new ResourceName("SystemParameters.WheelScrollLines")); + KnownResourceTable.Add(0x1c, new ResourceName("SystemColors.WindowBrush")); + KnownResourceTable.Add(0x85, new ResourceName("SystemParameters.WindowCaptionButtonHeight")); + KnownResourceTable.Add(0x84, new ResourceName("SystemParameters.WindowCaptionButtonWidth")); + KnownResourceTable.Add(0x90, new ResourceName("SystemParameters.WindowCaptionHeight")); + KnownResourceTable.Add(0x3a, new ResourceName("SystemColors.WindowColor")); + KnownResourceTable.Add(0x1d, new ResourceName("SystemColors.WindowFrameBrush")); + KnownResourceTable.Add(0x3b, new ResourceName("SystemColors.WindowFrameColor")); + KnownResourceTable.Add(30, new ResourceName("SystemColors.WindowTextBrush")); + KnownResourceTable.Add(60, new ResourceName("SystemColors.WindowTextColor")); + KnownResourceTable.Add(0xa9, new ResourceName("SystemParameters.WorkArea")); + } + + #endregion + + public bool IsKnownType(string type) + { + foreach (TypeDeclaration td in KnownTypeTable) + if (String.CompareOrdinal(td.Name, type) == 0) + return true; + + return false; + } + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/PropertyDeclaration.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/PropertyDeclaration.cs new file mode 100644 index 000000000..fcb7f6ba4 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/PropertyDeclaration.cs @@ -0,0 +1,58 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + internal class PropertyDeclaration + { + private TypeDeclaration declaringType; + private string name; + + // Methods + public PropertyDeclaration(string name) + { + this.name = name; + this.declaringType = null; + } + + public PropertyDeclaration(string name, TypeDeclaration declaringType) + { + this.name = name; + this.declaringType = declaringType; + } + + public override string ToString() + { + if (((this.DeclaringType != null) && (this.DeclaringType.Name == "XmlNamespace")) && ((this.DeclaringType.Namespace == null) && (this.DeclaringType.Assembly == null))) + { + if ((this.Name == null) || (this.Name.Length == 0)) + { + return "xmlns"; + } + return ("xmlns:" + this.Name); + } + return this.Name; + } + + // Properties + public TypeDeclaration DeclaringType + { + get + { + return this.declaringType; + } + } + + public string Name + { + get + { + return this.name; + } + } + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ResourceName.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ResourceName.cs new file mode 100644 index 000000000..a8b0b37d2 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ResourceName.cs @@ -0,0 +1,32 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + public class ResourceName + { + private string name; + + public ResourceName(string name) + { + this.name = name; + } + + public override string ToString() + { + return this.Name; + } + + public string Name + { + get + { + return this.name; + } + } + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs new file mode 100644 index 000000000..2efaab843 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs @@ -0,0 +1,137 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + internal class TypeDeclaration + { + private readonly XmlBamlReader reader; + + private readonly short _assemblyId; + private readonly bool _isKnown; + private readonly string _name; + private readonly string _namespaceName; + private readonly bool _isExtension; + private IType _type; + private bool _typeLoaded; + private readonly ITypeResolver resolver; + + public TypeDeclaration(ITypeResolver resolver, string name, string namespaceName, short assemblyId) + : this(null, resolver, name, namespaceName, assemblyId, true) + { + + } + + public TypeDeclaration(ITypeResolver resolver, string name, string namespaceName, short assemblyId, bool isExtension) + : this(null, resolver, name, namespaceName, assemblyId, true) + { + _isExtension = isExtension; + } + + public TypeDeclaration(XmlBamlReader reader, ITypeResolver resolver, string name, string namespaceName, short assemblyId) + : this(reader, resolver, name, namespaceName, assemblyId, true) + { + } + + public TypeDeclaration(XmlBamlReader reader, ITypeResolver resolver, string name, string namespaceName, short assemblyId, bool isKnown) + { + this.reader = reader; + this.resolver = resolver; + this._name = name; + this._namespaceName = namespaceName; + this._assemblyId = assemblyId; + this._isKnown = isKnown; + + if (!_isExtension) + _isExtension = name.EndsWith("Extension"); + } + + public override string ToString() + { + return this._name; + } + + public bool IsExtension + { + get { return _isExtension; } + } + + public string Assembly + { + get + { + if (reader != null) + return this.reader.GetAssembly(this.AssemblyId); + else + return KnownInfo.KnownAssemblyTable[this.AssemblyId]; + } + } + + public short AssemblyId + { + get { return _assemblyId; } + } + + public string Name + { + get + { + return this._name; + } + } + + public bool IsKnown + { + get { return _isKnown; } + } + + //public Type DotNetType + //{ + // get + // { + // if (!_typeLoaded) + // { + // _type = Type.GetType(String.Format("{0}.{1}, {2}", this.Namespace, this.Name, this.Assembly), false, true); + // _typeLoaded = true; + // } + + // return _type; + // } + //} + + public IType Type + { + get + { + if (!_typeLoaded) + { + if (this.Name.Length > 0) + _type = resolver.GetTypeByAssemblyQualifiedName(String.Format("{0}.{1}, {2}", this.Namespace, this.Name, this.Assembly)); + _typeLoaded = true; + } + + return _type; + } + } + + public string Namespace + { + get + { + return this._namespaceName; + } + } + + public override bool Equals(object obj) + { + TypeDeclaration td = obj as TypeDeclaration; + if (td != null) + return (this.Name == td.Name && this.Namespace == td.Namespace && this.AssemblyId == td.AssemblyId); + else + return false; + } + } + +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/WpfDependencyPropertyDescriptor.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/WpfDependencyPropertyDescriptor.cs new file mode 100644 index 000000000..2ac19f1a5 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/WpfDependencyPropertyDescriptor.cs @@ -0,0 +1,35 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + public class WpfDependencyPropertyDescriptor : MarshalByRefObject, IDependencyPropertyDescriptor + { + private readonly DependencyPropertyDescriptor _propertyDescriptor; + + public WpfDependencyPropertyDescriptor(DependencyPropertyDescriptor propertyDescriptor) + { + if (propertyDescriptor == null) throw new ArgumentNullException("propertyDescriptor"); + _propertyDescriptor = propertyDescriptor; + } + + #region IDependencyPropertyDescriptor Members + + public bool IsAttached + { + get { return _propertyDescriptor.IsAttached; } + } + + #endregion + + public override object InitializeLifetimeService() + { + return null; + } + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs new file mode 100644 index 000000000..393ac5c70 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs @@ -0,0 +1,193 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + internal class XmlBamlElement : XmlBamlNode + { + private ArrayList _arguments = new ArrayList(); + private XmlNamespaceCollection _namespaces = new XmlNamespaceCollection(); + private TypeDeclaration _typeDeclaration; + private KeysResourcesCollection _keysResources = new KeysResourcesCollection(); + private long _position; + + public XmlBamlElement() + { + } + + + public XmlBamlElement(XmlBamlElement parent) + { + this.Namespaces.AddRange(parent.Namespaces); + } + + public XmlNamespaceCollection Namespaces + { + get { return _namespaces; } + } + + public TypeDeclaration TypeDeclaration + { + get + { + return this._typeDeclaration; + } + set + { + this._typeDeclaration = value; + } + } + + public override XmlNodeType NodeType + { + get + { + return XmlNodeType.Element; + } + } + + public long Position + { + get { return _position; } + set { _position = value; } + } + + public override string ToString() + { + return String.Format("Element: {0}", TypeDeclaration.Name); + } + } + + internal class XmlBamlEndElement : XmlBamlElement + { + public XmlBamlEndElement(XmlBamlElement start) + { + this.TypeDeclaration = start.TypeDeclaration; + this.Namespaces.AddRange(start.Namespaces); + } + + public override XmlNodeType NodeType + { + get + { + return XmlNodeType.EndElement; + } + } + + public override string ToString() + { + return String.Format("EndElement: {0}", TypeDeclaration.Name); + } + } + + internal class KeyMapping + { + private string _key; + private TypeDeclaration _declaration; + private string _trueKey; + + public KeyMapping(string key, TypeDeclaration declaration, string trueKey) + { + _key = key; + _declaration = declaration; + _trueKey = trueKey; + } + + public string Key + { + get { return _key; } + } + + public TypeDeclaration Declaration + { + get { return _declaration; } + } + + public string TrueKey + { + get { return _trueKey; } + } + + public override string ToString() + { + return String.Format("{0} - {1} - {2}", Key, Declaration, TrueKey); + } + } + + internal class KeysResourcesCollection : List + { + public KeysResource Last + { + get + { + if (this.Count == 0) + return null; + return this[this.Count - 1]; + } + } + + public KeysResource First + { + get + { + if (this.Count == 0) + return null; + return this[0]; + } + } + } + + internal class KeysResource + { + private KeysTable _keys = new KeysTable(); + private ArrayList _staticResources = new ArrayList(); + + public KeysTable Keys + { + get { return _keys; } + } + + public ArrayList StaticResources + { + get { return _staticResources; } + } + } + + internal class KeysTable + { + private Hashtable table = new Hashtable(); + + public String this[long position] + { + get + { + return (string)this.table[position]; + } + set + { + this.table[position] = value; + } + } + + public int Count + { + get { return this.table.Count; } + } + + public void Remove(long position) + { + this.table.Remove(position); + } + + public bool HasKey(long position) + { + return this.table.ContainsKey(position); + } + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlNode.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlNode.cs new file mode 100644 index 000000000..1f27846b8 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlNode.cs @@ -0,0 +1,21 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + internal class XmlBamlNode + { + public virtual XmlNodeType NodeType + { + get { return XmlNodeType.None;} + } + } + + internal class XmlBamlNodeCollection : List + {} +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlProperty.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlProperty.cs new file mode 100644 index 000000000..2da34dd90 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlProperty.cs @@ -0,0 +1,86 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + internal class XmlBamlProperty : XmlBamlNode + { + private PropertyDeclaration propertyDeclaration; + private PropertyType propertyType; + private object value; + + public XmlBamlProperty(PropertyType propertyType) + { + this.propertyType = propertyType; + } + + public XmlBamlProperty(PropertyType propertyType, PropertyDeclaration propertyDeclaration) + { + this.propertyDeclaration = propertyDeclaration; + this.propertyType = propertyType; + } + + public override string ToString() + { + return this.PropertyDeclaration.Name; + } + + public PropertyDeclaration PropertyDeclaration + { + get + { + return this.propertyDeclaration; + } + set + { + this.propertyDeclaration = value; + } + } + + public PropertyType PropertyType + { + get + { + return this.propertyType; + } + } + + public object Value + { + get + { + return this.value; + } + set + { + this.value = value; + } + } + + public override XmlNodeType NodeType + { + get + { + return XmlNodeType.Attribute; + } + } + } + + internal enum PropertyType + { + Key, + Value, + Content, + List, + Dictionary, + Complex + } + + internal class XmlBamlPropertyCollection : List + { } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlPropertyElement.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlPropertyElement.cs new file mode 100644 index 000000000..fbb312cf0 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlPropertyElement.cs @@ -0,0 +1,48 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + internal class XmlBamlPropertyElement : XmlBamlElement + { + private readonly PropertyType _propertyType; + private PropertyDeclaration propertyDeclaration; + + + public XmlBamlPropertyElement(PropertyType propertyType, PropertyDeclaration propertyDeclaration) + { + _propertyType = propertyType; + this.propertyDeclaration = propertyDeclaration; + } + + public XmlBamlPropertyElement(XmlBamlElement parent, PropertyType propertyType, PropertyDeclaration propertyDeclaration) + : base(parent) + { + _propertyType = propertyType; + this.propertyDeclaration = propertyDeclaration; + this.TypeDeclaration = propertyDeclaration.DeclaringType; + } + + public PropertyDeclaration PropertyDeclaration + { + get + { + return this.propertyDeclaration; + } + } + + public PropertyType PropertyType + { + get { return _propertyType; } + } + + public override string ToString() + { + return String.Format("PropertyElement: {0}.{1}", TypeDeclaration.Name, PropertyDeclaration.Name); + } + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs new file mode 100644 index 000000000..ceb8b0f15 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs @@ -0,0 +1,1939 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Text; +using System.Xml; +using System.Windows.Media; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + public class XmlBamlReader : XmlReader, IXmlNamespaceResolver + { + + #region Variables + + private BamlBinaryReader reader; + private Hashtable assemblyTable = new Hashtable(); + private Hashtable stringTable = new Hashtable(); + private Hashtable typeTable = new Hashtable(); + private Hashtable propertyTable = new Hashtable(); + + private readonly ITypeResolver _resolver; + + private BamlRecordType currentType; + + private Stack elements = new Stack(); + private Stack readingElements = new Stack(); + private Stack keysResources = new Stack(); + private NodesCollection nodes = new NodesCollection(); + private List _mappings = new List(); + private XmlBamlNode _currentNode; + + private readonly KnownInfo KnownInfo; + + private int complexPropertyOpened = 0; + + private bool intoAttribute = false; + private bool initialized; + private bool _eof; + + private bool isPartialDefKeysClosed = true; + private bool isDefKeysClosed = true; + + private int bytesToSkip; + + private static readonly MethodInfo staticConvertCustomBinaryToObjectMethod = Type.GetType("System.Windows.Markup.XamlPathDataSerializer,PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35").GetMethod("StaticConvertCustomBinaryToObject", BindingFlags.Static | BindingFlags.Public); + private readonly TypeDeclaration XamlTypeDeclaration; + private readonly XmlNameTable _nameTable = new NameTable(); + private IDictionary _rootNamespaces; + + #endregion + + public XmlBamlReader(Stream stream) : this (stream, AppDomainTypeResolver.GetIntoNewAppDomain(Environment.CurrentDirectory)) + { + + } + + public XmlBamlReader(Stream stream, ITypeResolver resolver) + { + if (stream == null) + throw new ArgumentNullException("stream"); + if (resolver == null) + throw new ArgumentNullException("resolver"); + + _resolver = resolver; + reader = new BamlBinaryReader(stream); + + XamlTypeDeclaration = new TypeDeclaration(this.Resolver, "", "System.Windows.Markup", 0); + KnownInfo = new KnownInfo(resolver); + } + + /// + ///When overridden in a derived class, gets the value of the attribute with the specified . + /// + /// + /// + ///The value of the specified attribute. If the attribute is not found, null is returned. + /// + /// + ///The qualified name of the attribute. + public override string GetAttribute(string name) + { + throw new NotImplementedException(); + } + + /// + ///When overridden in a derived class, gets the value of the attribute with the specified and . + /// + /// + /// + ///The value of the specified attribute. If the attribute is not found, null is returned. This method does not move the reader. + /// + /// + ///The namespace URI of the attribute. + ///The local name of the attribute. + public override string GetAttribute(string name, string namespaceURI) + { + throw new NotImplementedException(); + } + + /// + ///When overridden in a derived class, gets the value of the attribute with the specified index. + /// + /// + /// + ///The value of the specified attribute. This method does not move the reader. + /// + /// + ///The index of the attribute. The index is zero-based. (The first attribute has index 0.) + public override string GetAttribute(int i) + { + throw new NotImplementedException(); + } + + /// + ///When overridden in a derived class, moves to the attribute with the specified . + /// + /// + /// + ///true if the attribute is found; otherwise, false. If false, the reader's position does not change. + /// + /// + ///The qualified name of the attribute. + public override bool MoveToAttribute(string name) + { + throw new NotImplementedException(); + } + + /// + ///When overridden in a derived class, moves to the attribute with the specified and . + /// + /// + /// + ///true if the attribute is found; otherwise, false. If false, the reader's position does not change. + /// + /// + ///The local name of the attribute. + ///The namespace URI of the attribute. + public override bool MoveToAttribute(string name, string ns) + { + throw new NotImplementedException(); + } + + /// + ///When overridden in a derived class, moves to the first attribute. + /// + /// + /// + ///true if an attribute exists (the reader moves to the first attribute); otherwise, false (the position of the reader does not change). + /// + /// + public override bool MoveToFirstAttribute() + { + intoAttribute = false; + if (nodes.Count > 0 && nodes.Peek() is XmlBamlProperty) + { + _currentNode = nodes.Dequeue(); + return true; + } + return false; + } + + /// + ///When overridden in a derived class, moves to the next attribute. + /// + /// + /// + ///true if there is a next attribute; false if there are no more attributes. + /// + /// + public override bool MoveToNextAttribute() + { + intoAttribute = false; + if (nodes.Count > 0 && nodes.Peek() is XmlBamlProperty) + { + _currentNode = nodes.Dequeue(); + return true; + } + return false; + } + + /// + ///When overridden in a derived class, moves to the element that contains the current attribute node. + /// + /// + /// + ///true if the reader is positioned on an attribute (the reader moves to the element that owns the attribute); false if the reader is not positioned on an attribute (the position of the reader does not change). + /// + /// + public override bool MoveToElement() + { + while (nodes.Peek() is XmlBamlProperty) + { + nodes.Dequeue(); + } + + return true; + } + + /// + ///When overridden in a derived class, parses the attribute value into one or more Text, EntityReference, or EndEntity nodes. + /// + /// + /// + ///true if there are nodes to return.false if the reader is not positioned on an attribute node when the initial call is made or if all the attribute values have been read.An empty attribute, such as, misc="", returns true with a single node with a value of String.Empty. + /// + /// + public override bool ReadAttributeValue() + { + if (!intoAttribute) + { + intoAttribute = true; + return true; + } + return false; + } + + /// + ///When overridden in a derived class, reads the next node from the stream. + /// + /// + /// + ///true if the next node was read successfully; false if there are no more nodes to read. + /// + /// + ///An error occurred while parsing the XML. + public override bool Read() + { + return ReadInternal(); + } + + private bool ReadInternal() + { + EnsureInit(); + + if (SetNextNode()) + return true; + + try + { + do + { + currentType = (BamlRecordType)reader.ReadByte(); + //Debug.WriteLine(currentType); + if (currentType == BamlRecordType.DocumentEnd) break; + + long position = reader.BaseStream.Position; + + ComputeBytesToSkip(); + ProcessNext(); + + if (bytesToSkip > 0) + { + reader.BaseStream.Position = position + bytesToSkip; + } + } + //while (currentType != BamlRecordType.DocumentEnd); + while (nodes.Count == 0 || (currentType != BamlRecordType.ElementEnd) || complexPropertyOpened > 0); + + return SetNextNode(); + } + catch (EndOfStreamException) + { + _eof = true; + return false; + } + } + + private bool SetNextNode() + { + while (nodes.Count > 0) + { + _currentNode = nodes.Dequeue(); + + if ((_currentNode is XmlBamlProperty)) continue; + + if (this.NodeType == XmlNodeType.EndElement) + { + if (readingElements.Count == 1) + _rootNamespaces = ((IXmlNamespaceResolver)this).GetNamespacesInScope(XmlNamespaceScope.All); + readingElements.Pop(); + } + else if (this.NodeType == XmlNodeType.Element) + readingElements.Push((XmlBamlElement)_currentNode); + + return true; + } + + return false; + } + + private void ProcessNext() + { + switch (currentType) + { + case BamlRecordType.DocumentStart: + { + reader.ReadBoolean(); + reader.ReadInt32(); + reader.ReadBoolean(); + break; + } + case BamlRecordType.DocumentEnd: + break; + case BamlRecordType.ElementStart: + this.ReadElementStart(); + break; + case BamlRecordType.ElementEnd: + this.ReadElementEnd(); + break; + case BamlRecordType.AssemblyInfo: + this.ReadAssemblyInfo(); + break; + case BamlRecordType.StringInfo: + this.ReadStringInfo(); + break; + case BamlRecordType.LineNumberAndPosition: + reader.ReadInt32(); + reader.ReadInt32(); + break; + case BamlRecordType.LinePosition: + reader.ReadInt32(); + break; + case BamlRecordType.XmlnsProperty: + this.ReadXmlnsProperty(); + break; + case BamlRecordType.ConnectionId: + reader.ReadInt32(); + break; + case BamlRecordType.DeferableContentStart: + reader.ReadInt32(); + break; + case BamlRecordType.DefAttribute: + this.ReadDefAttribute(); + break; + case BamlRecordType.DefAttributeKeyType: + this.ReadDefAttributeKeyType(); + break; + case BamlRecordType.DefAttributeKeyString: + this.ReadDefAttributeKeyString(); + break; + case BamlRecordType.AttributeInfo: + this.ReadAttributeInfo(); + break; + case BamlRecordType.PropertyListStart: + this.ReadPropertyListStart(); + break; + case BamlRecordType.PropertyListEnd: + this.ReadPropertyListEnd(); + break; + case BamlRecordType.Property: + this.ReadProperty(); + break; + case BamlRecordType.PropertyWithConverter: + this.ReadPropertyWithConverter(); + break; + case BamlRecordType.PropertyWithExtension: + this.ReadPropertyWithExtension(); + break; + case BamlRecordType.PropertyDictionaryStart: + this.ReadPropertyDictionaryStart(); + break; + case BamlRecordType.PropertyCustom: + this.ReadPropertyCustom(); + break; + case BamlRecordType.PropertyDictionaryEnd: + this.ReadPropertyDictionaryEnd(); + break; + case BamlRecordType.PropertyComplexStart: + this.ReadPropertyComplexStart(); + break; + case BamlRecordType.PropertyComplexEnd: + this.ReadPropertyComplexEnd(); + break; + case BamlRecordType.PIMapping: + this.ReadPIMapping(); + break; + case BamlRecordType.TypeInfo: + this.ReadTypeInfo(); + break; + case BamlRecordType.ContentProperty: + this.ReadContentProperty(); + break; + case BamlRecordType.ConstructorParametersStart: + ReadConstructorParametersStart(); + break; + case BamlRecordType.ConstructorParametersEnd: + ReadConstructorParametersEnd(); + break; + case BamlRecordType.ConstructorParameterType: + this.ReadConstructorParameterType(); + break; + case BamlRecordType.Text: + this.ReadText(); + break; + case BamlRecordType.TextWithConverter: + this.ReadTextWithConverter(); + break; + case BamlRecordType.PropertyWithStaticResourceId: + this.ReadPropertyWithStaticResourceIdentifier(); + break; + case BamlRecordType.OptimizedStaticResource: + this.ReadOptimizedStaticResource(); + break; + case BamlRecordType.KeyElementStart: + this.ReadKeyElementStart(); + break; + case BamlRecordType.KeyElementEnd: + this.ReadKeyElementEnd(); + break; + case BamlRecordType.PropertyTypeReference: + this.ReadPropertyTypeReference(); + break; + case BamlRecordType.StaticResourceStart: + ReadStaticResourceStart(); + break; + case BamlRecordType.StaticResourceEnd: + ReadStaticResourceEnd(); + break; + case BamlRecordType.StaticResourceId: + ReadStaticResourceId(); + break; + case BamlRecordType.PresentationOptionsAttribute: + this.ReadPresentationOptionsAttribute(); + break; + default: + break; + } + } + + private void ComputeBytesToSkip() + { + bytesToSkip = 0; + switch (currentType) + { + case BamlRecordType.PropertyWithConverter: + case BamlRecordType.DefAttributeKeyString: + case BamlRecordType.PresentationOptionsAttribute: + case BamlRecordType.Property: + case BamlRecordType.PropertyCustom: + case BamlRecordType.Text: + case BamlRecordType.TextWithConverter: + case BamlRecordType.XmlnsProperty: + case BamlRecordType.DefAttribute: + case BamlRecordType.PIMapping: + case BamlRecordType.AssemblyInfo: + case BamlRecordType.TypeInfo: + case BamlRecordType.AttributeInfo: + case BamlRecordType.StringInfo: + bytesToSkip = reader.ReadCompressedInt32(); + break; + } + } + + private void EnsureInit() + { + if (!initialized) + { + int startChars = reader.ReadInt32(); + String type = new String(new BinaryReader(this.reader.BaseStream, Encoding.Unicode).ReadChars(startChars >> 1)); + if (type != "MSBAML") + throw new NotSupportedException("Not a MS BAML"); + + int r = reader.ReadInt32(); + int s = reader.ReadInt32(); + int t = reader.ReadInt32(); + if (((r != 0x600000) || (s != 0x600000)) || (t != 0x600000)) + throw new NotSupportedException(); + + initialized = true; + } + } + + /// + ///When overridden in a derived class, changes the to Closed. + /// + /// + public override void Close() + { + //if (reader != null) + // reader.Close(); + reader = null; + } + + /// + ///When overridden in a derived class, resolves a namespace prefix in the current element's scope. + /// + /// + /// + ///The namespace URI to which the prefix maps or null if no matching prefix is found. + /// + /// + ///The prefix whose namespace URI you want to resolve. To match the default namespace, pass an empty string. + public override string LookupNamespace(string prefix) + { + if (readingElements.Count == 0) return null; + + XmlNamespaceCollection namespaces = readingElements.Peek().Namespaces; + + for (int x = 0; x < namespaces.Count; x++) + { + if (String.CompareOrdinal(namespaces[x].Prefix, prefix) == 0) + return namespaces[x].Namespace; + } + + return null; + } + + /// + ///When overridden in a derived class, resolves the entity reference for EntityReference nodes. + /// + /// + ///The reader is not positioned on an EntityReference node; this implementation of the reader cannot resolve entities ( returns false). + public override void ResolveEntity() + { + throw new NotImplementedException(); + } + + /// + ///When overridden in a derived class, gets the type of the current node. + /// + /// + /// + ///One of the values representing the type of the current node. + /// + /// + public override XmlNodeType NodeType + { + get + { + if (intoAttribute) return XmlNodeType.Text; + + return this.CurrentNode.NodeType; + } + } + + /// + ///When overridden in a derived class, gets the local name of the current node. + /// + /// + /// + ///The name of the current node with the prefix removed. For example, LocalName is book for the element <bk:book>.For node types that do not have a name (like Text, Comment, and so on), this property returns String.Empty. + /// + /// + public override string LocalName + { + get + { + if (intoAttribute) return String.Empty; + + String localName = String.Empty; + + XmlBamlNode node = this.CurrentNode; + if (node is XmlBamlProperty) + { + PropertyDeclaration pd = ((XmlBamlProperty)node).PropertyDeclaration; + localName = FormatPropertyDeclaration(pd, false, true, true); + } + else if (node is XmlBamlPropertyElement) + { + XmlBamlPropertyElement property = (XmlBamlPropertyElement)node; + localName = String.Format("{0}.{1}", property.TypeDeclaration.Name, property.PropertyDeclaration.Name); + } + else if (node is XmlBamlElement) + localName = ((XmlBamlElement)node).TypeDeclaration.Name; + + localName = this.NameTable.Add(localName); + + return localName; + } + } + + private PropertyDeclaration GetPropertyDeclaration(short identifier) + { + PropertyDeclaration declaration; + if (identifier >= 0) + { + declaration = (PropertyDeclaration)this.propertyTable[identifier]; + } + else + { + declaration = KnownInfo.KnownPropertyTable[-identifier]; + } + if (declaration == null) + { + throw new NotSupportedException(); + } + return declaration; + } + + private object GetResourceName(short identifier) + { + if (identifier >= 0) + { + PropertyDeclaration declaration = (PropertyDeclaration)this.propertyTable[identifier]; + return declaration; + } + else + { + identifier = (short)-identifier; + bool isNotKey = (identifier > 0xe8); + if (isNotKey) + identifier = (short)(identifier - 0xe8); + ResourceName resource = (ResourceName) KnownInfo.KnownResourceTable[(int)identifier]; + if (!isNotKey) + return new ResourceName(resource.Name + "Key"); + return resource; + } + } + + private void ReadPropertyDictionaryStart() + { + short identifier = reader.ReadInt16(); + + PropertyDeclaration pd = this.GetPropertyDeclaration(identifier); + XmlBamlElement element = elements.Peek(); + XmlBamlPropertyElement property = new XmlBamlPropertyElement(element, PropertyType.Dictionary, pd); + elements.Push(property); + nodes.Enqueue(property); + + isDefKeysClosed = true; + isPartialDefKeysClosed = true; + } + + private void ReadPropertyDictionaryEnd() + { + keysResources.Pop(); + + CloseElement(); + } + + private void ReadPropertyCustom() + { + short identifier = reader.ReadInt16(); + short serializerTypeId = reader.ReadInt16(); + bool isValueTypeId = (serializerTypeId & 0x4000) == 0x4000; + if (isValueTypeId) + serializerTypeId = (short)(serializerTypeId & ~0x4000); + + PropertyDeclaration pd = this.GetPropertyDeclaration(identifier); + string value; + switch (serializerTypeId) + { + case 0x2e8: + value = new BrushConverter().ConvertToString(SolidColorBrush.DeserializeFrom(reader)); + break; + case 0x2e9: + value = new Int32CollectionConverter().ConvertToString(DeserializeInt32CollectionFrom(reader)); + break; + case 0x89: + + short typeIdentifier = reader.ReadInt16(); + if (isValueTypeId) + { + TypeDeclaration typeDeclaration = this.GetTypeDeclaration(typeIdentifier); + string name = reader.ReadString(); + value = FormatPropertyDeclaration(new PropertyDeclaration(name, typeDeclaration), true, false, true); + } + else + value = FormatPropertyDeclaration(this.GetPropertyDeclaration(typeIdentifier), true, false, true); + break; + + case 0x2ea: + value = ((IFormattable)staticConvertCustomBinaryToObjectMethod.Invoke(null, new object[] { this.reader })).ToString("G", CultureInfo.InvariantCulture); + break; + case 0x2eb: + case 0x2f0: + value = Deserialize3DPoints(); + break; + case 0x2ec: + value = DeserializePoints(); + break; + case 0xc3: + // Enum + uint num = reader.ReadUInt32(); + value = num.ToString(); + break; + case 0x2e: + int b = reader.ReadByte(); + value = (b == 1) ? Boolean.TrueString : Boolean.FalseString; + break; + default: + return; + } + + XmlBamlProperty property = new XmlBamlProperty(PropertyType.Value, pd); + property.Value = value; + + nodes.Enqueue(property); + } + + private string DeserializePoints() + { + using (StringWriter writer = new StringWriter()) + { + int num10 = reader.ReadInt32(); + for (int k = 0; k < num10; k++) + { + if (k != 0) + writer.Write(" "); + for (int m = 0; m < 2; m++) + { + if (m != 0) + writer.Write(","); + writer.Write(reader.ReadCompressedDouble().ToString()); + } + } + return writer.ToString(); + } + } + + private String Deserialize3DPoints() + { + using (StringWriter writer = new StringWriter()) + { + int num14 = reader.ReadInt32(); + for (int i = 0; i < num14; i++) + { + if (i != 0) + { + writer.Write(" "); + } + for (int j = 0; j < 3; j++) + { + if (j != 0) + { + writer.Write(","); + } + writer.Write(reader.ReadCompressedDouble().ToString()); + } + } + return writer.ToString(); + } + } + + private static Int32Collection DeserializeInt32CollectionFrom(BinaryReader reader) + { + IntegerCollectionType type = (IntegerCollectionType)reader.ReadByte(); + int capacity = reader.ReadInt32(); + if (capacity < 0) + throw new ArgumentException(); + + Int32Collection ints = new Int32Collection(capacity); + switch (type) + { + case IntegerCollectionType.Byte: + for (int i = 0; i < capacity; i++) + { + ints.Add(reader.ReadByte()); + } + return ints; + + case IntegerCollectionType.UShort: + for (int j = 0; j < capacity; j++) + { + ints.Add(reader.ReadUInt16()); + } + return ints; + + case IntegerCollectionType.Integer: + for (int k = 0; k < capacity; k++) + { + int num7 = reader.ReadInt32(); + ints.Add(num7); + } + return ints; + + case IntegerCollectionType.Consecutive: + for (int m = reader.ReadInt32(); m < capacity; m++) + { + ints.Add(m); + } + return ints; + } + throw new ArgumentException(); + } + + private void ReadPropertyWithExtension() + { + short identifier = reader.ReadInt16(); + short x = reader.ReadInt16(); + short valueIdentifier = reader.ReadInt16(); + bool isValueType = (x & 0x4000) == 0x4000; + bool isStaticType = (x & 0x2000) == 0x2000; + x = (short)(x & 0xfff); + + PropertyDeclaration pd = this.GetPropertyDeclaration(identifier); + short extensionIdentifier = (short)-(x & 0xfff); + string value = String.Empty; + + switch (x) + { + case 0x25a: + // StaticExtension + object resource = this.GetResourceName(valueIdentifier); + if (resource is ResourceName) + value = this.GetStaticExtension(((ResourceName)resource).Name); + else if (resource is PropertyDeclaration) + value = this.GetStaticExtension(FormatPropertyDeclaration(((PropertyDeclaration)resource), true, false, false)); + break; + case 0x25b: // StaticResource + case 0xbd: // DynamicResource + if (isValueType) + { + value = this.GetTypeExtension(valueIdentifier); + } + else if (isStaticType) + { + TypeDeclaration extensionDeclaration = this.GetTypeDeclaration(extensionIdentifier); + value = GetExtension(extensionDeclaration, GetStaticExtension(GetResourceName(valueIdentifier).ToString())); + } + else + { + TypeDeclaration extensionDeclaration = this.GetTypeDeclaration(extensionIdentifier); + value = GetExtension(extensionDeclaration, (string)this.stringTable[valueIdentifier]); + } + break; + + case 0x27a: + // TemplateBinding + PropertyDeclaration pdValue = this.GetPropertyDeclaration(valueIdentifier); + value = GetTemplateBindingExtension(pdValue); + break; + default: + throw new NotSupportedException("Unknown property with extension"); + } + + XmlBamlProperty property = new XmlBamlProperty(PropertyType.Value, pd); + property.Value = value; + + nodes.Enqueue(property); + } + + private void ReadProperty() + { + short identifier = reader.ReadInt16(); + string text = reader.ReadString(); + + PropertyDeclaration pd = this.GetPropertyDeclaration(identifier); + XmlBamlProperty property = new XmlBamlProperty(PropertyType.Value, pd); + property.Value = text; + + nodes.Enqueue(property); + } + + private void ReadPropertyWithConverter() + { + short identifier = reader.ReadInt16(); + string text = reader.ReadString(); + reader.ReadInt16(); + + PropertyDeclaration pd = this.GetPropertyDeclaration(identifier); + XmlBamlProperty property = new XmlBamlProperty(PropertyType.Value, pd); + property.Value = text; + + nodes.Enqueue(property); + } + + private void ReadAttributeInfo() + { + short key = reader.ReadInt16(); + short identifier = reader.ReadInt16(); + reader.ReadByte(); + string name = reader.ReadString(); + TypeDeclaration declaringType = this.GetTypeDeclaration(identifier); + PropertyDeclaration declaration2 = new PropertyDeclaration(name, declaringType); + this.propertyTable.Add(key, declaration2); + } + + private void ReadDefAttributeKeyType() + { + short typeIdentifier = reader.ReadInt16(); + reader.ReadByte(); + int position = reader.ReadInt32(); + // TODO: shared + bool shared = reader.ReadBoolean(); + bool sharedSet = reader.ReadBoolean(); + + // TODO: handle shared + AddDefKey(position, this.GetTypeExtension(typeIdentifier)); + } + + private void ReadDefAttribute() + { + string text = reader.ReadString(); + short identifier = reader.ReadInt16(); + + PropertyDeclaration pd; + switch (identifier) + { + case -2: + pd = new PropertyDeclaration("Uid", XamlTypeDeclaration); + break; + case -1: + pd = new PropertyDeclaration("Name", XamlTypeDeclaration); + break; + default: + string recordName = (string)this.stringTable[identifier]; + if (recordName != "Key") throw new NotSupportedException(recordName); + pd = new PropertyDeclaration(recordName, XamlTypeDeclaration); + + AddDefKey(-1, text); + break; + } + + XmlBamlProperty property = new XmlBamlProperty(PropertyType.Key, pd); + property.Value = text; + + nodes.Enqueue(property); + } + + private void ReadDefAttributeKeyString() + { + short num = reader.ReadInt16(); + int position = reader.ReadInt32(); + //bool shared = reader.ReadBoolean(); + //bool sharedSet = reader.ReadBoolean(); + string text = (string)this.stringTable[num]; + if (text == null) + throw new NotSupportedException(); + + AddDefKey(position, text); + } + + private void AddDefKey(long position, string text) + { + // Guardo se la dichiarazione delle chiavi risulta chiusa + // Se è aperta c'è un sotto ResourceDictionary oppure è il root ResourceDictionary + if (isDefKeysClosed) + { + keysResources.Push(new KeysResourcesCollection()); + } + + // Guardo se è stata chiusa la dichiarazione parziale (mediante dichiarazione OptimizedStaticResource) + // Si chiude il ciclo di chiavi + if (isPartialDefKeysClosed) + { + keysResources.Peek().Add(new KeysResource()); + } + isDefKeysClosed = false; + isPartialDefKeysClosed = false; + + // TODO: handle shared + if (position >= 0) + keysResources.Peek().Last.Keys[position] = text; + } + + private void ReadXmlnsProperty() + { + string prefix = reader.ReadString(); + string @namespace = reader.ReadString(); + string[] textArray = new string[(uint)reader.ReadInt16()]; + for (int i = 0; i < textArray.Length; i++) + { + textArray[i] = (string)this.assemblyTable[reader.ReadInt16()]; + } + + XmlNamespaceCollection namespaces = elements.Peek().Namespaces; + // Mapping locale, ci aggiunto l'assembly + if (@namespace.StartsWith("clr-namespace:") && @namespace.IndexOf("assembly=") < 0) + { + XmlPIMapping mappingToChange = null; + foreach (XmlPIMapping mapping in this.Mappings) + { + if (String.CompareOrdinal(mapping.XmlNamespace, @namespace) == 0) + { + mappingToChange = mapping; + break; + } + } + if (mappingToChange == null) + throw new InvalidOperationException("Cannot find mapping"); + + @namespace = String.Format("{0};assembly={1}", @namespace, GetAssembly(mappingToChange.AssemblyId).Replace(" ", "")); + mappingToChange.XmlNamespace = @namespace; + } + namespaces.Add(new XmlNamespace(prefix, @namespace)); + } + + private void ReadElementEnd() + { + CloseElement(); + + // Provvedo all'eliminazione del gruppo di chiavi se sono sul root ResourceDictionary + // e si è chiuso uno degli elementi di primo livello e tutte le chiavi sono state usate + // Passo alla prossima lista + KeysResource keysResource = (elements.Count == 1 && keysResources.Count > 0) ? keysResources.Peek().First : null; + if (keysResource != null && keysResource.Keys.Count == 0) + keysResources.Peek().RemoveAt(0); + } + + private void ReadPropertyComplexStart() + { + short identifier = reader.ReadInt16(); + + PropertyDeclaration pd = this.GetPropertyDeclaration(identifier); + XmlBamlElement element = FindXmlBamlElement(); + + XmlBamlPropertyElement property = new XmlBamlPropertyElement(element, PropertyType.Complex, pd); + elements.Push(property); + nodes.Enqueue(property); + complexPropertyOpened++; + } + + private XmlBamlElement FindXmlBamlElement() + { + return elements.Peek(); + + //XmlBamlElement element; + //int x = nodes.Count - 1; + //do + //{ + // element = nodes[x] as XmlBamlElement; + // x--; + //} while (element == null); + //return element; + } + + private void ReadPropertyListStart() + { + short identifier = reader.ReadInt16(); + + PropertyDeclaration pd = this.GetPropertyDeclaration(identifier); + XmlBamlElement element = FindXmlBamlElement(); + XmlBamlPropertyElement property = new XmlBamlPropertyElement(element, PropertyType.List, pd); + elements.Push(property); + nodes.Enqueue(property); + } + + private void ReadPropertyListEnd() + { + CloseElement(); + } + + private void ReadPropertyComplexEnd() + { + XmlBamlPropertyElement propertyElement = (XmlBamlPropertyElement) elements.Peek(); + + CloseElement(); + + complexPropertyOpened--; + // Valuto se contiene tutte extension + int start = nodes.IndexOf(propertyElement) + 1; + IEnumerator enumerator = nodes.GetEnumerator(); + + int c = 0; + while (c < start && enumerator.MoveNext()) + c++; + + if (IsExtension(enumerator)) + { + start--; + nodes.RemoveAt(start); + nodes.RemoveLast(); + + StringBuilder sb = new StringBuilder(); + FormatElementExtension((XmlBamlElement) nodes[start], sb); + + XmlBamlProperty property = + new XmlBamlProperty(PropertyType.Complex, propertyElement.PropertyDeclaration); + property.Value = sb.ToString(); + nodes.Add(property); + + return; + } + } + + private void FormatElementExtension(XmlBamlElement element, StringBuilder sb) + { + sb.Append("{"); + sb.Append(FormatTypeDeclaration(element.TypeDeclaration)); + + int start = nodes.IndexOf(element); + nodes.RemoveAt(start); + + string sep = " "; + while (nodes.Count > start) + { + XmlBamlNode node = nodes[start]; + + if (node is XmlBamlEndElement) + { + sb.Append("}"); + nodes.RemoveAt(start); + break; + } + else if (node is XmlBamlPropertyElement) + { + nodes.RemoveAt(start); + + sb.Append(sep); + XmlBamlPropertyElement property = (XmlBamlPropertyElement)node; + sb.Append(property.PropertyDeclaration.Name); + sb.Append("="); + + node = nodes[start]; + nodes.RemoveLast(); + FormatElementExtension((XmlBamlElement)node, sb); + } + else if (node is XmlBamlElement) + { + sb.Append(sep); + FormatElementExtension((XmlBamlElement)node, sb); + } + else if (node is XmlBamlProperty) + { + nodes.RemoveAt(start); + + sb.Append(sep); + XmlBamlProperty property = (XmlBamlProperty)node; + sb.Append(property.PropertyDeclaration.Name); + sb.Append("="); + sb.Append(property.Value); + } + else if (node is XmlBamlText) + { + nodes.RemoveAt(start); + + sb.Append(sep); + sb.Append(((XmlBamlText)node).Text); + } + sep = ","; + } + } + + private static bool IsExtension(IEnumerator enumerator) + { + bool r = true; + while (enumerator.MoveNext() && r) + { + object node = enumerator.Current; + if (node is XmlBamlElement && !(node is XmlBamlEndElement) && !((XmlBamlElement)node).TypeDeclaration.IsExtension) + { + r = false; + } + } + + return r; + } + + private void CloseElement() + { + nodes.Enqueue(new XmlBamlEndElement(elements.Pop())); + } + + private void ReadElementStart() + { + short identifier = reader.ReadInt16(); + reader.ReadByte(); + TypeDeclaration declaration = GetTypeDeclaration(identifier); + + XmlBamlElement element; + XmlBamlElement parentElement = null; + if (elements.Count > 0) + { + parentElement = elements.Peek(); + element = new XmlBamlElement(parentElement); + element.Position = this.reader.BaseStream.Position; + + // Porto l'inizio del padre all'inizio del primo figlio + if (parentElement.Position == 0 && complexPropertyOpened == 0) + parentElement.Position = element.Position; + } + else + element = new XmlBamlElement(); + + element.TypeDeclaration = declaration; + elements.Push(element); + nodes.Enqueue(element); + + if (parentElement != null && complexPropertyOpened == 0) + { + // Calcolo la posizione dell'elemento rispetto al padre + long position = element.Position - parentElement.Position; + KeysResource keysResource = (keysResources.Count > 0) ? keysResources.Peek().First : null; + if (keysResource != null && keysResource.Keys.HasKey(position)) + { + string key = keysResource.Keys[position]; + // Rimuovo la chiave perché è stata usata + keysResource.Keys.Remove(position); + + AddKeyToElement(key); + } + } + } + + private void AddKeyToElement(string key) + { + PropertyDeclaration pd = new PropertyDeclaration("Key", XamlTypeDeclaration); + XmlBamlProperty property = new XmlBamlProperty(PropertyType.Key, pd); + + property.Value = key; + + nodes.Enqueue(property); + } + + private XmlPIMapping FindByClrNamespaceAndAssemblyId(TypeDeclaration declaration) + { + return FindByClrNamespaceAndAssemblyId(declaration.Namespace, declaration.AssemblyId); + } + + private XmlPIMapping FindByClrNamespaceAndAssemblyId(string clrNamespace, int assemblyId) + { + if (clrNamespace == XamlTypeDeclaration.Namespace && assemblyId == XamlTypeDeclaration.AssemblyId) + return new XmlPIMapping(XmlPIMapping.XamlNamespace, 0, clrNamespace); + + for (int x = 0; x < Mappings.Count; x++) + { + XmlPIMapping xp = Mappings[x]; + if (xp.AssemblyId == assemblyId && String.CompareOrdinal(xp.ClrNamespace, clrNamespace) == 0) + return xp; + } + + return null; + } + + private void ReadPIMapping() + { + string xmlNamespace = reader.ReadString(); + string clrNamespace = reader.ReadString(); + short assemblyId = reader.ReadInt16(); + + Mappings.Add(new XmlPIMapping(xmlNamespace, assemblyId, clrNamespace)); + } + + private void ReadContentProperty() + { + reader.ReadInt16(); + + // Non serve aprire niente, è il default + } + + private static void ReadConstructorParametersStart() + { + //this.constructorParameterTable.Add(this.elements.Peek()); + //PromoteDataToComplexProperty(); + } + + private static void ReadConstructorParametersEnd() + { + //this.constructorParameterTable.Remove(this.elements.Peek()); + //properties.Pop(); + } + + private void ReadConstructorParameterType() + { + short identifier = reader.ReadInt16(); + + //TypeDeclaration declaration = GetTypeDeclaration(identifier); + nodes.Enqueue(new XmlBamlText(GetTypeExtension(identifier))); + } + + private void ReadText() + { + string text = reader.ReadString(); + + nodes.Enqueue(new XmlBamlText(text)); + } + + private void ReadKeyElementStart() + { + short typeIdentifier = reader.ReadInt16(); + byte valueIdentifier = reader.ReadByte(); + // TODO: handle shared + //bool shared = (valueIdentifier & 1) != 0; + //bool sharedSet = (valueIdentifier & 2) != 0; + int position = reader.ReadInt32(); + reader.ReadBoolean(); + reader.ReadBoolean(); + + TypeDeclaration declaration = this.GetTypeDeclaration(typeIdentifier); + + XmlBamlPropertyElement property = new XmlBamlPropertyElement(elements.Peek(), PropertyType.Key, new PropertyDeclaration("Key", declaration)); + property.Position = position; + elements.Push(property); + nodes.Enqueue(property); + complexPropertyOpened++; + } + + private void ReadKeyElementEnd() + { + XmlBamlPropertyElement propertyElement = (XmlBamlPropertyElement)elements.Peek(); + + CloseElement(); + complexPropertyOpened--; + if (complexPropertyOpened == 0) + { + + int start = nodes.IndexOf(propertyElement); + + StringBuilder sb = new StringBuilder(); + FormatElementExtension((XmlBamlElement)nodes[start], sb); + AddDefKey(propertyElement.Position, sb.ToString()); + } + } + + private static void ReadStaticResourceStart() + { + //short identifier = reader.ReadInt16(); + //byte n = reader.ReadByte(); + //TypeDeclaration declaration = this.GetTypeDeclaration(identifier); + //this.staticResourceTable.Add(declaration); + + throw new NotImplementedException("StaticResourceStart"); + } + + private static void ReadStaticResourceEnd() + { + throw new NotImplementedException("ReadStaticResourceEnd"); + } + + private static void ReadStaticResourceId() + { + //short identifier = reader.ReadInt16(); + //object staticResource = this.GetStaticResource(identifier); + //TypeDeclaration declaration = this.GetTypeDeclaration(-603); + + throw new NotImplementedException("StaticResourceId"); + } + + private void ReadPresentationOptionsAttribute() + { + string text = reader.ReadString(); + short valueIdentifier = reader.ReadInt16(); + + PropertyDeclaration pd = new PropertyDeclaration(this.stringTable[valueIdentifier].ToString()); + + XmlBamlProperty property = new XmlBamlProperty(PropertyType.Value, pd); + property.Value = text; + } + + private void ReadPropertyTypeReference() + { + short identifier = reader.ReadInt16(); + short typeIdentifier = reader.ReadInt16(); + + PropertyDeclaration pd = this.GetPropertyDeclaration(identifier); + string value = this.GetTypeExtension(typeIdentifier); + + XmlBamlProperty property = new XmlBamlProperty(PropertyType.Value, pd); + property.Value = value; + + nodes.Enqueue(property); + } + + private void ReadOptimizedStaticResource() + { + byte num = reader.ReadByte(); + short typeIdentifier = reader.ReadInt16(); + bool isValueType = (num & 1) == 1; + bool isStaticType = (num & 2) == 2; + object resource; + + if (isValueType) + resource = this.GetTypeExtension(typeIdentifier); + else if (isStaticType) + { + ResourceName resourceName = (ResourceName)this.GetResourceName(typeIdentifier); + resource = GetStaticExtension(resourceName.Name); + } + else + { + resource = this.stringTable[typeIdentifier]; + } + + //this.staticResourceTable.Add(resource); + isPartialDefKeysClosed = true; + // Aggiungo la risorsa nell'ultimo gruppo + keysResources.Peek().Last.StaticResources.Add(resource); + } + + private string GetTemplateBindingExtension(PropertyDeclaration propertyDeclaration) + { + return String.Format("{{TemplateBinding {0}}}", FormatPropertyDeclaration(propertyDeclaration, true, false, false)); + } + + private string GetStaticExtension(string name) + { + string prefix = this.LookupPrefix(XmlPIMapping.XamlNamespace, false); + if (String.IsNullOrEmpty(prefix)) + return String.Format("{{Static {0}}}", name); + else + return String.Format("{{{0}:Static {1}}}", prefix, name); + } + + private string GetExtension(TypeDeclaration declaration, string value) + { + return String.Format("{{{0} {1}}}", FormatTypeDeclaration(declaration), value); + } + + private string GetTypeExtension(short typeIdentifier) + { + string prefix = this.LookupPrefix(XmlPIMapping.XamlNamespace, false); + if (String.IsNullOrEmpty(prefix)) + return String.Format("{{Type {0}}}", FormatTypeDeclaration(GetTypeDeclaration(typeIdentifier))); + else + return String.Format("{{{0}:Type {1}}}", prefix, FormatTypeDeclaration(GetTypeDeclaration(typeIdentifier))); + } + + private string FormatTypeDeclaration(TypeDeclaration typeDeclaration) + { + XmlPIMapping mapping = FindByClrNamespaceAndAssemblyId(typeDeclaration.Namespace, typeDeclaration.AssemblyId); + string prefix = (mapping != null) ? this.LookupPrefix(mapping.XmlNamespace, false) : null; + string name = typeDeclaration.Name; + if (name.EndsWith("Extension")) + name = name.Substring(0, name.Length - 9); + if (String.IsNullOrEmpty(prefix)) + return name; + else + return String.Format("{0}:{1}", prefix, name); + } + + + + private string FormatPropertyDeclaration(PropertyDeclaration propertyDeclaration, bool withPrefix, bool useReading, bool checkType) + { + StringBuilder sb = new StringBuilder(); + + TypeDeclaration elementDeclaration = (useReading) ? readingElements.Peek().TypeDeclaration : elements.Peek().TypeDeclaration; + + IDependencyPropertyDescriptor descriptor = null; + bool areValidTypes = elementDeclaration.Type != null && propertyDeclaration.DeclaringType.Type != null; + if (areValidTypes) + descriptor = this.Resolver.GetDependencyPropertyDescriptor(propertyDeclaration.Name, elementDeclaration.Type, propertyDeclaration.DeclaringType.Type); + + bool isDescendant = (areValidTypes && (propertyDeclaration.DeclaringType.Type.Equals(elementDeclaration.Type) || elementDeclaration.Type.IsSubclassOf(propertyDeclaration.DeclaringType.Type))); + bool isAttached = (descriptor != null && descriptor.IsAttached); + bool differentType = ((propertyDeclaration.DeclaringType != propertyDeclaration.DeclaringType || !isDescendant)); + + if (withPrefix) + { + XmlPIMapping mapping = FindByClrNamespaceAndAssemblyId(propertyDeclaration.DeclaringType.Namespace, propertyDeclaration.DeclaringType.AssemblyId); + string prefix = (mapping != null) ? this.LookupPrefix(mapping.XmlNamespace, false) : null; + + if (!String.IsNullOrEmpty(prefix)) + { + sb.Append(prefix); + sb.Append(":"); + } + } + if ((differentType || isAttached || !checkType) && propertyDeclaration.DeclaringType.Name.Length > 0) + { + sb.Append(propertyDeclaration.DeclaringType.Name); + sb.Append("."); + } + sb.Append(propertyDeclaration.Name); + + return sb.ToString(); + } + + private void ReadPropertyWithStaticResourceIdentifier() + { + short identifier = reader.ReadInt16(); + short staticIdentifier = reader.ReadInt16(); + + PropertyDeclaration pd = this.GetPropertyDeclaration(identifier); + object staticResource = this.GetStaticResource(staticIdentifier); + + string prefix = this.LookupPrefix(XmlPIMapping.PresentationNamespace, false); + string value = String.Format("{{{0}{1}StaticResource {2}}}", prefix, (String.IsNullOrEmpty(prefix)) ? String.Empty : ":", staticResource); + + XmlBamlProperty property = new XmlBamlProperty(PropertyType.Value, pd); + property.Value = value; + + nodes.Enqueue(property); + } + + + private object GetStaticResource(short identifier) + { + // Recupero la risorsa nel gruppo corrente + foreach (KeysResourcesCollection resource in keysResources) + { + // TODO: controllare. Se non lo trova nel gruppo corrente, va in quello successivo + for (int x = 0; x < resource.Count; x++) + { + KeysResource resourceGroup = resource[x]; + if (resourceGroup.StaticResources.Count > identifier) + if (x > 0) + break; + //return "%" + resourceGroup.StaticResources[identifier] + "%"; + else + return resourceGroup.StaticResources[identifier]; + } + } + + //return "???"; + throw new ArgumentException("Cannot find StaticResource", "identifier"); + } + + private void ReadTextWithConverter() + { + string text = reader.ReadString(); + reader.ReadInt16(); + + nodes.Enqueue(new XmlBamlText(text)); + } + + private void ReadTypeInfo() + { + short typeId = reader.ReadInt16(); + short assemblyId = reader.ReadInt16(); + string fullName = reader.ReadString(); + assemblyId = (short)(assemblyId & 0xfff); + TypeDeclaration declaration; + int length = fullName.LastIndexOf('.'); + if (length != -1) + { + string name = fullName.Substring(length + 1); + string namespaceName = fullName.Substring(0, length); + declaration = new TypeDeclaration(this, this.Resolver, name, namespaceName, assemblyId, false); + } + else + { + declaration = new TypeDeclaration(this, this.Resolver, fullName, string.Empty, assemblyId, false); + } + this.typeTable.Add(typeId, declaration); + } + + private void ReadAssemblyInfo() + { + short key = reader.ReadInt16(); + string text = reader.ReadString(); + this.assemblyTable.Add(key, text); + } + + private void ReadStringInfo() + { + short key = reader.ReadInt16(); + string text = reader.ReadString(); + this.stringTable.Add(key, text); + } + + private TypeDeclaration GetTypeDeclaration(short identifier) + { + TypeDeclaration declaration; + if (identifier >= 0) + declaration = (TypeDeclaration)this.typeTable[identifier]; + else + declaration = KnownInfo.KnownTypeTable[-identifier]; + + if (declaration == null) + throw new NotSupportedException(); + + return declaration; + } + + internal string GetAssembly(short identifier) + { + return this.assemblyTable[identifier].ToString(); + } + + private XmlBamlNode CurrentNode + { + get + { + return _currentNode; + } + } + + /// + ///When overridden in a derived class, gets the namespace URI (as defined in the W3C Namespace specification) of the node on which the reader is positioned. + /// + /// + /// + ///The namespace URI of the current node; otherwise an empty string. + /// + /// + public override string NamespaceURI + { + get + { + if (intoAttribute) return String.Empty; + + TypeDeclaration declaration; + XmlBamlNode node = this.CurrentNode; + if (node is XmlBamlProperty) + { + declaration = ((XmlBamlProperty)node).PropertyDeclaration.DeclaringType; + TypeDeclaration elementDeclaration = this.readingElements.Peek().TypeDeclaration; + + XmlPIMapping propertyMapping = FindByClrNamespaceAndAssemblyId(declaration) ?? XmlPIMapping.Presentation; + XmlPIMapping elementMapping = FindByClrNamespaceAndAssemblyId(elementDeclaration) ?? XmlPIMapping.Presentation; + if (String.CompareOrdinal(propertyMapping.XmlNamespace, elementMapping.XmlNamespace) == 0 + || (elementDeclaration.Type != null && declaration.Type != null && elementDeclaration.Type.IsSubclassOf(declaration.Type))) + return String.Empty; + } + else if (node is XmlBamlElement) + declaration = ((XmlBamlElement)node).TypeDeclaration; + else + return String.Empty; + + XmlPIMapping mapping = FindByClrNamespaceAndAssemblyId(declaration); + if (mapping == null) + mapping = XmlPIMapping.Presentation; + + return mapping.XmlNamespace; + } + } + + /// + ///When overridden in a derived class, gets the namespace prefix associated with the current node. + /// + /// + /// + ///The namespace prefix associated with the current node. + /// + /// + public override string Prefix + { + get + { + if (!intoAttribute) + return ((IXmlNamespaceResolver)this).LookupPrefix(this.NamespaceURI) ?? String.Empty; + return String.Empty; + } + } + + /// + ///When overridden in a derived class, gets a value indicating whether the current node can have a . + /// + /// + /// + ///true if the node on which the reader is currently positioned can have a Value; otherwise, false. If false, the node has a value of String.Empty. + /// + /// + public override bool HasValue + { + get { return this.Value != null; } + } + + /// + /// Returns object used to resolve types + /// + public ITypeResolver Resolver + { + get { return _resolver; } + } + + /// + ///When overridden in a derived class, gets the text value of the current node. + /// + /// + /// + ///The value returned depends on the of the node. The following table lists node types that have a value to return. All other node types return String.Empty.Node type Value AttributeThe value of the attribute. CDATAThe content of the CDATA section. CommentThe content of the comment. DocumentTypeThe internal subset. ProcessingInstructionThe entire content, excluding the target. SignificantWhitespaceThe white space between markup in a mixed content model. TextThe content of the text node. WhitespaceThe white space between markup. XmlDeclarationThe content of the declaration. + /// + /// + public override string Value + { + get + { + XmlBamlNode node = this.CurrentNode; + if (node is XmlBamlProperty) + return ((XmlBamlProperty)node).Value.ToString(); + else if (node is XmlBamlText) + return ((XmlBamlText)node).Text; + else if (node is XmlBamlElement) + return String.Empty; + + return String.Empty; + } + } + + /// + /// Return root namespaces + /// + public IDictionary RootNamespaces + { + get { return _rootNamespaces; } + } + + /// + ///When overridden in a derived class, gets the depth of the current node in the XML document. + /// + /// + /// + ///The depth of the current node in the XML document. + /// + /// + public override int Depth + { + get { return this.readingElements.Count; } + } + + /// + ///When overridden in a derived class, gets the base URI of the current node. + /// + /// + /// + ///The base URI of the current node. + /// + /// + public override string BaseURI + { + get { return String.Empty; } + } + + /// + ///When overridden in a derived class, gets a value indicating whether the current node is an empty element (for example, <MyElement/>). + /// + /// + /// + ///true if the current node is an element ( equals XmlNodeType.Element) that ends with />; otherwise, false. + /// + /// + public override bool IsEmptyElement + { + get { return false; } + } + + //public override bool IsDefault + //{ + // get + // { + // return this.NamespaceURI == null; + // } + //} + + /// + ///When overridden in a derived class, gets the number of attributes on the current node. + /// + /// + /// + ///The number of attributes on the current node. + /// + /// + public override int AttributeCount + { + get { throw new NotImplementedException(); } + } + + /// + ///When overridden in a derived class, gets a value indicating whether the reader is positioned at the end of the stream. + /// + /// + /// + ///true if the reader is positioned at the end of the stream; otherwise, false. + /// + /// + public override bool EOF + { + get { return _eof; } + } + + /// + ///When overridden in a derived class, gets the state of the reader. + /// + /// + /// + ///One of the values. + /// + /// + public override ReadState ReadState + { + get + { + if (!initialized) + return ReadState.Initial; + else if (reader == null) + return ReadState.Closed; + else if (this.EOF) + return ReadState.EndOfFile; + else + return ReadState.Interactive; + } + } + + public List Mappings + { + get { return _mappings; } + } + + /// + ///When overridden in a derived class, gets the associated with this implementation. + /// + /// + /// + ///The XmlNameTable enabling you to get the atomized version of a string within the node. + /// + /// + public override XmlNameTable NameTable + { + get { return _nameTable; } + } + + #region IXmlNamespaceResolver Members + + /// + ///Gets a collection of defined prefix-namespace Mappings that are currently in scope. + /// + /// + /// + ///An that contains the current in-scope namespaces. + /// + /// + ///An value that specifies the type of namespace nodes to return. + IDictionary IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope) + { + XmlNamespaceCollection namespaces = readingElements.Peek().Namespaces; + Dictionary list = new Dictionary(); + foreach (XmlNamespace ns in namespaces) + { + list.Add(ns.Prefix, ns.Namespace); + } + + return list; + } + + /// + ///Gets the namespace URI mapped to the specified prefix. + /// + /// + /// + ///The namespace URI that is mapped to the prefix; null if the prefix is not mapped to a namespace URI. + /// + /// + ///The prefix whose namespace URI you wish to find. + string IXmlNamespaceResolver.LookupNamespace(string prefix) + { + return this.LookupNamespace(prefix); + } + + /// + ///Gets the prefix that is mapped to the specified namespace URI. + /// + /// + /// + ///The prefix that is mapped to the namespace URI; null if the namespace URI is not mapped to a prefix. + /// + /// + ///The namespace URI whose prefix you wish to find. + string IXmlNamespaceResolver.LookupPrefix(string namespaceName) + { + return this.LookupPrefix(namespaceName, true); + } + + private string LookupPrefix(string namespaceName, bool useReading) + { + Stack elements; + if (useReading) + elements = readingElements; + else + elements = this.elements; + + if (elements.Count == 0) return null; + XmlNamespaceCollection namespaces = elements.Peek().Namespaces; + + return LookupPrefix(namespaceName, namespaces); + } + + private static string LookupPrefix(string namespaceName, XmlNamespaceCollection namespaces) + { + for (int x = 0; x < namespaces.Count; x++) + { + if (String.CompareOrdinal(namespaces[x].Namespace, namespaceName) == 0) + return namespaces[x].Prefix; + } + + return null; + } + + #endregion + + #region IntegerCollectionType + + internal enum IntegerCollectionType : byte + { + Byte = 2, + Consecutive = 1, + Integer = 4, + Unknown = 0, + UShort = 3 + } + + #endregion + + #region NodesCollection + + internal class NodesCollection : List + { + public XmlBamlNode Last + { + get + { + if (this.Count > 0) + { + int i = this.Count - 1; + return this[i]; + } + return null; + } + } + + public void RemoveLast() + { + if (this.Count > 0) + this.Remove(this.Last); + } + + public XmlBamlNode Dequeue() + { + return DequeueInternal(true); + } + + public XmlBamlNode Peek() + { + return DequeueInternal(false); + } + + private XmlBamlNode DequeueInternal(bool remove) + { + if (this.Count > 0) + { + XmlBamlNode node = this[0]; + if (remove) + this.RemoveAt(0); + return node; + } + else + return null; + } + + + public void Enqueue(XmlBamlNode node) + { + this.Add(node); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlText.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlText.cs new file mode 100644 index 000000000..56114cac3 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlText.cs @@ -0,0 +1,33 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + internal class XmlBamlText : XmlBamlNode + { + private string _text; + + public XmlBamlText(string text) + { + _text = text; + } + + public string Text + { + get { return _text; } + } + + public override System.Xml.XmlNodeType NodeType + { + get + { + return XmlNodeType.Text; + } + } + } +} diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlNamespace.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlNamespace.cs new file mode 100644 index 000000000..c064931b5 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlNamespace.cs @@ -0,0 +1,47 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System.Collections.Generic; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + internal class XmlNamespace + { + private string _prefix; + private string _namespace; + + public XmlNamespace(string prefix, string ns) + { + _prefix = prefix; + _namespace = ns; + } + + public string Prefix + { + get { return _prefix; } + } + + public string Namespace + { + get { return _namespace; } + } + + public override bool Equals(object obj) + { + if (obj is XmlNamespace) + { + XmlNamespace o = (XmlNamespace)obj; + return (o.Prefix.Equals(this.Prefix) && o.Namespace.Equals(this.Namespace)); + } + return base.Equals(obj); + } + + public override int GetHashCode() + { + return _prefix.GetHashCode() + _namespace.GetHashCode() >> 20; + } + } + + internal class XmlNamespaceCollection : List + {} +} \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlPIMapping.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlPIMapping.cs new file mode 100644 index 000000000..3c321c8f1 --- /dev/null +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlPIMapping.cs @@ -0,0 +1,63 @@ +// Copyright (c) Cristian Civera (cristian@aspitalia.com) +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; + +namespace Ricciolo.StylesExplorer.MarkupReflection +{ + /// + /// Rappresenta la mappatura tra namespace XML e namespace CLR con relativo assembly + /// + public class XmlPIMapping + { + private string _xmlNamespace; + private short _assemblyId; + private string _clrNamespace; + private static XmlPIMapping _default = new XmlPIMapping(PresentationNamespace, 0, String.Empty); + + public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml"; + public const string PresentationNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; + public const string PresentationOptionsNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"; + public const string McNamespace = "http://schemas.openxmlformats.org/markup-compatibility/2006"; + + public XmlPIMapping(string xmlNamespace, short assemblyId, string clrNamespace) + { + _xmlNamespace = xmlNamespace; + _assemblyId = assemblyId; + _clrNamespace = clrNamespace; + } + + /// + /// Restituisce o imposta il namespace XML + /// + public string XmlNamespace + { + get { return _xmlNamespace; } + set { _xmlNamespace = value;} + } + + /// + /// Restituisce l'id dell'assembly + /// + public short AssemblyId + { + get { return _assemblyId; } + } + + /// + /// Restituisce il namespace clr + /// + public string ClrNamespace + { + get { return _clrNamespace; } + } + + /// + /// Restituisce il mapping di default di WPF + /// + public static XmlPIMapping Presentation + { + get { return _default; } + } + } +} \ No newline at end of file From d3f31d054ea26ead91c7c95bbd13865fe7424ddf Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 23 May 2011 18:08:36 +0200 Subject: [PATCH 64/65] implement basic plug-in --- ILSpy.BamlDecompiler/BamlResourceEntryNode.cs | 61 +++ .../BamlResourceNodeFactory.cs | 29 ++ .../ILSpy.BamlDecompiler.csproj | 63 ++- ILSpy.BamlDecompiler/MyClass.cs | 16 - .../Properties/AssemblyInfo.cs | 4 +- ILSpy/BamlDecompiler.cs | 445 ------------------ ILSpy/CSharpLanguage.cs | 23 +- ILSpy/ILSpy.csproj | 1 - ILSpy/TreeNodes/ILSpyTreeNode.cs | 2 +- ILSpy/TreeNodes/ResourceEntryNode.cs | 2 +- ILSpy/TreeNodes/ResourceTreeNode.cs | 2 +- ILSpy/TreeNodes/XamlResourceNode.cs | 2 +- 12 files changed, 165 insertions(+), 485 deletions(-) create mode 100644 ILSpy.BamlDecompiler/BamlResourceEntryNode.cs create mode 100644 ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs delete mode 100644 ILSpy.BamlDecompiler/MyClass.cs delete mode 100644 ILSpy/BamlDecompiler.cs diff --git a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs new file mode 100644 index 000000000..40d850c4a --- /dev/null +++ b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs @@ -0,0 +1,61 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Xml.Linq; + +using ICSharpCode.AvalonEdit.Highlighting; +using ICSharpCode.ILSpy.TextView; +using ICSharpCode.ILSpy.TreeNodes; +using Ricciolo.StylesExplorer.MarkupReflection; + +namespace ILSpy.BamlDecompiler +{ + public sealed class BamlResourceEntryNode : ResourceEntryNode + { + public BamlResourceEntryNode(string key, Stream data) : base(key, data) + { + } + + public override bool View(DecompilerTextView textView) + { + AvalonEditTextOutput output = new AvalonEditTextOutput(); + IHighlightingDefinition highlighting = null; + + textView.RunWithCancellation( + token => Task.Factory.StartNew( + () => { + try { + if (LoadBaml(output)) + highlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml"); + } catch (Exception ex) { + output.Write(ex.ToString()); + } + return output; + }), + t => textView.ShowNode(t.Result, this, highlighting) + ); + return true; + } + + bool LoadBaml(AvalonEditTextOutput output) + { + var asm = this.Ancestors().OfType().FirstOrDefault().LoadedAssembly; + MemoryStream bamlStream = new MemoryStream(); + Data.Position = 0; + Data.CopyTo(bamlStream); + bamlStream.Position = 0; + + XDocument xamlDocument; + using (XmlBamlReader reader = new XmlBamlReader(bamlStream)) + xamlDocument = XDocument.Load(reader); + + output.Write(xamlDocument.ToString()); + return true; + } + } +} \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs new file mode 100644 index 000000000..a1b77fb6b --- /dev/null +++ b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs @@ -0,0 +1,29 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) + +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; + +using ICSharpCode.ILSpy.TreeNodes; + +namespace ILSpy.BamlDecompiler +{ + [Export(typeof(IResourceNodeFactory))] + public sealed class BamlResourceNodeFactory : IResourceNodeFactory + { + public ILSpyTreeNode CreateNode(Mono.Cecil.Resource resource) + { + return null; + } + + public ILSpyTreeNode CreateNode(string key, Stream data) + { + if (key.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) + return new BamlResourceEntryNode(key, data); + else + return null; + } + } +} diff --git a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj index 7424fec6f..587959be6 100644 --- a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj +++ b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj @@ -6,42 +6,66 @@ x86 Library ILSpy.BamlDecompiler - ILSpy.BamlDecompiler + ILSpy.BamlDecompiler.Plugin v4.0 Client Properties + False + False + 4 + false x86 + False + Auto + 4194304 + 4096 - bin\Debug\ - True + ..\ILSpy\bin\Debug\ + true Full False True DEBUG;TRACE - bin\Release\ - False + ..\ILSpy\bin\Release\ + false None True False TRACE + + 3.0 + + + 3.0 + + + 4.0 + 3.5 + + 4.0 + 3.5 + + 3.0 + - + + @@ -69,5 +93,32 @@ + + + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1} + ICSharpCode.AvalonEdit + False + + + {984CC812-9470-4A13-AFF9-CC44068D666C} + ICSharpCode.Decompiler + False + + + {1E85EFF9-E370-4683-83E4-8A3D063FF791} + ILSpy + False + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + False + + + {DDE2A481-8271-4EAC-A330-8FA6A38D13D1} + ICSharpCode.TreeView + False + + \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/MyClass.cs b/ILSpy.BamlDecompiler/MyClass.cs deleted file mode 100644 index f89c0f24e..000000000 --- a/ILSpy.BamlDecompiler/MyClass.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt) - -using System; -using System.Collections.Generic; - -namespace ILSpy.BamlDecompiler -{ - /// - /// Description of MyClass. - /// - public class MyClass - { - - } -} \ No newline at end of file diff --git a/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs b/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs index 54a525812..f28440c93 100644 --- a/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs +++ b/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs @@ -9,11 +9,11 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("ILSpy.BamlDecompiler")] +[assembly: AssemblyTitle("ILSpy.BamlDecompiler.Plugin")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ILSpy.BamlDecompiler")] +[assembly: AssemblyProduct("ILSpy.BamlDecompiler.Plugin")] [assembly: AssemblyCopyright("Copyright 2011")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/ILSpy/BamlDecompiler.cs b/ILSpy/BamlDecompiler.cs deleted file mode 100644 index 07c60b13e..000000000 --- a/ILSpy/BamlDecompiler.cs +++ /dev/null @@ -1,445 +0,0 @@ -// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.ComponentModel.Composition; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using System.Windows.Baml2006; -using System.Xaml; -using System.Xaml.Schema; -using System.Xml; -using System.Xml.Linq; -using ICSharpCode.AvalonEdit.Highlighting; -using ICSharpCode.ILSpy.TextView; -using ICSharpCode.ILSpy.TreeNodes; -using System.Diagnostics; -using System.Collections; -using System.Collections.Generic; - -namespace ICSharpCode.ILSpy.Baml -{ - /// Caution: use in separate AppDomain only! - sealed class BamlDecompiler : MarshalByRefObject - { - public BamlDecompiler() - { - } - - abstract class XamlNode - { - public readonly List Children = new List(); - - public abstract void WriteTo(XamlWriter writer); - } - - [Conditional("DEBUG")] - static void Log(string format, params object[] args) - { - Debug.WriteLine(format, args); - } - - sealed class XamlObjectNode : XamlNode - { - public readonly XamlType Type; - - public XamlObjectNode(XamlType type) - { - this.Type = type; - } - - public override void WriteTo(XamlWriter writer) - { - Log("StartObject {0}", this.Type); - writer.WriteStartObject(this.Type); - Debug.Indent(); - foreach (XamlNode node in this.Children) - node.WriteTo(writer); - Debug.Unindent(); - Log("EndObject"); - writer.WriteEndObject(); - } - } - - sealed class XamlGetObjectNode : XamlNode - { - public override void WriteTo(XamlWriter writer) - { - Log("GetObject"); - writer.WriteGetObject(); - Debug.Indent(); - foreach (XamlNode node in this.Children) - node.WriteTo(writer); - Debug.Unindent(); - Log("EndObject"); - writer.WriteEndObject(); - } - } - - sealed class XamlMemberNode : XamlNode - { - public XamlMember Member; - - public XamlMemberNode(XamlMember member) - { - this.Member = member; - } - - public override void WriteTo(XamlWriter writer) - { - Log("StartMember {0}", this.Member); - writer.WriteStartMember(this.Member); - Debug.Indent(); - foreach (XamlNode node in this.Children) - node.WriteTo(writer); - Debug.Unindent(); - Log("EndMember"); - writer.WriteEndMember(); - } - } - - sealed class XamlValueNode : XamlNode - { - public readonly object Value; - - public XamlValueNode(object value) - { - this.Value = value; - } - - public override void WriteTo(XamlWriter writer) - { - Log("Value {0}", this.Value); - Debug.Assert(this.Children.Count == 0); - // requires XamlReaderSettings.ValuesMustBeString = true to work properly - writer.WriteValue(this.Value); - } - } - - sealed class XamlNamespaceDeclarationNode : XamlNode - { - public readonly NamespaceDeclaration Namespace; - - public XamlNamespaceDeclarationNode(NamespaceDeclaration @namespace) - { - this.Namespace = @namespace; - } - - public override void WriteTo(XamlWriter writer) - { - Log("NamespaceDeclaration {0}", this.Namespace); - Debug.Assert(this.Children.Count == 0); - writer.WriteNamespace(this.Namespace); - } - } - - static List Parse(XamlReader reader) - { - List currentList = new List(); - Stack> stack = new Stack>(); - while (reader.Read()) { - switch (reader.NodeType) { - case XamlNodeType.None: - break; - case XamlNodeType.StartObject: - XamlObjectNode obj = new XamlObjectNode(reader.Type); - currentList.Add(obj); - stack.Push(currentList); - currentList = obj.Children; - break; - case XamlNodeType.GetObject: - XamlGetObjectNode getObject = new XamlGetObjectNode(); - currentList.Add(getObject); - stack.Push(currentList); - currentList = getObject.Children; - break; - case XamlNodeType.StartMember: - XamlMemberNode member = new XamlMemberNode(reader.Member); - currentList.Add(member); - stack.Push(currentList); - currentList = member.Children; - break; - case XamlNodeType.Value: - currentList.Add(new XamlValueNode(reader.Value)); - break; - case XamlNodeType.NamespaceDeclaration: - currentList.Add(new XamlNamespaceDeclarationNode(reader.Namespace)); - break; - case XamlNodeType.EndObject: - case XamlNodeType.EndMember: - currentList = stack.Pop(); - break; - default: - throw new InvalidOperationException("Invalid value for XamlNodeType"); - } - } - if (stack.Count != 0) - throw new InvalidOperationException("Imbalanced stack"); - return currentList; - } - - void AvoidContentProperties(XamlNode node) - { - foreach (XamlNode child in node.Children) - AvoidContentProperties(child); - - - XamlObjectNode obj = node as XamlObjectNode; - if (obj != null) { - // Visit all except for the last child: - for (int i = 0; i < obj.Children.Count - 1; i++) { - // Avoids using content property syntax for simple string values, if the content property is not the last member. - // Without this, we cannot decompile <GridViewColumn Header="Culture" DisplayMemberBinding="{Binding Culture}" />, - // because the Header property is the content property, but there is no way to represent the Binding as an element. - XamlMemberNode memberNode = obj.Children[i] as XamlMemberNode; - if (memberNode != null && memberNode.Member == obj.Type.ContentProperty) { - if (memberNode.Children.Count == 1 && memberNode.Children[0] is XamlValueNode) { - // By creating a clone of the XamlMember, we prevent WPF from knowing that it's the content property. - XamlMember member = memberNode.Member; - memberNode.Member = new XamlMember(member.Name, member.DeclaringType, member.IsAttachable); - } - } - } - // We also need to avoid using content properties that have a markup extension as value, as the XamlXmlWriter would always expand those: - for (int i = 0; i < obj.Children.Count; i++) { - XamlMemberNode memberNode = obj.Children[i] as XamlMemberNode; - if (memberNode != null && memberNode.Member == obj.Type.ContentProperty && memberNode.Children.Count == 1) { - XamlObjectNode me = memberNode.Children[0] as XamlObjectNode; - if (me != null && me.Type.IsMarkupExtension) { - // By creating a clone of the XamlMember, we prevent WPF from knowing that it's the content property. - XamlMember member = memberNode.Member; - memberNode.Member = new XamlMember(member.Name, member.DeclaringType, member.IsAttachable); - } - } - } - } - } - - /// - /// It seems like BamlReader will always output 'x:Key' as last property. However, it must be specified as attribute in valid .xaml, so we move it to the front - /// of the attribute list. - /// - void MoveXKeyToFront(XamlNode node) - { - foreach (XamlNode child in node.Children) - MoveXKeyToFront(child); - - XamlObjectNode obj = node as XamlObjectNode; - if (obj != null && obj.Children.Count > 0) { - XamlMemberNode memberNode = obj.Children[obj.Children.Count - 1] as XamlMemberNode; - if (memberNode != null && memberNode.Member == XamlLanguage.Key) { - // move memberNode in front of the first member node: - for (int i = 0; i < obj.Children.Count; i++) { - if (obj.Children[i] is XamlMemberNode) { - obj.Children.Insert(i, memberNode); - obj.Children.RemoveAt(obj.Children.Count - 1); - break; - } - } - } - } - } - - AssemblyResolver asmResolver; - - Assembly AssemblyResolve(object sender, ResolveEventArgs args) - { - string path = asmResolver.FindAssembly(args.Name); - - if (path == null) - return null; - - return Assembly.LoadFile(path); - } - - public string DecompileBaml(MemoryStream bamlCode, string containingAssemblyFile, ConnectMethodDecompiler connectMethodDecompiler, AssemblyResolver asmResolver) - { - this.asmResolver = asmResolver; - AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve; - - bamlCode.Position = 0; - TextWriter w = new StringWriter(); - - Assembly assembly = Assembly.LoadFile(containingAssemblyFile); - - Baml2006Reader reader = new Baml2006Reader(bamlCode, new XamlReaderSettings() { ValuesMustBeString = true, LocalAssembly = assembly }); - var xamlDocument = Parse(reader); - - string bamlTypeName = xamlDocument.OfType().First().Type.UnderlyingType.FullName; - - var eventMappings = connectMethodDecompiler.DecompileEventMappings(bamlTypeName); - - foreach (var xamlNode in xamlDocument) { - RemoveConnectionIds(xamlNode, eventMappings, reader.SchemaContext); - AvoidContentProperties(xamlNode); - MoveXKeyToFront(xamlNode); - } - - XDocument doc = new XDocument(); - XamlXmlWriter writer = new XamlXmlWriter(doc.CreateWriter(), reader.SchemaContext, new XamlXmlWriterSettings { AssumeValidInput = true }); - foreach (var xamlNode in xamlDocument) - xamlNode.WriteTo(writer); - writer.Close(); - - // Fix namespace references - string suffixToRemove = ";assembly=" + assembly.GetName().Name; - foreach (XAttribute attrib in doc.Root.Attributes()) { - if (attrib.Name.Namespace == XNamespace.Xmlns) { - if (attrib.Value.EndsWith(suffixToRemove, StringComparison.Ordinal)) { - string newNamespace = attrib.Value.Substring(0, attrib.Value.Length - suffixToRemove.Length); - ChangeXmlNamespace(doc, attrib.Value, newNamespace); - attrib.Value = newNamespace; - } - } - } - - return doc.ToString(); - } - - void RemoveConnectionIds(XamlNode node, Dictionary eventMappings, XamlSchemaContext context) - { - foreach (XamlNode child in node.Children) - RemoveConnectionIds(child, eventMappings, context); - - XamlObjectNode obj = node as XamlObjectNode; - if (obj != null && obj.Children.Count > 0) { - var removableNodes = new List(); - var addableNodes = new List(); - foreach (XamlMemberNode memberNode in obj.Children.OfType()) { - if (memberNode.Member == XamlLanguage.ConnectionId && memberNode.Children.Single() is XamlValueNode) { - var value = memberNode.Children.Single() as XamlValueNode; - int id; - if (value.Value is string && int.TryParse(value.Value as string, out id) && eventMappings.ContainsKey(id)) { - var map = eventMappings[id]; - foreach (var entry in map) { - if (entry.IsAttached) { - var type = context.GetXamlType(Type.GetType(entry.AttachSourceType)); - var member = new XamlMemberNode(new XamlMember(entry.EventName, type, true)); - member.Children.Add(new XamlValueNode(entry.MethodName)); - addableNodes.Add(member); - } else { - var member = new XamlMemberNode(obj.Type.GetMember(entry.EventName)); - member.Children.Add(new XamlValueNode(entry.MethodName)); - addableNodes.Add(member); - } - } - removableNodes.Add(memberNode); - } - } - } - foreach (var rnode in removableNodes) - node.Children.Remove(rnode); - node.Children.InsertRange(node.Children.Count > 1 ? node.Children.Count - 1 : 0, addableNodes); - } - } - - /// - /// Changes all references from oldNamespace to newNamespace in the document. - /// - void ChangeXmlNamespace(XDocument doc, XNamespace oldNamespace, XNamespace newNamespace) - { - foreach (XElement e in doc.Descendants()) { - if (e.Name.Namespace == oldNamespace) - e.Name = newNamespace + e.Name.LocalName; - } - } - } - - [Export(typeof(IResourceNodeFactory))] - sealed class BamlResourceNodeFactory : IResourceNodeFactory - { - public ILSpyTreeNode CreateNode(Mono.Cecil.Resource resource) - { - return null; - } - - public ILSpyTreeNode CreateNode(string key, Stream data) - { - if (key.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) - return new BamlResourceEntryNode(key, data); - else - return null; - } - } - - sealed class BamlResourceEntryNode : ResourceEntryNode - { - public BamlResourceEntryNode(string key, Stream data) : base(key, data) - { - } - - internal override bool View(DecompilerTextView textView) - { - AvalonEditTextOutput output = new AvalonEditTextOutput(); - IHighlightingDefinition highlighting = null; - - textView.RunWithCancellation( - token => Task.Factory.StartNew( - () => { - try { - if (LoadBaml(output)) - highlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml"); - } catch (Exception ex) { - output.Write(ex.ToString()); - } - return output; - }), - t => textView.ShowNode(t.Result, this, highlighting) - ); - return true; - } - - bool LoadBaml(AvalonEditTextOutput output) - { - var asm = this.Ancestors().OfType().FirstOrDefault().LoadedAssembly; - - AppDomain bamlDecompilerAppDomain = null; - try { - BamlDecompiler decompiler = CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, asm.FileName); - - MemoryStream bamlStream = new MemoryStream(); - Data.Position = 0; - Data.CopyTo(bamlStream); - - output.Write(decompiler.DecompileBaml(bamlStream, asm.FileName, new ConnectMethodDecompiler(asm), new AssemblyResolver(asm))); - return true; - } finally { - if (bamlDecompilerAppDomain != null) - AppDomain.Unload(bamlDecompilerAppDomain); - } - } - - public static BamlDecompiler CreateBamlDecompilerInAppDomain(ref AppDomain appDomain, string assemblyFileName) - { - if (appDomain == null) { - // Construct and initialize settings for a second AppDomain. - AppDomainSetup bamlDecompilerAppDomainSetup = new AppDomainSetup(); -// bamlDecompilerAppDomainSetup.ApplicationBase = "file:///" + Path.GetDirectoryName(assemblyFileName); - bamlDecompilerAppDomainSetup.DisallowBindingRedirects = false; - bamlDecompilerAppDomainSetup.DisallowCodeDownload = true; - bamlDecompilerAppDomainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; - - // Create the second AppDomain. - appDomain = AppDomain.CreateDomain("BamlDecompiler AD", null, bamlDecompilerAppDomainSetup); - } - return (BamlDecompiler)appDomain.CreateInstanceAndUnwrap(typeof(BamlDecompiler).Assembly.FullName, typeof(BamlDecompiler).FullName); - } - } -} \ No newline at end of file diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs index 2408055fc..ad3ee5ae1 100644 --- a/ILSpy/CSharpLanguage.cs +++ b/ILSpy/CSharpLanguage.cs @@ -437,17 +437,18 @@ namespace ICSharpCode.ILSpy if (fileName.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) { MemoryStream ms = new MemoryStream(); entryStream.CopyTo(ms); - var decompiler = Baml.BamlResourceEntryNode.CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, assembly.FileName); - string xaml = null; - try { - xaml = decompiler.DecompileBaml(ms, assembly.FileName, new ConnectMethodDecompiler(assembly), new AssemblyResolver(assembly)); - } - catch (XamlXmlWriterException) { } // ignore XAML writer exceptions - if (xaml != null) { - File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml); - yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml")); - continue; - } + // TODO implement extension point +// var decompiler = Baml.BamlResourceEntryNode.CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, assembly.FileName); +// string xaml = null; +// try { +// xaml = decompiler.DecompileBaml(ms, assembly.FileName, new ConnectMethodDecompiler(assembly), new AssemblyResolver(assembly)); +// } +// catch (XamlXmlWriterException) { } // ignore XAML writer exceptions +// if (xaml != null) { +// File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml); +// yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml")); +// continue; +// } } using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) { entryStream.CopyTo(fs); diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 0bda1e382..3eaca83ce 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -93,7 +93,6 @@ - diff --git a/ILSpy/TreeNodes/ILSpyTreeNode.cs b/ILSpy/TreeNodes/ILSpyTreeNode.cs index 0ead7be94..ea92d8f22 100644 --- a/ILSpy/TreeNodes/ILSpyTreeNode.cs +++ b/ILSpy/TreeNodes/ILSpyTreeNode.cs @@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes /// This method is called on the main thread when only a single item is selected. /// If it returns false, normal decompilation is used to view the item. /// - internal virtual bool View(TextView.DecompilerTextView textView) + public virtual bool View(TextView.DecompilerTextView textView) { return false; } diff --git a/ILSpy/TreeNodes/ResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceEntryNode.cs index 43638064d..cddab8326 100644 --- a/ILSpy/TreeNodes/ResourceEntryNode.cs +++ b/ILSpy/TreeNodes/ResourceEntryNode.cs @@ -132,7 +132,7 @@ namespace ICSharpCode.ILSpy.TreeNodes get { return Images.ResourceImage; } } - internal override bool View(DecompilerTextView textView) + public override bool View(DecompilerTextView textView) { try { AvalonEditTextOutput output = new AvalonEditTextOutput(); diff --git a/ILSpy/TreeNodes/ResourceTreeNode.cs b/ILSpy/TreeNodes/ResourceTreeNode.cs index 5e79845ba..1c1a1f08a 100644 --- a/ILSpy/TreeNodes/ResourceTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceTreeNode.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } } - internal override bool View(DecompilerTextView textView) + public override bool View(DecompilerTextView textView) { EmbeddedResource er = r as EmbeddedResource; if (er != null) { diff --git a/ILSpy/TreeNodes/XamlResourceNode.cs b/ILSpy/TreeNodes/XamlResourceNode.cs index 0ed226a1d..13912e348 100644 --- a/ILSpy/TreeNodes/XamlResourceNode.cs +++ b/ILSpy/TreeNodes/XamlResourceNode.cs @@ -52,7 +52,7 @@ namespace ICSharpCode.ILSpy.Xaml { } - internal override bool View(DecompilerTextView textView) + public override bool View(DecompilerTextView textView) { AvalonEditTextOutput output = new AvalonEditTextOutput(); IHighlightingDefinition highlighting = null; From 1bd14655d07583ae251ca62783b8e12d82f34f05 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 23 May 2011 18:11:55 +0200 Subject: [PATCH 65/65] Ricciolo.StylesExplorer.MarkupReflection FIX: properly set _eof when reaching end of file --- .../XmlBamlReader.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs index ceb8b0f15..615c02d4d 100644 --- a/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs +++ b/ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs @@ -264,7 +264,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection //while (currentType != BamlRecordType.DocumentEnd); while (nodes.Count == 0 || (currentType != BamlRecordType.ElementEnd) || complexPropertyOpened > 0); - return SetNextNode(); + if (!SetNextNode()) { + _eof = true; + return false; + } + return true; } catch (EndOfStreamException) {