Browse Source

Fix #284 - Ability to disable decompilation of anonymous types to "var"

pull/863/head
Siegfried Pammer 8 years ago
parent
commit
d33c334f5a
  1. 2
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 15
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  4. 6
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  5. 17
      ICSharpCode.Decompiler/DecompilerSettings.cs
  6. 1
      ILSpy/Options/DecompilerSettingsPanel.xaml
  7. 2
      ILSpy/Options/DecompilerSettingsPanel.xaml.cs

2
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -195,7 +195,7 @@ namespace ICSharpCode.Decompiler.CSharp
} else if (type.IsCompilerGenerated()) { } else if (type.IsCompilerGenerated()) {
// if (type.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal)) // if (type.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
// return true; // return true;
if (type.IsAnonymousType()) if (settings.AnonymousTypes && type.IsAnonymousType())
return true; return true;
} }
} }

15
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1011,7 +1011,7 @@ namespace ICSharpCode.Decompiler.CSharp
simplifiedDelegateCreation.Arguments.Clear(); simplifiedDelegateCreation.Arguments.Clear();
simplifiedDelegateCreation.Arguments.Add(replacement); simplifiedDelegateCreation.Arguments.Add(replacement);
replacement = simplifiedDelegateCreation; replacement = simplifiedDelegateCreation;
} else if (!expectedType.ContainsAnonymousType()) { } else if (!settings.AnonymousTypes || !expectedType.ContainsAnonymousType()) {
replacement = new CastExpression(ConvertType(expectedType), replacement); replacement = new CastExpression(ConvertType(expectedType), replacement);
} }
return replacement return replacement
@ -1025,7 +1025,7 @@ namespace ICSharpCode.Decompiler.CSharp
int i = 0; int i = 0;
foreach (var parameter in method.Parameters) { foreach (var parameter in method.Parameters) {
var pd = astBuilder.ConvertParameter(parameter); var pd = astBuilder.ConvertParameter(parameter);
if (parameter.Type.ContainsAnonymousType()) if (settings.AnonymousTypes && parameter.Type.ContainsAnonymousType())
pd.Type = null; pd.Type = null;
ILVariable v; ILVariable v;
if (variables.TryGetValue(i, out v)) if (variables.TryGetValue(i, out v))
@ -1111,7 +1111,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (inst.OpCode == OpCode.NewObj) { if (inst.OpCode == OpCode.NewObj) {
var argumentExpressions = arguments.SelectArray(arg => arg.Expression); var argumentExpressions = arguments.SelectArray(arg => arg.Expression);
if (method.DeclaringType.IsAnonymousType()) { if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType()) {
AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression(); AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
var parameters = inst.Method.Parameters; var parameters = inst.Method.Parameters;
if (CanInferAnonymousTypePropertyNamesFromArguments(argumentExpressions, parameters)) { if (CanInferAnonymousTypePropertyNamesFromArguments(argumentExpressions, parameters)) {
@ -1171,7 +1171,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (!argumentsCasted) { if (!argumentsCasted) {
argumentsCasted = true; argumentsCasted = true;
for (int i = 0; i < arguments.Length; i++) { for (int i = 0; i < arguments.Length; i++) {
if (!method.Parameters[i].Type.ContainsAnonymousType()) if (!settings.AnonymousTypes || !method.Parameters[i].Type.ContainsAnonymousType())
arguments[i] = arguments[i].ConvertTo(method.Parameters[i].Type, this); arguments[i] = arguments[i].ConvertTo(method.Parameters[i].Type, this);
} }
} else if (!targetCasted) { } else if (!targetCasted) {
@ -1196,7 +1196,7 @@ namespace ICSharpCode.Decompiler.CSharp
methodName = method.ImplementedInterfaceMembers[0].Name; methodName = method.ImplementedInterfaceMembers[0].Name;
} }
var mre = new MemberReferenceExpression(targetExpr, methodName); var mre = new MemberReferenceExpression(targetExpr, methodName);
if (requireTypeArguments && !method.TypeArguments.Any(a => a.ContainsAnonymousType())) if (requireTypeArguments && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType())))
mre.TypeArguments.AddRange(method.TypeArguments.Select(ConvertType)); mre.TypeArguments.AddRange(method.TypeArguments.Select(ConvertType));
var argumentExpressions = arguments.Select(arg => arg.Expression); var argumentExpressions = arguments.Select(arg => arg.Expression);
expr = new InvocationExpression(mre, argumentExpressions); expr = new InvocationExpression(mre, argumentExpressions);
@ -1621,8 +1621,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
ArraySpecifier[] additionalSpecifiers; ArraySpecifier[] additionalSpecifiers;
AstType typeExpression; AstType typeExpression;
bool isAnonymouslyTyped = type.ContainsAnonymousType(); if (settings.AnonymousTypes && type.ContainsAnonymousType()) {
if (isAnonymouslyTyped) {
typeExpression = null; typeExpression = null;
additionalSpecifiers = new[] { new ArraySpecifier() }; additionalSpecifiers = new[] { new ArraySpecifier() };
} else { } else {
@ -1639,7 +1638,7 @@ namespace ICSharpCode.Decompiler.CSharp
Initializer = root Initializer = root
}; };
expr.AdditionalArraySpecifiers.AddRange(additionalSpecifiers); expr.AdditionalArraySpecifiers.AddRange(additionalSpecifiers);
if (!isAnonymouslyTyped) if (!(bool)type.ContainsAnonymousType())
expr.Arguments.AddRange(newArr.Indices.Select(i => Translate(i).Expression)); expr.Arguments.AddRange(newArr.Indices.Select(i => Translate(i).Expression));
return expr.WithILInstruction(block) return expr.WithILInstruction(block)
.WithRR(new ArrayCreateResolveResult(new ArrayType(compilation, type, dimensions), newArr.Indices.Select(i => Translate(i).ResolveResult).ToArray(), elementResolveResults)); .WithRR(new ArrayCreateResolveResult(new ArrayType(compilation, type, dimensions), newArr.Indices.Select(i => Translate(i).ResolveResult).ToArray(), elementResolveResults));

2
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs

@ -363,7 +363,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
if (assignment != null && assignment.Operator == AssignmentOperatorType.Assign && assignment.Left.IsMatch(expectedExpr)) { if (assignment != null && assignment.Operator == AssignmentOperatorType.Assign && assignment.Left.IsMatch(expectedExpr)) {
AstType type; AstType type;
if (v.Type.ContainsAnonymousType()) { if (context.Settings.AnonymousTypes && v.Type.ContainsAnonymousType()) {
type = new SimpleType("var"); type = new SimpleType("var");
} else { } else {
type = context.TypeSystemAstBuilder.ConvertType(v.Type); type = context.TypeSystemAstBuilder.ConvertType(v.Type);

6
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -280,7 +280,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// variable is used, so we'll create a variable declaration // variable is used, so we'll create a variable declaration
variable.Kind = IL.VariableKind.UsingLocal; variable.Kind = IL.VariableKind.UsingLocal;
usingStatement.ResourceAcquisition = new VariableDeclarationStatement { usingStatement.ResourceAcquisition = new VariableDeclarationStatement {
Type = variable.Type.ContainsAnonymousType() ? new SimpleType("var") : context.TypeSystemAstBuilder.ConvertType(variable.Type), Type = context.Settings.AnonymousTypes && variable.Type.ContainsAnonymousType() ? new SimpleType("var") : context.TypeSystemAstBuilder.ConvertType(variable.Type),
Variables = { Variables = {
new VariableInitializer { new VariableInitializer {
Name = variableName, Name = variableName,
@ -401,7 +401,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
itemVar.Kind = IL.VariableKind.ForeachLocal; itemVar.Kind = IL.VariableKind.ForeachLocal;
ForeachStatement foreachStatement = new ForeachStatement { ForeachStatement foreachStatement = new ForeachStatement {
VariableType = itemVar.Type.ContainsAnonymousType() ? new SimpleType("var") : context.TypeSystemAstBuilder.ConvertType(itemVar.Type), VariableType = context.Settings.AnonymousTypes && itemVar.Type.ContainsAnonymousType() ? new SimpleType("var") : context.TypeSystemAstBuilder.ConvertType(itemVar.Type),
VariableName = itemVar.Name, VariableName = itemVar.Name,
InExpression = m.Get<Expression>("collection").Single().Detach(), InExpression = m.Get<Expression>("collection").Single().Detach(),
EmbeddedStatement = newBody EmbeddedStatement = newBody
@ -533,7 +533,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
itemVar.Kind = IL.VariableKind.ForeachLocal; itemVar.Kind = IL.VariableKind.ForeachLocal;
ForeachStatement foreachStatement = new ForeachStatement ForeachStatement foreachStatement = new ForeachStatement
{ {
VariableType = itemVar.Type.ContainsAnonymousType() ? new SimpleType("var") : context.TypeSystemAstBuilder.ConvertType(itemVar.Type), VariableType = context.Settings.AnonymousTypes && itemVar.Type.ContainsAnonymousType() ? new SimpleType("var") : context.TypeSystemAstBuilder.ConvertType(itemVar.Type),
VariableName = itemVar.Name, VariableName = itemVar.Name,
}.WithILVariable(itemVar); }.WithILVariable(itemVar);
BlockStatement body = new BlockStatement(); BlockStatement body = new BlockStatement();

17
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -41,7 +41,22 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool anonymousTypes = true;
/// <summary>
/// Decompile anonymous types.
/// </summary>
public bool AnonymousTypes {
get { return anonymousTypes; }
set {
if (anonymousTypes != value) {
anonymousTypes = value;
OnPropertyChanged("AnonymousTypes");
}
}
}
bool expressionTrees = true; bool expressionTrees = true;
/// <summary> /// <summary>

1
ILSpy/Options/DecompilerSettingsPanel.xaml

@ -4,6 +4,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Margin="10"> <StackPanel Margin="10">
<CheckBox IsChecked="{Binding AnonymousMethods}">Decompile anonymous methods/lambdas</CheckBox> <CheckBox IsChecked="{Binding AnonymousMethods}">Decompile anonymous methods/lambdas</CheckBox>
<CheckBox IsChecked="{Binding AnonymousTypes}">Decompile anonymous types</CheckBox>
<CheckBox IsChecked="{Binding YieldReturn}">Decompile enumerators (yield return)</CheckBox> <CheckBox IsChecked="{Binding YieldReturn}">Decompile enumerators (yield return)</CheckBox>
<CheckBox IsChecked="{Binding AsyncAwait}">Decompile async methods (async/await)</CheckBox> <CheckBox IsChecked="{Binding AsyncAwait}">Decompile async methods (async/await)</CheckBox>
<CheckBox IsChecked="{Binding QueryExpressions}" IsEnabled="{Binding AnonymousMethods}">Decompile query expressions</CheckBox> <CheckBox IsChecked="{Binding QueryExpressions}" IsEnabled="{Binding AnonymousMethods}">Decompile query expressions</CheckBox>

2
ILSpy/Options/DecompilerSettingsPanel.xaml.cs

@ -51,6 +51,7 @@ namespace ICSharpCode.ILSpy.Options
XElement e = settings["DecompilerSettings"]; XElement e = settings["DecompilerSettings"];
DecompilerSettings s = new DecompilerSettings(); DecompilerSettings s = new DecompilerSettings();
s.AnonymousMethods = (bool?)e.Attribute("anonymousMethods") ?? s.AnonymousMethods; s.AnonymousMethods = (bool?)e.Attribute("anonymousMethods") ?? s.AnonymousMethods;
s.AnonymousTypes = (bool?)e.Attribute("anonymousTypes") ?? s.AnonymousTypes;
s.YieldReturn = (bool?)e.Attribute("yieldReturn") ?? s.YieldReturn; s.YieldReturn = (bool?)e.Attribute("yieldReturn") ?? s.YieldReturn;
s.AsyncAwait = (bool?)e.Attribute("asyncAwait") ?? s.AsyncAwait; s.AsyncAwait = (bool?)e.Attribute("asyncAwait") ?? s.AsyncAwait;
s.AutomaticProperties = (bool?) e.Attribute("automaticProperties") ?? s.AutomaticProperties; s.AutomaticProperties = (bool?) e.Attribute("automaticProperties") ?? s.AutomaticProperties;
@ -67,6 +68,7 @@ namespace ICSharpCode.ILSpy.Options
DecompilerSettings s = (DecompilerSettings)this.DataContext; DecompilerSettings s = (DecompilerSettings)this.DataContext;
XElement section = new XElement("DecompilerSettings"); XElement section = new XElement("DecompilerSettings");
section.SetAttributeValue("anonymousMethods", s.AnonymousMethods); section.SetAttributeValue("anonymousMethods", s.AnonymousMethods);
section.SetAttributeValue("anonymousTypes", s.AnonymousTypes);
section.SetAttributeValue("yieldReturn", s.YieldReturn); section.SetAttributeValue("yieldReturn", s.YieldReturn);
section.SetAttributeValue("asyncAwait", s.AsyncAwait); section.SetAttributeValue("asyncAwait", s.AsyncAwait);
section.SetAttributeValue("automaticProperties", s.AutomaticProperties); section.SetAttributeValue("automaticProperties", s.AutomaticProperties);

Loading…
Cancel
Save