Browse Source

Merge branch '1.0'

pull/263/head
Daniel Grunwald 14 years ago
parent
commit
c43d47589a
  1. 6
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 17
      ICSharpCode.Decompiler/Ast/NameVariables.cs
  3. 35
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  4. 1
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
  5. 4
      ICSharpCode.Decompiler/ILAst/ILCodes.cs
  6. 145
      ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs
  7. 35
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
  8. 133
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  9. 1
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  10. 79
      ICSharpCode.Decompiler/Tests/InitializerTests.cs
  11. 6
      ICSharpCode.Decompiler/Tests/TestRunner.cs
  12. 109
      ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
  13. 3
      ILSpy.BamlDecompiler/CecilDependencyPropertyDescriptor.cs
  14. 2
      ILSpy.BamlDecompiler/CecilType.cs
  15. 2
      ILSpy.BamlDecompiler/CecilTypeResolver.cs
  16. 8
      ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
  17. 183
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/AppDomainTypeResolver.cs
  18. 112
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlAssembly.cs
  19. 80
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlFile.cs
  20. 64
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/DotNetType.cs
  21. 6
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KeyMapping.cs
  22. 4
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/KnownInfo.cs
  23. 68
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/NodesCollection.cs
  24. 80
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/TypeDeclaration.cs
  25. 35
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/WpfDependencyPropertyDescriptor.cs
  26. 19
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs
  27. 2
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlPropertyElement.cs
  28. 210
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs
  29. 23
      ILSpy.BamlDecompiler/Tests/Cases/Dictionary1.xaml
  30. 1
      ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj
  31. 17
      ILSpy.BamlDecompiler/Tests/TestRunner.cs
  32. 4
      ILSpy/AssemblyList.cs
  33. 9
      ILSpy/LoadedAssembly.cs
  34. 15
      ILSpy/MainWindow.xaml.cs
  35. 2
      ILSpy/XmlDoc/XmlDocKeyProvider.cs
  36. 4
      SharpTreeView/SharpTreeView.cs

6
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -782,9 +782,15 @@ namespace ICSharpCode.Decompiler.Ast @@ -782,9 +782,15 @@ namespace ICSharpCode.Decompiler.Ast
}
}
ObjectCreateExpression oce = arg1 as ObjectCreateExpression;
DefaultValueExpression dve = arg1 as DefaultValueExpression;
if (oce != null) {
oce.Initializer = initializer;
return oce;
} else if (dve != null) {
oce = new ObjectCreateExpression(dve.Type.Detach());
oce.CopyAnnotationsFrom(dve);
oce.Initializer = initializer;
return oce;
} else {
return new AssignmentExpression(arg1, initializer);
}

17
ICSharpCode.Decompiler/Ast/NameVariables.cs

@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.Ast
nv.AddExistingName(v.Name);
} else if (v.OriginalVariable != null && context.Settings.UseDebugSymbols) {
string varName = v.OriginalVariable.Name;
if (string.IsNullOrEmpty(varName) || varName.StartsWith("V_", StringComparison.Ordinal) || varName.StartsWith("CS$", StringComparison.Ordinal))
if (string.IsNullOrEmpty(varName) || varName.StartsWith("V_", StringComparison.Ordinal) || !IsValidName(varName))
{
// don't use the name from the debug symbols if it looks like a generated name
v.Name = null;
@ -86,6 +86,19 @@ namespace ICSharpCode.Decompiler.Ast @@ -86,6 +86,19 @@ namespace ICSharpCode.Decompiler.Ast
}
}
static bool IsValidName(string varName)
{
if (string.IsNullOrEmpty(varName))
return false;
if (!(char.IsLetter(varName[0]) || varName[0] == '_'))
return false;
for (int i = 1; i < varName.Length; i++) {
if (!(char.IsLetterOrDigit(varName[i]) || varName[i] == '_'))
return false;
}
return true;
}
DecompilerContext context;
List<string> fieldNamesInCurrentType;
Dictionary<string, int> typeNames = new Dictionary<string, int>();
@ -139,7 +152,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -139,7 +152,7 @@ namespace ICSharpCode.Decompiler.Ast
typeNames.Add(nameWithoutDigits, number - 1);
}
int count = ++typeNames[nameWithoutDigits];
if (count > 1) {
if (count != 1) {
return nameWithoutDigits + count.ToString();
} else {
return nameWithoutDigits;

35
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -42,6 +42,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -42,6 +42,7 @@ namespace ICSharpCode.Decompiler.ILAst
SimplifyTernaryOperator,
SimplifyNullCoalescing,
JoinBasicBlocks,
SimplifyShiftOperators,
TransformDecimalCtorToConstant,
SimplifyLdObjAndStObj,
SimplifyCustomShortCircuit,
@ -54,6 +55,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -54,6 +55,7 @@ namespace ICSharpCode.Decompiler.ILAst
FindLoops,
FindConditions,
FlattenNestedMovableBlocks,
RemoveEndFinally,
RemoveRedundantCode2,
GotoRemoval,
DuplicateReturns,
@ -131,7 +133,10 @@ namespace ICSharpCode.Decompiler.ILAst @@ -131,7 +133,10 @@ namespace ICSharpCode.Decompiler.ILAst
if (abortBeforeStep == ILAstOptimizationStep.JoinBasicBlocks) return;
modified |= block.RunOptimization(new SimpleControlFlow(context, method).JoinBasicBlocks);
if (abortBeforeStep == ILAstOptimizationStep.SimplifyShiftOperators) return;
modified |= block.RunOptimization(SimplifyShiftOperators);
if (abortBeforeStep == ILAstOptimizationStep.TransformDecimalCtorToConstant) return;
modified |= block.RunOptimization(TransformDecimalCtorToConstant);
modified |= block.RunOptimization(SimplifyLdcI4ConvI8);
@ -178,6 +183,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -178,6 +183,9 @@ namespace ICSharpCode.Decompiler.ILAst
if (abortBeforeStep == ILAstOptimizationStep.FlattenNestedMovableBlocks) return;
FlattenBasicBlocks(method);
if (abortBeforeStep == ILAstOptimizationStep.RemoveEndFinally) return;
RemoveEndFinally(method);
if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode2) return;
RemoveRedundantCode(method);
@ -534,6 +542,25 @@ namespace ICSharpCode.Decompiler.ILAst @@ -534,6 +542,25 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
/// <summary>
/// Replace endfinally with jump to the end of the finally block
/// </summary>
void RemoveEndFinally(ILBlock method)
{
// Go thought the list in reverse so that we do the nested blocks first
foreach(var tryCatch in method.GetSelfAndChildrenRecursive<ILTryCatchBlock>(tc => tc.FinallyBlock != null).Reverse()) {
ILLabel label = new ILLabel() { Name = "EndFinally_" + nextLabelIndex++ };
tryCatch.FinallyBlock.Body.Add(label);
foreach(var block in tryCatch.FinallyBlock.GetSelfAndChildrenRecursive<ILBlock>()) {
for (int i = 0; i < block.Body.Count; i++) {
if (block.Body[i].Match(ILCode.Endfinally)) {
block.Body[i] = new ILExpression(ILCode.Br, label).WithILRanges(((ILExpression)block.Body[i]).ILRanges);
}
}
}
}
}
/// <summary>
/// Reduce the nesting of conditions.
/// It should be done on flat data that already had most gotos removed
@ -766,6 +793,12 @@ namespace ICSharpCode.Decompiler.ILAst @@ -766,6 +793,12 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
public static ILExpression WithILRanges(this ILExpression expr, IEnumerable<ILRange> ilranges)
{
expr.ILRanges.AddRange(ilranges);
return expr;
}
public static void RemoveTail(this List<ILNode> body, params ILCode[] codes)
{
for (int i = 0; i < codes.Length; i++) {

1
ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -43,6 +43,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -43,6 +43,7 @@ namespace ICSharpCode.Decompiler.ILAst
void AccumulateSelfAndChildrenRecursive<T>(List<T> list, Func<T, bool> predicate) where T:ILNode
{
// Note: RemoveEndFinally depends on self coming before children
T thisAsT = this as T;
if (thisAsT != null && (predicate == null || predicate(thisAsT)))
list.Add(thisAsT);

4
ICSharpCode.Decompiler/ILAst/ILCodes.cs

@ -261,8 +261,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -261,8 +261,8 @@ namespace ICSharpCode.Decompiler.ILAst
// InitCollection(CallGetter(Collection, InitializedObject))),
// Call(Add, InitializedObject, 2, 3),
// Call(Add, InitializedObject, 4, 5)))
InitObject, // Object initializer: first arg is newobj, remaining args are the initializing statements
InitCollection, // Collection initializer: first arg is newobj, remaining args are the initializing statements
InitObject, // Object initializer: first arg is newobj/defaultvalue, remaining args are the initializing statements
InitCollection, // Collection initializer: first arg is newobj/defaultvalue, remaining args are the initializing statements
InitializedObject, // Refers the the object being initialized (refers to first arg in parent InitObject or InitCollection instruction)
TernaryOp, // ?:

145
ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs

@ -93,9 +93,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -93,9 +93,9 @@ namespace ICSharpCode.Decompiler.ILAst
List<ILExpression> ctorArgs;
ArrayType arrayType;
if (expr.Match(ILCode.Stloc, out v, out newarrExpr) &&
newarrExpr.Match(ILCode.Newobj, out ctor, out ctorArgs) &&
(arrayType = (ctor.DeclaringType as ArrayType)) != null &&
arrayType.Rank == ctorArgs.Count) {
newarrExpr.Match(ILCode.Newobj, out ctor, out ctorArgs) &&
(arrayType = (ctor.DeclaringType as ArrayType)) != null &&
arrayType.Rank == ctorArgs.Count) {
// Clone the type, so we can muck about with the Dimensions
arrayType = new ArrayType(arrayType.ElementType, arrayType.Rank);
var arrayLengths = new int[arrayType.Rank];
@ -124,19 +124,24 @@ namespace ICSharpCode.Decompiler.ILAst @@ -124,19 +124,24 @@ namespace ICSharpCode.Decompiler.ILAst
MethodReference methodRef;
ILExpression methodArg1;
ILExpression methodArg2;
FieldDefinition field;
FieldReference fieldRef;
if (body.ElementAtOrDefault(pos).Match(ILCode.Call, out methodRef, out methodArg1, out methodArg2) &&
methodRef.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers" &&
methodRef.Name == "InitializeArray" &&
methodArg1.Match(ILCode.Ldloc, out v2) &&
array == v2 &&
methodArg2.Match(ILCode.Ldtoken, out field) &&
field != null && field.InitialValue != null) {
ILExpression[] newArr = new ILExpression[arrayLength];
if (DecodeArrayInitializer(TypeAnalysis.GetTypeCode(arrayType.GetElementType()), field.InitialValue, newArr)) {
values = newArr;
foundPos = pos;
return true;
methodRef.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers" &&
methodRef.Name == "InitializeArray" &&
methodArg1.Match(ILCode.Ldloc, out v2) &&
array == v2 &&
methodArg2.Match(ILCode.Ldtoken, out fieldRef))
{
FieldDefinition fieldDef = fieldRef.ResolveWithinSameModule();
if (fieldDef != null && fieldDef.InitialValue != null) {
ILExpression[] newArr = new ILExpression[arrayLength];
if (DecodeArrayInitializer(TypeAnalysis.GetTypeCode(arrayType.GetElementType()),
fieldDef.InitialValue, newArr))
{
values = newArr;
foundPos = pos;
return true;
}
}
}
values = null;
@ -148,7 +153,6 @@ namespace ICSharpCode.Decompiler.ILAst @@ -148,7 +153,6 @@ namespace ICSharpCode.Decompiler.ILAst
{
switch (elementType) {
case TypeCode.Boolean:
case TypeCode.SByte:
case TypeCode.Byte:
if (initialValue.Length == output.Length) {
for (int j = 0; j < output.Length; j++) {
@ -157,9 +161,15 @@ namespace ICSharpCode.Decompiler.ILAst @@ -157,9 +161,15 @@ namespace ICSharpCode.Decompiler.ILAst
return true;
}
return false;
case TypeCode.Char:
case TypeCode.SByte:
if (initialValue.Length == output.Length) {
for (int j = 0; j < output.Length; j++) {
output[j] = new ILExpression(ILCode.Ldc_I4, (int)unchecked((sbyte)initialValue[j]));
}
return true;
}
return false;
case TypeCode.Int16:
case TypeCode.UInt16:
if (initialValue.Length == output.Length * 2) {
for (int j = 0; j < output.Length; j++) {
output[j] = new ILExpression(ILCode.Ldc_I4, (int)BitConverter.ToInt16(initialValue, j * 2));
@ -167,6 +177,15 @@ namespace ICSharpCode.Decompiler.ILAst @@ -167,6 +177,15 @@ namespace ICSharpCode.Decompiler.ILAst
return true;
}
return false;
case TypeCode.Char:
case TypeCode.UInt16:
if (initialValue.Length == output.Length * 2) {
for (int j = 0; j < output.Length; j++) {
output[j] = new ILExpression(ILCode.Ldc_I4, (int)BitConverter.ToUInt16(initialValue, j * 2));
}
return true;
}
return false;
case TypeCode.Int32:
case TypeCode.UInt32:
if (initialValue.Length == output.Length * 4) {
@ -218,18 +237,45 @@ namespace ICSharpCode.Decompiler.ILAst @@ -218,18 +237,45 @@ namespace ICSharpCode.Decompiler.ILAst
Debug.Assert(body[pos] == expr); // should be called for top-level expressions only
ILVariable v;
ILExpression newObjExpr;
TypeReference newObjType;
bool isValueType;
MethodReference ctor;
List<ILExpression> ctorArgs;
// v = newObj(ctor, ctorArgs)
if (!(expr.Match(ILCode.Stloc, out v, out newObjExpr) && newObjExpr.Match(ILCode.Newobj, out ctor, out ctorArgs)))
if (expr.Match(ILCode.Stloc, out v, out newObjExpr)) {
if (newObjExpr.Match(ILCode.Newobj, out ctor, out ctorArgs)) {
// v = newObj(ctor, ctorArgs)
newObjType = ctor.DeclaringType;
isValueType = false;
} else if (newObjExpr.Match(ILCode.DefaultValue, out newObjType)) {
// v = defaultvalue(type)
isValueType = true;
} else {
return false;
}
} else if (expr.Match(ILCode.Call, out ctor, out ctorArgs)) {
// call(SomeStruct::.ctor, ldloca(v), remainingArgs)
if (ctorArgs.Count > 0 && ctorArgs[0].Match(ILCode.Ldloca, out v)) {
isValueType = true;
newObjType = ctor.DeclaringType;
ctorArgs = new List<ILExpression>(ctorArgs);
ctorArgs.RemoveAt(0);
newObjExpr = new ILExpression(ILCode.Newobj, ctor, ctorArgs);
} else {
return false;
}
} else {
return false;
}
if (newObjType.IsValueType != isValueType)
return false;
int originalPos = pos;
// don't use object initializer syntax for closures
if (Ast.Transforms.DelegateConstruction.IsPotentialClosure(context, ctor.DeclaringType.ResolveWithinSameModule()))
if (Ast.Transforms.DelegateConstruction.IsPotentialClosure(context, newObjType.ResolveWithinSameModule()))
return false;
ILExpression initializer = ParseObjectInitializer(body, ref pos, v, newObjExpr, IsCollectionType(ctor.DeclaringType));
ILExpression initializer = ParseObjectInitializer(body, ref pos, v, newObjExpr, IsCollectionType(newObjType), isValueType);
if (initializer.Arguments.Count == 1) // only newobj argument, no initializer elements
return false;
@ -242,16 +288,36 @@ namespace ICSharpCode.Decompiler.ILAst @@ -242,16 +288,36 @@ namespace ICSharpCode.Decompiler.ILAst
return false; // reached end of block, but there should be another instruction which consumes the initialized object
ILInlining inlining = new ILInlining(method);
// one ldloc for each initializer argument, and another ldloc for the use of the initialized object
if (inlining.numLdloc.GetOrDefault(v) != totalElementCount + 1)
return false;
if (!(inlining.numStloc.GetOrDefault(v) == 1 && inlining.numLdloca.GetOrDefault(v) == 0))
return false;
if (isValueType) {
// one ldloc for the use of the initialized object
if (inlining.numLdloc.GetOrDefault(v) != 1)
return false;
// one ldloca for each initializer argument, and also for the ctor call (if it exists)
if (inlining.numLdloca.GetOrDefault(v) != totalElementCount + (expr.Code == ILCode.Call ? 1 : 0))
return false;
// one stloc for the initial store (if no ctor call was used)
if (inlining.numStloc.GetOrDefault(v) != (expr.Code == ILCode.Call ? 0 : 1))
return false;
} else {
// one ldloc for each initializer argument, and another ldloc for the use of the initialized object
if (inlining.numLdloc.GetOrDefault(v) != totalElementCount + 1)
return false;
if (!(inlining.numStloc.GetOrDefault(v) == 1 && inlining.numLdloca.GetOrDefault(v) == 0))
return false;
}
ILExpression nextExpr = body[pos] as ILExpression;
if (!inlining.CanInlineInto(nextExpr, v, initializer))
return false;
expr.Arguments[0] = initializer;
if (expr.Code == ILCode.Stloc) {
expr.Arguments[0] = initializer;
} else {
Debug.Assert(expr.Code == ILCode.Call);
expr.Code = ILCode.Stloc;
expr.Operand = v;
expr.Arguments.Clear();
expr.Arguments.Add(initializer);
}
// remove all the instructions that were pulled into the initializer
body.RemoveRange(originalPos + 1, pos - originalPos - 1);
@ -288,7 +354,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -288,7 +354,7 @@ namespace ICSharpCode.Decompiler.ILAst
{
if (expr == null)
return false;
if (expr.Code == ILCode.CallvirtSetter || expr.Code == ILCode.Stfld) {
if (expr.Code == ILCode.CallvirtSetter || expr.Code == ILCode.CallSetter || expr.Code == ILCode.Stfld) {
return expr.Arguments.Count == 2;
}
return false;
@ -320,9 +386,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -320,9 +386,8 @@ namespace ICSharpCode.Decompiler.ILAst
/// <param name="v">The variable that holds the object being initialized</param>
/// <param name="newObjExpr">The newobj instruction</param>
/// <returns>InitObject instruction</returns>
ILExpression ParseObjectInitializer(List<ILNode> body, ref int pos, ILVariable v, ILExpression newObjExpr, bool isCollection)
ILExpression ParseObjectInitializer(List<ILNode> body, ref int pos, ILVariable v, ILExpression newObjExpr, bool isCollection, bool isValueType)
{
Debug.Assert(((ILExpression)body[pos]).Code == ILCode.Stloc);
// Take care not to modify any existing ILExpressions in here.
// We just construct new ones around the old ones, any modifications must wait until the whole
// object/collection initializer was analyzed.
@ -332,13 +397,13 @@ namespace ICSharpCode.Decompiler.ILAst @@ -332,13 +397,13 @@ namespace ICSharpCode.Decompiler.ILAst
while (++pos < body.Count) {
ILExpression nextExpr = body[pos] as ILExpression;
if (IsSetterInObjectInitializer(nextExpr)) {
if (!AdjustInitializerStack(initializerStack, nextExpr.Arguments[0], v, false)) {
if (!AdjustInitializerStack(initializerStack, nextExpr.Arguments[0], v, false, isValueType)) {
CleanupInitializerStackAfterFailedAdjustment(initializerStack);
break;
}
initializerStack[initializerStack.Count - 1].Arguments.Add(nextExpr);
} else if (IsAddMethodCall(nextExpr)) {
if (!AdjustInitializerStack(initializerStack, nextExpr.Arguments[0], v, true)) {
if (!AdjustInitializerStack(initializerStack, nextExpr.Arguments[0], v, true, isValueType)) {
CleanupInitializerStackAfterFailedAdjustment(initializerStack);
break;
}
@ -351,20 +416,26 @@ namespace ICSharpCode.Decompiler.ILAst @@ -351,20 +416,26 @@ namespace ICSharpCode.Decompiler.ILAst
return objectInitializer;
}
static bool AdjustInitializerStack(List<ILExpression> initializerStack, ILExpression argument, ILVariable v, bool isCollection)
static bool AdjustInitializerStack(List<ILExpression> initializerStack, ILExpression argument, ILVariable v, bool isCollection, bool isValueType)
{
// Argument is of the form 'getter(getter(...(v)))'
// Unpack it into a list of getters:
List<ILExpression> getters = new List<ILExpression>();
while (argument.Code == ILCode.CallvirtGetter || argument.Code == ILCode.Ldfld) {
while (argument.Code == ILCode.CallvirtGetter || argument.Code == ILCode.CallGetter || argument.Code == ILCode.Ldfld) {
getters.Add(argument);
if (argument.Arguments.Count != 1)
return false;
argument = argument.Arguments[0];
}
// Ensure that the final argument is 'v'
if (!argument.MatchLdloc(v))
return false;
if (isValueType) {
ILVariable loadedVar;
if (!(argument.Match(ILCode.Ldloca, out loadedVar) && loadedVar == v))
return false;
} else {
if (!argument.MatchLdloc(v))
return false;
}
// Now compare the getters with those that are currently active on the initializer stack:
int i;
for (i = 1; i <= Math.Min(getters.Count, initializerStack.Count - 1); i++) {

35
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -868,5 +868,40 @@ namespace ICSharpCode.Decompiler.ILAst @@ -868,5 +868,40 @@ namespace ICSharpCode.Decompiler.ILAst
return false;
}
#endregion
#region SimplifyShiftOperators
static bool SimplifyShiftOperators(List<ILNode> body, ILExpression expr, int pos)
{
// C# compiles "a << b" to "a << (b & 31)", so we will remove the "& 31" if possible.
bool modified = false;
SimplifyShiftOperators(expr, ref modified);
return modified;
}
static void SimplifyShiftOperators(ILExpression expr, ref bool modified)
{
for (int i = 0; i < expr.Arguments.Count; i++)
SimplifyShiftOperators(expr.Arguments[i], ref modified);
if (expr.Code != ILCode.Shl && expr.Code != ILCode.Shr && expr.Code != ILCode.Shr_Un)
return;
var a = expr.Arguments[1];
if (a.Code != ILCode.And || a.Arguments[1].Code != ILCode.Ldc_I4 || expr.InferredType == null)
return;
int mask;
switch (expr.InferredType.MetadataType) {
case MetadataType.Int32:
case MetadataType.UInt32: mask = 31; break;
case MetadataType.Int64:
case MetadataType.UInt64: mask = 63; break;
default: return;
}
if ((int)a.Arguments[1].Operand != mask) return;
var res = a.Arguments[0];
res.ILRanges.AddRange(a.ILRanges);
res.ILRanges.AddRange(a.Arguments[1].ILRanges);
expr.Arguments[1] = res;
modified = true;
}
#endregion
}
}

133
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -323,13 +323,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -323,13 +323,7 @@ namespace ICSharpCode.Decompiler.ILAst
if (forceInferChildren) {
for (int i = 0; i < expr.Arguments.Count; i++) {
if (i == 0 && method.HasThis) {
ILExpressionPrefix constraint = expr.GetPrefix(ILCode.Constrained);
if (constraint != null)
InferTypeForExpression(expr.Arguments[i], new ByReferenceType((TypeReference)constraint.Operand));
else if (method.DeclaringType.IsValueType)
InferTypeForExpression(expr.Arguments[i], new ByReferenceType(method.DeclaringType));
else
InferTypeForExpression(expr.Arguments[i], method.DeclaringType);
InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(method.DeclaringType, expr.GetPrefix(ILCode.Constrained)));
} else {
InferTypeForExpression(expr.Arguments[i], SubstituteTypeArgs(method.Parameters[method.HasThis ? i - 1 : i].ParameterType, method));
}
@ -361,17 +355,22 @@ namespace ICSharpCode.Decompiler.ILAst @@ -361,17 +355,22 @@ namespace ICSharpCode.Decompiler.ILAst
#endregion
#region Load/Store Fields
case ILCode.Ldfld:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[0], ((FieldReference)expr.Operand).DeclaringType);
if (forceInferChildren) {
InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(((FieldReference)expr.Operand).DeclaringType, expr.GetPrefix(ILCode.Constrained)));
}
return GetFieldType((FieldReference)expr.Operand);
case ILCode.Ldsfld:
return GetFieldType((FieldReference)expr.Operand);
case ILCode.Ldflda:
if (forceInferChildren) {
InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(((FieldReference)expr.Operand).DeclaringType, expr.GetPrefix(ILCode.Constrained)));
}
return new ByReferenceType(GetFieldType((FieldReference)expr.Operand));
case ILCode.Ldsflda:
return new ByReferenceType(GetFieldType((FieldReference)expr.Operand));
case ILCode.Stfld:
if (forceInferChildren) {
InferTypeForExpression(expr.Arguments[0], ((FieldReference)expr.Operand).DeclaringType);
InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(((FieldReference)expr.Operand).DeclaringType, expr.GetPrefix(ILCode.Constrained)));
InferTypeForExpression(expr.Arguments[1], GetFieldType((FieldReference)expr.Operand));
}
return GetFieldType((FieldReference)expr.Operand);
@ -515,14 +514,47 @@ namespace ICSharpCode.Decompiler.ILAst @@ -515,14 +514,47 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Rem_Un:
return InferArgumentsInBinaryOperator(expr, false, expectedType);
case ILCode.Shl:
case ILCode.Shr:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
return InferTypeForExpression(expr.Arguments[0], typeSystem.Int32);
if (expectedType != null && (
expectedType.MetadataType == MetadataType.Int32 || expectedType.MetadataType == MetadataType.UInt32 ||
expectedType.MetadataType == MetadataType.Int64 || expectedType.MetadataType == MetadataType.UInt64)
)
return NumericPromotion(InferTypeForExpression(expr.Arguments[0], expectedType));
else
return NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
case ILCode.Shr:
case ILCode.Shr_Un:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
return InferTypeForExpression(expr.Arguments[0], typeSystem.UInt32);
{
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
TypeReference type = NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
TypeReference expectedInputType = null;
switch (type.MetadataType) {
case MetadataType.Int32:
if (expr.Code == ILCode.Shr_Un)
expectedInputType = typeSystem.UInt32;
break;
case MetadataType.UInt32:
if (expr.Code == ILCode.Shr)
expectedInputType = typeSystem.Int32;
break;
case MetadataType.Int64:
if (expr.Code == ILCode.Shr_Un)
expectedInputType = typeSystem.UInt64;
break;
case MetadataType.UInt64:
if (expr.Code == ILCode.Shr)
expectedInputType = typeSystem.UInt64;
break;
}
if (expectedInputType != null) {
InferTypeForExpression(expr.Arguments[0], expectedInputType);
return expectedInputType;
} else {
return type;
}
}
case ILCode.CompoundAssignment:
{
TypeReference varType = InferTypeForExpression(expr.Arguments[0].Arguments[0], null);
@ -543,9 +575,19 @@ namespace ICSharpCode.Decompiler.ILAst @@ -543,9 +575,19 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Ldc_I4:
if (IsBoolean(expectedType) && ((int)expr.Operand == 0 || (int)expr.Operand == 1))
return typeSystem.Boolean;
return (IsIntegerOrEnum(expectedType) || expectedType is PointerType) ? expectedType : typeSystem.Int32;
if (expectedType is PointerType && (int)expr.Operand == 0)
return expectedType;
if (IsIntegerOrEnum(expectedType) && OperandFitsInType(expectedType, (int)expr.Operand))
return expectedType;
else
return typeSystem.Int32;
case ILCode.Ldc_I8:
return (IsIntegerOrEnum(expectedType) || expectedType is PointerType) ? expectedType : typeSystem.Int64;
if (expectedType is PointerType && (long)expr.Operand == 0)
return expectedType;
if (IsIntegerOrEnum(expectedType) && GetInformationAmount(expectedType) >= NativeInt)
return expectedType;
else
return typeSystem.Int64;
case ILCode.Ldc_R4:
return typeSystem.Single;
case ILCode.Ldc_R8:
@ -753,6 +795,41 @@ namespace ICSharpCode.Decompiler.ILAst @@ -753,6 +795,41 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
/// <summary>
/// Wraps 'type' in a ByReferenceType if it is a value type. If a constrained prefix is specified,
/// returns the constrained type wrapped in a ByReferenceType.
/// </summary>
TypeReference MakeRefIfValueType(TypeReference type, ILExpressionPrefix constrainedPrefix)
{
if (constrainedPrefix != null)
return new ByReferenceType((TypeReference)constrainedPrefix.Operand);
if (type.IsValueType)
return new ByReferenceType(type);
else
return type;
}
/// <summary>
/// Promotes primitive types smaller than int32 to int32.
/// </summary>
/// <remarks>
/// Always promotes to signed int32.
/// </remarks>
TypeReference NumericPromotion(TypeReference type)
{
if (type == null)
return null;
switch (type.MetadataType) {
case MetadataType.SByte:
case MetadataType.Int16:
case MetadataType.Byte:
case MetadataType.UInt16:
return typeSystem.Int32;
default:
return type;
}
}
TypeReference HandleConversion(int targetBitSize, bool targetSigned, ILExpression arg, TypeReference expectedType, TypeReference targetType)
{
if (targetBitSize >= NativeInt && expectedType is PointerType) {
@ -1043,6 +1120,28 @@ namespace ICSharpCode.Decompiler.ILAst @@ -1043,6 +1120,28 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
static bool OperandFitsInType(TypeReference type, int num)
{
TypeDefinition typeDef = type.Resolve() as TypeDefinition;
if (typeDef != null && typeDef.IsEnum) {
type = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType;
}
switch (type.MetadataType) {
case MetadataType.SByte:
return sbyte.MinValue <= num && num <= sbyte.MaxValue;
case MetadataType.Int16:
return short.MinValue <= num && num <= short.MaxValue;
case MetadataType.Byte:
return byte.MinValue <= num && num <= byte.MaxValue;
case MetadataType.Char:
return char.MinValue <= num && num <= char.MaxValue;
case MetadataType.UInt16:
return ushort.MinValue <= num && num <= ushort.MaxValue;
default:
return true;
}
}
static bool IsArrayPointerOrReference(TypeReference type)
{
TypeSpecification typeSpec = type as TypeSpecification;

1
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -63,6 +63,7 @@ @@ -63,6 +63,7 @@
<Compile Include="PInvoke.cs" />
<Compile Include="QueryExpressions.cs" />
<Compile Include="Switch.cs" />
<Compile Include="TypeAnalysisTests.cs" />
<Compile Include="UndocumentedExpressions.cs" />
<Compile Include="UnsafeCode.cs" />
<Compile Include="Types\S_TypeDeclarations.cs" />

79
ICSharpCode.Decompiler/Tests/InitializerTests.cs

@ -52,8 +52,37 @@ public class InitializerTests @@ -52,8 +52,37 @@ public class InitializerTests
get;
set;
}
public InitializerTests.StructData NestedStruct
{
get;
set;
}
}
private struct StructData
{
public int Field;
public int Property
{
get;
set;
}
public InitializerTests.Data MoreData
{
get;
set;
}
public StructData(int initialValue)
{
this = default(InitializerTests.StructData);
this.Field = initialValue;
this.Property = initialValue;
}
}
// Helper methods used to ensure initializers used within expressions work correctly
private static void X(object a, object b)
{
@ -456,7 +485,53 @@ public class InitializerTests @@ -456,7 +485,53 @@ public class InitializerTests
}
});
}
public static void StructInitializer_DefaultConstructor()
{
InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData
{
Field = 1,
Property = 2
});
}
public static void StructInitializer_ExplicitConstructor()
{
InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData(0)
{
Field = 1,
Property = 2
});
}
public static void StructInitializerWithInitializationOfNestedObjects()
{
InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData
{
MoreData =
{
a = InitializerTests.MyEnum.a,
FieldList =
{
InitializerTests.MyEnum2.c,
InitializerTests.MyEnum2.d
}
}
});
}
public static void StructInitializerWithinObjectInitializer()
{
InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
{
NestedStruct = new InitializerTests.StructData(2)
{
Field = 1,
Property = 2
}
});
}
public void MultidimensionalInit()
{
int[,] expr_09 = new int[, ]

6
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -142,6 +142,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -142,6 +142,12 @@ namespace ICSharpCode.Decompiler.Tests
TestFile(@"..\..\Tests\YieldReturn.cs");
}
[Test]
public void TypeAnalysis()
{
TestFile(@"..\..\Tests\TypeAnalysisTests.cs");
}
static void TestFile(string fileName)
{
string code = File.ReadAllText(fileName);

109
ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
public class TypeAnalysisTests
{
public byte SubtractFrom256(byte b)
{
return (byte)(256 - (int)b);
}
#region Shift
public int LShiftInteger(int num1, int num2)
{
return num1 << num2;
}
public uint LShiftUnsignedInteger(uint num1, uint num2)
{
return num1 << (int)num2;
}
public long LShiftLong(long num1, long num2)
{
return num1 << (int)num2;
}
public ulong LShiftUnsignedLong(ulong num1, ulong num2)
{
return num1 << (int)num2;
}
public int RShiftInteger(int num1, int num2)
{
return num1 >> num2;
}
public uint RShiftUnsignedInteger(uint num1, int num2)
{
return num1 >> num2;
}
public long RShiftLong(long num1, long num2)
{
return num1 >> (int)num2;
}
public ulong RShiftUnsignedLong(ulong num1, ulong num2)
{
return num1 >> (int)num2;
}
public int ShiftByte(byte num)
{
return (int)num << 8;
}
public int RShiftByte(byte num)
{
return num >> 8;
}
public uint RShiftByteWithZeroExtension(byte num)
{
return (uint)num >> 8;
}
public int RShiftByteAsSByte(byte num)
{
return (sbyte)num >> 8;
}
public int RShiftSByte(sbyte num)
{
return num >> 8;
}
public uint RShiftSByteWithZeroExtension(sbyte num)
{
return (uint)num >> 8;
}
public int RShiftSByteAsByte(sbyte num)
{
return (byte)num >> 8;
}
#endregion
public int GetHashCode(long num)
{
return (int)num ^ (int)(num >> 32);
}
}

3
ILSpy.BamlDecompiler/CecilDependencyPropertyDescriptor.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.ILSpy;
using Mono.Cecil;
@ -16,6 +17,8 @@ namespace ILSpy.BamlDecompiler @@ -16,6 +17,8 @@ namespace ILSpy.BamlDecompiler
public CecilDependencyPropertyDescriptor(string member, TypeDefinition type)
{
if (type == null)
throw new ArgumentNullException("type");
this.member = member;
this.type = type;
}

2
ILSpy.BamlDecompiler/CecilType.cs

@ -15,6 +15,8 @@ namespace ILSpy.BamlDecompiler @@ -15,6 +15,8 @@ namespace ILSpy.BamlDecompiler
public CecilType(TypeDefinition type)
{
if (type == null)
throw new ArgumentNullException("type");
this.type = type;
}

2
ILSpy.BamlDecompiler/CecilTypeResolver.cs

@ -52,7 +52,7 @@ namespace ILSpy.BamlDecompiler @@ -52,7 +52,7 @@ namespace ILSpy.BamlDecompiler
var otherAssembly = resolver.Resolve(assemblyName);
if (otherAssembly == null)
throw new Exception("could not resolve '" + assemblyName + "'!");
type = otherAssembly.MainModule.GetType(fullName);
type = otherAssembly.MainModule.GetType(fullName.Replace('+', '/'));
}
return new CecilType(type);

8
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

@ -80,23 +80,17 @@ @@ -80,23 +80,17 @@
<Compile Include="ConnectMethodDecompiler.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\AppDomainTypeResolver.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\BamlAssembly.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\BamlBinaryReader.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\BamlFile.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\BamlRecordType.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\DotNetType.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\IDependencyPropertyDescriptor.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\IType.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\ITypeResolver.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\KeyMapping.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\KnownInfo.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\NodesCollection.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\PropertyDeclaration.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\ResourceName.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\TypeDeclaration.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\WpfDependencyPropertyDescriptor.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlElement.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlNode.cs" />
<Compile Include="Ricciolo.StylesExplorer.MarkupReflection\XmlBamlProperty.cs" />

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

@ -1,183 +0,0 @@ @@ -1,183 +0,0 @@
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Text;
using System.IO;
using System.Linq;
using Microsoft.Win32;
using System.Threading;
using System.Security.Permissions;
using System.Security;
namespace Ricciolo.StylesExplorer.MarkupReflection
{
public delegate void AssemblyResolveEventHandler(object s, AssemblyResolveEventArgs e);
public class AppDomainTypeResolver : MarshalByRefObject, ITypeResolver
{
private readonly AppDomain _domain;
private string baseDir;
public event AssemblyResolveEventHandler AssemblyResolve;
public static AppDomainTypeResolver GetIntoNewAppDomain(string baseDir)
{
AppDomainSetup info = new AppDomainSetup();
info.ApplicationBase = Environment.CurrentDirectory;
AppDomain domain = AppDomain.CreateDomain("AppDomainTypeResolver", null, info, new PermissionSet(PermissionState.Unrestricted));
AppDomainTypeResolver resolver = (AppDomainTypeResolver)domain.CreateInstanceAndUnwrap(typeof(AppDomainTypeResolver).Assembly.FullName,
typeof(AppDomainTypeResolver).FullName, false, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, new object[] { domain, baseDir }, null, null, null);
return resolver;
}
Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args)
{
// Cerco di risolvere automaticamente
AssemblyName name = new AssemblyName(args.Name);
string fileName = Path.Combine(this.baseDir, name.Name + ".exe");
if (!File.Exists(fileName))
fileName = Path.Combine(this.baseDir, name.Name + ".dll");
// Carico il percorso autocalcolato
if (File.Exists(fileName))
return Assembly.LoadFile(fileName);
if (AssemblyResolve != null)
{
AssemblyResolveEventArgs e = new AssemblyResolveEventArgs(args.Name, this.baseDir);
AssemblyResolve(this, e);
if (!String.IsNullOrEmpty(e.Location) && File.Exists(e.Location))
return Assembly.LoadFile(e.Location);
}
return null;
}
public static void DestroyResolver(AppDomainTypeResolver resolver)
{
if (resolver == null) throw new ArgumentNullException("resolver");
ThreadPool.QueueUserWorkItem(delegate
{
AppDomain.Unload(resolver.Domain);
});
}
protected AppDomainTypeResolver(AppDomain domain, string baseDir)
{
_domain = domain;
this.baseDir = baseDir;
domain.AssemblyResolve += new ResolveEventHandler(domain_AssemblyResolve);
}
public BamlAssembly LoadAssembly(AssemblyName asm)
{
//return new BamlAssembly(Assembly.Load(asm));
return new BamlAssembly(_domain.Load(asm));
}
public BamlAssembly LoadAssembly(string location)
{
Assembly asm = Assembly.LoadFile(location);
return new BamlAssembly(asm);
//return _domain.Load(System.IO.File.ReadAllBytes(location));
//return Assembly.LoadFrom(location);
}
public BamlAssembly[] GetReferencedAssemblies(BamlAssembly asm)
{
AssemblyName[] list = asm.Assembly.GetReferencedAssemblies();
return (from an in list
select this.LoadAssembly(an)).ToArray();
}
public AppDomain Domain
{
get { return _domain; }
}
#region ITypeResolver Members
public IType GetTypeByAssemblyQualifiedName(string name)
{
return new DotNetType(name);
}
public IDependencyPropertyDescriptor GetDependencyPropertyDescriptor(string name, IType ownerType, IType targetType)
{
if (name == null) throw new ArgumentNullException("name");
if (ownerType == null) throw new ArgumentNullException("ownerType");
if (targetType == null) throw new ArgumentNullException("targetType");
Type dOwnerType = ((DotNetType)ownerType).Type;
Type dTargetType = ((DotNetType)targetType).Type;
try
{
DependencyPropertyDescriptor propertyDescriptor = DependencyPropertyDescriptor.FromName(name, dOwnerType, dTargetType);
if (propertyDescriptor != null)
return new WpfDependencyPropertyDescriptor(propertyDescriptor);
return null;
}
catch (Exception)
{
return null;
}
}
public bool IsLocalAssembly(string name)
{
return false;
}
public string RuntimeVersion {
get {
throw new NotImplementedException();
}
}
#endregion
public override object InitializeLifetimeService()
{
return null;
}
}
public class AssemblyResolveEventArgs : MarshalByRefObject
{
private string _location;
private string _name;
private string _baseDir;
public AssemblyResolveEventArgs(string name, string baseDir)
{
_name = name;
_baseDir = baseDir;
}
public string Location
{
get { return _location; }
set { _location = value; }
}
public string Name
{
get { return _name; }
}
public string BaseDir
{
get { return _baseDir; }
}
}
}

112
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlAssembly.cs

@ -1,112 +0,0 @@ @@ -1,112 +0,0 @@
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Text;
namespace Ricciolo.StylesExplorer.MarkupReflection
{
public class BamlAssembly : MarshalByRefObject
{
private readonly string _filePath;
private Assembly _assembly;
private BamlFileList _bamlFile;
public BamlAssembly(Assembly assembly)
{
_assembly = assembly;
_filePath = assembly.CodeBase;
ReadBaml();
}
public BamlAssembly(string filePath)
{
this._filePath = Path.GetFullPath(filePath);
this._assembly = Assembly.LoadFile(this.FilePath);
if (String.Compare(this.Assembly.CodeBase, this.FilePath, true) != 0)
throw new ArgumentException("Cannot load filePath because Assembly is already loaded", "filePath");
ReadBaml();
}
private void ReadBaml()
{
// Get available names
string[] resources = this.Assembly.GetManifestResourceNames();
foreach (string res in resources)
{
// Solo le risorse
if (String.Compare(Path.GetExtension(res), ".resources", true) != 0) continue;
// Get stream
using (Stream stream = this.Assembly.GetManifestResourceStream(res))
{
try
{
ResourceReader reader = new ResourceReader(stream);
foreach (DictionaryEntry entry in reader)
{
if (String.Compare(Path.GetExtension(entry.Key.ToString()), ".baml", true) == 0 && entry.Value is Stream)
{
BamlFile bm = new BamlFile(GetAssemblyResourceUri(entry.Key.ToString()), (Stream)entry.Value);
this.BamlFiles.Add(bm);
}
}
}
catch (ArgumentException)
{}
}
}
}
private Uri GetAssemblyResourceUri(string resourceName)
{
AssemblyName asm = this.Assembly.GetName();
byte[] data = asm.GetPublicKeyToken();
StringBuilder token = new StringBuilder(data.Length * 2);
for (int x = 0; x < data.Length; x++)
{
token.Append(data[x].ToString("x", System.Globalization.CultureInfo.InvariantCulture));
}
return new Uri(String.Format(@"{0};V{1};{2};component\{3}", asm.Name, asm.Version, token, Path.ChangeExtension(resourceName, ".xaml")), UriKind.RelativeOrAbsolute);
}
public string FilePath
{
get { return _filePath; }
}
public Assembly Assembly
{
get { return _assembly; }
}
public BamlFileList BamlFiles
{
get
{
if (_bamlFile == null)
_bamlFile = new BamlFileList();
return _bamlFile;
}
}
public override object InitializeLifetimeService()
{
return null;
}
}
[Serializable()]
public class BamlFileList : Collection<BamlFile>
{}
}

80
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/BamlFile.cs

@ -1,80 +0,0 @@ @@ -1,80 +0,0 @@
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Resources;
using System.Text;
using System.Windows;
namespace Ricciolo.StylesExplorer.MarkupReflection
{
/// <summary>
/// Rappresenta un singole file Baml all'interno di un assembly
/// </summary>
public class BamlFile : Component
{
private Uri _uri;
private readonly Stream _stream;
public BamlFile(Uri uri, Stream stream)
{
if (uri == null)
new ArgumentNullException("uri");
if (stream == null)
throw new ArgumentNullException("stream");
_uri = uri;
_stream = stream;
}
/// <summary>
/// Carica il Baml attraverso il motore di WPF con Application.LoadComponent
/// </summary>
/// <returns></returns>
public object LoadContent()
{
try
{
return Application.LoadComponent(this.Uri);
}
catch (Exception e)
{
throw new InvalidOperationException("Invalid baml file.", e);
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
this.Stream.Dispose();
}
public override object InitializeLifetimeService()
{
return null;
}
/// <summary>
/// Restituisce lo stream originale contenente il Baml
/// </summary>
public Stream Stream
{
get { return _stream; }
}
/// <summary>
/// Restituisce l'indirizzo secondo lo schema pack://
/// </summary>
public Uri Uri
{
get { return _uri; }
}
}
}

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

@ -1,64 +0,0 @@ @@ -1,64 +0,0 @@
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
using System.Collections.Generic;
using System.Text;
namespace Ricciolo.StylesExplorer.MarkupReflection
{
public class DotNetType : MarshalByRefObject, IType
{
private readonly string _assemblyQualifiedName;
private Type _type;
public DotNetType(string assemblyQualifiedName)
{
if (assemblyQualifiedName == null) throw new ArgumentNullException("assemblyQualifiedName");
_assemblyQualifiedName = assemblyQualifiedName;
_type = Type.GetType(assemblyQualifiedName, false, true);
}
#region IType Members
public string AssemblyQualifiedName
{
get { return _assemblyQualifiedName; }
}
public bool IsSubclassOf(IType type)
{
if (type == null) throw new ArgumentNullException("type");
if (!(type is DotNetType)) throw new ArgumentException("type");
if (_type == null) return false;
return this._type.IsSubclassOf(((DotNetType)type).Type);
}
public bool Equals(IType type)
{
if (type == null) throw new ArgumentNullException("type");
if (!(type is DotNetType)) throw new ArgumentException("type");
if (_type == null) return false;
return this._type.Equals(((DotNetType)type).Type);
}
public IType BaseType {
get {
return new DotNetType(this._type.BaseType.AssemblyQualifiedName);
}
}
#endregion
public Type Type
{
get { return _type; }
}
public override object InitializeLifetimeService()
{
return null;
}
}
}

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

@ -36,5 +36,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -36,5 +36,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
this.staticResources = new List<object>();
this.Position = -1;
}
public override string ToString()
{
return '"' + KeyString + '"';
}
}
}

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

@ -58,7 +58,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -58,7 +58,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
KnownTypeTable[9] = new TypeDeclaration(resolver, "Animatable", "System.Windows.Media.Animaton", 1);
KnownTypeTable[10] = new TypeDeclaration(resolver, "AnimationClock", "System.Windows.Media.Animation", 1);
KnownTypeTable[11] = new TypeDeclaration(resolver, "AnimationTimeline", "System.Windows.Media.Animation", 1);
KnownTypeTable[12] = new TypeDeclaration(resolver, "Application", "System.Net.Mime", 3);
KnownTypeTable[12] = new TypeDeclaration(resolver, "Application", "System.Windows", 0);
KnownTypeTable[13] = new TypeDeclaration(resolver, "ArcSegment", "System.Windows.Media", 1);
KnownTypeTable[14] = new TypeDeclaration(resolver, "ArrayExtension", "System.Windows.Markup", 0);
KnownTypeTable[15] = new TypeDeclaration(resolver, "AxisAngleRotation3D", "System.Windows.Media.Media3D", 1);
@ -127,7 +127,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -127,7 +127,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
KnownTypeTable[0x4e] = new TypeDeclaration(resolver, "CollectionContainer", "System.Windows.Data", 0);
KnownTypeTable[0x4f] = new TypeDeclaration(resolver, "CollectionView", "System.Windows.Data", 0);
KnownTypeTable[80] = new TypeDeclaration(resolver, "CollectionViewSource", "System.Windows.Data", 0);
KnownTypeTable[0x51] = new TypeDeclaration(resolver, "Color", "Microsoft.Win32", 2);
KnownTypeTable[0x51] = new TypeDeclaration(resolver, "Color", "Win32Native", "Microsoft.Win32", 2);
KnownTypeTable[0x52] = new TypeDeclaration(resolver, "ColorAnimation", "System.Windows.Media.Animation", 1);
KnownTypeTable[0x53] = new TypeDeclaration(resolver, "ColorAnimationBase", "System.Windows.Media.Animation", 1);
KnownTypeTable[0x54] = new TypeDeclaration(resolver, "ColorAnimationUsingKeyFrames", "System.Windows.Media.Animation", 1);

68
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/NodesCollection.cs

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Windows.Media;
namespace Ricciolo.StylesExplorer.MarkupReflection
{
class NodesCollection : List<XmlBamlNode>
{
public XmlBamlNode Last
{
get
{
if (this.Count > 0)
{
int i = this.Count - 1;
return this[i];
}
return null;
}
}
public void RemoveLast()
{
if (this.Count > 0)
this.Remove(this.Last);
}
public XmlBamlNode Dequeue()
{
return DequeueInternal(true);
}
public XmlBamlNode Peek()
{
return DequeueInternal(false);
}
XmlBamlNode DequeueInternal(bool remove)
{
if (this.Count > 0)
{
XmlBamlNode node = this[0];
if (remove)
this.RemoveAt(0);
return node;
}
else
return null;
}
public void Enqueue(XmlBamlNode node)
{
this.Add(node);
}
}
}

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

@ -8,11 +8,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -8,11 +8,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
internal class TypeDeclaration
{
private readonly XmlBamlReader reader;
private readonly short _assemblyId;
private readonly bool _isKnown;
private readonly string _name;
private readonly string _namespaceName;
private readonly bool _isExtension;
private IType _type;
private bool _typeLoaded;
@ -21,7 +16,12 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -21,7 +16,12 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public TypeDeclaration(ITypeResolver resolver, string name, string namespaceName, short assemblyId)
: this(null, resolver, name, namespaceName, assemblyId, true)
{
}
public TypeDeclaration(ITypeResolver resolver, string name, string enclosingTypeName, string namespaceName, short assemblyId)
: this(null, resolver, name, namespaceName, assemblyId, true)
{
this.EnclosingTypeName = enclosingTypeName;
}
public TypeDeclaration(ITypeResolver resolver, string name, string namespaceName, short assemblyId, bool isExtension)
@ -39,10 +39,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -39,10 +39,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
{
this.reader = reader;
this.resolver = resolver;
this._name = name;
this._namespaceName = namespaceName;
this._assemblyId = assemblyId;
this._isKnown = isKnown;
this.Name = name;
this.Namespace = namespaceName;
this.AssemblyId = assemblyId;
this.IsKnown = isKnown;
if (!_isExtension)
_isExtension = name.EndsWith("Extension");
@ -50,8 +50,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -50,8 +50,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public override string ToString()
{
return this._name;
return this.Name;
}
public string EnclosingTypeName { get; private set; }
public bool IsExtension
{
@ -60,8 +62,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -60,8 +62,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public string Assembly
{
get
{
get {
if (reader != null)
return this.reader.GetAssembly(this.AssemblyId);
else
@ -69,46 +70,19 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -69,46 +70,19 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
}
}
public short AssemblyId
{
get { return _assemblyId; }
}
public short AssemblyId { get; private set; }
public string Name
{
get
{
return this._name;
}
}
public string Name { get; private set; }
public bool IsKnown
{
get { return _isKnown; }
}
public bool IsKnown { get; private set; }
//public Type DotNetType
//{
// get
// {
// if (!_typeLoaded)
// {
// _type = Type.GetType(String.Format("{0}.{1}, {2}", this.Namespace, this.Name, this.Assembly), false, true);
// _typeLoaded = true;
// }
// return _type;
// }
//}
public IType Type
{
public IType Type {
get
{
if (!_typeLoaded)
{
if (this.Name.Length > 0)
_type = resolver.GetTypeByAssemblyQualifiedName(String.Format("{0}.{1}, {2}", this.Namespace, this.Name, this.Assembly));
_type = resolver.GetTypeByAssemblyQualifiedName(AssemblyQualifiedName);
_typeLoaded = true;
}
@ -116,26 +90,28 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -116,26 +90,28 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
}
}
public string Namespace
{
get
{
return this._namespaceName;
}
public string Namespace { get; private set; }
public string FullyQualifiedName {
get { return EnclosingTypeName == null ? string.Format("{0}.{1}", Namespace, Name) : string.Format("{0}.{1}+{2}", Namespace, EnclosingTypeName, Name); }
}
public string AssemblyQualifiedName {
get { return string.Format("{0}, {1}", FullyQualifiedName, Assembly); }
}
public override bool Equals(object obj)
{
TypeDeclaration td = obj as TypeDeclaration;
if (td != null)
return (this.Name == td.Name && this.Namespace == td.Namespace && this.AssemblyId == td.AssemblyId);
return (this.Name == td.Name && this.EnclosingTypeName == td.EnclosingTypeName && this.Namespace == td.Namespace && this.AssemblyId == td.AssemblyId);
else
return false;
}
public override int GetHashCode()
{
return this.AssemblyId ^ this.Name.GetHashCode() ^ this.Namespace.GetHashCode();
return this.AssemblyId ^ this.Name.GetHashCode() ^ this.EnclosingTypeName.GetHashCode() ^ this.Namespace.GetHashCode();
}
}

35
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/WpfDependencyPropertyDescriptor.cs

@ -1,35 +0,0 @@ @@ -1,35 +0,0 @@
// Copyright (c) Cristian Civera (cristian@aspitalia.com)
// This code is distributed under the MS-PL (for details please see \doc\MS-PL.txt)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
namespace Ricciolo.StylesExplorer.MarkupReflection
{
public class WpfDependencyPropertyDescriptor : MarshalByRefObject, IDependencyPropertyDescriptor
{
private readonly DependencyPropertyDescriptor _propertyDescriptor;
public WpfDependencyPropertyDescriptor(DependencyPropertyDescriptor propertyDescriptor)
{
if (propertyDescriptor == null) throw new ArgumentNullException("propertyDescriptor");
_propertyDescriptor = propertyDescriptor;
}
#region IDependencyPropertyDescriptor Members
public bool IsAttached
{
get { return _propertyDescriptor.IsAttached; }
}
#endregion
public override object InitializeLifetimeService()
{
return null;
}
}
}

19
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlElement.cs

@ -23,8 +23,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -23,8 +23,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
this.Namespaces.AddRange(parent.Namespaces);
}
public XmlNamespaceCollection Namespaces
{
public XmlNamespaceCollection Namespaces {
get { return _namespaces; }
}
@ -42,11 +41,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -42,11 +41,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public override string ToString()
{
return String.Format("Element: {0}", TypeDeclaration.Name);
return string.Format("Element: {0}", TypeDeclaration.Name);
}
}
internal class XmlBamlEndElement : XmlBamlElement
class XmlBamlEndElement : XmlBamlElement
{
public XmlBamlEndElement(XmlBamlElement start)
{
@ -54,19 +53,13 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -54,19 +53,13 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
this.Namespaces.AddRange(start.Namespaces);
}
public override XmlNodeType NodeType
{
get
{
return XmlNodeType.EndElement;
}
public override XmlNodeType NodeType {
get { return XmlNodeType.EndElement; }
}
public override string ToString()
{
return String.Format("EndElement: {0}", TypeDeclaration.Name);
return string.Format("EndElement: {0}", TypeDeclaration.Name);
}
}
}

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

@ -41,7 +41,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -41,7 +41,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public override string ToString()
{
return String.Format("PropertyElement: {0}.{1}", TypeDeclaration.Name, PropertyDeclaration.Name);
return String.Format("PropertyElement: {0}.{1}", TypeDeclaration.Name.Replace('+', '.'), PropertyDeclaration.Name);
}
}
}

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

@ -41,9 +41,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -41,9 +41,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
bool intoAttribute = false;
bool initialized;
bool _eof;
bool isPartialDefKeysClosed = true;
bool isDefKeysClosed = true;
#region Context
Stack<ReaderContext> layer = new Stack<ReaderContext>();
@ -79,13 +76,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -79,13 +76,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
List<KeyMapping> keys = new List<KeyMapping>();
KeyMapping LastKey {
get {
KeyMapping last = keys.LastOrDefault();
if (last == null)
keys.Add(last = new KeyMapping());
return last;
}
get { return keys.LastOrDefault(); }
}
void LayerPop()
@ -112,11 +103,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -112,11 +103,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
public const string XWPFNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
public const string DefaultWPFNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
public XmlBamlReader(Stream stream) : this (stream, AppDomainTypeResolver.GetIntoNewAppDomain(Environment.CurrentDirectory))
{
}
public XmlBamlReader(Stream stream, ITypeResolver resolver)
{
if (stream == null)
@ -339,7 +325,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -339,7 +325,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
else
currentType = (BamlRecordType)type;
if (currentType.ToString().EndsWith("End"))
Debug.Unindent();
Debug.WriteLine(string.Format("{0} (0x{0:x})", currentType));
if (currentType.ToString().EndsWith("Start"))
Debug.Indent();
}
bool SetNextNode()
@ -402,6 +392,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -402,6 +392,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
break;
case BamlRecordType.DeferableContentStart:
Current.IsDeferred = true;
keys = new List<KeyMapping>();
currentKey = 0;
reader.ReadInt32();
break;
case BamlRecordType.DefAttribute:
@ -637,9 +629,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -637,9 +629,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
{
get
{
if (intoAttribute) return String.Empty;
if (intoAttribute) return string.Empty;
String localName = String.Empty;
String localName = string.Empty;
XmlBamlNode node = this.CurrentNode;
if (node is XmlBamlSimpleProperty) {
@ -689,13 +681,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -689,13 +681,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
object GetResourceName(short identifier)
{
if (identifier >= 0)
{
if (identifier >= 0) {
PropertyDeclaration declaration = this.propertyTable[identifier];
return declaration;
}
else
{
} else {
identifier = (short)-identifier;
bool isNotKey = (identifier > 0xe8);
if (isNotKey)
@ -998,6 +987,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -998,6 +987,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
bool sharedSet = reader.ReadBoolean();
string text = this.stringTable[stringId];
Debug.Print("KeyString: " + text);
if (text == null)
throw new NotSupportedException();
@ -1039,6 +1029,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1039,6 +1029,8 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
void ReadElementEnd()
{
CloseElement();
if (Current.IsDeferred)
keys = null;
LayerPop();
}
@ -1095,12 +1087,12 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1095,12 +1087,12 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
// this property could be a markup extension
// try to convert it
int start = nodes.IndexOf(propertyElement) + 1;
IEnumerator enumerator = nodes.GetEnumerator();
IEnumerator<XmlBamlNode> enumerator = nodes.GetEnumerator();
// move enumerator to the start of this property value
for (int i = 0; i < start && enumerator.MoveNext(); i++) ;
if (IsExtension(enumerator)) {
if (IsExtension(enumerator) && start < nodes.Count - 1) {
start--;
nodes.RemoveAt(start);
nodes.RemoveLast();
@ -1173,11 +1165,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1173,11 +1165,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
}
}
bool IsExtension(IEnumerator enumerator)
bool IsExtension(IEnumerator<XmlBamlNode> enumerator)
{
while (enumerator.MoveNext()) {
object node = enumerator.Current;
if (node is XmlBamlElement && !(node is XmlBamlEndElement) && !((XmlBamlElement)node).TypeDeclaration.IsExtension)
var node = enumerator.Current;
if (node.NodeType == XmlNodeType.Element && !((XmlBamlElement)node).TypeDeclaration.IsExtension)
return false;
}
@ -1231,7 +1223,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1231,7 +1223,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
nodes.Enqueue(element);
if (oldDeclaration != null) {
nodes.Enqueue(new XmlBamlSimpleProperty(XWPFNamespace, "Class", string.Format("{0}.{1}", oldDeclaration.Namespace, oldDeclaration.Name)));
nodes.Enqueue(new XmlBamlSimpleProperty(XWPFNamespace, "Class", oldDeclaration.FullyQualifiedName.Replace('+', '.')));
}
if (parentElement != null && complexPropertyOpened == 0 && !Current.IsInStaticResource && Current.Previous.IsDeferred) {
@ -1342,9 +1334,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1342,9 +1334,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
CloseElement();
complexPropertyOpened--;
if (complexPropertyOpened == 0)
{
if (complexPropertyOpened == 0) {
int start = nodes.IndexOf(propertyElement);
StringBuilder sb = new StringBuilder();
@ -1409,27 +1399,26 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1409,27 +1399,26 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
void ReadOptimizedStaticResource()
{
byte num = reader.ReadByte();
byte flags = reader.ReadByte();
short typeIdentifier = reader.ReadInt16();
bool isValueType = (num & 1) == 1;
bool isStaticType = (num & 2) == 2;
bool isValueType = (flags & 1) == 1;
bool isStaticType = (flags & 2) == 2;
object resource;
if (isValueType)
resource = this.GetTypeExtension(typeIdentifier);
else if (isStaticType)
{
ResourceName resourceName = (ResourceName)this.GetResourceName(typeIdentifier);
resource = GetStaticExtension(resourceName.Name);
}
else
{
resource = GetTypeExtension(typeIdentifier);
else if (isStaticType) {
object name = GetResourceName(typeIdentifier);
if (name is ResourceName)
resource = GetStaticExtension(((ResourceName)name).Name);
else if (name is PropertyDeclaration)
resource = GetStaticExtension(FormatPropertyDeclaration(((PropertyDeclaration)name), true, false, false));
else
throw new InvalidOperationException("Invalid resource: " + name.GetType());
} else {
resource = this.stringTable[typeIdentifier];
}
//this.staticResourceTable.Add(resource);
isPartialDefKeysClosed = true;
// Aggiungo la risorsa nell'ultimo gruppo
LastKey.StaticResources.Add(resource);
}
@ -1474,8 +1463,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1474,8 +1463,6 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
return String.Format("{0}:{1}", prefix, name);
}
string FormatPropertyDeclaration(PropertyDeclaration propertyDeclaration, bool withPrefix, bool useReading, bool checkType)
{
StringBuilder sb = new StringBuilder();
@ -1511,11 +1498,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1511,11 +1498,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
void ReadPropertyWithStaticResourceIdentifier()
{
short identifier = reader.ReadInt16();
short staticIdentifier = reader.ReadInt16();
short propertyId = reader.ReadInt16();
short index = reader.ReadInt16();
PropertyDeclaration pd = this.GetPropertyDeclaration(identifier);
object staticResource = GetStaticResource(staticIdentifier);
PropertyDeclaration pd = this.GetPropertyDeclaration(propertyId);
object staticResource = GetStaticResource(index);
string prefix = this.LookupPrefix(XmlPIMapping.PresentationNamespace, false);
string value = String.Format("{{{0}{1}StaticResource {2}}}", prefix, (String.IsNullOrEmpty(prefix)) ? String.Empty : ":", staticResource);
@ -1528,10 +1515,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1528,10 +1515,10 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
object GetStaticResource(short identifier)
{
if (identifier < LastKey.StaticResources.Count)
return LastKey.StaticResources[(int)identifier];
if (identifier < keys[currentKey - 1].StaticResources.Count)
return keys[currentKey - 1].StaticResources[(int)identifier];
// return "???" + identifier +"???";
// return "???" + identifier + "???";
throw new ArgumentException("Cannot find StaticResource", "identifier");
}
@ -1595,11 +1582,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1595,11 +1582,11 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
TypeDeclaration GetKnownTypeDeclarationByName(string name)
{
foreach (var type in KnownInfo.KnownTypeTable) {
if (name == string.Format("{0}.{1}, {2}", type.Namespace, type.Name, type.Assembly))
if (name == type.AssemblyQualifiedName)
return type;
}
throw new NotSupportedException();
throw new NotSupportedException("Type '" + name + "' not found!");
}
internal string GetAssembly(short identifier)
@ -1607,26 +1594,18 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1607,26 +1594,18 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
return this.assemblyTable[identifier];
}
XmlBamlNode CurrentNode
{
get
{
return _currentNode;
}
XmlBamlNode CurrentNode {
get { return _currentNode; }
}
///<summary>
///When overridden in a derived class, gets the namespace URI (as defined in the W3C Namespace specification) of the node on which the reader is positioned.
///</summary>
///
///<returns>
///The namespace URI of the current node; otherwise an empty string.
///</returns>
///
public override string NamespaceURI
{
get
{
public override string NamespaceURI {
get {
if (intoAttribute) return String.Empty;
TypeDeclaration declaration;
@ -1664,11 +1643,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1664,11 +1643,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
///<summary>
///When overridden in a derived class, gets the namespace prefix associated with the current node.
///</summary>
///
///<returns>
///The namespace prefix associated with the current node.
///</returns>
///
public override string Prefix
{
get
@ -1682,11 +1659,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1682,11 +1659,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
///<summary>
///When overridden in a derived class, gets a value indicating whether the current node can have a <see cref="P:System.Xml.XmlReader.Value"></see>.
///</summary>
///
///<returns>
///true if the node on which the reader is currently positioned can have a Value; otherwise, false. If false, the node has a value of String.Empty.
///</returns>
///
public override bool HasValue
{
get { return this.Value != null; }
@ -1703,11 +1678,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1703,11 +1678,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
///<summary>
///When overridden in a derived class, gets the text value of the current node.
///</summary>
///
///<returns>
///The value returned depends on the <see cref="P:System.Xml.XmlReader.NodeType"></see> of the node. The following table lists node types that have a value to return. All other node types return String.Empty.Node type Value AttributeThe value of the attribute. CDATAThe content of the CDATA section. CommentThe content of the comment. DocumentTypeThe internal subset. ProcessingInstructionThe entire content, excluding the target. SignificantWhitespaceThe white space between markup in a mixed content model. TextThe content of the text node. WhitespaceThe white space between markup. XmlDeclarationThe content of the declaration.
///</returns>
///
public override string Value
{
get
@ -1737,11 +1710,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1737,11 +1710,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
///<summary>
///When overridden in a derived class, gets the depth of the current node in the XML document.
///</summary>
///
///<returns>
///The depth of the current node in the XML document.
///</returns>
///
public override int Depth
{
get { return this.readingElements.Count; }
@ -1750,11 +1721,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1750,11 +1721,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
///<summary>
///When overridden in a derived class, gets the base URI of the current node.
///</summary>
///
///<returns>
///The base URI of the current node.
///</returns>
///
public override string BaseURI
{
get { return String.Empty; }
@ -1763,62 +1732,42 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1763,62 +1732,42 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
///<summary>
///When overridden in a derived class, gets a value indicating whether the current node is an empty element (for example, &lt;MyElement/&gt;).
///</summary>
///
///<returns>
///true if the current node is an element (<see cref="P:System.Xml.XmlReader.NodeType"></see> equals XmlNodeType.Element) that ends with /&gt;; otherwise, false.
///</returns>
///
public override bool IsEmptyElement
{
get { return false; }
}
//public override bool IsDefault
//{
// get
// {
// return this.NamespaceURI == null;
// }
//}
///<summary>
///When overridden in a derived class, gets the number of attributes on the current node.
///</summary>
///
///<returns>
///The number of attributes on the current node.
///</returns>
///
public override int AttributeCount
{
public override int AttributeCount {
get { throw new NotImplementedException(); }
}
///<summary>
///When overridden in a derived class, gets a value indicating whether the reader is positioned at the end of the stream.
///</summary>
///
///<returns>
///true if the reader is positioned at the end of the stream; otherwise, false.
///</returns>
///
public override bool EOF
{
public override bool EOF {
get { return _eof; }
}
///<summary>
///When overridden in a derived class, gets the state of the reader.
///</summary>
///
///<returns>
///One of the <see cref="T:System.Xml.ReadState"></see> values.
///</returns>
///
public override ReadState ReadState
{
get
{
public override ReadState ReadState {
get {
if (!initialized)
return ReadState.Initial;
else if (reader == null)
@ -1838,11 +1787,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1838,11 +1787,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
///<summary>
///When overridden in a derived class, gets the <see cref="T:System.Xml.XmlNameTable"></see> associated with this implementation.
///</summary>
///
///<returns>
///The XmlNameTable enabling you to get the atomized version of a string within the node.
///</returns>
///
public override XmlNameTable NameTable
{
get { return _nameTable; }
@ -1938,60 +1885,5 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -1938,60 +1885,5 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
}
#endregion
#region NodesCollection
internal class NodesCollection : List<XmlBamlNode>
{
public XmlBamlNode Last
{
get
{
if (this.Count > 0)
{
int i = this.Count - 1;
return this[i];
}
return null;
}
}
public void RemoveLast()
{
if (this.Count > 0)
this.Remove(this.Last);
}
public XmlBamlNode Dequeue()
{
return DequeueInternal(true);
}
public XmlBamlNode Peek()
{
return DequeueInternal(false);
}
XmlBamlNode DequeueInternal(bool remove)
{
if (this.Count > 0)
{
XmlBamlNode node = this[0];
if (remove)
this.RemoveAt(0);
return node;
}
else
return null;
}
public void Enqueue(XmlBamlNode node)
{
this.Add(node);
}
}
#endregion
}
}

23
ILSpy.BamlDecompiler/Tests/Cases/Dictionary1.xaml

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Color x:Key="VeryDark" A="255" R="70" G="70" B="70" />
<Color x:Key="Dark" A="255" R="102" G="102" B="102" />
<Color x:Key="Medium" A="255" R="140" G="140" B="140" />
<Color x:Key="Light" A="255" R="204" G="204" B="204" />
<Color x:Key="VeryLight" A="255" R="241" G="241" B="241" />
<Color x:Key="OffWhite" A="255" R="255" G="255" B="255" />
<Color x:Key="Highlight" A="255" R="220" G="107" B="47" />
<SolidColorBrush x:Key="VeryDarkBrush" Color="{StaticResource VeryDark}" />
<SolidColorBrush x:Key="DarkBrush" Color="{StaticResource Dark}" />
<SolidColorBrush x:Key="MediumBrush" Color="{StaticResource Medium}" />
<SolidColorBrush x:Key="LightBrush" Color="{StaticResource Light}" />
<SolidColorBrush x:Key="VeryLightBrush" Color="{StaticResource VeryLight}" />
<SolidColorBrush x:Key="OffWhiteBrush" Color="{StaticResource OffWhite}" />
<SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource Highlight}" />
<LinearGradientBrush x:Key="EdgeBorder" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#0000" Offset="0" />
<GradientStop Color="#1000" Offset="0.65" />
<GradientStop Color="#3000" Offset="1" />
</LinearGradientBrush>
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#6FFF" />
<SolidColorBrush x:Key="SelectedBackgroundBrush" Color="{StaticResource Light}" />
</ResourceDictionary>

1
ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -128,6 +128,7 @@ @@ -128,6 +128,7 @@
</Page>
<Page Include="Cases\SimpleDictionary.xaml" />
<Page Include="Cases\SimpleNames.xaml" />
<Page Include="Cases\Dictionary1.xaml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

17
ILSpy.BamlDecompiler/Tests/TestRunner.cs

@ -61,18 +61,27 @@ namespace ILSpy.BamlDecompiler.Tests @@ -61,18 +61,27 @@ namespace ILSpy.BamlDecompiler.Tests
RunTest("cases/attachedevent");
}
[Test]
public void Dictionary1()
{
RunTest("cases/dictionary1");
}
#region RunTest
void RunTest(string name)
{
string asmPath = typeof(TestRunner).Assembly.Location;
RunTest(name, typeof(TestRunner).Assembly.Location, Path.Combine("..\\..\\Tests", name + ".xaml"));
}
void RunTest(string name, string asmPath, string sourcePath)
{
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(File.ReadAllText(path), document.ToString());
CodeAssert.AreEqual(File.ReadAllText(sourcePath), document.ToString());
}
Stream LoadBaml(Resource res, string name)

4
ILSpy/AssemblyList.cs

@ -41,6 +41,8 @@ namespace ICSharpCode.ILSpy @@ -41,6 +41,8 @@ namespace ICSharpCode.ILSpy
/// <summary>Dirty flag, used to mark modifications so that the list is saved later</summary>
bool dirty;
internal readonly ConcurrentDictionary<string, LoadedAssembly> assemblyLookupCache = new ConcurrentDictionary<string, LoadedAssembly>();
/// <summary>
/// The assemblies in this list.
/// Needs locking for multi-threaded access!
@ -101,6 +103,7 @@ namespace ICSharpCode.ILSpy @@ -101,6 +103,7 @@ namespace ICSharpCode.ILSpy
void Assemblies_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
assemblyLookupCache.Clear();
// Whenever the assembly list is modified, mark it as dirty
// and enqueue a task that saves it once the UI has finished modifying the assembly list.
if (!dirty) {
@ -111,6 +114,7 @@ namespace ICSharpCode.ILSpy @@ -111,6 +114,7 @@ namespace ICSharpCode.ILSpy
delegate {
dirty = false;
AssemblyListManager.SaveList(this);
assemblyLookupCache.Clear();
})
);
}

9
ILSpy/LoadedAssembly.cs

@ -17,11 +17,11 @@ @@ -17,11 +17,11 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Threading;
using ICSharpCode.ILSpy.Options;
using Mono.Cecil;
@ -134,6 +134,8 @@ namespace ICSharpCode.ILSpy @@ -134,6 +134,8 @@ namespace ICSharpCode.ILSpy
if (!disposed) {
disposed = true;
assemblyLoadDisableCount--;
// clear the lookup cache since we might have stored the lookups failed due to DisableAssemblyLoad()
MainWindow.Instance.CurrentAssemblyList.assemblyLookupCache.Clear();
}
}
}
@ -178,6 +180,11 @@ namespace ICSharpCode.ILSpy @@ -178,6 +180,11 @@ namespace ICSharpCode.ILSpy
}
public LoadedAssembly LookupReferencedAssembly(string fullName)
{
return assemblyList.assemblyLookupCache.GetOrAdd(fullName, LookupReferencedAssemblyInternal);
}
LoadedAssembly LookupReferencedAssemblyInternal(string fullName)
{
foreach (LoadedAssembly asm in assemblyList.GetAssemblies()) {
if (asm.AssemblyDefinition != null && fullName.Equals(asm.AssemblyDefinition.FullName, StringComparison.OrdinalIgnoreCase))

15
ILSpy/MainWindow.xaml.cs

@ -208,6 +208,8 @@ namespace ICSharpCode.ILSpy @@ -208,6 +208,8 @@ namespace ICSharpCode.ILSpy
}
var args = new CommandLineArguments(lines);
if (HandleCommandLineArguments(args)) {
if (!args.NoActivate && WindowState == WindowState.Minimized)
WindowState = WindowState.Normal;
HandleCommandLineArgumentsAfterShowList(args);
handled = true;
return (IntPtr)1;
@ -392,9 +394,16 @@ namespace ICSharpCode.ILSpy @@ -392,9 +394,16 @@ namespace ICSharpCode.ILSpy
internal void SelectNode(SharpTreeNode obj)
{
if (obj != null) {
// Set both the selection and focus to ensure that keyboard navigation works as expected.
treeView.FocusNode(obj);
treeView.SelectedItem = obj;
if (!obj.AncestorsAndSelf().Any(node => node.IsHidden)) {
// Set both the selection and focus to ensure that keyboard navigation works as expected.
treeView.FocusNode(obj);
treeView.SelectedItem = obj;
} else {
MessageBox.Show("Navigation failed because the target is hidden or a compiler-generated class.\n" +
"Please disable all filters that might hide the item (i.e. activate " +
"\"View > Show internal types and members\") and try again.",
"ILSpy", MessageBoxButton.OK, MessageBoxImage.Exclamation);
}
}
}

2
ILSpy/XmlDoc/XmlDocKeyProvider.cs

@ -169,6 +169,7 @@ namespace ICSharpCode.ILSpy.XmlDoc @@ -169,6 +169,7 @@ namespace ICSharpCode.ILSpy.XmlDoc
} else {
dotPos = key.LastIndexOf('.');
}
if (dotPos < 0) return null;
TypeDefinition type = FindType(module, key.Substring(2, dotPos - 2));
if (type == null)
return null;
@ -192,6 +193,7 @@ namespace ICSharpCode.ILSpy.XmlDoc @@ -192,6 +193,7 @@ namespace ICSharpCode.ILSpy.XmlDoc
} else {
ns = string.Empty;
}
if (string.IsNullOrEmpty(name)) return null;
TypeDefinition type = module.GetType(ns, name);
if (type == null && ns.Length > 0) {
// try if this is a nested type

4
SharpTreeView/SharpTreeView.cs

@ -152,6 +152,10 @@ namespace ICSharpCode.TreeView @@ -152,6 +152,10 @@ namespace ICSharpCode.TreeView
var list = SelectedItems.Cast<SharpTreeNode>().Except(selectedOldItems).ToList();
SetSelectedItems(list);
}
// reset the focus to the previous node
SelectedIndex = Math.Max(0, e.OldStartingIndex - 1);
if (SelectedItem != null)
FocusNode((SharpTreeNode)SelectedItem);
}
}

Loading…
Cancel
Save