Browse Source

Merge branch 'master' of git://github.com/icsharpcode/ILSpy

pull/205/head
Pent Ploompuu 15 years ago
parent
commit
77c3be280b
  1. 49
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 2
      ICSharpCode.Decompiler/Ast/NameVariables.cs
  3. 15
      ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs
  4. 4
      ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  5. 133
      ICSharpCode.Decompiler/CodeMappings.cs
  6. 35
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  7. 19
      ICSharpCode.Decompiler/ILAst/GotoRemoval.cs
  8. 9
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  9. 4
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  10. 2
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  11. 1
      ICSharpCode.Decompiler/ITextOutput.cs
  12. 20
      ICSharpCode.Decompiler/PlainTextOutput.cs
  13. 8
      ICSharpCode.Decompiler/Tests/Generics.cs
  14. 2
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  15. 2
      ICSharpCode.Decompiler/Tests/TestRunner.cs
  16. 57
      ILSpy.BamlDecompiler/BamlResourceEntryNode.cs
  17. 10
      ILSpy.BamlDecompiler/CecilType.cs
  18. 25
      ILSpy.BamlDecompiler/CecilTypeResolver.cs
  19. 22
      ILSpy.BamlDecompiler/Extensions.cs
  20. 2
      ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
  21. 3
      ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs
  22. 11
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs
  23. 6
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs
  24. 3
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs
  25. 2
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs
  26. 36
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs
  27. 5
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs
  28. 58
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs
  29. 34
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlSimpleProperty.cs
  30. 3
      ILSpy.BamlDecompiler/Tests/Cases/Simple.xaml
  31. 26
      ILSpy.BamlDecompiler/Tests/Cases/Simple.xaml.cs
  32. 1
      ILSpy.BamlDecompiler/Tests/Cases/SimpleDictionary.xaml
  33. 109
      ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj
  34. 31
      ILSpy.BamlDecompiler/Tests/Properties/AssemblyInfo.cs
  35. 73
      ILSpy.BamlDecompiler/Tests/TestRunner.cs
  36. 12
      ILSpy.sln
  37. 5
      ILSpy/AboutPage.cs
  38. 36
      ILSpy/AnalyzerTreeView.cs
  39. 123
      ILSpy/AvalonEdit/ITextMarker.cs
  40. 83
      ILSpy/AvalonEdit/IconBarManager.cs
  41. 243
      ILSpy/AvalonEdit/IconBarMargin.cs
  42. 189
      ILSpy/AvalonEdit/IconMarginActionsProvider.cs
  43. 67
      ILSpy/AvalonEdit/TextEditorWeakEventManager.cs
  44. 292
      ILSpy/AvalonEdit/TextMarkerService.cs
  45. 97
      ILSpy/Bookmarks/BookmarkBase.cs
  46. 28
      ILSpy/Bookmarks/BookmarkEventHandler.cs
  47. 116
      ILSpy/Bookmarks/BookmarkManager.cs
  48. 50
      ILSpy/Bookmarks/Commands.cs
  49. 69
      ILSpy/Bookmarks/IBookmark.cs
  50. 21
      ILSpy/Bookmarks/MarkerBookmark.cs
  51. 157
      ILSpy/Bookmarks/MemberBookmark.cs
  52. 178
      ILSpy/Commands.cs
  53. 32
      ILSpy/Commands/BrowseBackCommand.cs
  54. 32
      ILSpy/Commands/BrowseForwardCommand.cs
  55. 58
      ILSpy/Commands/CommandWrapper.cs
  56. 69
      ILSpy/Commands/DecompileAllCommand.cs
  57. 31
      ILSpy/Commands/ExitCommand.cs
  58. 0
      ILSpy/Commands/ExportCommandAttribute.cs
  59. 33
      ILSpy/Commands/OpenCommand.cs
  60. 34
      ILSpy/Commands/OpenFromGacCommand.cs
  61. 33
      ILSpy/Commands/RefreshCommand.cs
  62. 32
      ILSpy/Commands/SaveCommand.cs
  63. 31
      ILSpy/Commands/ShowAnalyzerCommand.cs
  64. 39
      ILSpy/Commands/SimpleCommand.cs
  65. 61
      ILSpy/ILSpy.csproj
  66. 27
      ILSpy/IPane.cs
  67. BIN
      ILSpy/Images/Delete.png
  68. 3
      ILSpy/Images/Images.cs
  69. BIN
      ILSpy/Images/OverlayInternal.png
  70. BIN
      ILSpy/Images/OverlayProtected.png
  71. BIN
      ILSpy/Images/OverlayProtectedInternal.png
  72. BIN
      ILSpy/Images/ResourceXml.png
  73. BIN
      ILSpy/Images/ResourceXsd.png
  74. BIN
      ILSpy/Images/ResourceXslt.png
  75. 48
      ILSpy/Languages/CSharpLanguage.cs
  76. 0
      ILSpy/Languages/ILAstLanguage.cs
  77. 18
      ILSpy/Languages/ILLanguage.cs
  78. 105
      ILSpy/Languages/Language.cs
  79. 60
      ILSpy/Languages/Languages.cs
  80. 5
      ILSpy/LoadedAssembly.cs
  81. 2
      ILSpy/Properties/AssemblyInfo.template.cs
  82. 8
      ILSpy/SearchPane.cs
  83. 81
      ILSpy/TextView/DecompilerTextView.cs
  84. 43
      ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
  85. 6
      ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs
  86. 8
      ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs
  87. 11
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs
  88. 15
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs
  89. 15
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs
  90. 15
      ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs
  91. 10
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs
  92. 7
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs
  93. 17
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs
  94. 8
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  95. 33
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs
  96. 8
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs
  97. 11
      ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs
  98. 13
      ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs
  99. 104
      ILSpy/TreeNodes/BaseTypesEntryNode.cs
  100. 96
      ILSpy/TreeNodes/BaseTypesTreeNode.cs
  101. Some files were not shown because too many files have changed in this diff Show More

49
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.Ast
DoNotUsePrimitiveTypeNames = 4
}
public class AstBuilder : ICodeMappings
public class AstBuilder : BaseCodeMappings
{
DecompilerContext context;
CompilationUnit astCompileUnit = new CompilationUnit();
@ -65,6 +65,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -65,6 +65,8 @@ namespace ICSharpCode.Decompiler.Ast
this.DecompileMethodBodies = true;
this.LocalVariables = new ConcurrentDictionary<int, IEnumerable<ILVariable>>();
this.CodeMappings = new Dictionary<int, List<MemberMapping>>();
this.DecompiledMemberReferences = new Dictionary<int, MemberReference>();
}
public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings)
@ -259,10 +261,6 @@ namespace ICSharpCode.Decompiler.Ast @@ -259,10 +261,6 @@ namespace ICSharpCode.Decompiler.Ast
/// <returns>TypeDeclaration or DelegateDeclaration.</returns>
public AttributedNode CreateType(TypeDefinition typeDef)
{
// create CSharp code mappings - used for debugger
if (this.CodeMappings == null)
this.CodeMappings = new Tuple<string, List<MemberMapping>>(typeDef.FullName, new List<MemberMapping>());
// create type
TypeDefinition oldCurrentType = context.CurrentType;
context.CurrentType = typeDef;
@ -732,7 +730,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -732,7 +730,8 @@ namespace ICSharpCode.Decompiler.Ast
AttributedNode CreateMethod(MethodDefinition methodDef)
{
// Create mapping - used in debugger
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings);
CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef);
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[methodDef.MetadataToken.ToInt32()]);
MethodDeclaration astMethod = new MethodDeclaration().WithAnnotation(methodMapping);
astMethod.AddAnnotation(methodDef);
@ -820,7 +819,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -820,7 +819,8 @@ namespace ICSharpCode.Decompiler.Ast
ConstructorDeclaration CreateConstructor(MethodDefinition methodDef)
{
// Create mapping - used in debugger
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings);
CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef);
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[methodDef.MetadataToken.ToInt32()]);
ConstructorDeclaration astMethod = new ConstructorDeclaration();
astMethod.AddAnnotation(methodDef);
@ -884,9 +884,11 @@ namespace ICSharpCode.Decompiler.Ast @@ -884,9 +884,11 @@ namespace ICSharpCode.Decompiler.Ast
}
astProp.Name = CleanName(propDef.Name);
astProp.ReturnType = ConvertType(propDef.PropertyType, propDef);
if (propDef.GetMethod != null) {
// Create mapping - used in debugger
MemberMapping methodMapping = propDef.GetMethod.CreateCodeMapping(this.CodeMappings);
CreateCodeMappings(propDef.GetMethod.MetadataToken.ToInt32(), propDef);
MemberMapping methodMapping = propDef.GetMethod.CreateCodeMapping(this.CodeMappings[propDef.GetMethod.MetadataToken.ToInt32()], propDef);
astProp.Getter = new Accessor();
astProp.Getter.Body = CreateMethodBody(propDef.GetMethod);
@ -900,7 +902,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -900,7 +902,8 @@ namespace ICSharpCode.Decompiler.Ast
}
if (propDef.SetMethod != null) {
// Create mapping - used in debugger
MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings);
CreateCodeMappings(propDef.SetMethod.MetadataToken.ToInt32(), propDef);
MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings[propDef.SetMethod.MetadataToken.ToInt32()], propDef);
astProp.Setter = new Accessor();
astProp.Setter.Body = CreateMethodBody(propDef.SetMethod);
@ -967,9 +970,11 @@ namespace ICSharpCode.Decompiler.Ast @@ -967,9 +970,11 @@ namespace ICSharpCode.Decompiler.Ast
astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod);
else
astEvent.PrivateImplementationType = ConvertType(eventDef.AddMethod.Overrides.First().DeclaringType);
if (eventDef.AddMethod != null) {
// Create mapping - used in debugger
MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings);
CreateCodeMappings(eventDef.AddMethod.MetadataToken.ToInt32(), eventDef);
MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[eventDef.AddMethod.MetadataToken.ToInt32()], eventDef);
astEvent.AddAccessor = new Accessor {
Body = CreateMethodBody(eventDef.AddMethod)
@ -980,7 +985,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -980,7 +985,8 @@ namespace ICSharpCode.Decompiler.Ast
}
if (eventDef.RemoveMethod != null) {
// Create mapping - used in debugger
MemberMapping methodMapping = eventDef.RemoveMethod.CreateCodeMapping(this.CodeMappings);
CreateCodeMappings(eventDef.RemoveMethod.MetadataToken.ToInt32(), eventDef);
MemberMapping methodMapping = eventDef.RemoveMethod.CreateCodeMapping(this.CodeMappings[eventDef.RemoveMethod.MetadataToken.ToInt32()], eventDef);
astEvent.RemoveAccessor = new Accessor {
Body = CreateMethodBody(eventDef.RemoveMethod)
@ -1009,6 +1015,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -1009,6 +1015,8 @@ namespace ICSharpCode.Decompiler.Ast
FieldDeclaration CreateField(FieldDefinition fieldDef)
{
this.DecompiledMemberReferences.Add(fieldDef.MetadataToken.ToInt32(), fieldDef);
FieldDeclaration astField = new FieldDeclaration();
astField.AddAnnotation(fieldDef);
VariableInitializer initializer = new VariableInitializer(CleanName(fieldDef.Name));
@ -1151,7 +1159,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1151,7 +1159,7 @@ namespace ICSharpCode.Decompiler.Ast
MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
#region DllImportAttribute
if (methodDefinition.HasPInvokeInfo) {
if (methodDefinition.HasPInvokeInfo && methodDefinition.PInvokeInfo != null) {
PInvokeInfo info = methodDefinition.PInvokeInfo;
Ast.Attribute dllImport = CreateNonCustomAttribute(typeof(DllImportAttribute));
dllImport.Arguments.Add(new PrimitiveExpression(info.Module.Name));
@ -1501,13 +1509,13 @@ namespace ICSharpCode.Decompiler.Ast @@ -1501,13 +1509,13 @@ namespace ICSharpCode.Decompiler.Ast
{ // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs)
TypeDefinition enumDefinition = type.Resolve();
if (enumDefinition != null && enumDefinition.IsEnum) {
TypeCode enumBaseTypeCode = TypeCode.Int32;
foreach (FieldDefinition field in enumDefinition.Fields) {
if (field.IsStatic && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val))
return ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field);
return ConvertType(type).Member(field.Name).WithAnnotation(field);
else if (!field.IsStatic && field.IsRuntimeSpecialName)
type = field.FieldType; // use primitive type of the enum
enumBaseTypeCode = TypeAnalysis.GetTypeCode(field.FieldType); // use primitive type of the enum
}
TypeCode enumBaseTypeCode = TypeAnalysis.GetTypeCode(type);
if (IsFlagsEnum(enumDefinition)) {
long enumValue = val;
Expression expr = null;
@ -1534,7 +1542,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1534,7 +1542,7 @@ namespace ICSharpCode.Decompiler.Ast
continue; // skip None enum value
if ((fieldValue & enumValue) == fieldValue) {
var fieldExpression = ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field);
var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field);
if (expr == null)
expr = fieldExpression;
else
@ -1543,7 +1551,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1543,7 +1551,7 @@ namespace ICSharpCode.Decompiler.Ast
enumValue &= ~fieldValue;
}
if ((fieldValue & negatedEnumValue) == fieldValue) {
var fieldExpression = ConvertType(enumDefinition).Member(field.Name).WithAnnotation(field);
var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field);
if (negatedExpr == null)
negatedExpr = fieldExpression;
else
@ -1561,7 +1569,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1561,7 +1569,7 @@ namespace ICSharpCode.Decompiler.Ast
return new UnaryOperatorExpression(UnaryOperatorType.BitNot, negatedExpr);
}
}
return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(enumDefinition));
return new Ast.PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(type));
}
}
TypeCode code = TypeAnalysis.GetTypeCode(type);
@ -1655,11 +1663,6 @@ namespace ICSharpCode.Decompiler.Ast @@ -1655,11 +1663,6 @@ namespace ICSharpCode.Decompiler.Ast
&& TypesHierarchyHelpers.IsVisibleFromDerived(m, derived.DeclaringType));
}
/// <summary>
/// <inheritdoc/>
/// </summary>
public Tuple<string, List<MemberMapping>> CodeMappings { get; private set; }
/// <summary>
/// Gets the local variables for the current decompiled type, method, etc.
/// <remarks>The key is the metadata token.</remarks>

2
ICSharpCode.Decompiler/Ast/NameVariables.cs

@ -288,6 +288,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -288,6 +288,8 @@ namespace ICSharpCode.Decompiler.Ast
string GetNameByType(TypeReference type)
{
type = TypeAnalysis.UnpackModifiers(type);
GenericInstanceType git = type as GenericInstanceType;
if (git != null && git.ElementType.FullName == "System.Nullable`1" && git.GenericArguments.Count == 1) {
type = ((GenericInstanceType)type).GenericArguments[0];

15
ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs

@ -148,9 +148,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -148,9 +148,9 @@ namespace ICSharpCode.Decompiler.Ast
public void StartNode(AstNode node)
{
// code mappings
var ranges = node.Annotation<List<ILRange>>();
if (ranges != null && ranges.Count > 0)
{
if (ranges != null && ranges.Count > 0) {
// find the ancestor that has method mapping as annotation
if (node.Parent != null)
{
@ -170,6 +170,17 @@ namespace ICSharpCode.Decompiler.Ast @@ -170,6 +170,17 @@ namespace ICSharpCode.Decompiler.Ast
}
}
// definitions of types and their members
Predicate<AstNode> predicate = n => n is AttributedNode;
if (predicate(node)) {
var n = node as AttributedNode;
int c = 0;
if (n != null)
c = n.Attributes.Count;
node.AddAnnotation(Tuple.Create(output.CurrentLine + c, output.CurrentColumn));
}
nodeStack.Push(node);
}

4
ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

@ -136,6 +136,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -136,6 +136,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
// Create AnonymousMethodExpression and prepare parameters
AnonymousMethodExpression ame = new AnonymousMethodExpression();
ame.CopyAnnotationsFrom(objectCreateExpression); // copy ILRanges etc.
ame.RemoveAnnotations<MethodReference>(); // remove reference to delegate ctor
ame.AddAnnotation(method); // add reference to anonymous method
ame.Parameters.AddRange(AstBuilder.MakeParameters(method, isLambda: true));
ame.HasParameterList = true;
@ -180,6 +183,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -180,6 +183,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
if (isLambda) {
LambdaExpression lambda = new LambdaExpression();
lambda.CopyAnnotationsFrom(ame);
ame.Parameters.MoveTo(lambda.Parameters);
Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression;
returnExpr.Remove();

133
ICSharpCode.Decompiler/CodeMappings.cs

@ -35,14 +35,36 @@ namespace ICSharpCode.Decompiler @@ -35,14 +35,36 @@ namespace ICSharpCode.Decompiler
}
/// <summary>
/// Interface for decompliler classes : AstBuilder & ReflectionDisassembler.
/// Base class for decompliler classes : AstBuilder & ReflectionDisassembler.
/// </summary>
public interface ICodeMappings
public abstract class BaseCodeMappings
{
/// <summary>
/// Gets the code mappings.
/// <remarks>Key is the metadata token.</remarks>
/// </summary>
Tuple<string, List<MemberMapping>> CodeMappings { get; }
public Dictionary<int, List<MemberMapping>> CodeMappings { get; protected set; }
/// <summary>
/// Gets the MembeReference that is decompiled (a MethodDefinition, PropertyDefinition etc.)
/// <remarks>Key is the metadata token.</remarks>
/// </summary>
public Dictionary<int, MemberReference> DecompiledMemberReferences { get; protected set; }
/// <summary>
/// Create data in the CodeMappings and DecompiledMemberReferences.
/// </summary>
/// <param name="token">Token of the current method.</param>
/// <param name="member">Current member (MethodDefinition, PropertyDefinition, EventDefinition).</param>
/// <remarks>The token is used in CodeMappings; member (and its token) is used in DecompiledMemberReferences.</remarks>
protected virtual void CreateCodeMappings(int token, MemberReference member)
{
this.CodeMappings.Add(token, new List<MemberMapping>());
int t = member.MetadataToken.ToInt32();
if (!this.DecompiledMemberReferences.ContainsKey(t))
this.DecompiledMemberReferences.Add(t, member);
}
}
/// <summary>
@ -112,9 +134,9 @@ namespace ICSharpCode.Decompiler @@ -112,9 +134,9 @@ namespace ICSharpCode.Decompiler
public MemberReference MemberReference { get; internal set; }
/// <summary>
/// Metadata token of the method.
/// Metadata token of the member.
/// </summary>
public uint MetadataToken { get; internal set; }
public int MetadataToken { get; internal set; }
/// <summary>
/// Gets or sets the code size for the member mapping.
@ -148,15 +170,17 @@ namespace ICSharpCode.Decompiler @@ -148,15 +170,17 @@ namespace ICSharpCode.Decompiler
/// Code mappings helper class.
/// </summary>
public static class CodeMappings
{
{
/// <summary>
/// Create code mapping for a method.
/// </summary>
/// <param name="method">Method to create the mapping for.</param>
/// <param name="sourceCodeMappings">Source code mapping storage.</param>
/// <param name="codeMappings">Source code mapping storage.</param>
/// <param name="actualMemberReference">The actual member reference.</param>
internal static MemberMapping CreateCodeMapping(
this MethodDefinition member,
Tuple<string, List<MemberMapping>> codeMappings)
List<MemberMapping> codeMappings,
MemberReference actualMemberReference = null)
{
if (member == null || !member.HasBody)
return null;
@ -166,17 +190,16 @@ namespace ICSharpCode.Decompiler @@ -166,17 +190,16 @@ namespace ICSharpCode.Decompiler
// create IL/CSharp code mappings - used in debugger
MemberMapping currentMemberMapping = null;
if (codeMappings.Item1 == member.DeclaringType.FullName) {
var mapping = codeMappings.Item2;
if (mapping.Find(map => (int)map.MetadataToken == member.MetadataToken.ToInt32()) == null) {
currentMemberMapping = new MemberMapping() {
MetadataToken = (uint)member.MetadataToken.ToInt32(),
MemberReference = member.DeclaringType.Resolve(),
MemberCodeMappings = new List<SourceCodeMapping>(),
CodeSize = member.Body.CodeSize
};
mapping.Add(currentMemberMapping);
}
if (codeMappings.Find(map => map.MetadataToken == member.MetadataToken.ToInt32()) == null) {
currentMemberMapping = new MemberMapping() {
MetadataToken = member.MetadataToken.ToInt32(),
MemberCodeMappings = new List<SourceCodeMapping>(),
MemberReference = actualMemberReference ?? member,
CodeSize = member.Body.CodeSize
};
codeMappings.Add(currentMemberMapping);
}
return currentMemberMapping;
@ -186,31 +209,19 @@ namespace ICSharpCode.Decompiler @@ -186,31 +209,19 @@ namespace ICSharpCode.Decompiler
/// Gets source code mapping and metadata token based on type name and line number.
/// </summary>
/// <param name="codeMappings">Code mappings storage.</param>
/// <param name="typeName">Type name.</param>
/// <param name="typeName">Member reference name.</param>
/// <param name="lineNumber">Line number.</param>
/// <param name="metadataToken">Metadata token.</param>
/// <returns></returns>
public static SourceCodeMapping GetInstructionByTypeAndLine(
this Tuple<string, List<MemberMapping>> codeMappings,
string memberReferenceName,
public static SourceCodeMapping GetInstructionByLineNumber(
this List<MemberMapping> codeMappings,
int lineNumber,
out uint metadataToken)
out int metadataToken)
{
if (codeMappings == null)
throw new ArgumentNullException("CodeMappings storage must be valid!");
throw new ArgumentException("CodeMappings storage must be valid!");
if (codeMappings.Item1 != memberReferenceName) {
metadataToken = 0;
return null;
}
if (lineNumber <= 0) {
metadataToken = 0;
return null;
}
var methodMappings = codeMappings.Item2;
foreach (var maping in methodMappings) {
foreach (var maping in codeMappings) {
var map = maping.MemberCodeMappings.Find(m => m.SourceCodeLine == lineNumber);
if (map != null) {
metadataToken = maping.MetadataToken;
@ -226,40 +237,32 @@ namespace ICSharpCode.Decompiler @@ -226,40 +237,32 @@ namespace ICSharpCode.Decompiler
/// Gets a mapping given a type, a token and an IL offset.
/// </summary>
/// <param name="codeMappings">Code mappings storage.</param>
/// <param name="typeName">Type name.</param>
/// <param name="token">Token.</param>
/// <param name="ilOffset">IL offset.</param>
/// <param name="isMatch">True, if perfect match.</param>
/// <returns>A code mapping.</returns>
public static SourceCodeMapping GetInstructionByTypeTokenAndOffset(
this Tuple<string, List<MemberMapping>> codeMappings,
string memberReferenceName,
uint token,
int ilOffset, out bool isMatch)
public static SourceCodeMapping GetInstructionByTokenAndOffset(
this List<MemberMapping> codeMappings,
int token,
int ilOffset,
out bool isMatch)
{
isMatch = false;
memberReferenceName = memberReferenceName.Replace("+", "/");
if (codeMappings == null)
throw new ArgumentNullException("CodeMappings storage must be valid!");
if (codeMappings.Item1 != memberReferenceName) {
return null;
}
var methodMappings = codeMappings.Item2;
var maping = methodMappings.Find(m => m.MetadataToken == token);
var maping = codeMappings.Find(m => m.MetadataToken == token);
if (maping == null) {
if (maping == null)
return null;
}
// try find an exact match
var map = maping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From <= ilOffset && ilOffset < m.ILInstructionOffset.To);
if (map == null) {
// get the immediate next one
map = maping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From >= ilOffset);
map = maping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From > ilOffset);
isMatch = false;
if (map == null)
map = maping.MemberCodeMappings.LastOrDefault(); // get the last
@ -275,38 +278,32 @@ namespace ICSharpCode.Decompiler @@ -275,38 +278,32 @@ namespace ICSharpCode.Decompiler
/// Gets the source code and type name from metadata token and offset.
/// </summary>
/// <param name="codeMappings">Code mappings storage.</param>
/// <param name="typeName">Current type name.</param>
/// <param name="token">Metadata token.</param>
/// <param name="ilOffset">IL offset.</param>
/// <param name="typeName">Type definition.</param>
/// <param name="line">Line number.</param>
/// <remarks>It is possible to exist to different types from different assemblies with the same metadata token.</remarks>
public static bool GetSourceCodeFromMetadataTokenAndOffset(
this Tuple<string, List<MemberMapping>> codeMappings,
string memberReferenceName,
uint token,
public static bool GetInstructionByTokenAndOffset(
this List<MemberMapping> codeMappings,
int token,
int ilOffset,
out MemberReference type,
out MemberReference member,
out int line)
{
type = null;
member = null;
line = 0;
if (codeMappings == null)
throw new ArgumentNullException("CodeMappings storage must be valid!");
memberReferenceName = memberReferenceName.Replace("+", "/");
if (codeMappings.Item1 != memberReferenceName)
return false;
throw new ArgumentException("CodeMappings storage must be valid!");
var mapping = codeMappings.Item2.Find(m => m.MetadataToken == token);
var mapping = codeMappings.Find(m => m.MetadataToken == token);
if (mapping == null)
return false;
var codeMapping = mapping.MemberCodeMappings.Find(
cm => cm.ILInstructionOffset.From <= ilOffset && ilOffset <= cm.ILInstructionOffset.To - 1);
if (codeMapping == null) {
codeMapping = mapping.MemberCodeMappings.Find(cm => (cm.ILInstructionOffset.From >= ilOffset));
codeMapping = mapping.MemberCodeMappings.Find(cm => cm.ILInstructionOffset.From > ilOffset);
if (codeMapping == null) {
codeMapping = mapping.MemberCodeMappings.LastOrDefault();
if (codeMapping == null)
@ -314,7 +311,7 @@ namespace ICSharpCode.Decompiler @@ -314,7 +311,7 @@ namespace ICSharpCode.Decompiler
}
}
type = mapping.MemberReference;
member = mapping.MemberReference;
line = codeMapping.SourceCodeLine;
return true;
}

35
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -30,12 +30,13 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -30,12 +30,13 @@ namespace ICSharpCode.Decompiler.Disassembler
/// <summary>
/// Disassembles type and member definitions.
/// </summary>
public sealed class ReflectionDisassembler : ICodeMappings
public sealed class ReflectionDisassembler : BaseCodeMappings
{
ITextOutput output;
CancellationToken cancellationToken;
bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings)
MethodBodyDisassembler methodBodyDisassembler;
MemberReference currentMember;
public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
{
@ -44,6 +45,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -44,6 +45,9 @@ namespace ICSharpCode.Decompiler.Disassembler
this.output = output;
this.cancellationToken = cancellationToken;
this.methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken);
this.CodeMappings = new Dictionary<int, List<MemberMapping>>();
this.DecompiledMemberReferences = new Dictionary<int, MemberReference>();
}
#region Disassemble Method
@ -99,6 +103,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -99,6 +103,9 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleMethod(MethodDefinition method)
{
// set current member
currentMember = method;
// write method header
output.WriteDefinition(".method ", method);
DisassembleMethodInternal(method);
@ -117,7 +124,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -117,7 +124,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if ((method.Attributes & MethodAttributes.PInvokeImpl) == MethodAttributes.PInvokeImpl) {
output.Write("pinvokeimpl");
if (method.HasPInvokeInfo) {
if (method.HasPInvokeInfo && method.PInvokeInfo != null) {
PInvokeInfo info = method.PInvokeInfo;
output.Write("(\"" + NRefactory.CSharp.OutputVisitor.ConvertString(info.Module.Name) + "\"");
@ -164,7 +171,6 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -164,7 +171,6 @@ namespace ICSharpCode.Decompiler.Disassembler
//call convention
WriteEnum(method.CallingConvention & (MethodCallingConvention)0x1f, callingConvention);
//return type
method.ReturnType.WriteTo(output);
output.Write(' ');
@ -214,7 +220,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -214,7 +220,8 @@ namespace ICSharpCode.Decompiler.Disassembler
if (method.HasBody) {
// create IL code mappings - used in debugger
MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings);
CreateCodeMappings(method.MetadataToken.ToInt32(), currentMember);
MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[method.MetadataToken.ToInt32()], currentMember);
methodBodyDisassembler.Disassemble(method.Body, methodMapping);
}
@ -669,6 +676,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -669,6 +676,9 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleField(FieldDefinition field)
{
// create mappings for decompiled fields only
this.DecompiledMemberReferences.Add(field.MetadataToken.ToInt32(), field);
output.WriteDefinition(".field ", field);
WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility);
const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA;
@ -704,6 +714,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -704,6 +714,9 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleProperty(PropertyDefinition property)
{
// set current member
currentMember = property;
output.WriteDefinition(".property ", property);
WriteFlags(property.Attributes, propertyAttributes);
if (property.HasThis)
@ -725,6 +738,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -725,6 +738,7 @@ namespace ICSharpCode.Decompiler.Disassembler
WriteAttributes(property.CustomAttributes);
WriteNestedMethod(".get", property.GetMethod);
WriteNestedMethod(".set", property.SetMethod);
foreach (var method in property.OtherMethods) {
WriteNestedMethod(".other", method);
}
@ -750,6 +764,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -750,6 +764,9 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleEvent(EventDefinition ev)
{
// set current member
currentMember = ev;
output.WriteDefinition(".event ", ev);
WriteFlags(ev.Attributes, eventAttributes);
ev.EventType.WriteTo(output, ILNameSyntax.TypeName);
@ -803,10 +820,6 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -803,10 +820,6 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleType(TypeDefinition type)
{
// create IL code mappings - used for debugger
if (this.CodeMappings == null)
this.CodeMappings = new Tuple<string, List<MemberMapping>>(type.FullName, new List<MemberMapping>());
// start writing IL
output.WriteDefinition(".class ", type);
@ -1141,11 +1154,5 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1141,11 +1154,5 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine();
}
}
/// <inheritdoc/>
public Tuple<string, List<MemberMapping>> CodeMappings {
get;
private set;
}
}
}

19
ICSharpCode.Decompiler/ILAst/GotoRemoval.cs

@ -98,10 +98,27 @@ namespace ICSharpCode.Decompiler.ILAst @@ -98,10 +98,27 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
// Remove redundant return
// Remove redundant return at the end of method
if (method.Body.Count > 0 && method.Body.Last().Match(ILCode.Ret) && ((ILExpression)method.Body.Last()).Arguments.Count == 0) {
method.Body.RemoveAt(method.Body.Count - 1);
}
// Remove unreachable return statements
bool modified = false;
foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
for (int i = 0; i < block.Body.Count - 1;) {
if (block.Body[i].IsUnconditionalControlFlow() && block.Body[i+1].Match(ILCode.Ret)) {
modified = true;
block.Body.RemoveAt(i+1);
} else {
i++;
}
}
}
if (modified) {
// More removals might be possible
new GotoRemoval().RemoveGotos(method);
}
}
IEnumerable<ILNode> GetParents(ILNode node)

9
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -281,6 +281,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -281,6 +281,8 @@ namespace ICSharpCode.Decompiler.ILAst
int varCount = methodDef.Body.Variables.Count;
var exceptionHandlerStarts = new HashSet<ByteCode>(methodDef.Body.ExceptionHandlers.Select(eh => instrToByteCode[eh.HandlerStart]));
// Add known states
if(methodDef.Body.HasExceptionHandlers) {
foreach(ExceptionHandler ex in methodDef.Body.ExceptionHandlers) {
@ -347,7 +349,12 @@ namespace ICSharpCode.Decompiler.ILAst @@ -347,7 +349,12 @@ namespace ICSharpCode.Decompiler.ILAst
// Find all successors
List<ByteCode> branchTargets = new List<ByteCode>();
if (!byteCode.Code.IsUnconditionalControlFlow()) {
branchTargets.Add(byteCode.Next);
if (exceptionHandlerStarts.Contains(byteCode.Next)) {
// Do not fall though down to exception handler
// It is invalid IL as per ECMA-335 §12.4.2.8.1, but some obfuscators produce it
} else {
branchTargets.Add(byteCode.Next);
}
}
if (byteCode.Operand is Instruction[]) {
foreach(Instruction inst in (Instruction[])byteCode.Operand) {

4
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -58,6 +58,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -58,6 +58,7 @@ namespace ICSharpCode.Decompiler.ILAst
RemoveRedundantCode2,
GotoRemoval,
DuplicateReturns,
GotoRemoval2,
ReduceIfNesting,
InlineVariables3,
CachedDelegateInitialization,
@ -190,6 +191,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -190,6 +191,9 @@ namespace ICSharpCode.Decompiler.ILAst
if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns) return;
DuplicateReturnStatements(method);
if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval2) return;
new GotoRemoval().RemoveGotos(method);
if (abortBeforeStep == ILAstOptimizationStep.ReduceIfNesting) return;
ReduceIfNesting(method);

2
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -864,7 +864,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -864,7 +864,7 @@ namespace ICSharpCode.Decompiler.ILAst
return null;
}
static TypeReference UnpackModifiers(TypeReference type)
internal static TypeReference UnpackModifiers(TypeReference type)
{
while (type is OptionalModifierType || type is RequiredModifierType)
type = ((TypeSpecification)type).ElementType;

1
ICSharpCode.Decompiler/ITextOutput.cs

@ -24,6 +24,7 @@ namespace ICSharpCode.Decompiler @@ -24,6 +24,7 @@ namespace ICSharpCode.Decompiler
public interface ITextOutput
{
int CurrentLine { get; }
int CurrentColumn { get; }
void Indent();
void Unindent();

20
ICSharpCode.Decompiler/PlainTextOutput.cs

@ -23,25 +23,33 @@ namespace ICSharpCode.Decompiler @@ -23,25 +23,33 @@ namespace ICSharpCode.Decompiler
{
public sealed class PlainTextOutput : ITextOutput
{
const int TAB_SIZE = 4;
readonly TextWriter writer;
int indent;
bool needsIndent;
int lineNumber = 1;
int columnNumber = 1;
public PlainTextOutput(TextWriter writer)
{
if (writer == null)
throw new ArgumentNullException("writer");
this.writer = writer;
CurrentLine = 1;
}
public PlainTextOutput()
{
this.writer = new StringWriter();
CurrentLine = 1;
}
public int CurrentLine { get; set; }
public int CurrentLine {
get { return lineNumber; }
}
public int CurrentColumn {
get { return columnNumber; }
}
public override string ToString()
{
@ -64,6 +72,7 @@ namespace ICSharpCode.Decompiler @@ -64,6 +72,7 @@ namespace ICSharpCode.Decompiler
needsIndent = false;
for (int i = 0; i < indent; i++) {
writer.Write('\t');
columnNumber += TAB_SIZE - 1;
}
}
}
@ -72,19 +81,22 @@ namespace ICSharpCode.Decompiler @@ -72,19 +81,22 @@ namespace ICSharpCode.Decompiler
{
WriteIndent();
writer.Write(ch);
columnNumber++;
}
public void Write(string text)
{
WriteIndent();
writer.Write(text);
columnNumber += text.Length;
}
public void WriteLine()
{
lineNumber++;
writer.WriteLine();
needsIndent = true;
++CurrentLine;
columnNumber = TAB_SIZE * indent;
}
public void WriteDefinition(string text, object definition)

8
ICSharpCode.Decompiler/Tests/Generics.cs

@ -29,6 +29,12 @@ public static class Generics @@ -29,6 +29,12 @@ public static class Generics
public Y Item2;
}
public enum NestedEnum
{
A,
B
}
private T[] arr;
public MyArray(int capacity)
@ -75,11 +81,13 @@ public static class Generics @@ -75,11 +81,13 @@ public static class Generics
}
}
private const Generics.MyArray<string>.NestedEnum enumVal = Generics.MyArray<string>.NestedEnum.A;
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<int>[]);
private static Type type6 = typeof(Generics.MyArray<>.NestedEnum);
public static void MethodWithConstraint<T, S>() where T : class, S where S : ICloneable, new()
{

2
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -13,8 +13,8 @@ @@ -13,8 +13,8 @@
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<NoWarn>67,169</NoWarn>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<NoWarn>67,169,1058,728</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget>

2
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -164,7 +164,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -164,7 +164,7 @@ namespace ICSharpCode.Decompiler.Tests
{
CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
CompilerParameters options = new CompilerParameters();
options.CompilerOptions = "/unsafe";
options.CompilerOptions = "/unsafe /o-";
options.ReferencedAssemblies.Add("System.Core.dll");
CompilerResults results = provider.CompileAssemblyFromSource(options, code);
try {

57
ILSpy.BamlDecompiler/BamlResourceEntryNode.cs

@ -3,14 +3,17 @@ @@ -3,14 +3,17 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using Mono.Cecil;
using Ricciolo.StylesExplorer.MarkupReflection;
namespace ILSpy.BamlDecompiler
@ -45,17 +48,55 @@ namespace ILSpy.BamlDecompiler @@ -45,17 +48,55 @@ namespace ILSpy.BamlDecompiler
bool LoadBaml(AvalonEditTextOutput output)
{
var asm = this.Ancestors().OfType<AssemblyTreeNode>().FirstOrDefault().LoadedAssembly;
MemoryStream bamlStream = new MemoryStream();
Data.Position = 0;
Data.CopyTo(bamlStream);
bamlStream.Position = 0;
XDocument xamlDocument = LoadIntoDocument(asm.GetAssemblyResolver(), asm.AssemblyDefinition, Data);
output.Write(xamlDocument.ToString());
return true;
}
internal static XDocument LoadIntoDocument(IAssemblyResolver resolver, AssemblyDefinition asm, Stream stream)
{
XDocument xamlDocument;
using (XmlBamlReader reader = new XmlBamlReader(bamlStream, new CecilTypeResolver(asm)))
using (XmlBamlReader reader = new XmlBamlReader(stream, new CecilTypeResolver(resolver, asm)))
xamlDocument = XDocument.Load(reader);
ConvertToEmptyElements(xamlDocument.Root);
MoveNamespacesToRoot(xamlDocument);
return xamlDocument;
}
static void MoveNamespacesToRoot(XDocument xamlDocument)
{
var additionalXmlns = new List<XAttribute> {
new XAttribute("xmlns", XmlBamlReader.DefaultWPFNamespace),
new XAttribute(XName.Get("x", XNamespace.Xmlns.NamespaceName), XmlBamlReader.XWPFNamespace)
};
output.Write(xamlDocument.ToString());
return true;
foreach (var element in xamlDocument.Root.DescendantsAndSelf()) {
if (element.Name.NamespaceName != XmlBamlReader.DefaultWPFNamespace && !additionalXmlns.Any(ka => ka.Value == element.Name.NamespaceName)) {
string newPrefix = new string(element.Name.LocalName.Where(c => char.IsUpper(c)).ToArray()).ToLowerInvariant();
int current = additionalXmlns.Count(ka => ka.Name.Namespace == XNamespace.Xmlns && ka.Name.LocalName.TrimEnd(ch => char.IsNumber(ch)) == newPrefix);
if (current > 0)
newPrefix += (current + 1).ToString();
XName defaultXmlns = XName.Get(newPrefix, XNamespace.Xmlns.NamespaceName);
if (element.Name.NamespaceName != XmlBamlReader.DefaultWPFNamespace)
additionalXmlns.Add(new XAttribute(defaultXmlns, element.Name.NamespaceName));
}
}
foreach (var xmlns in additionalXmlns.Except(xamlDocument.Root.Attributes())) {
xamlDocument.Root.Add(xmlns);
}
}
static void ConvertToEmptyElements(XElement element)
{
foreach (var el in element.Elements()) {
if (!el.IsEmpty && !el.HasElements && el.Value == "") {
el.RemoveNodes();
continue;
}
ConvertToEmptyElements(el);
}
}
}
}

10
ILSpy.BamlDecompiler/CecilType.cs

@ -67,5 +67,15 @@ namespace ILSpy.BamlDecompiler @@ -67,5 +67,15 @@ namespace ILSpy.BamlDecompiler
{
return string.Format("[CecilType Type={0}]", type);
}
public IType BaseType {
get {
TypeDefinition td = type.BaseType.Resolve();
if (td == null)
throw new Exception("could not resolve '" + type.BaseType.FullName + "'!");
return new CecilType(td);
}
}
}
}

25
ILSpy.BamlDecompiler/CecilTypeResolver.cs

@ -14,11 +14,18 @@ namespace ILSpy.BamlDecompiler @@ -14,11 +14,18 @@ namespace ILSpy.BamlDecompiler
/// </summary>
public class CecilTypeResolver : ITypeResolver
{
LoadedAssembly assembly;
IAssemblyResolver resolver;
AssemblyDefinition thisAssembly;
public CecilTypeResolver(LoadedAssembly assembly)
public CecilTypeResolver(IAssemblyResolver resolver, AssemblyDefinition asm)
{
this.assembly = assembly;
this.resolver = resolver;
this.thisAssembly = asm;
}
public bool IsLocalAssembly(string name)
{
return name == this.thisAssembly.Name.Name;
}
public IType GetTypeByAssemblyQualifiedName(string name)
@ -31,12 +38,12 @@ namespace ILSpy.BamlDecompiler @@ -31,12 +38,12 @@ namespace ILSpy.BamlDecompiler
string fullName = name.Substring(0, comma);
string assemblyName = name.Substring(comma + 1).Trim();
var type = assembly.AssemblyDefinition.MainModule.GetType(fullName);
var type = thisAssembly.MainModule.GetType(fullName);
if (type == null) {
var otherAssembly = assembly.LookupReferencedAssembly(assemblyName);
var otherAssembly = resolver.Resolve(assemblyName);
if (otherAssembly == null)
throw new Exception("could not resolve '" + assemblyName + "'!");
type = otherAssembly.AssemblyDefinition.MainModule.GetType(fullName);
type = otherAssembly.MainModule.GetType(fullName);
}
return new CecilType(type);
@ -49,5 +56,11 @@ namespace ILSpy.BamlDecompiler @@ -49,5 +56,11 @@ namespace ILSpy.BamlDecompiler
return new CecilDependencyPropertyDescriptor(name, ((CecilType)ownerType).type);
}
public string RuntimeVersion {
get {
return thisAssembly.MainModule.Runtime.ToString();
}
}
}
}

22
ILSpy.BamlDecompiler/Extensions.cs

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
// 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.Linq;
namespace ILSpy.BamlDecompiler
{
public static class Extensions
{
public static string TrimEnd(this string target, Func<char, bool> predicate)
{
if (target == null)
throw new ArgumentNullException("target");
while (predicate(target.LastOrDefault()))
target = target.Remove(target.Length - 1);
return target;
}
}
}

2
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

@ -77,6 +77,7 @@ @@ -77,6 +77,7 @@
<Compile Include="CecilDependencyPropertyDescriptor.cs" />
<Compile Include="CecilType.cs" />
<Compile Include="CecilTypeResolver.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\AppDomainTypeResolver.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\BamlAssembly.cs" />
@ -97,6 +98,7 @@ @@ -97,6 +98,7 @@
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlProperty.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlPropertyElement.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlReader.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlSimpleProperty.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlText.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlNamespace.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlPIMapping.cs" />

3
ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
#endregion
@ -22,6 +23,8 @@ using System.Runtime.InteropServices; @@ -22,6 +23,8 @@ using System.Runtime.InteropServices;
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)]
[assembly: InternalsVisibleTo("ILSpy.BamlDecompiler.Tests")]
// The assembly version has following format :
//
// Major.Minor.Build.Revision

11
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs

@ -131,6 +131,17 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -131,6 +131,17 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
return null;
}
}
public bool IsLocalAssembly(string name)
{
return false;
}
public string RuntimeVersion {
get {
throw new NotImplementedException();
}
}
#endregion

6
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs

@ -42,6 +42,12 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -42,6 +42,12 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
if (_type == null) return false;
return this._type.Equals(((DotNetType)type).Type);
}
public IType BaseType {
get {
return new DotNetType(this._type.BaseType.AssemblyQualifiedName);
}
}
#endregion

3
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/IType.cs

@ -8,10 +8,11 @@ using System.Text; @@ -8,10 +8,11 @@ using System.Text;
namespace Ricciolo.StylesExplorer.MarkupReflection
{
/// <summary>
/// Interface rappresenting a DotNet type
/// Interface representing a DotNet type
/// </summary>
public interface IType
{
IType BaseType { get; }
string AssemblyQualifiedName { get; }
bool IsSubclassOf(IType type);
bool Equals(IType type);

2
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/ITypeResolver.cs

@ -9,6 +9,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -9,6 +9,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
{
public interface ITypeResolver
{
string RuntimeVersion { get; }
bool IsLocalAssembly(string name);
IType GetTypeByAssemblyQualifiedName(string name);
IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IType ownerType, IType targetType);
}

36
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs

@ -34,12 +34,16 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -34,12 +34,16 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
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";
switch (resolver.RuntimeVersion) {
case "Net_2_0":
LoadKnownAssemblies30();
break;
case "Net_4_0":
LoadKnownAssemblies40();
break;
default:
throw new NotSupportedException();
}
KnownTypeTable = new TypeDeclaration[760];
KnownTypeTable[0] = new TypeDeclaration(resolver, string.Empty, string.Empty, 0);
@ -1305,6 +1309,26 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1305,6 +1309,26 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
KnownResourceTable.Add(0xa9, new ResourceName("SystemParameters.WorkArea"));
}
void LoadKnownAssemblies30()
{
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";
}
void LoadKnownAssemblies40()
{
KnownAssemblyTable = new string[5];
KnownAssemblyTable[0] = "PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
KnownAssemblyTable[1] = "PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
KnownAssemblyTable[2] = "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
KnownAssemblyTable[3] = "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
KnownAssemblyTable[4] = "WindowBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
}
#endregion
public bool IsKnownType(string type)

5
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs

@ -132,6 +132,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -132,6 +132,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
else
return false;
}
public override int GetHashCode()
{
return this.AssemblyId ^ this.Name.GetHashCode() ^ this.Namespace.GetHashCode();
}
}
}

58
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs

@ -8,6 +8,7 @@ using System.ComponentModel; @@ -8,6 +8,7 @@ using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;
@ -54,6 +55,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -54,6 +55,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
private readonly TypeDeclaration XamlTypeDeclaration;
private readonly XmlNameTable _nameTable = new NameTable();
private IDictionary<string, string> _rootNamespaces;
public const string XWPFNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
public const string DefaultWPFNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
#endregion
@ -159,7 +163,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -159,7 +163,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public override bool MoveToFirstAttribute()
{
intoAttribute = false;
if (nodes.Count > 0 && nodes.Peek() is XmlBamlProperty)
if (nodes.Count > 0 && (nodes.Peek() is XmlBamlProperty || nodes.Peek() is XmlBamlSimpleProperty))
{
_currentNode = nodes.Dequeue();
return true;
@ -178,7 +182,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -178,7 +182,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public override bool MoveToNextAttribute()
{
intoAttribute = false;
if (nodes.Count > 0 && nodes.Peek() is XmlBamlProperty)
if (nodes.Count > 0 && (nodes.Peek() is XmlBamlProperty || nodes.Peek() is XmlBamlSimpleProperty))
{
_currentNode = nodes.Dequeue();
return true;
@ -196,7 +200,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -196,7 +200,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
///
public override bool MoveToElement()
{
while (nodes.Peek() is XmlBamlProperty)
while (nodes.Peek() is XmlBamlProperty || nodes.Peek() is XmlBamlSimpleProperty)
{
nodes.Dequeue();
}
@ -284,13 +288,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -284,13 +288,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
else
currentType = (BamlRecordType)type;
if (currentType.ToString().EndsWith("End"))
Debug.Unindent();
Debug.WriteLine(currentType);
if (currentType.ToString().StartsWith("Start"))
Debug.Indent();
// Debug.WriteLine(currentType);
}
private bool SetNextNode()
@ -300,6 +298,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -300,6 +298,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
_currentNode = nodes.Dequeue();
if ((_currentNode is XmlBamlProperty)) continue;
if ((_currentNode is XmlBamlSimpleProperty)) continue;
if (this.NodeType == XmlNodeType.EndElement)
{
@ -451,7 +450,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -451,7 +450,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
break;
default:
throw new NotImplementedException("UnsupportedNode: " + currentType);
break;
}
}
@ -586,7 +584,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -586,7 +584,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
String localName = String.Empty;
XmlBamlNode node = this.CurrentNode;
if (node is XmlBamlProperty)
if (node is XmlBamlSimpleProperty) {
var simpleNode = (XmlBamlSimpleProperty)node;
localName = simpleNode.LocalName;
} else if (node is XmlBamlProperty)
{
PropertyDeclaration pd = ((XmlBamlProperty)node).PropertyDeclaration;
localName = FormatPropertyDeclaration(pd, false, true, true);
@ -1057,9 +1058,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1057,9 +1058,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
private void ReadPropertyComplexEnd()
{
if (!(elements.Peek() is XmlBamlPropertyElement))
throw new InvalidCastException();
XmlBamlPropertyElement propertyElement = (XmlBamlPropertyElement) elements.Peek();
CloseElement();
@ -1191,10 +1189,22 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1191,10 +1189,22 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
}
else
element = new XmlBamlElement();
// the type is defined in the local assembly, i.e., the main assembly
// and this is the root element
TypeDeclaration oldDeclaration = null;
if (_resolver.IsLocalAssembly(declaration.Assembly) && parentElement == null) {
oldDeclaration = declaration;
declaration = GetKnownTypeDeclarationByName(declaration.Type.BaseType.AssemblyQualifiedName);
}
element.TypeDeclaration = declaration;
elements.Push(element);
nodes.Enqueue(element);
if (oldDeclaration != null) {
nodes.Enqueue(new XmlBamlSimpleProperty(XWPFNamespace, "Class", string.Format("{0}.{1}", oldDeclaration.Namespace, oldDeclaration.Name)));
}
if (parentElement != null && complexPropertyOpened == 0)
{
@ -1572,6 +1582,16 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1572,6 +1582,16 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
return declaration;
}
TypeDeclaration GetKnownTypeDeclarationByName(string name)
{
foreach (var type in KnownInfo.KnownTypeTable) {
if (name == string.Format("{0}.{1}, {2}", type.Namespace, type.Name, type.Assembly))
return type;
}
throw new NotSupportedException();
}
internal string GetAssembly(short identifier)
{
@ -1602,7 +1622,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1602,7 +1622,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
TypeDeclaration declaration;
XmlBamlNode node = this.CurrentNode;
if (node is XmlBamlProperty)
if (node is XmlBamlSimpleProperty)
return ((XmlBamlSimpleProperty)node).NamespaceName;
else if (node is XmlBamlProperty)
{
declaration = ((XmlBamlProperty)node).PropertyDeclaration.DeclaringType;
TypeDeclaration elementDeclaration = this.readingElements.Peek().TypeDeclaration;
@ -1678,7 +1700,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1678,7 +1700,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
get
{
XmlBamlNode node = this.CurrentNode;
if (node is XmlBamlProperty)
if (node is XmlBamlSimpleProperty)
return ((XmlBamlSimpleProperty)node).Value;
else if (node is XmlBamlProperty)
return ((XmlBamlProperty)node).Value.ToString();
else if (node is XmlBamlText)
return ((XmlBamlText)node).Text;

34
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlSimpleProperty.cs

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
// 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.Text;
using System.Xml;
namespace Ricciolo.StylesExplorer.MarkupReflection
{
class XmlBamlSimpleProperty : XmlBamlNode
{
public string NamespaceName { get; private set; }
public string LocalName { get; private set; }
public string Value { get; private set; }
public XmlBamlSimpleProperty(string namespaceName, string localName, string value)
{
if (string.IsNullOrWhiteSpace(namespaceName))
throw new ArgumentException("namespaceName");
if (string.IsNullOrWhiteSpace(localName))
throw new ArgumentException("localName");
if (value == null)
throw new ArgumentNullException("value");
this.NamespaceName = namespaceName;
this.LocalName = localName;
this.Value = value;
}
public override XmlNodeType NodeType {
get { return XmlNodeType.Attribute; }
}
}
}

3
ILSpy.BamlDecompiler/Tests/Cases/Simple.xaml

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
<Window x:Class="ILSpy.BamlDecompiler.Tests.Cases.Simple" Title="ILSpy.BamlDecompiler.Tests.Cases" Height="300" Width="300" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid />
</Window>

26
ILSpy.BamlDecompiler/Tests/Cases/Simple.xaml.cs

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
// 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.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace ILSpy.BamlDecompiler.Tests.Cases
{
/// <summary>
/// Interaction logic for Simple.xaml
/// </summary>
public partial class Simple : Window
{
public Simple()
{
InitializeComponent();
}
}
}

1
ILSpy.BamlDecompiler/Tests/Cases/SimpleDictionary.xaml

@ -0,0 +1 @@ @@ -0,0 +1 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"></ResourceDictionary>

109
ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<ProjectGuid>{1169E6D1-1899-43D4-A500-07CE4235B388}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>Library</OutputType>
<RootNamespace>ILSpy.BamlDecompiler.Tests</RootNamespace>
<AssemblyName>ILSpy.BamlDecompiler.Tests</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget>
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
<FileAlignment>4096</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>..\bin\Debug\</OutputPath>
<DebugSymbols>true</DebugSymbols>
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>..\bin\Release\</OutputPath>
<DebugSymbols>false</DebugSymbols>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Reference Include="DiffLib">
<HintPath>..\..\packages\DiffLib.1.0.0.55\lib\net35-Client\DiffLib.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\..\ICSharpCode.Decompiler\Tests\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="PresentationCore">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="PresentationFramework">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Cases\Simple.xaml.cs">
<DependentUpon>Simple.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestRunner.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ICSharpCode.Decompiler\Tests\ICSharpCode.Decompiler.Tests.csproj">
<Project>{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}</Project>
<Name>ICSharpCode.Decompiler.Tests</Name>
</ProjectReference>
<ProjectReference Include="..\..\ILSpy\ILSpy.csproj">
<Project>{1E85EFF9-E370-4683-83E4-8A3D063FF791}</Project>
<Name>ILSpy</Name>
</ProjectReference>
<ProjectReference Include="..\..\Mono.Cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Name>ICSharpCode.TreeView</Name>
</ProjectReference>
<ProjectReference Include="..\ILSpy.BamlDecompiler.csproj">
<Project>{A6BAD2BA-76BA-461C-8B6D-418607591247}</Project>
<Name>ILSpy.BamlDecompiler</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Cases" />
<Folder Include="Properties" />
</ItemGroup>
<ItemGroup>
<Page Include="Cases\Simple.xaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Page>
<Page Include="Cases\SimpleDictionary.xaml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

31
ILSpy.BamlDecompiler/Tests/Properties/AssemblyInfo.cs

@ -0,0 +1,31 @@ @@ -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.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ILSpy.BamlDecompiler.Tests")]
[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.*")]

73
ILSpy.BamlDecompiler/Tests/TestRunner.cs

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
// 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;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Resources;
using System.Xml.Linq;
using ICSharpCode.Decompiler.Tests.Helpers;
using ICSharpCode.ILSpy;
using Mono.Cecil;
using NUnit.Framework;
using Ricciolo.StylesExplorer.MarkupReflection;
namespace ILSpy.BamlDecompiler.Tests
{
[TestFixture]
public class TestRunner
{
[Test]
public void Simple()
{
RunTest("cases/simple");
}
[Test]
public void SimpleDictionary()
{
RunTest("cases/simpledictionary");
}
void RunTest(string name)
{
string asmPath = typeof(TestRunner).Assembly.Location;
var assembly = AssemblyDefinition.ReadAssembly(asmPath);
Resource res = assembly.MainModule.Resources.First();
Stream bamlStream = LoadBaml(res, name + ".baml");
Assert.IsNotNull(bamlStream);
XDocument document = BamlResourceEntryNode.LoadIntoDocument(new DefaultAssemblyResolver(), assembly, bamlStream);
string path = Path.Combine("..\\..\\Tests", name + ".xaml");
CodeAssert.AreEqual(document.ToString(), File.ReadAllText(path));
}
Stream LoadBaml(Resource res, string name)
{
EmbeddedResource er = res as EmbeddedResource;
if (er != null) {
Stream s = er.GetResourceStream();
s.Position = 0;
ResourceReader reader;
try {
reader = new ResourceReader(s);
}
catch (ArgumentException) {
return null;
}
foreach (DictionaryEntry entry in reader.Cast<DictionaryEntry>().OrderBy(e => e.Key.ToString())) {
if (entry.Key.ToString() == name) {
if (entry.Value is Stream)
return (Stream)entry.Value;
if (entry.Value is byte[])
return new MemoryStream((byte[])entry.Value);
}
}
}
return null;
}
}
}

12
ILSpy.sln

@ -1,7 +1,7 @@ @@ -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
@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "Mono.Ceci @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Pdb", "Mono.Ceci
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.BamlDecompiler", "ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj", "{A6BAD2BA-76BA-461C-8B6D-418607591247}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.BamlDecompiler.Tests", "ILSpy.BamlDecompiler\Tests\ILSpy.BamlDecompiler.Tests.csproj", "{1169E6D1-1899-43D4-A500-07CE4235B388}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -115,6 +117,14 @@ Global @@ -115,6 +117,14 @@ Global
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|x86.Build.0 = Release|x86
{A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|x86.ActiveCfg = Release|x86
{1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.Build.0 = Debug|x86
{1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.ActiveCfg = Debug|x86
{1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|x86.Build.0 = Debug|x86
{1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|x86.ActiveCfg = Debug|x86
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.Build.0 = Release|x86
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.ActiveCfg = Release|x86
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|x86.Build.0 = Release|x86
{1169E6D1-1899-43D4-A500-07CE4235B388}.Release|x86.ActiveCfg = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

5
ILSpy/AboutPage.cs

@ -31,8 +31,10 @@ using System.Windows.Data; @@ -31,8 +31,10 @@ using System.Windows.Data;
using System.Windows.Input;
using System.Xml;
using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.TextView;
namespace ICSharpCode.ILSpy
@ -94,6 +96,9 @@ namespace ICSharpCode.ILSpy @@ -94,6 +96,9 @@ namespace ICSharpCode.ILSpy
output.AddVisualLineElementGenerator(new MyLinkElementGenerator("MIT License", "resource:license.txt"));
output.AddVisualLineElementGenerator(new MyLinkElementGenerator("LGPL", "resource:LGPL.txt"));
textView.ShowText(output);
//reset icon bar
textView.manager.Bookmarks.Clear();
}
sealed class MyLinkElementGenerator : LinkElementGenerator

36
ILSpy/AnalyzerTreeView.cs

@ -17,15 +17,6 @@ @@ -17,15 +17,6 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.ILSpy.TreeNodes.Analyzer;
using ICSharpCode.TreeView;
@ -37,9 +28,11 @@ namespace ICSharpCode.ILSpy @@ -37,9 +28,11 @@ namespace ICSharpCode.ILSpy
public partial class AnalyzerTreeView : SharpTreeView, IPane
{
static AnalyzerTreeView instance;
public static AnalyzerTreeView Instance {
get {
public static AnalyzerTreeView Instance
{
get
{
if (instance == null) {
App.Current.VerifyAccess();
instance = new AnalyzerTreeView();
@ -47,42 +40,33 @@ namespace ICSharpCode.ILSpy @@ -47,42 +40,33 @@ namespace ICSharpCode.ILSpy
return instance;
}
}
private AnalyzerTreeView()
{
this.ShowRoot = false;
this.Root = new AnalyzerTreeNode { Language = MainWindow.Instance.CurrentLanguage };
ContextMenuProvider.Add(this);
}
public void Show()
{
if (!IsVisible)
MainWindow.Instance.ShowInBottomPane("Analyzer", this);
}
public void Show(AnalyzerTreeNode node)
{
Show();
node.IsExpanded = true;
this.Root.Children.Add(node);
this.SelectedItem = node;
this.FocusNode(node);
}
void IPane.Closed()
{
this.Root.Children.Clear();
}
}
[ExportMainMenuCommand(Menu = "_View", Header = "_Analyzer", MenuCategory = "ShowPane", MenuOrder = 100)]
sealed class ShowAnalyzerCommand : SimpleCommand
{
public override void Execute(object parameter)
{
AnalyzerTreeView.Instance.Show();
}
}
}

123
ILSpy/AvalonEdit/ITextMarker.cs

@ -0,0 +1,123 @@ @@ -0,0 +1,123 @@
// 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.Windows.Media;
using ICSharpCode.ILSpy.Bookmarks;
namespace ICSharpCode.ILSpy.AvalonEdit
{
/// <summary>
/// Represents a text marker.
/// </summary>
public interface ITextMarker
{
/// <summary>
/// Gets the start offset of the marked text region.
/// </summary>
int StartOffset { get; }
/// <summary>
/// Gets the end offset of the marked text region.
/// </summary>
int EndOffset { get; }
/// <summary>
/// Gets the length of the marked region.
/// </summary>
int Length { get; }
/// <summary>
/// Deletes the text marker.
/// </summary>
void Delete();
/// <summary>
/// Gets whether the text marker was deleted.
/// </summary>
bool IsDeleted { get; }
/// <summary>
/// Event that occurs when the text marker is deleted.
/// </summary>
event EventHandler Deleted;
/// <summary>
/// Gets/Sets the background color.
/// </summary>
Color? BackgroundColor { get; set; }
/// <summary>
/// Gets/Sets the foreground color.
/// </summary>
Color? ForegroundColor { get; set; }
/// <summary>
/// Gets/Sets the type of the marker. Use TextMarkerType.None for normal markers.
/// </summary>
TextMarkerType MarkerType { get; set; }
/// <summary>
/// Gets/Sets the color of the marker.
/// </summary>
Color MarkerColor { get; set; }
/// <summary>
/// Gets/Sets an object with additional data for this text marker.
/// </summary>
object Tag { get; set; }
/// <summary>
/// Gets/Sets an object that will be displayed as tooltip in the text editor.
/// </summary>
object ToolTip { get; set; }
/// <summary>
/// Gets or sets if the marker is visible or not.
/// </summary>
Predicate<object> IsVisible { get; set; }
/// <summary>
/// Gets or sets the bookmark.
/// </summary>
IBookmark Bookmark { get; set; }
}
public enum TextMarkerType
{
/// <summary>
/// Use no marker
/// </summary>
None,
/// <summary>
/// Use squiggly underline marker
/// </summary>
SquigglyUnderline
}
public interface ITextMarkerService
{
/// <summary>
/// Creates a new text marker. The text marker will be invisible at first,
/// you need to set one of the Color properties to make it visible.
/// </summary>
ITextMarker Create(int startOffset, int length);
/// <summary>
/// Gets the list of text markers.
/// </summary>
IEnumerable<ITextMarker> TextMarkers { get; }
/// <summary>
/// Removes the specified text marker.
/// </summary>
void Remove(ITextMarker marker);
/// <summary>
/// Removes all text markers that match the condition.
/// </summary>
void RemoveAll(Predicate<ITextMarker> predicate);
}
}

83
ILSpy/AvalonEdit/IconBarManager.cs

@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
// 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;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.ILSpy.AvalonEdit
{
/// <summary>
/// Stores the entries in the icon bar margin. Multiple icon bar margins
/// can use the same manager if split view is used.
/// </summary>
public class IconBarManager : IBookmarkMargin
{
ObservableCollection<IBookmark> bookmarks = new ObservableCollection<IBookmark>();
public IconBarManager()
{
bookmarks.CollectionChanged += bookmarks_CollectionChanged;
}
public IList<IBookmark> Bookmarks {
get { return bookmarks; }
}
void bookmarks_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Redraw();
}
public void Redraw()
{
if (RedrawRequested != null)
RedrawRequested(this, EventArgs.Empty);
}
public event EventHandler RedrawRequested;
internal void UpdateClassMemberBookmarks(IEnumerable<AstNode> nodes)
{
this.bookmarks.Clear();
if (nodes == null || nodes.Count() == 0)
return;
foreach (var n in nodes) {
switch (n.NodeType) {
case NodeType.TypeDeclaration:
case NodeType.TypeReference:
this.bookmarks.Add(new TypeBookmark(n));
break;
case NodeType.Member:
this.bookmarks.Add(new MemberBookmark(n));
break;
default:
// do nothing
break;
}
}
}
}
}

243
ILSpy/AvalonEdit/IconBarMargin.cs

@ -0,0 +1,243 @@ @@ -0,0 +1,243 @@
// 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.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.AvalonEdit
{
public class IconBarMargin : AbstractMargin, IDisposable
{
readonly IconBarManager manager;
public IconBarMargin(IconBarManager manager)
{
BookmarkManager.Added += delegate { InvalidateVisual(); };
BookmarkManager.Removed += delegate { InvalidateVisual(); };
this.manager = manager;
}
public IconBarManager Manager {
get { return manager; }
}
public IList<MemberReference> DecompiledMembers { get; set; }
public virtual void Dispose()
{
this.TextView = null; // detach from TextView (will also detach from manager)
}
/// <inheritdoc/>
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
// accept clicks even when clicking on the background
return new PointHitTestResult(this, hitTestParameters.HitPoint);
}
/// <inheritdoc/>
protected override Size MeasureOverride(Size availableSize)
{
return new Size(18, 0);
}
protected override void OnRender(DrawingContext drawingContext)
{
Size renderSize = this.RenderSize;
drawingContext.DrawRectangle(SystemColors.ControlBrush, null,
new Rect(0, 0, renderSize.Width, renderSize.Height));
drawingContext.DrawLine(new Pen(SystemColors.ControlDarkBrush, 1),
new Point(renderSize.Width - 0.5, 0),
new Point(renderSize.Width - 0.5, renderSize.Height));
ICSharpCode.AvalonEdit.Rendering.TextView textView = this.TextView;
if (textView != null && textView.VisualLinesValid) {
// create a dictionary line number => first bookmark
Dictionary<int, IBookmark> bookmarkDict = new Dictionary<int, IBookmark>();
foreach (var bm in BookmarkManager.Bookmarks) {
if (!DecompiledMembers.Contains(bm.MemberReference))
continue;
int line = bm.LineNumber;
IBookmark existingBookmark;
if (!bookmarkDict.TryGetValue(line, out existingBookmark) || bm.ZOrder > existingBookmark.ZOrder)
bookmarkDict[line] = bm;
}
foreach (var bm in manager.Bookmarks) {
int line = bm.LineNumber;
IBookmark existingBookmark;
if (!bookmarkDict.TryGetValue(line, out existingBookmark) || bm.ZOrder > existingBookmark.ZOrder)
bookmarkDict[line] = bm;
}
Size pixelSize = PixelSnapHelpers.GetPixelSize(this);
foreach (VisualLine line in textView.VisualLines) {
int lineNumber = line.FirstDocumentLine.LineNumber;
IBookmark bm;
if (bookmarkDict.TryGetValue(lineNumber, out bm)) {
Rect rect = new Rect(0, PixelSnapHelpers.Round(line.VisualTop - textView.VerticalOffset, pixelSize.Height), 16, 16);
if (dragDropBookmark == bm && dragStarted)
drawingContext.PushOpacity(0.5);
drawingContext.DrawImage(bm.Image, rect);
if (dragDropBookmark == bm && dragStarted)
drawingContext.Pop();
}
}
if (dragDropBookmark != null && dragStarted) {
Rect rect = new Rect(0, PixelSnapHelpers.Round(dragDropCurrentPoint - 8, pixelSize.Height), 16, 16);
drawingContext.DrawImage(dragDropBookmark.Image, rect);
}
}
}
IBookmark dragDropBookmark; // bookmark being dragged (!=null if drag'n'drop is active)
double dragDropStartPoint;
double dragDropCurrentPoint;
bool dragStarted; // whether drag'n'drop operation has started (mouse was moved minimum distance)
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
int line = GetLineFromMousePosition(e);
if (!e.Handled && line > 0) {
IBookmark bm = GetBookmarkFromLine(line);
if (bm != null) {
bm.MouseDown(e);
if (!e.Handled) {
if (e.ChangedButton == MouseButton.Left && bm.CanDragDrop && CaptureMouse()) {
StartDragDrop(bm, e);
e.Handled = true;
}
}
}
}
// don't allow selecting text through the IconBarMargin
if (e.ChangedButton == MouseButton.Left)
e.Handled = true;
}
IBookmark GetBookmarkFromLine(int line)
{
BookmarkBase result = null;
foreach (BookmarkBase bm in BookmarkManager.Bookmarks) {
if (bm.LineNumber == line &&
this.DecompiledMembers != null && this.DecompiledMembers.Contains(bm.MemberReference)) {
if (result == null || bm.ZOrder > result.ZOrder)
return result;
}
}
return manager.Bookmarks.FirstOrDefault(b => b.LineNumber == line);
}
protected override void OnLostMouseCapture(MouseEventArgs e)
{
CancelDragDrop();
base.OnLostMouseCapture(e);
}
void StartDragDrop(IBookmark bm, MouseEventArgs e)
{
dragDropBookmark = bm;
dragDropStartPoint = dragDropCurrentPoint = e.GetPosition(this).Y;
if (TextView != null) {
TextArea area = TextView.Services.GetService(typeof(TextArea)) as TextArea;
if (area != null)
area.PreviewKeyDown += TextArea_PreviewKeyDown;
}
}
void CancelDragDrop()
{
if (dragDropBookmark != null) {
dragDropBookmark = null;
dragStarted = false;
if (TextView != null) {
TextArea area = TextView.Services.GetService(typeof(TextArea)) as TextArea;
if (area != null)
area.PreviewKeyDown -= TextArea_PreviewKeyDown;
}
ReleaseMouseCapture();
InvalidateVisual();
}
}
void TextArea_PreviewKeyDown(object sender, KeyEventArgs e)
{
// any key press cancels drag'n'drop
CancelDragDrop();
if (e.Key == Key.Escape)
e.Handled = true;
}
internal int GetLineFromMousePosition(MouseEventArgs e)
{
ICSharpCode.AvalonEdit.Rendering.TextView textView = this.TextView;
if (textView == null)
return 0;
VisualLine vl = textView.GetVisualLineFromVisualTop(e.GetPosition(textView).Y + textView.ScrollOffset.Y);
if (vl == null)
return 0;
return vl.FirstDocumentLine.LineNumber;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (dragDropBookmark != null) {
dragDropCurrentPoint = e.GetPosition(this).Y;
if (Math.Abs(dragDropCurrentPoint - dragDropStartPoint) > SystemParameters.MinimumVerticalDragDistance)
dragStarted = true;
InvalidateVisual();
}
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
base.OnMouseUp(e);
int line = GetLineFromMousePosition(e);
if (!e.Handled && dragDropBookmark != null) {
if (dragStarted) {
if (line != 0)
dragDropBookmark.Drop(line);
e.Handled = true;
}
CancelDragDrop();
}
if (!e.Handled && line != 0) {
var bm = GetBookmarkFromLine(line);
if (bm != null) {
bm.MouseUp(e);
if (bm is BookmarkBase) {
if ((bm as BookmarkBase).CanToggle) {
BookmarkManager.RemoveMark(bm as BookmarkBase);
InvalidateVisual();
}
}
if (e.Handled)
return;
}
if (e.ChangedButton == MouseButton.Left) {
// TODO: notify subscribers
}
InvalidateVisual();
}
}
}
}

189
ILSpy/AvalonEdit/IconMarginActionsProvider.cs

@ -0,0 +1,189 @@ @@ -0,0 +1,189 @@
// 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.Linq;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.ILSpy.Bookmarks;
namespace ICSharpCode.ILSpy.AvalonEdit
{
#region Context menu extensibility
public interface IBookmarkContextMenuEntry
{
bool IsVisible(IBookmark[] bookmarks);
bool IsEnabled(IBookmark[] bookmarks);
void Execute(IBookmark[] bookmarks);
}
public interface IBookmarkContextMenuEntryMetadata
{
string Icon { get; }
string Header { get; }
string Category { get; }
double Order { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class ExportBookmarkContextMenuEntryAttribute : ExportAttribute, IBookmarkContextMenuEntryMetadata
{
public ExportBookmarkContextMenuEntryAttribute()
: base(typeof(IBookmarkContextMenuEntry))
{
}
public string Icon { get; set; }
public string Header { get; set; }
public string Category { get; set; }
public double Order { get; set; }
}
#endregion
#region Actions (simple clicks) - this will be used for creating bookmarks (e.g. Breakpoint bookmarks)
public interface IBookmarkActionEntry
{
bool IsEnabled();
void Execute();
}
public interface IBookmarkActionMetadata
{
string Category { get; }
double Order { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class ExportBookmarkActionEntryAttribute : ExportAttribute, IBookmarkActionMetadata
{
public ExportBookmarkActionEntryAttribute()
: base(typeof(IBookmarkActionEntry))
{
}
public string Icon { get; set; }
public string Header { get; set; }
public string Category { get; set; }
public double Order { get; set; }
}
#endregion
internal class IconMarginActionsProvider
{
/// <summary>
/// Enables extensible context menu support for the specified icon margin.
/// </summary>
public static void Add(IconBarMargin margin)
{
var provider = new IconMarginActionsProvider(margin);
margin.MouseDown += provider.MouseDown;
margin.ContextMenu = new ContextMenu();
}
readonly IconBarMargin margin;
[ImportMany(typeof(IBookmarkContextMenuEntry))]
Lazy<IBookmarkContextMenuEntry, IBookmarkContextMenuEntryMetadata>[] contextEntries = null;
[ImportMany(typeof(IBookmarkActionEntry))]
Lazy<IBookmarkActionEntry, IBookmarkActionMetadata>[] actionEntries = null;
private IconMarginActionsProvider(IconBarMargin margin)
{
this.margin = margin;
App.CompositionContainer.ComposeParts(this);
}
void MouseDown(object sender, MouseButtonEventArgs e)
{
int line = margin.GetLineFromMousePosition(e);
var bookmarks = margin.Manager.Bookmarks.ToArray();
if (bookmarks.Length == 0) {
// don't show the menu
e.Handled = true;
this.margin.ContextMenu = null;
return;
}
if (e.LeftButton == MouseButtonState.Pressed) {
foreach (var category in actionEntries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.Category)) {
foreach (var entryPair in category) {
IBookmarkActionEntry entry = entryPair.Value;
if (entryPair.Value.IsEnabled()) {
entry.Execute();
}
}
}
}
if (e.RightButton == MouseButtonState.Pressed) {
// check if we are on a Member
var bookmark = bookmarks.FirstOrDefault(b => b.LineNumber == line);
if (bookmark == null) {
// don't show the menu
e.Handled = true;
this.margin.ContextMenu = null;
return;
}
var marks = new[] { bookmark };
ContextMenu menu = new ContextMenu();
foreach (var category in contextEntries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.Category)) {
if (menu.Items.Count > 0) {
menu.Items.Add(new Separator());
}
foreach (var entryPair in category) {
IBookmarkContextMenuEntry entry = entryPair.Value;
if (entry.IsVisible(marks)) {
MenuItem menuItem = new MenuItem();
menuItem.Header = entryPair.Metadata.Header;
if (!string.IsNullOrEmpty(entryPair.Metadata.Icon)) {
menuItem.Icon = new Image {
Width = 16,
Height = 16,
Source = Images.LoadImage(entry, entryPair.Metadata.Icon)
};
}
if (entryPair.Value.IsEnabled(marks)) {
menuItem.Click += delegate { entry.Execute(marks); };
} else
menuItem.IsEnabled = false;
menu.Items.Add(menuItem);
}
}
}
if (menu.Items.Count > 0)
margin.ContextMenu = menu;
else
// hide the context menu.
e.Handled = true;
}
}
}
}

67
ILSpy/AvalonEdit/TextEditorWeakEventManager.cs

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
// 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.Windows;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.ILSpy.AvalonEdit
{
public static class TextEditorWeakEventManager
{
public sealed class MouseHover : WeakEventManagerBase<MouseHover, TextEditor>
{
protected override void StopListening(TextEditor source)
{
source.MouseHover -= DeliverEvent;
}
protected override void StartListening(TextEditor source)
{
source.MouseHover += DeliverEvent;
}
}
public sealed class MouseHoverStopped : WeakEventManagerBase<MouseHoverStopped, TextEditor>
{
protected override void StopListening(TextEditor source)
{
source.MouseHoverStopped -= DeliverEvent;
}
protected override void StartListening(TextEditor source)
{
source.MouseHoverStopped += DeliverEvent;
}
}
public sealed class MouseDown : WeakEventManagerBase<MouseDown, TextEditor>
{
protected override void StopListening(TextEditor source)
{
source.MouseDown -= DeliverEvent;
}
protected override void StartListening(TextEditor source)
{
source.MouseDown += DeliverEvent;
}
}
}
}

292
ILSpy/AvalonEdit/TextMarkerService.cs

@ -0,0 +1,292 @@ @@ -0,0 +1,292 @@
// 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.ComponentModel.Composition;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.ILSpy.Bookmarks;
namespace ICSharpCode.ILSpy.AvalonEdit
{
/// <summary>
/// Handles the text markers for a code editor.
/// </summary>
public sealed class TextMarkerService : DocumentColorizingTransformer, IBackgroundRenderer, ITextMarkerService
{
TextEditor codeEditor;
TextSegmentCollection<TextMarker> markers = new TextSegmentCollection<TextMarker>();
public TextMarkerService()
{
}
public TextEditor CodeEditor {
get { return codeEditor; }
set { codeEditor = value; }
}
#region ITextMarkerService
public ITextMarker Create(int startOffset, int length)
{
int textLength = codeEditor.TextArea.TextView.Document.TextLength;
if (startOffset < 0 || startOffset > textLength)
throw new ArgumentOutOfRangeException("startOffset", startOffset, "Value must be between 0 and " + textLength);
if (length < 0 || startOffset + length > textLength)
throw new ArgumentOutOfRangeException("length", length, "length must not be negative and startOffset+length must not be after the end of the document");
TextMarker m = new TextMarker(this, startOffset, length);
markers.Add(m);
// no need to mark segment for redraw: the text marker is invisible until a property is set
return m;
}
public IEnumerable<ITextMarker> GetMarkersAtOffset(int offset)
{
return markers.FindSegmentsContaining(offset);
}
public IEnumerable<ITextMarker> TextMarkers {
get { return markers; }
}
public void RemoveAll(Predicate<ITextMarker> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
foreach (TextMarker m in markers.ToArray()) {
if (predicate(m))
Remove(m);
}
}
public void Remove(ITextMarker marker)
{
if (marker == null)
return;
TextMarker m = marker as TextMarker;
if (markers.Remove(m)) {
Redraw(m);
m.OnDeleted();
}
}
/// <summary>
/// Redraws the specified text segment.
/// </summary>
public void Redraw(ISegment segment)
{
codeEditor.TextArea.TextView.Redraw(segment, DispatcherPriority.Normal);
}
#endregion
#region DocumentColorizingTransformer
protected override void ColorizeLine(DocumentLine line)
{
if (markers == null)
return;
int lineStart = line.Offset;
int lineEnd = lineStart + line.Length;
foreach (TextMarker marker in markers.FindOverlappingSegments(lineStart, line.Length).Reverse()) {
if (!marker.IsVisible(marker.Bookmark))
continue;
Brush foregroundBrush = null;
if (marker.ForegroundColor != null) {
foregroundBrush = new SolidColorBrush(marker.ForegroundColor.Value);
foregroundBrush.Freeze();
}
ChangeLinePart(
Math.Max(marker.StartOffset, lineStart),
Math.Min(marker.EndOffset, lineEnd),
element => {
if (foregroundBrush != null) {
element.TextRunProperties.SetForegroundBrush(foregroundBrush);
}
}
);
}
}
#endregion
#region IBackgroundRenderer
public KnownLayer Layer {
get {
// draw behind selection
return KnownLayer.Selection;
}
}
public void Draw(ICSharpCode.AvalonEdit.Rendering.TextView textView, DrawingContext drawingContext)
{
if (textView == null)
throw new ArgumentNullException("textView");
if (drawingContext == null)
throw new ArgumentNullException("drawingContext");
if (markers == null || !textView.VisualLinesValid)
return;
var visualLines = textView.VisualLines;
if (visualLines.Count == 0)
return;
int viewStart = visualLines.First().FirstDocumentLine.Offset;
int viewEnd = visualLines.Last().LastDocumentLine.Offset + visualLines.Last().LastDocumentLine.Length;
foreach (TextMarker marker in markers.FindOverlappingSegments(viewStart, viewEnd - viewStart).Reverse()) {
if (!marker.IsVisible(marker.Bookmark))
continue;
if (marker.BackgroundColor != null) {
BackgroundGeometryBuilder geoBuilder = new BackgroundGeometryBuilder();
geoBuilder.AlignToWholePixels = true;
geoBuilder.CornerRadius = 3;
geoBuilder.AddSegment(textView, marker);
Geometry geometry = geoBuilder.CreateGeometry();
if (geometry != null) {
Color color = marker.BackgroundColor.Value;
SolidColorBrush brush = new SolidColorBrush(color);
brush.Freeze();
drawingContext.DrawGeometry(brush, null, geometry);
}
}
if (marker.MarkerType != TextMarkerType.None) {
foreach (Rect r in BackgroundGeometryBuilder.GetRectsForSegment(textView, marker)) {
Point startPoint = r.BottomLeft;
Point endPoint = r.BottomRight;
Pen usedPen = new Pen(new SolidColorBrush(marker.MarkerColor), 1);
usedPen.Freeze();
switch (marker.MarkerType) {
case TextMarkerType.SquigglyUnderline:
double offset = 2.5;
int count = Math.Max((int)((endPoint.X - startPoint.X) / offset) + 1, 4);
StreamGeometry geometry = new StreamGeometry();
using (StreamGeometryContext ctx = geometry.Open()) {
ctx.BeginFigure(startPoint, false, false);
ctx.PolyLineTo(CreatePoints(startPoint, endPoint, offset, count).ToArray(), true, false);
}
geometry.Freeze();
drawingContext.DrawGeometry(Brushes.Transparent, usedPen, geometry);
break;
}
}
}
}
}
IEnumerable<Point> CreatePoints(Point start, Point end, double offset, int count)
{
for (int i = 0; i < count; i++)
yield return new Point(start.X + i * offset, start.Y - ((i + 1) % 2 == 0 ? offset : 0));
}
#endregion
}
sealed class TextMarker : TextSegment, ITextMarker
{
readonly TextMarkerService service;
public TextMarker(TextMarkerService service, int startOffset, int length)
{
if (service == null)
throw new ArgumentNullException("service");
this.service = service;
this.StartOffset = startOffset;
this.Length = length;
this.markerType = TextMarkerType.None;
}
public event EventHandler Deleted;
public bool IsDeleted {
get { return !this.IsConnectedToCollection; }
}
public void Delete()
{
service.Remove(this);
}
internal void OnDeleted()
{
if (Deleted != null)
Deleted(this, EventArgs.Empty);
}
void Redraw()
{
service.Redraw(this);
}
Color? backgroundColor;
public Color? BackgroundColor {
get { return backgroundColor; }
set {
if (backgroundColor != value) {
backgroundColor = value;
Redraw();
}
}
}
Color? foregroundColor;
public Color? ForegroundColor {
get { return foregroundColor; }
set {
if (foregroundColor != value) {
foregroundColor = value;
Redraw();
}
}
}
public object Tag { get; set; }
TextMarkerType markerType;
public TextMarkerType MarkerType {
get { return markerType; }
set {
if (markerType != value) {
markerType = value;
Redraw();
}
}
}
Color markerColor;
public Color MarkerColor {
get { return markerColor; }
set {
if (markerColor != value) {
markerColor = value;
Redraw();
}
}
}
/// <inheritdoc/>
public object ToolTip { get; set; }
/// <inheritdoc/>
public Predicate<object> IsVisible { get; set; }
/// <inheritdoc/>
public IBookmark Bookmark { get; set; }
}
}

97
ILSpy/Bookmarks/BookmarkBase.cs

@ -0,0 +1,97 @@ @@ -0,0 +1,97 @@
// 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.Windows.Input;
using System.Windows.Media;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Bookmarks
{
/// <summary>
/// A bookmark that can be attached to an AvalonEdit TextDocument.
/// </summary>
public class BookmarkBase : IBookmark
{
AstLocation location;
protected virtual void RemoveMark()
{
}
public AstLocation Location {
get { return location; }
set { location = value; }
}
public event EventHandler DocumentChanged;
protected virtual void OnDocumentChanged(EventArgs e)
{
if (DocumentChanged != null) {
DocumentChanged(this, e);
}
}
protected virtual void Redraw()
{
}
public MemberReference MemberReference { get; set; }
public int LineNumber {
get { return location.Line; }
}
public int ColumnNumber {
get { return location.Column; }
}
public virtual int ZOrder {
get { return 0; }
}
/// <summary>
/// Gets if the bookmark can be toggled off using the 'set/unset bookmark' command.
/// </summary>
public virtual bool CanToggle {
get {
return true;
}
}
public BookmarkBase(MemberReference member, AstLocation location)
{
this.MemberReference = member;
this.Location = location;
}
public virtual ImageSource Image {
get { return null; }
}
public virtual void MouseDown(MouseButtonEventArgs e)
{
}
public virtual void MouseUp(MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left && CanToggle) {
RemoveMark();
e.Handled = true;
}
}
public virtual bool CanDragDrop {
get { return false; }
}
public virtual void Drop(int lineNumber)
{
}
}
}

28
ILSpy/Bookmarks/BookmarkEventHandler.cs

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
// 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;
namespace ICSharpCode.ILSpy.Bookmarks
{
public delegate void BookmarkEventHandler(object sender, BookmarkEventArgs e);
/// <summary>
/// Description of BookmarkEventHandler.
/// </summary>
public class BookmarkEventArgs : EventArgs
{
BookmarkBase bookmark;
public BookmarkBase Bookmark {
get {
return bookmark;
}
}
public BookmarkEventArgs(BookmarkBase bookmark)
{
this.bookmark = bookmark;
}
}
}

116
ILSpy/Bookmarks/BookmarkManager.cs

@ -0,0 +1,116 @@ @@ -0,0 +1,116 @@
// 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 ICSharpCode.Decompiler;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
using Mono.CSharp;
namespace ICSharpCode.ILSpy.Bookmarks
{
/// <summary>
/// Static class that maintains the list of bookmarks and breakpoints.
/// </summary>
public static partial class BookmarkManager
{
static List<BookmarkBase> bookmarks = new List<BookmarkBase>();
public static List<BookmarkBase> Bookmarks {
get {
return bookmarks;
}
}
public static List<BookmarkBase> GetBookmarks(string typeName)
{
if (typeName == null)
throw new ArgumentNullException("typeName");
List<BookmarkBase> marks = new List<BookmarkBase>();
foreach (BookmarkBase mark in bookmarks) {
if (typeName == mark.MemberReference.FullName) {
marks.Add(mark);
}
}
return marks;
}
public static void AddMark(BookmarkBase bookmark)
{
if (bookmark == null) return;
if (bookmarks.Contains(bookmark)) return;
if (bookmarks.Exists(b => IsEqualBookmark(b, bookmark))) return;
bookmarks.Add(bookmark);
OnAdded(new BookmarkEventArgs(bookmark));
}
static bool IsEqualBookmark(BookmarkBase a, BookmarkBase b)
{
if (a == b)
return true;
if (a == null || b == null)
return false;
if (a.GetType() != b.GetType())
return false;
if (a.MemberReference.FullName != b.MemberReference.FullName)
return false;
return a.LineNumber == b.LineNumber;
}
public static void RemoveMark(BookmarkBase bookmark)
{
bookmarks.Remove(bookmark);
OnRemoved(new BookmarkEventArgs(bookmark));
}
public static void Clear()
{
while (bookmarks.Count > 0) {
var b = bookmarks[bookmarks.Count - 1];
bookmarks.RemoveAt(bookmarks.Count - 1);
OnRemoved(new BookmarkEventArgs(b));
}
}
internal static void Initialize()
{
}
static void OnRemoved(BookmarkEventArgs e)
{
if (Removed != null) {
Removed(null, e);
}
}
static void OnAdded(BookmarkEventArgs e)
{
if (Added != null) {
Added(null, e);
}
}
public static void ToggleBookmark(string typeName, int line,
Predicate<BookmarkBase> canToggle,
Func<AstLocation, BookmarkBase> bookmarkFactory)
{
foreach (BookmarkBase bookmark in GetBookmarks(typeName)) {
if (canToggle(bookmark) && bookmark.LineNumber == line) {
BookmarkManager.RemoveMark(bookmark);
return;
}
}
// no bookmark at that line: create a new bookmark
BookmarkManager.AddMark(bookmarkFactory(new AstLocation(line, 0)));
}
public static event BookmarkEventHandler Removed;
public static event BookmarkEventHandler Added;
}
}

50
ILSpy/Bookmarks/Commands.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// 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 ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.TreeNodes.Analyzer;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Bookmarks
{
[ExportBookmarkContextMenuEntry(Header = "Analyze", Icon = "images/Search.png", Category="Default")]
internal sealed class AnalyzeBookmarkEntry : IBookmarkContextMenuEntry
{
public bool IsVisible(IBookmark[] marks)
{
return true;
}
public bool IsEnabled(IBookmark[] marks)
{
return true;
}
public void Execute(IBookmark[] marks)
{
foreach (var mark in marks) {
if (!(mark is MemberBookmark))
continue;
var member = (mark as MemberBookmark).Node.Annotation<MemberReference>();
AnalyzeContextMenuEntry.Analyze(member);
}
}
}
}

69
ILSpy/Bookmarks/IBookmark.cs

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
// 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.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Input;
using System.Windows.Media;
namespace ICSharpCode.ILSpy.Bookmarks
{
/// <summary>
/// The bookmark margin.
/// </summary>
public interface IBookmarkMargin
{
/// <summary>
/// Gets the list of bookmarks.
/// </summary>
IList<IBookmark> Bookmarks { get; }
/// <summary>
/// Redraws the bookmark margin. Bookmarks need to call this method when the Image changes.
/// </summary>
void Redraw();
}
/// <summary>
/// Represents a bookmark in the bookmark margin.
/// </summary>
public interface IBookmark
{
/// <summary>
/// Gets the line number of the bookmark.
/// </summary>
int LineNumber { get; }
/// <summary>
/// Gets the image.
/// </summary>
ImageSource Image { get; }
/// <summary>
/// Gets the Z-Order of the bookmark icon.
/// </summary>
int ZOrder { get; }
/// <summary>
/// Handles the mouse down event.
/// </summary>
void MouseDown(MouseButtonEventArgs e);
/// <summary>
/// Handles the mouse up event.
/// </summary>
void MouseUp(MouseButtonEventArgs e);
/// <summary>
/// Gets whether this bookmark can be dragged around.
/// </summary>
bool CanDragDrop { get; }
/// <summary>
/// Notifies the bookmark that it was dropped on the specified line.
/// </summary>
void Drop(int lineNumber);
}
}

21
ILSpy/Bookmarks/MarkerBookmark.cs

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
// 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 ICSharpCode.NRefactory.CSharp;
using ICSharpCode.ILSpy.AvalonEdit;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Bookmarks
{
public abstract class MarkerBookmark : BookmarkBase
{
public MarkerBookmark(MemberReference member, AstLocation location) : base(member, location)
{
}
public ITextMarker Marker { get; set; }
public abstract ITextMarker CreateMarker(ITextMarkerService markerService, int offset, int length);
}
}

157
ILSpy/Bookmarks/MemberBookmark.cs

@ -0,0 +1,157 @@ @@ -0,0 +1,157 @@
// 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.Windows;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Bookmarks
{
/// <summary>
/// Bookmark used to give additional operations for class members.
/// Does not derive from SDBookmark because it is not stored in the central BookmarkManager,
/// but only in the document's BookmarkManager.
/// </summary>
public class MemberBookmark : IBookmark
{
AstNode node;
public AstNode Node {
get {
return node;
}
}
public MemberBookmark(AstNode node)
{
this.node = node;
}
public virtual ImageSource Image {
get {
var attrNode = (AttributedNode)node;
if (node is EnumMemberDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.EnumValue);
if (node is FieldDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Field);
if (node is PropertyDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Property);
if (node is EventDeclaration || node is CustomEventDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Event);
if (node is IndexerDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Indexer);
if (node is OperatorDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Operator);
if (node is ConstructorDeclaration || node is DestructorDeclaration)
return GetMemberOverlayedImage(attrNode, MemberIcon.Constructor);
return GetMemberOverlayedImage(attrNode, MemberIcon.Method);
}
}
ImageSource GetMemberOverlayedImage(AttributedNode attrNode, MemberIcon icon)
{
switch (attrNode.Modifiers & Modifiers.VisibilityMask) {
case Modifiers.Protected:
return Images.GetIcon(icon, AccessOverlayIcon.Protected, (attrNode.Modifiers & Modifiers.Static) == Modifiers.Static);
case Modifiers.Private:
return Images.GetIcon(icon, AccessOverlayIcon.Private, (attrNode.Modifiers & Modifiers.Static) == Modifiers.Static);
case Modifiers.Internal:
return Images.GetIcon(icon, AccessOverlayIcon.Internal, (attrNode.Modifiers & Modifiers.Static) == Modifiers.Static);
}
return Images.GetIcon(icon, AccessOverlayIcon.Public, (attrNode.Modifiers & Modifiers.Static) == Modifiers.Static);
}
public int LineNumber {
get {
var t = node.Annotation<Tuple<int, int>>();
if (t != null)
return t.Item1;
return 0;
}
}
public virtual void MouseDown(MouseButtonEventArgs e)
{
}
public virtual void MouseUp(MouseButtonEventArgs e)
{
}
int IBookmark.ZOrder {
get { return -10; }
}
bool IBookmark.CanDragDrop {
get { return false; }
}
void IBookmark.Drop(int lineNumber)
{
throw new NotSupportedException();
}
}
public class TypeBookmark : MemberBookmark
{
public TypeBookmark(AstNode node) : base (node)
{
}
public override ImageSource Image {
get {
var attrNode = (AttributedNode)Node;
if (Node is DelegateDeclaration)
return GetTypeOverlayedImage(attrNode, TypeIcon.Delegate);
if (Node is TypeDeclaration) {
var n = Node as TypeDeclaration;
switch (n.ClassType)
{
case ClassType.Delegate:
return GetTypeOverlayedImage(attrNode, TypeIcon.Delegate);
case ClassType.Enum:
return GetTypeOverlayedImage(attrNode, TypeIcon.Enum);
case ClassType.Struct:
return GetTypeOverlayedImage(attrNode, TypeIcon.Struct);
case ClassType.Interface:
return GetTypeOverlayedImage(attrNode, TypeIcon.Interface);
}
}
if ((attrNode.Modifiers & Modifiers.Static) == Modifiers.Static)
return GetTypeOverlayedImage(attrNode, TypeIcon.StaticClass);
return GetTypeOverlayedImage(attrNode, TypeIcon.Class);
}
}
ImageSource GetTypeOverlayedImage(AttributedNode attrNode, TypeIcon icon)
{
switch (attrNode.Modifiers & Modifiers.VisibilityMask) {
case Modifiers.Protected:
return Images.GetIcon(icon, AccessOverlayIcon.Protected);
case Modifiers.Private:
return Images.GetIcon(icon, AccessOverlayIcon.Private);
case Modifiers.Internal:
return Images.GetIcon(icon, AccessOverlayIcon.Internal);
}
return Images.GetIcon(icon, AccessOverlayIcon.Public);
}
}
}

178
ILSpy/Commands.cs

@ -1,178 +0,0 @@ @@ -1,178 +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.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_File", Header = "E_xit", MenuOrder = 99999, MenuCategory = "Exit")]
sealed class ExitCommand : SimpleCommand
{
public override void Execute(object parameter)
{
MainWindow.Instance.Close();
}
}
[ExportToolbarCommand(ToolTip = "Back", ToolbarIcon = "Images/Back.png", ToolbarCategory = "Navigation", ToolbarOrder = 0)]
sealed class BrowseBackCommand : CommandWrapper {
public BrowseBackCommand() : base(NavigationCommands.BrowseBack) {}
}
[ExportToolbarCommand(ToolTip = "Forward", ToolbarIcon = "Images/Forward.png", ToolbarCategory = "Navigation", ToolbarOrder = 1)]
sealed class BrowseForwardCommand : CommandWrapper {
public BrowseForwardCommand() : base(NavigationCommands.BrowseForward) {}
}
[ExportToolbarCommand(ToolTip = "Open", ToolbarIcon = "Images/Open.png", ToolbarCategory = "Open", ToolbarOrder = 0)]
[ExportMainMenuCommand(Menu = "_File", MenuIcon = "Images/Open.png", MenuCategory = "Open", MenuOrder = 0)]
sealed class OpenCommand : CommandWrapper {
public OpenCommand() : base(ApplicationCommands.Open) {}
}
[ExportMainMenuCommand(Menu = "_File", Header = "Open from _GAC", MenuCategory = "Open", MenuOrder = 1)]
sealed class OpenFromGacCommand : SimpleCommand
{
public override void Execute(object parameter)
{
OpenFromGacDialog dlg = new OpenFromGacDialog();
dlg.Owner = MainWindow.Instance;
if (dlg.ShowDialog() == true) {
MainWindow.Instance.OpenFiles(dlg.SelectedFileNames);
}
}
}
[ExportToolbarCommand(ToolTip = "Reload all assemblies", ToolbarIcon = "Images/Refresh.png", ToolbarCategory = "Open", ToolbarOrder = 2)]
[ExportMainMenuCommand(Menu = "_File", Header = "Reload", MenuIcon = "Images/Refresh.png", MenuCategory = "Open", MenuOrder = 2)]
sealed class RefreshCommand : CommandWrapper {
public RefreshCommand() : base(NavigationCommands.Refresh) {}
}
[ExportMainMenuCommand(Menu = "_File", Header = "_Save Code...", MenuIcon = "Images/SaveFile.png", MenuCategory = "Save", MenuOrder = 0)]
sealed class SaveCommand : CommandWrapper
{
public SaveCommand() : base(ApplicationCommands.Save) {}
}
#if DEBUG
[ExportMainMenuCommand(Menu = "_File", Header = "DEBUG -- Decompile All", MenuCategory = "Open", MenuOrder = 2.5)]
sealed class DecompileAllCommand : SimpleCommand
{
public override bool CanExecute(object parameter)
{
return System.IO.Directory.Exists("c:\\temp\\decompiled");
}
public override void Execute(object parameter)
{
MainWindow.Instance.TextView.RunWithCancellation(
ct => Task<AvalonEditTextOutput>.Factory.StartNew(
() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
Parallel.ForEach(
MainWindow.Instance.CurrentAssemblyList.GetAssemblies(),
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct },
delegate (LoadedAssembly asm) {
if (!asm.HasLoadError) {
Stopwatch w = Stopwatch.StartNew();
Exception exception = null;
using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs")) {
try {
new CSharpLanguage().DecompileAssembly(
asm, new Decompiler.PlainTextOutput(writer),
new DecompilationOptions { FullDecompilation = true, CancellationToken = ct });
} catch (Exception ex) {
writer.WriteLine(ex.ToString());
exception = ex;
}
}
lock (output) {
output.Write(asm.ShortName + " - " + w.Elapsed);
if (exception != null) {
output.Write(" - ");
output.Write(exception.GetType().Name);
}
output.WriteLine();
}
}
});
return output;
}
),
task => MainWindow.Instance.TextView.ShowText(task.Result));
}
}
#endif
class CommandWrapper : ICommand
{
ICommand wrappedCommand;
public CommandWrapper(ICommand wrappedCommand)
{
this.wrappedCommand = wrappedCommand;
}
public static ICommand Unwrap(ICommand command)
{
CommandWrapper w = command as CommandWrapper;
if (w != null)
return w.wrappedCommand;
else
return command;
}
public event EventHandler CanExecuteChanged {
add { wrappedCommand.CanExecuteChanged += value; }
remove { wrappedCommand.CanExecuteChanged -= value; }
}
public void Execute(object parameter)
{
wrappedCommand.Execute(parameter);
}
public bool CanExecute(object parameter)
{
return wrappedCommand.CanExecute(parameter);
}
}
public abstract class SimpleCommand : ICommand
{
public event EventHandler CanExecuteChanged {
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public abstract void Execute(object parameter);
public virtual bool CanExecute(object parameter)
{
return true;
}
}
}

32
ILSpy/Commands/BrowseBackCommand.cs

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
// 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.Windows.Input;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = "Back", ToolbarIcon = "Images/Back.png", ToolbarCategory = "Navigation", ToolbarOrder = 0)]
sealed class BrowseBackCommand : CommandWrapper
{
public BrowseBackCommand()
: base(NavigationCommands.BrowseBack)
{
}
}
}

32
ILSpy/Commands/BrowseForwardCommand.cs

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
// 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.Windows.Input;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = "Forward", ToolbarIcon = "Images/Forward.png", ToolbarCategory = "Navigation", ToolbarOrder = 1)]
sealed class BrowseForwardCommand : CommandWrapper
{
public BrowseForwardCommand()
: base(NavigationCommands.BrowseForward)
{
}
}
}

58
ILSpy/Commands/CommandWrapper.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
// 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.Windows.Input;
namespace ICSharpCode.ILSpy
{
class CommandWrapper : ICommand
{
private ICommand wrappedCommand;
public CommandWrapper(ICommand wrappedCommand)
{
this.wrappedCommand = wrappedCommand;
}
public static ICommand Unwrap(ICommand command)
{
CommandWrapper w = command as CommandWrapper;
if (w != null)
return w.wrappedCommand;
else
return command;
}
public event EventHandler CanExecuteChanged
{
add { wrappedCommand.CanExecuteChanged += value; }
remove { wrappedCommand.CanExecuteChanged -= value; }
}
public void Execute(object parameter)
{
wrappedCommand.Execute(parameter);
}
public bool CanExecute(object parameter)
{
return wrappedCommand.CanExecute(parameter);
}
}
}

69
ILSpy/Commands/DecompileAllCommand.cs

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
// 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.
#if DEBUG
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using ICSharpCode.ILSpy.TextView;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_File", Header = "DEBUG -- Decompile All", MenuCategory = "Open", MenuOrder = 2.5)]
sealed class DecompileAllCommand : SimpleCommand
{
public override bool CanExecute(object parameter)
{
return System.IO.Directory.Exists("c:\\temp\\decompiled");
}
public override void Execute(object parameter)
{
MainWindow.Instance.TextView.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
Parallel.ForEach(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct }, delegate(LoadedAssembly asm) {
if (!asm.HasLoadError) {
Stopwatch w = Stopwatch.StartNew();
Exception exception = null;
using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs")) {
try {
new CSharpLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions { FullDecompilation = true, CancellationToken = ct });
}
catch (Exception ex) {
writer.WriteLine(ex.ToString());
exception = ex;
}
}
lock (output) {
output.Write(asm.ShortName + " - " + w.Elapsed);
if (exception != null) {
output.Write(" - ");
output.Write(exception.GetType().Name);
}
output.WriteLine();
}
}
});
return output;
}), task => MainWindow.Instance.TextView.ShowText(task.Result));
}
}
}
#endif

31
ILSpy/Commands/ExitCommand.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_File", Header = "E_xit", MenuOrder = 99999, MenuCategory = "Exit")]
sealed class ExitCommand : SimpleCommand
{
public override void Execute(object parameter)
{
MainWindow.Instance.Close();
}
}
}

0
ILSpy/ExportCommandAttribute.cs → ILSpy/Commands/ExportCommandAttribute.cs

33
ILSpy/Commands/OpenCommand.cs

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
// 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.Windows.Input;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = "Open", ToolbarIcon = "Images/Open.png", ToolbarCategory = "Open", ToolbarOrder = 0)]
[ExportMainMenuCommand(Menu = "_File", MenuIcon = "Images/Open.png", MenuCategory = "Open", MenuOrder = 0)]
sealed class OpenCommand : CommandWrapper
{
public OpenCommand()
: base(ApplicationCommands.Open)
{
}
}
}

34
ILSpy/Commands/OpenFromGacCommand.cs

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_File", Header = "Open from _GAC", MenuCategory = "Open", MenuOrder = 1)]
sealed class OpenFromGacCommand : SimpleCommand
{
public override void Execute(object parameter)
{
OpenFromGacDialog dlg = new OpenFromGacDialog();
dlg.Owner = MainWindow.Instance;
if (dlg.ShowDialog() == true)
MainWindow.Instance.OpenFiles(dlg.SelectedFileNames);
}
}
}

33
ILSpy/Commands/RefreshCommand.cs

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
// 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.Windows.Input;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = "Reload all assemblies", ToolbarIcon = "Images/Refresh.png", ToolbarCategory = "Open", ToolbarOrder = 2)]
[ExportMainMenuCommand(Menu = "_File", Header = "Reload", MenuIcon = "Images/Refresh.png", MenuCategory = "Open", MenuOrder = 2)]
sealed class RefreshCommand : CommandWrapper
{
public RefreshCommand()
: base(NavigationCommands.Refresh)
{
}
}
}

32
ILSpy/Commands/SaveCommand.cs

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
// 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.Windows.Input;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_File", Header = "_Save Code...", MenuIcon = "Images/SaveFile.png", MenuCategory = "Save", MenuOrder = 0)]
sealed class SaveCommand : CommandWrapper
{
public SaveCommand()
: base(ApplicationCommands.Save)
{
}
}
}

31
ILSpy/Commands/ShowAnalyzerCommand.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_View", Header = "_Analyzer", MenuCategory = "ShowPane", MenuOrder = 100)]
sealed class ShowAnalyzerCommand : SimpleCommand
{
public override void Execute(object parameter)
{
AnalyzerTreeView.Instance.Show();
}
}
}

39
ILSpy/Commands/SimpleCommand.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
// 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.Windows.Input;
namespace ICSharpCode.ILSpy
{
public abstract class SimpleCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public abstract void Execute(object parameter);
public virtual bool CanExecute(object parameter)
{
return true;
}
}
}

61
ILSpy/ILSpy.csproj

@ -93,19 +93,36 @@ @@ -93,19 +93,36 @@
</Compile>
<Compile Include="AssemblyList.cs" />
<Compile Include="AssemblyListManager.cs" />
<Compile Include="Commands\BrowseBackCommand.cs" />
<Compile Include="Commands\BrowseForwardCommand.cs" />
<Compile Include="AvalonEdit\IconBarManager.cs" />
<Compile Include="AvalonEdit\IconBarMargin.cs" />
<Compile Include="AvalonEdit\IconMarginActionsProvider.cs" />
<Compile Include="AvalonEdit\TextMarkerService.cs" />
<Compile Include="AvalonEdit\TextEditorWeakEventManager.cs" />
<Compile Include="AvalonEdit\ITextMarker.cs" />
<Compile Include="Bookmarks\BookmarkBase.cs" />
<Compile Include="Bookmarks\BookmarkEventHandler.cs" />
<Compile Include="Bookmarks\BookmarkManager.cs" />
<Compile Include="Bookmarks\Commands.cs" />
<Compile Include="Bookmarks\MemberBookmark.cs" />
<Compile Include="Bookmarks\IBookmark.cs" />
<Compile Include="Bookmarks\MarkerBookmark.cs" />
<Compile Include="CommandLineArguments.cs" />
<Compile Include="Commands.cs" />
<Compile Include="Commands\ExitCommand.cs" />
<Compile Include="Commands\CommandWrapper.cs" />
<Compile Include="ConnectMethodDecompiler.cs" />
<Compile Include="Controls\DockedPane.cs" />
<Compile Include="Commands\DecompileAllCommand.cs" />
<Compile Include="DecompilerSettingsPanel.xaml.cs">
<DependentUpon>DecompilerSettingsPanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="DisplaySettings.cs" />
<Compile Include="ExportCommandAttribute.cs" />
<Compile Include="Commands\ExportCommandAttribute.cs" />
<Compile Include="Controls\SearchBox.cs" />
<Compile Include="Controls\SortableGridViewColumn.cs" />
<Compile Include="CSharpLanguage.cs" />
<Compile Include="Languages\CSharpLanguage.cs" />
<Compile Include="DecompilationOptions.cs" />
<Compile Include="ExtensionMethods.cs" />
<Compile Include="FilterSettings.cs" />
@ -113,19 +130,23 @@ @@ -113,19 +130,23 @@
<Compile Include="GacInterop.cs" />
<Compile Include="GuessFileType.cs" />
<Compile Include="ContextMenuEntry.cs" />
<Compile Include="ILAstLanguage.cs" />
<Compile Include="ILLanguage.cs" />
<Compile Include="Languages\ILAstLanguage.cs" />
<Compile Include="Languages\ILLanguage.cs" />
<Compile Include="ILSpySettings.cs" />
<Compile Include="Images\AccessOverlayIcon.cs" />
<Compile Include="Images\MemberIcon.cs" />
<Compile Include="Images\TypeIcon.cs" />
<Compile Include="IPane.cs" />
<Compile Include="ISmartTextOutput.cs" />
<Compile Include="Language.cs" />
<Compile Include="Languages\Language.cs" />
<Compile Include="Images\Images.cs" />
<Compile Include="Languages\Languages.cs" />
<Compile Include="LoadedAssembly.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="NavigationHistory.cs" />
<Compile Include="NavigationState.cs" />
<Compile Include="Commands\OpenCommand.cs" />
<Compile Include="Commands\OpenFromGacCommand.cs" />
<Compile Include="OpenFromGacDialog.xaml.cs">
<DependentUpon>OpenFromGacDialog.xaml</DependentUpon>
<SubType>Code</SubType>
@ -135,6 +156,8 @@ @@ -135,6 +156,8 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Commands\RefreshCommand.cs" />
<Compile Include="Commands\SaveCommand.cs" />
<Compile Include="SearchPane.cs">
<SubType>Code</SubType>
</Compile>
@ -142,6 +165,8 @@ @@ -142,6 +165,8 @@
<DependentUpon>DisplaySettingsPanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Commands\SimpleCommand.cs" />
<Compile Include="Commands\ShowAnalyzerCommand.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzeContextMenuEntry.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedEventOverridesTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedEventTreeNode.cs" />
@ -158,8 +183,16 @@ @@ -158,8 +183,16 @@
<Compile Include="TreeNodes\Analyzer\AnalyzedVirtualMethodUsedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\Helpers.cs" />
<Compile Include="TreeNodes\Analyzer\ScopedWhereUsedAnalyzer.cs" />
<Compile Include="TreeNodes\BaseTypesEntryNode.cs" />
<Compile Include="TreeNodes\DerivedTypesEntryNode.cs" />
<Compile Include="TreeNodes\FilterResult.cs" />
<Compile Include="TreeNodes\IMemberTreeNode.cs" />
<Compile Include="TreeNodes\XamlResourceNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\CursorResourceEntryNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\ImageResourceEntryNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\XmlResourceNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\IResourceNodeFactory.cs" />
<Compile Include="TreeNodes\ResourceNodes\ResourcesFileTreeNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\XamlResourceNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyOverridesTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyTreeNode.cs" />
<Compile Include="XmlDoc\AddXmlDocTransform.cs" />
@ -218,9 +251,9 @@ @@ -218,9 +251,9 @@
<Compile Include="TreeNodes\NamespaceTreeNode.cs" />
<Compile Include="TreeNodes\PropertyTreeNode.cs" />
<Compile Include="TreeNodes\ReferenceFolderTreeNode.cs" />
<Compile Include="TreeNodes\ResourceEntryNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\ResourceEntryNode.cs" />
<Compile Include="TreeNodes\ResourceListTreeNode.cs" />
<Compile Include="TreeNodes\ResourceTreeNode.cs" />
<Compile Include="TreeNodes\ResourceNodes\ResourceTreeNode.cs" />
<Compile Include="TreeNodes\ThreadingSupport.cs" />
<Compile Include="TreeNodes\TypeTreeNode.cs" />
<EmbeddedResource Include="TextView\ILAsm-Mode.xshd" />
@ -312,5 +345,15 @@ @@ -312,5 +345,15 @@
<Name>ICSharpCode.TreeView</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\ResourceXml.png" />
<Resource Include="Images\ResourceXsd.png" />
<Resource Include="Images\ResourceXslt.png" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Folder Include="AvalonEdit" />
<Folder Include="Bookmarks" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

27
ILSpy/IPane.cs

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.ILSpy
{
public interface IPane
{
void Closed();
}
}

BIN
ILSpy/Images/Delete.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 584 B

3
ILSpy/Images/Images.cs

@ -59,6 +59,9 @@ namespace ICSharpCode.ILSpy @@ -59,6 +59,9 @@ namespace ICSharpCode.ILSpy
public static readonly BitmapImage Resource = LoadBitmap("Resource");
public static readonly BitmapImage ResourceImage = LoadBitmap("ResourceImage");
public static readonly BitmapImage ResourceResourcesFile = LoadBitmap("ResourceResourcesFile");
public static readonly BitmapImage ResourceXml = LoadBitmap("ResourceXml");
public static readonly BitmapImage ResourceXsd = LoadBitmap("ResourceXsd");
public static readonly BitmapImage ResourceXslt = LoadBitmap("ResourceXslt");
public static readonly BitmapImage Class = LoadBitmap("Class");
public static readonly BitmapImage Struct = LoadBitmap("Struct");

BIN
ILSpy/Images/OverlayInternal.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
ILSpy/Images/OverlayProtected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 352 B

After

Width:  |  Height:  |  Size: 351 B

BIN
ILSpy/Images/OverlayProtectedInternal.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 B

After

Width:  |  Height:  |  Size: 440 B

BIN
ILSpy/Images/ResourceXml.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

BIN
ILSpy/Images/ResourceXsd.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
ILSpy/Images/ResourceXslt.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

48
ILSpy/CSharpLanguage.cs → ILSpy/Languages/CSharpLanguage.cs

@ -23,11 +23,11 @@ using System.ComponentModel.Composition; @@ -23,11 +23,11 @@ using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Resources;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xaml;
using System.Xml;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Ast.Transforms;
@ -100,6 +100,7 @@ namespace ICSharpCode.ILSpy @@ -100,6 +100,7 @@ namespace ICSharpCode.ILSpy
codeDomBuilder.AddMethod(method);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
}
NotifyDecompilationFinished(codeDomBuilder);
}
class SelectCtorTransform : IAstTransform
@ -144,6 +145,7 @@ namespace ICSharpCode.ILSpy @@ -144,6 +145,7 @@ namespace ICSharpCode.ILSpy
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: property.DeclaringType, isSingleMember: true);
codeDomBuilder.AddProperty(property);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
NotifyDecompilationFinished(codeDomBuilder);
}
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
@ -157,6 +159,7 @@ namespace ICSharpCode.ILSpy @@ -157,6 +159,7 @@ namespace ICSharpCode.ILSpy
AddFieldsAndCtors(codeDomBuilder, field.DeclaringType, field.IsStatic);
}
RunTransformsAndGenerateCode(codeDomBuilder, output, options, new SelectFieldTransform(field));
NotifyDecompilationFinished(codeDomBuilder);
}
/// <summary>
@ -200,6 +203,7 @@ namespace ICSharpCode.ILSpy @@ -200,6 +203,7 @@ namespace ICSharpCode.ILSpy
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: ev.DeclaringType, isSingleMember: true);
codeDomBuilder.AddEvent(ev);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
NotifyDecompilationFinished(codeDomBuilder);
}
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
@ -207,6 +211,7 @@ namespace ICSharpCode.ILSpy @@ -207,6 +211,7 @@ namespace ICSharpCode.ILSpy
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: type);
codeDomBuilder.AddType(type);
RunTransformsAndGenerateCode(codeDomBuilder, output, options);
NotifyDecompilationFinished(codeDomBuilder);
}
void RunTransformsAndGenerateCode(AstBuilder astBuilder, ITextOutput output, DecompilationOptions options, IAstTransform additionalTransform = null)
@ -230,6 +235,46 @@ namespace ICSharpCode.ILSpy @@ -230,6 +235,46 @@ namespace ICSharpCode.ILSpy
WriteProjectFile(new TextOutputWriter(output), files, assembly.AssemblyDefinition.MainModule);
} else {
base.DecompileAssembly(assembly, output, options);
output.WriteLine();
ModuleDefinition mainModule = assembly.AssemblyDefinition.MainModule;
if (mainModule.EntryPoint != null) {
output.Write("// Entry point: ");
output.WriteReference(mainModule.EntryPoint.DeclaringType.FullName + "." + mainModule.EntryPoint.Name, mainModule.EntryPoint);
output.WriteLine();
}
switch (mainModule.Architecture) {
case TargetArchitecture.I386:
if ((mainModule.Attributes & ModuleAttributes.Required32Bit) == ModuleAttributes.Required32Bit)
output.WriteLine("// Architecture: x86");
else
output.WriteLine("// Architecture: AnyCPU");
break;
case TargetArchitecture.AMD64:
output.WriteLine("// Architecture: x64");
break;
case TargetArchitecture.IA64:
output.WriteLine("// Architecture: Itanium-64");
break;
}
if ((mainModule.Attributes & ModuleAttributes.ILOnly) == 0) {
output.WriteLine("// This assembly contains unmanaged code.");
}
switch (mainModule.Runtime) {
case TargetRuntime.Net_1_0:
output.WriteLine("// Runtime: .NET 1.0");
break;
case TargetRuntime.Net_1_1:
output.WriteLine("// Runtime: .NET 1.1");
break;
case TargetRuntime.Net_2_0:
output.WriteLine("// Runtime: .NET 2.0");
break;
case TargetRuntime.Net_4_0:
output.WriteLine("// Runtime: .NET 4.0");
break;
}
output.WriteLine();
// don't automatically load additional assemblies when an assembly node is selected in the tree view
using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad()) {
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: assembly.AssemblyDefinition.MainModule);
@ -238,6 +283,7 @@ namespace ICSharpCode.ILSpy @@ -238,6 +283,7 @@ namespace ICSharpCode.ILSpy
codeDomBuilder.GenerateCode(output);
}
}
OnDecompilationFinished(null);
}
#region WriteProjectFile

0
ILSpy/ILAstLanguage.cs → ILSpy/Languages/ILAstLanguage.cs

18
ILSpy/ILLanguage.cs → ILSpy/Languages/ILLanguage.cs

@ -18,8 +18,6 @@ @@ -18,8 +18,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil;
@ -52,12 +50,16 @@ namespace ICSharpCode.ILSpy @@ -52,12 +50,16 @@ namespace ICSharpCode.ILSpy
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken).DisassembleMethod(method);
var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
dis.DisassembleMethod(method);
NotifyDecompilationFinished(dis);
}
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
{
new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken).DisassembleField(field);
var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
dis.DisassembleField(field);
NotifyDecompilationFinished(dis);
}
public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
@ -76,6 +78,7 @@ namespace ICSharpCode.ILSpy @@ -76,6 +78,7 @@ namespace ICSharpCode.ILSpy
output.WriteLine();
rd.DisassembleMethod(m);
}
NotifyDecompilationFinished(rd);
}
public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
@ -94,16 +97,20 @@ namespace ICSharpCode.ILSpy @@ -94,16 +97,20 @@ namespace ICSharpCode.ILSpy
output.WriteLine();
rd.DisassembleMethod(m);
}
NotifyDecompilationFinished(rd);
}
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{
new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken).DisassembleType(type);
var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
dis.DisassembleType(type);
NotifyDecompilationFinished(dis);
}
public override void DecompileNamespace(string nameSpace, IEnumerable<TypeDefinition> types, ITextOutput output, DecompilationOptions options)
{
new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken).DisassembleNamespace(nameSpace, types);
OnDecompilationFinished(null);
}
public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
@ -122,6 +129,7 @@ namespace ICSharpCode.ILSpy @@ -122,6 +129,7 @@ namespace ICSharpCode.ILSpy
output.WriteLine();
rd.WriteModuleContents(assembly.AssemblyDefinition.MainModule);
}
OnDecompilationFinished(null);
}
public override string TypeToString(TypeReference t, bool includeNamespace, ICustomAttributeProvider attributeProvider)

105
ILSpy/Language.cs → ILSpy/Languages/Language.cs

@ -17,20 +17,56 @@ @@ -17,20 +17,56 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Decompilation event arguments.
/// </summary>
public sealed class DecompileEventArgs : EventArgs
{
/// <summary>
/// Gets ot sets the code mappings
/// </summary>
public Dictionary<int, List<MemberMapping>> CodeMappings { get; internal set; }
/// <summary>
/// Gets or sets the local variables.
/// </summary>
public ConcurrentDictionary<int, IEnumerable<ILVariable>> LocalVariables { get; internal set; }
/// <summary>
/// Gets the list of MembeReferences that are decompiled (TypeDefinitions, MethodDefinitions, etc)
/// </summary>
public Dictionary<int, MemberReference> DecompiledMemberReferences { get; internal set; }
/// <summary>
/// Gets (or internal sets) the AST nodes.
/// </summary>
public IEnumerable<AstNode> AstNodes { get; internal set; }
}
/// <summary>
/// Base class for language-specific decompiler implementations.
/// </summary>
public abstract class Language
{
/// <summary>
/// Decompile finished event.
/// </summary>
public event EventHandler<DecompileEventArgs> DecompileFinished;
/// <summary>
/// Gets the name of the language (as shown in the UI)
/// </summary>
@ -85,6 +121,7 @@ namespace ICSharpCode.ILSpy @@ -85,6 +121,7 @@ namespace ICSharpCode.ILSpy
public virtual void DecompileNamespace(string nameSpace, IEnumerable<TypeDefinition> types, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, nameSpace);
OnDecompilationFinished(null);
}
public virtual void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
@ -155,43 +192,39 @@ namespace ICSharpCode.ILSpy @@ -155,43 +192,39 @@ namespace ICSharpCode.ILSpy
{
return member;
}
}
public static class Languages
{
static ReadOnlyCollection<Language> allLanguages;
/// <summary>
/// A list of all languages.
/// </summary>
public static ReadOnlyCollection<Language> AllLanguages
protected virtual void OnDecompilationFinished(DecompileEventArgs e)
{
get
{
return allLanguages;
if (DecompileFinished != null) {
DecompileFinished(this, e);
}
}
internal static void Initialize(CompositionContainer composition)
{
List<Language> languages = new List<Language>();
languages.AddRange(composition.GetExportedValues<Language>());
languages.Add(new ILLanguage(true));
#if DEBUG
languages.AddRange(ILAstLanguage.GetDebugLanguages());
languages.AddRange(CSharpLanguage.GetDebugLanguages());
#endif
allLanguages = languages.AsReadOnly();
}
/// <summary>
/// Gets a language using its name.
/// If the language is not found, C# is returned instead.
/// </summary>
public static Language GetLanguage(string name)
{
return AllLanguages.FirstOrDefault(l => l.Name == name) ?? AllLanguages.First();
protected void NotifyDecompilationFinished(BaseCodeMappings b)
{
if (b is AstBuilder) {
var builder = b as AstBuilder;
var nodes = TreeTraversal
.PreOrder((AstNode)builder.CompilationUnit, n => n.Children)
.Where(n => n is AttributedNode && n.Annotation<Tuple<int, int>>() != null);
OnDecompilationFinished(new DecompileEventArgs {
CodeMappings = builder.CodeMappings,
LocalVariables = builder.LocalVariables,
DecompiledMemberReferences = builder.DecompiledMemberReferences,
AstNodes = nodes
});
}
if (b is ReflectionDisassembler) {
var dis = b as ReflectionDisassembler;
OnDecompilationFinished(new DecompileEventArgs {
CodeMappings = dis.CodeMappings,
DecompiledMemberReferences = dis.DecompiledMemberReferences,
AstNodes = null // TODO: how can I find the nodes with line numbers from dis?
});
}
}
}
}

60
ILSpy/Languages/Languages.cs

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
// 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;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
namespace ICSharpCode.ILSpy
{
public static class Languages
{
private static ReadOnlyCollection<Language> allLanguages;
/// <summary>
/// A list of all languages.
/// </summary>
public static ReadOnlyCollection<Language> AllLanguages
{
get { return allLanguages; }
}
internal static void Initialize(CompositionContainer composition)
{
List<Language> languages = new List<Language>();
languages.AddRange(composition.GetExportedValues<Language>());
languages.Add(new ILLanguage(true));
#if DEBUG
languages.AddRange(ILAstLanguage.GetDebugLanguages());
languages.AddRange(CSharpLanguage.GetDebugLanguages());
#endif
allLanguages = languages.AsReadOnly();
}
/// <summary>
/// Gets a language using its name.
/// If the language is not found, C# is returned instead.
/// </summary>
public static Language GetLanguage(string name)
{
return AllLanguages.FirstOrDefault(l => l.Name == name) ?? AllLanguages.First();
}
}
}

5
ILSpy/LoadedAssembly.cs

@ -171,6 +171,11 @@ namespace ICSharpCode.ILSpy @@ -171,6 +171,11 @@ namespace ICSharpCode.ILSpy
}
}
public IAssemblyResolver GetAssemblyResolver()
{
return new MyAssemblyResolver(this);
}
public LoadedAssembly LookupReferencedAssembly(string fullName)
{
foreach (LoadedAssembly asm in assemblyList.GetAssemblies()) {

2
ILSpy/Properties/AssemblyInfo.template.cs

@ -31,7 +31,7 @@ using System.Runtime.InteropServices; @@ -31,7 +31,7 @@ using System.Runtime.InteropServices;
internal static class RevisionClass
{
public const string Major = "1";
public const string Major = "2";
public const string Minor = "0";
public const string Build = "0";
public const string Revision = "$INSERTREVISION$";

8
ILSpy/SearchPane.cs

@ -35,14 +35,6 @@ using Mono.Cecil; @@ -35,14 +35,6 @@ using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Notifies panes when they are closed.
/// </summary>
public interface IPane
{
void Closed();
}
/// <summary>
/// Search pane
/// </summary>

81
ILSpy/TextView/DecompilerTextView.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Globalization;
@ -35,12 +36,16 @@ using System.Windows.Media; @@ -35,12 +36,16 @@ using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using System.Xml;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.XmlDoc;
using ICSharpCode.NRefactory.Documentation;
@ -55,7 +60,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -55,7 +60,7 @@ namespace ICSharpCode.ILSpy.TextView
/// Contains all the threading logic that makes the decompiler work in the background.
/// </summary>
[Export, PartCreationPolicy(CreationPolicy.Shared)]
public sealed partial class DecompilerTextView : UserControl
public sealed partial class DecompilerTextView : UserControl, IDisposable
{
readonly ReferenceElementGenerator referenceElementGenerator;
readonly UIElementGenerator uiElementGenerator;
@ -66,6 +71,10 @@ namespace ICSharpCode.ILSpy.TextView @@ -66,6 +71,10 @@ namespace ICSharpCode.ILSpy.TextView
DefinitionLookup definitionLookup;
CancellationTokenSource currentCancellationTokenSource;
internal readonly IconBarManager manager;
readonly IconBarMargin iconMargin;
readonly TextMarkerService textMarkerService;
#region Constructor
public DecompilerTextView()
{
@ -79,6 +88,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -79,6 +88,7 @@ namespace ICSharpCode.ILSpy.TextView
}
});
this.Loaded+= new RoutedEventHandler(DecompilerTextView_Loaded);
InitializeComponent();
this.referenceElementGenerator = new ReferenceElementGenerator(this.JumpToReference, this.IsLink);
textEditor.TextArea.TextView.ElementGenerators.Add(referenceElementGenerator);
@ -89,8 +99,49 @@ namespace ICSharpCode.ILSpy.TextView @@ -89,8 +99,49 @@ 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") });
// add marker service & margin
iconMargin = new IconBarMargin((manager = new IconBarManager()));
textMarkerService = new TextMarkerService();
textMarkerService.CodeEditor = textEditor;
textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService);
textEditor.TextArea.TextView.LineTransformers.Add(textMarkerService);
textEditor.ShowLineNumbers = true;
DisplaySettingsPanel.CurrentDisplaySettings.PropertyChanged += CurrentDisplaySettings_PropertyChanged;
textEditor.TextArea.LeftMargins.Insert(0, iconMargin);
textEditor.TextArea.TextView.VisualLinesChanged += delegate { iconMargin.InvalidateVisual(); };
ShowLineMargin();
// Bookmarks context menu
IconMarginActionsProvider.Add(iconMargin);
}
void DecompilerTextView_Loaded(object sender, RoutedEventArgs e)
{
ShowLineMargin();
}
#endregion
#region Line margin
void CurrentDisplaySettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "ShowLineNumbers") {
ShowLineMargin();
}
}
void ShowLineMargin()
{
foreach (var margin in this.textEditor.TextArea.LeftMargins) {
if (margin is LineNumberMargin || margin is System.Windows.Shapes.Line) {
margin.Visibility = DisplaySettingsPanel.CurrentDisplaySettings.ShowLineNumbers ? Visibility.Visible : Visibility.Collapsed;
}
}
}
#endregion
#region Tooltip support
@ -355,12 +406,14 @@ namespace ICSharpCode.ILSpy.TextView @@ -355,12 +406,14 @@ namespace ICSharpCode.ILSpy.TextView
output.WriteLine(ex.ToString());
}
ShowOutput(output);
} finally {
iconMargin.InvalidateVisual();
}
decompiledNodes = context.TreeNodes;
});
}
static Task<AvalonEditTextOutput> DecompileAsync(DecompilationContext context, int outputLengthLimit)
Task<AvalonEditTextOutput> DecompileAsync(DecompilationContext context, int outputLengthLimit)
{
Debug.WriteLine("Start decompilation of {0} tree nodes", context.TreeNodes.Length);
@ -405,9 +458,10 @@ namespace ICSharpCode.ILSpy.TextView @@ -405,9 +458,10 @@ namespace ICSharpCode.ILSpy.TextView
return tcs.Task;
}
static void DecompileNodes(DecompilationContext context, ITextOutput textOutput)
void DecompileNodes(DecompilationContext context, ITextOutput textOutput)
{
var nodes = context.TreeNodes;
context.Language.DecompileFinished += Language_DecompileFinished;
for (int i = 0; i < nodes.Length; i++) {
if (i > 0)
textOutput.WriteLine();
@ -415,6 +469,20 @@ namespace ICSharpCode.ILSpy.TextView @@ -415,6 +469,20 @@ namespace ICSharpCode.ILSpy.TextView
context.Options.CancellationToken.ThrowIfCancellationRequested();
nodes[i].Decompile(context.Language, textOutput, context.Options);
}
context.Language.DecompileFinished -= Language_DecompileFinished;
}
void Language_DecompileFinished(object sender, DecompileEventArgs e)
{
if (e != null) {
manager.UpdateClassMemberBookmarks(e.AstNodes);
if (iconMargin.DecompiledMembers == null) {
iconMargin.DecompiledMembers = new List<MemberReference>();
}
iconMargin.DecompiledMembers.AddRange(e.DecompiledMemberReferences.Values.AsEnumerable());
} else {
manager.UpdateClassMemberBookmarks(null);
}
}
#endregion
@ -604,6 +672,11 @@ namespace ICSharpCode.ILSpy.TextView @@ -604,6 +672,11 @@ namespace ICSharpCode.ILSpy.TextView
state.DecompiledNodes = decompiledNodes;
return state;
}
public void Dispose()
{
DisplaySettingsPanel.CurrentDisplaySettings.PropertyChanged -= CurrentDisplaySettings_PropertyChanged;
}
}
public class DecompilerTextViewState

43
ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs

@ -35,10 +35,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -35,10 +35,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
foreach (IMemberTreeNode node in selectedNodes) {
if (!(node.Member is TypeDefinition
|| node.Member is FieldDefinition
|| node.Member is MethodDefinition
|| Analyzer.AnalyzedPropertyTreeNode.CanShow(node.Member)
|| Analyzer.AnalyzedEventTreeNode.CanShow(node.Member)))
|| node.Member is FieldDefinition
|| node.Member is MethodDefinition
|| Analyzer.AnalyzedPropertyTreeNode.CanShow(node.Member)
|| Analyzer.AnalyzedEventTreeNode.CanShow(node.Member)))
return false;
}
@ -50,22 +50,27 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -50,22 +50,27 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
// TODO: figure out when equivalent nodes are already present
// and focus those instead.
foreach (IMemberTreeNode node in selectedNodes) {
TypeDefinition type = node.Member as TypeDefinition;
if (type != null)
AnalyzerTreeView.Instance.Show(new AnalyzedTypeTreeNode(type));
FieldDefinition field = node.Member as FieldDefinition;
if (field != null)
AnalyzerTreeView.Instance.Show(new AnalyzedFieldTreeNode(field));
MethodDefinition method = node.Member as MethodDefinition;
if (method != null)
AnalyzerTreeView.Instance.Show(new AnalyzedMethodTreeNode(method));
var propertyAnalyzer = Analyzer.AnalyzedPropertyTreeNode.TryCreateAnalyzer(node.Member);
if (propertyAnalyzer != null)
AnalyzerTreeView.Instance.Show(propertyAnalyzer);
var eventAnalyzer = Analyzer.AnalyzedEventTreeNode.TryCreateAnalyzer(node.Member);
if (eventAnalyzer != null)
AnalyzerTreeView.Instance.Show(eventAnalyzer);
Analyze(node.Member);
}
}
public static void Analyze(MemberReference member)
{
TypeDefinition type = member as TypeDefinition;
if (type != null)
AnalyzerTreeView.Instance.Show(new AnalyzedTypeTreeNode(type));
FieldDefinition field = member as FieldDefinition;
if (field != null)
AnalyzerTreeView.Instance.Show(new AnalyzedFieldTreeNode(field));
MethodDefinition method = member as MethodDefinition;
if (method != null)
AnalyzerTreeView.Instance.Show(new AnalyzedMethodTreeNode(method));
var propertyAnalyzer = Analyzer.AnalyzedPropertyTreeNode.TryCreateAnalyzer(member);
if (propertyAnalyzer != null)
AnalyzerTreeView.Instance.Show(propertyAnalyzer);
var eventAnalyzer = Analyzer.AnalyzedEventTreeNode.TryCreateAnalyzer(member);
if (eventAnalyzer != null)
AnalyzerTreeView.Instance.Show(eventAnalyzer);
}
}
}

6
ILSpy/TreeNodes/Analyzer/AnalyzedEventFiredByTreeNode.cs

@ -77,7 +77,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -77,7 +77,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
foundMethods = new ConcurrentDictionary<MethodDefinition, int>();
foreach (var child in FindReferencesInType(analyzedEvent.DeclaringType)) {
foreach (var child in FindReferencesInType(analyzedEvent.DeclaringType).OrderBy(n => n.Text)) {
yield return child;
}
@ -117,7 +117,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -117,7 +117,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (found) {
MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) {
yield return new AnalyzedMethodTreeNode(codeLocation);
var node = new AnalyzedMethodTreeNode(codeLocation);
node.Language = this.Language;
yield return node;
}
}
}

8
ILSpy/TreeNodes/Analyzer/AnalyzedEventOverridesTreeNode.cs

@ -71,7 +71,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -71,7 +71,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedEvent, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
@ -86,7 +88,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -86,7 +88,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (TypesHierarchyHelpers.IsBaseEvent(analyzedEvent, eventDef)) {
MethodDefinition anyAccessor = eventDef.AddMethod ?? eventDef.RemoveMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
yield return new AnalyzedEventTreeNode(eventDef, hidesParent ? "(hides) " : "");
var node = new AnalyzedEventTreeNode(eventDef, hidesParent ? "(hides) " : "");
node.Language = this.Language;
yield return node;
}
}
}

11
ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessTreeNode.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -74,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -74,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foundMethods = new Lazy<Hashtable>(LazyThreadSafetyMode.ExecutionAndPublication);
var analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedField, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct)) {
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
@ -93,8 +94,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -93,8 +94,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (Instruction instr in method.Body.Instructions) {
if (CanBeReference(instr.OpCode.Code)) {
FieldReference fr = instr.Operand as FieldReference;
if (fr != null && fr.Name == name &&
Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) &&
if (fr != null && fr.Name == name &&
Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType) &&
fr.Resolve() == analyzedField) {
found = true;
break;
@ -107,7 +108,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -107,7 +108,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (found) {
MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) {
yield return new AnalyzedMethodTreeNode(codeLocation);
var node = new AnalyzedMethodTreeNode(codeLocation);
node.Language = this.Language;
yield return node;
}
}
}

15
ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceEventImplementedByTreeNode.cs

@ -71,7 +71,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -71,7 +71,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
@ -84,15 +86,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -84,15 +86,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (EventDefinition ev in type.Events.Where(e => e.Name == analyzedEvent.Name)) {
MethodDefinition accessor = ev.AddMethod ?? ev.RemoveMethod;
if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef))
yield return new AnalyzedEventTreeNode(ev);
if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef)) {
var node = new AnalyzedEventTreeNode(ev);
node.Language = this.Language;
yield return node;
}
yield break;
}
foreach (EventDefinition ev in type.Events.Where(e => e.Name.EndsWith(analyzedEvent.Name))) {
MethodDefinition accessor = ev.AddMethod ?? ev.RemoveMethod;
if (accessor.HasOverrides && accessor.Overrides.Any(m => m.Resolve() == analyzedMethod)) {
yield return new AnalyzedEventTreeNode(ev);
var node = new AnalyzedEventTreeNode(ev);
node.Language = this.Language;
yield return node;
}
}
}

15
ILSpy/TreeNodes/Analyzer/AnalyzedInterfaceMethodImplementedByTreeNode.cs

@ -69,7 +69,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -69,7 +69,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
@ -81,14 +83,19 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -81,14 +83,19 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
yield break;
foreach (MethodDefinition method in type.Methods.Where(m => m.Name == analyzedMethod.Name)) {
if (TypesHierarchyHelpers.MatchInterfaceMethod(method, analyzedMethod, implementedInterfaceRef))
yield return new AnalyzedMethodTreeNode(method);
if (TypesHierarchyHelpers.MatchInterfaceMethod(method, analyzedMethod, implementedInterfaceRef)) {
var node = new AnalyzedMethodTreeNode(method);
node.Language = this.Language;
yield return node;
}
yield break;
}
foreach (MethodDefinition method in type.Methods) {
if (method.HasOverrides && method.Overrides.Any(m => m.Resolve() == analyzedMethod)) {
yield return new AnalyzedMethodTreeNode(method);
var node = new AnalyzedMethodTreeNode(method);
node.Language = this.Language;
yield return node;
}
}
}

15
ILSpy/TreeNodes/Analyzer/AnalyzedInterfacePropertyImplementedByTreeNode.cs

@ -71,7 +71,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -71,7 +71,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
@ -84,15 +86,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -84,15 +86,20 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (PropertyDefinition property in type.Properties.Where(e => e.Name == analyzedProperty.Name)) {
MethodDefinition accessor = property.GetMethod ?? property.SetMethod;
if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef))
yield return new AnalyzedPropertyTreeNode(property);
if (TypesHierarchyHelpers.MatchInterfaceMethod(accessor, analyzedMethod, implementedInterfaceRef)) {
var node = new AnalyzedPropertyTreeNode(property);
node.Language = this.Language;
yield return node;
}
yield break;
}
foreach (PropertyDefinition property in type.Properties.Where(e => e.Name.EndsWith(analyzedProperty.Name))) {
MethodDefinition accessor = property.GetMethod ?? property.SetMethod;
if (accessor.HasOverrides && accessor.Overrides.Any(m => m.Resolve() == analyzedMethod)) {
yield return new AnalyzedPropertyTreeNode(property);
var node = new AnalyzedPropertyTreeNode(property);
node.Language = this.Language;
yield return node;
}
}
}

10
ILSpy/TreeNodes/Analyzer/AnalyzedMethodOverridesTreeNode.cs

@ -76,12 +76,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -76,12 +76,14 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
{
SharpTreeNode newNode = null;
AnalyzerTreeNode newNode = null;
try {
if (!TypesHierarchyHelpers.IsBaseType(analyzedMethod.DeclaringType, type, resolveTypeArguments: false))
yield break;
@ -97,8 +99,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -97,8 +99,10 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
// ignore this type definition. maybe add a notification about such cases.
}
if (newNode != null)
if (newNode != null) {
newNode.Language = this.Language;
yield return newNode;
}
}
public static bool CanShow(MethodDefinition method)

7
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -71,7 +72,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -71,7 +72,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foundMethods = new ConcurrentDictionary<MethodDefinition, int>();
var analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct)) {
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
@ -100,7 +101,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -100,7 +101,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (found) {
MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) {
yield return new AnalyzedMethodTreeNode(codeLocation);
var node= new AnalyzedMethodTreeNode(codeLocation);
node.Language = this.Language;
yield return node;
}
}
}

17
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsesTreeNode.cs

@ -51,14 +51,25 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -51,14 +51,25 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
protected override void LoadChildren()
{
analyzedMethod.Body = null;
foreach (var child in GetChildren().OrderBy(n => n.Text)) {
this.Children.Add(child);
}
}
private IEnumerable<AnalyzerTreeNode> GetChildren()
{
foreach (var f in GetUsedFields().Distinct()) {
this.Children.Add(new AnalyzedFieldTreeNode(f));
var node = new AnalyzedFieldTreeNode(f);
node.Language = this.Language;
yield return node;
}
foreach (var m in GetUsedMethods().Distinct()) {
this.Children.Add(new AnalyzedMethodTreeNode(m));
var node = new AnalyzedMethodTreeNode(m);
node.Language = this.Language;
yield return node;
}
analyzedMethod.Body = null;
}
private IEnumerable<MethodDefinition> GetUsedMethods()

8
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -72,7 +72,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -72,7 +72,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedProperty, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
@ -88,7 +90,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -88,7 +90,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) {
MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
yield return new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : "");
var node = new AnalyzedPropertyTreeNode(property, hidesParent ? "(hides) " : "");
node.Language = this.Language;
yield return node;
}
}
}

33
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExposedByTreeNode.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -68,7 +69,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -68,7 +69,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedType, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
@ -80,23 +83,35 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -80,23 +83,35 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
yield break;
foreach (FieldDefinition field in type.Fields) {
if (TypeIsExposedBy(field))
yield return new AnalyzedFieldTreeNode(field);
if (TypeIsExposedBy(field)) {
var node = new AnalyzedFieldTreeNode(field);
node.Language = this.Language;
yield return node;
}
}
foreach (PropertyDefinition property in type.Properties) {
if (TypeIsExposedBy(property))
yield return new AnalyzedPropertyTreeNode(property);
if (TypeIsExposedBy(property)) {
var node = new AnalyzedPropertyTreeNode(property);
node.Language = this.Language;
yield return node;
}
}
foreach (EventDefinition eventDef in type.Events) {
if (TypeIsExposedBy(eventDef))
yield return new AnalyzedEventTreeNode(eventDef);
if (TypeIsExposedBy(eventDef)) {
var node = new AnalyzedEventTreeNode(eventDef);
node.Language = this.Language;
yield return node;
}
}
foreach (MethodDefinition method in type.Methods) {
if (TypeIsExposedBy(method))
yield return new AnalyzedMethodTreeNode(method);
if (TypeIsExposedBy(method)) {
var node = new AnalyzedMethodTreeNode(method);
node.Language = this.Language;
yield return node;
}
}
}

8
ILSpy/TreeNodes/Analyzer/AnalyzedTypeExtensionMethodsTreeNode.cs

@ -69,7 +69,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -69,7 +69,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedType, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
@ -79,7 +81,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -79,7 +81,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
foreach (MethodDefinition method in type.Methods) {
if (method.IsStatic && HasExtensionAttribute(method)) {
if (method.HasParameters && method.Parameters[0].ParameterType.Resolve() == analyzedType) {
yield return new AnalyzedMethodTreeNode(method);
var node = new AnalyzedMethodTreeNode(method);
node.Language = this.Language;
yield return node;
}
}
}

11
ILSpy/TreeNodes/Analyzer/AnalyzedTypeInstantiationsTreeNode.cs

@ -74,7 +74,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -74,7 +74,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
ScopedWhereUsedAnalyzer<SharpTreeNode> analyzer;
analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedType, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
}
private IEnumerable<SharpTreeNode> FindReferencesInType(TypeDefinition type)
@ -102,8 +104,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -102,8 +104,11 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
method.Body = null;
if (found)
yield return new AnalyzedMethodTreeNode(method);
if (found) {
var node = new AnalyzedMethodTreeNode(method);
node.Language = this.Language;
yield return node;
}
}
}

13
ILSpy/TreeNodes/Analyzer/AnalyzedVirtualMethodUsedByTreeNode.cs

@ -75,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -75,7 +75,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
InitializeAnalyzer();
var analyzer = new ScopedWhereUsedAnalyzer<SharpTreeNode>(analyzedMethod, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct)) {
foreach (var child in analyzer.PerformAnalysis(ct).OrderBy(n => n.Text)) {
yield return child;
}
@ -95,8 +95,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -95,8 +95,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
possibleTypes = new List<TypeReference>();
TypeReference type = analyzedMethod.DeclaringType.BaseType;
while (type !=null)
{
while (type != null) {
possibleTypes.Add(type);
type = type.Resolve().BaseType;
}
@ -120,8 +119,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -120,8 +119,8 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
MethodReference mr = instr.Operand as MethodReference;
if (mr != null && mr.Name == name) {
// explicit call to the requested method
if (instr.OpCode.Code == Code.Call
&& Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType)
if (instr.OpCode.Code == Code.Call
&& Helpers.IsReferencedBy(analyzedMethod.DeclaringType, mr.DeclaringType)
&& mr.Resolve() == analyzedMethod) {
found = true;
prefix = "(as base) ";
@ -147,7 +146,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -147,7 +146,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
if (found) {
MethodDefinition codeLocation = this.Language.GetOriginalCodeLocation(method) as MethodDefinition;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) {
yield return new AnalyzedMethodTreeNode(codeLocation, prefix);
var node = new AnalyzedMethodTreeNode(codeLocation);
node.Language = this.Language;
yield return node;
}
}
}

104
ILSpy/TreeNodes/BaseTypesEntryNode.cs

@ -0,0 +1,104 @@ @@ -0,0 +1,104 @@
// 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.Linq;
using ICSharpCode.Decompiler;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TreeNodes
{
sealed class BaseTypesEntryNode : ILSpyTreeNode, IMemberTreeNode
{
private TypeReference tr;
private TypeDefinition def;
private bool isInterface;
public BaseTypesEntryNode(TypeReference tr, bool isInterface)
{
if (tr == null)
throw new ArgumentNullException("tr");
this.tr = tr;
this.def = tr.Resolve();
this.isInterface = isInterface;
this.LazyLoading = true;
}
public override bool ShowExpander
{
get { return def != null && (def.BaseType != null || def.HasInterfaces); }
}
public override object Text
{
get { return this.Language.TypeToString(tr, true); }
}
public override object Icon
{
get
{
if (def != null)
return TypeTreeNode.GetIcon(def);
else
return isInterface ? Images.Interface : Images.Class;
}
}
protected override void LoadChildren()
{
if (def != null)
BaseTypesTreeNode.AddBaseTypes(this.Children, def);
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
// on item activation, try to resolve once again (maybe the user loaded the assembly in the meantime)
if (def == null) {
def = tr.Resolve();
if (def != null)
this.LazyLoading = true;
// re-load children
}
e.Handled = ActivateItem(this, def);
}
internal static bool ActivateItem(SharpTreeNode node, TypeDefinition def)
{
if (def != null) {
var assemblyListNode = node.Ancestors().OfType<AssemblyListTreeNode>().FirstOrDefault();
if (assemblyListNode != null) {
assemblyListNode.Select(assemblyListNode.FindTypeNode(def));
return true;
}
}
return false;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, language.TypeToString(tr, true));
}
MemberReference IMemberTreeNode.Member
{
get { return tr; }
}
}
}

96
ILSpy/TreeNodes/BaseTypesTreeNode.cs

@ -17,9 +17,7 @@ @@ -17,9 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Windows.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -32,26 +30,28 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -32,26 +30,28 @@ namespace ICSharpCode.ILSpy.TreeNodes
sealed class BaseTypesTreeNode : ILSpyTreeNode
{
readonly TypeDefinition type;
public BaseTypesTreeNode(TypeDefinition type)
{
this.type = type;
this.LazyLoading = true;
}
public override object Text {
public override object Text
{
get { return "Base Types"; }
}
public override object Icon {
public override object Icon
{
get { return Images.SuperTypes; }
}
protected override void LoadChildren()
{
AddBaseTypes(this.Children, type);
}
internal static void AddBaseTypes(SharpTreeNodeCollection children, TypeDefinition type)
{
if (type.BaseType != null)
@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
children.Add(new BaseTypesEntryNode(i, true));
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(EnsureLazyChildren));
@ -69,78 +69,4 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -69,78 +69,4 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
}
sealed class BaseTypesEntryNode : ILSpyTreeNode, IMemberTreeNode
{
TypeReference tr;
TypeDefinition def;
bool isInterface;
public BaseTypesEntryNode(TypeReference tr, bool isInterface)
{
if (tr == null)
throw new ArgumentNullException("tr");
this.tr = tr;
this.def = tr.Resolve();
this.isInterface = isInterface;
this.LazyLoading = true;
}
public override bool ShowExpander {
get {
return def != null && (def.BaseType != null || def.HasInterfaces);
}
}
public override object Text {
get { return this.Language.TypeToString(tr, true); }
}
public override object Icon {
get {
if (def != null)
return TypeTreeNode.GetIcon(def);
else
return isInterface ? Images.Interface : Images.Class;
}
}
protected override void LoadChildren()
{
if (def != null)
BaseTypesTreeNode.AddBaseTypes(this.Children, def);
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
// on item activation, try to resolve once again (maybe the user loaded the assembly in the meantime)
if (def == null) {
def = tr.Resolve();
if (def != null)
this.LazyLoading = true; // re-load children
}
e.Handled = ActivateItem(this, def);
}
internal static bool ActivateItem(SharpTreeNode node, TypeDefinition def)
{
if (def != null) {
var assemblyListNode = node.Ancestors().OfType<AssemblyListTreeNode>().FirstOrDefault();
if (assemblyListNode != null) {
assemblyListNode.Select(assemblyListNode.FindTypeNode(def));
return true;
}
}
return false;
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, language.TypeToString(tr, true));
}
MemberReference IMemberTreeNode.Member {
get { return tr; }
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save