Browse Source

Improve decompiler behavior is System.ValueTuple exists in multiple referenced assemblies.

This can happen if an application is compiled for .NET 4.6.2 and references
System.ValueTuple.dll; but ILSpy loads the latest mscorlib (e.g. .NET 4.7)
which also contains struct System.ValueTuple.
pull/1425/head
Daniel Grunwald 6 years ago
parent
commit
113acd48c1
  1. 3
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  2. 16
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  3. 5
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
  4. 9
      ICSharpCode.Decompiler/Semantics/TupleResolveResult.cs
  5. 2
      ICSharpCode.Decompiler/TypeSystem/TupleType.cs

3
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -164,7 +164,8 @@ namespace ICSharpCode.Decompiler.CSharp
} }
return tuple.WithRR(new TupleResolveResult( return tuple.WithRR(new TupleResolveResult(
expressionBuilder.compilation, expressionBuilder.compilation,
elementRRs.ToImmutableArray() elementRRs.ToImmutableArray(),
valueTupleAssembly: inst.Method.DeclaringType.GetDefinition()?.ParentModule
)).WithILInstruction(inst); )).WithILInstruction(inst);
} }
return Build(inst.OpCode, inst.Method, inst.Arguments, constrainedTo: inst.ConstrainedTo) return Build(inst.OpCode, inst.Method, inst.Arguments, constrainedTo: inst.ConstrainedTo)

16
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -384,9 +384,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
bool TypeMatches(IType type, ITypeDefinition typeDef, IReadOnlyList<IType> typeArguments) bool TypeMatches(IType type, ITypeDefinition typeDef, IReadOnlyList<IType> typeArguments)
{ {
if (typeDef.TypeParameterCount == 0) { if (typeDef.TypeParameterCount == 0) {
return typeDef.Equals(type); return TypeDefMatches(typeDef, type);
} else { } else {
if (!typeDef.Equals(type.GetDefinition())) if (!TypeDefMatches(typeDef, type.GetDefinition()))
return false; return false;
ParameterizedType pt = type as ParameterizedType; ParameterizedType pt = type as ParameterizedType;
if (pt == null) { if (pt == null) {
@ -401,6 +401,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
} }
bool TypeDefMatches(ITypeDefinition typeDef, IType type)
{
if (type.Name != typeDef.Name || type.Namespace != typeDef.Namespace || type.TypeParameterCount != typeDef.TypeParameterCount)
return false;
bool defIsNested = typeDef.DeclaringTypeDefinition != null;
bool typeIsNested = type.DeclaringType != null;
if (defIsNested && typeIsNested)
return TypeDefMatches(typeDef.DeclaringTypeDefinition, type.DeclaringType);
else
return defIsNested == typeIsNested;
}
/// <summary> /// <summary>
/// Adds type arguments to the result type. /// Adds type arguments to the result type.
/// </summary> /// </summary>

5
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -224,7 +224,10 @@ namespace ICSharpCode.Decompiler.CSharp
newElementRRs.Add(newElementExpr.ResolveResult); newElementRRs.Add(newElementExpr.ResolveResult);
} }
return newTupleExpr.WithILInstruction(this.ILInstructions) return newTupleExpr.WithILInstruction(this.ILInstructions)
.WithRR(new TupleResolveResult(expressionBuilder.compilation, newElementRRs.ToImmutableArray())); .WithRR(new TupleResolveResult(
expressionBuilder.compilation, newElementRRs.ToImmutableArray(),
valueTupleAssembly: targetTupleType.GetDefinition()?.ParentModule
));
} }
var compilation = expressionBuilder.compilation; var compilation = expressionBuilder.compilation;
var conversions = Resolver.CSharpConversions.Get(compilation); var conversions = Resolver.CSharpConversions.Get(compilation);

9
ICSharpCode.Decompiler/Semantics/TupleResolveResult.cs

@ -35,8 +35,9 @@ namespace ICSharpCode.Decompiler.Semantics
public TupleResolveResult(ICompilation compilation, public TupleResolveResult(ICompilation compilation,
ImmutableArray<ResolveResult> elements, ImmutableArray<ResolveResult> elements,
ImmutableArray<string> elementNames = default(ImmutableArray<string>)) ImmutableArray<string> elementNames = default(ImmutableArray<string>),
: base(GetTupleType(compilation, elements, elementNames)) IModule valueTupleAssembly = null)
: base(GetTupleType(compilation, elements, elementNames, valueTupleAssembly))
{ {
this.Elements = elements; this.Elements = elements;
} }
@ -46,12 +47,12 @@ namespace ICSharpCode.Decompiler.Semantics
return Elements; return Elements;
} }
static IType GetTupleType(ICompilation compilation, ImmutableArray<ResolveResult> elements, ImmutableArray<string> elementNames) static IType GetTupleType(ICompilation compilation, ImmutableArray<ResolveResult> elements, ImmutableArray<string> elementNames, IModule valueTupleAssembly)
{ {
if (elements.Any(e => e.Type.Kind == TypeKind.None || e.Type.Kind == TypeKind.Null)) if (elements.Any(e => e.Type.Kind == TypeKind.None || e.Type.Kind == TypeKind.Null))
return SpecialType.NoType; return SpecialType.NoType;
else else
return new TupleType(compilation, elements.Select(e => e.Type).ToImmutableArray(), elementNames); return new TupleType(compilation, elements.Select(e => e.Type).ToImmutableArray(), elementNames, valueTupleAssembly);
} }
} }
} }

2
ICSharpCode.Decompiler/TypeSystem/TupleType.cs

@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
private static IType FindValueTupleType(ICompilation compilation, IModule valueTupleAssembly, int tpc) private static IType FindValueTupleType(ICompilation compilation, IModule valueTupleAssembly, int tpc)
{ {
FullTypeName typeName = new TopLevelTypeName("System", "ValueTuple", tpc); var typeName = new TopLevelTypeName("System", "ValueTuple", tpc);
if (valueTupleAssembly != null) { if (valueTupleAssembly != null) {
var typeDef = valueTupleAssembly.GetTypeDefinition(typeName); var typeDef = valueTupleAssembly.GetTypeDefinition(typeName);
if (typeDef != null) if (typeDef != null)

Loading…
Cancel
Save