Browse Source

Reimplement CSharpLanguage.TypeToString

pull/863/head
Siegfried Pammer 8 years ago
parent
commit
206497e6c1
  1. 201
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 47
      ILSpy/Languages/CSharpLanguage.cs

201
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -771,5 +771,206 @@ namespace ICSharpCode.Decompiler.CSharp @@ -771,5 +771,206 @@ namespace ICSharpCode.Decompiler.CSharp
}
return eventDecl;
}
#region Convert Type Reference
/// <summary>
/// Converts a type reference.
/// </summary>
/// <param name="type">The Cecil type reference that should be converted into
/// a type system type reference.</param>
/// <param name="typeAttributes">Attributes associated with the Cecil type reference.
/// This is used to support the 'dynamic' type.</param>
public static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes = null, ConvertTypeOptions options = ConvertTypeOptions.None)
{
int typeIndex = 0;
return ConvertType(type, typeAttributes, ref typeIndex, options);
}
static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex, ConvertTypeOptions options)
{
while (type is OptionalModifierType || type is RequiredModifierType) {
type = ((TypeSpecification)type).ElementType;
}
if (type == null) {
return AstType.Null;
}
if (type is Mono.Cecil.ByReferenceType) {
typeIndex++;
// by reference type cannot be represented in C#; so we'll represent it as a pointer instead
return ConvertType((type as Mono.Cecil.ByReferenceType).ElementType, typeAttributes, ref typeIndex, options)
.MakePointerType();
} else if (type is Mono.Cecil.PointerType) {
typeIndex++;
return ConvertType((type as Mono.Cecil.PointerType).ElementType, typeAttributes, ref typeIndex, options)
.MakePointerType();
} else if (type is Mono.Cecil.ArrayType) {
typeIndex++;
return ConvertType((type as Mono.Cecil.ArrayType).ElementType, typeAttributes, ref typeIndex, options)
.MakeArrayType((type as Mono.Cecil.ArrayType).Rank);
} else if (type is GenericInstanceType) {
GenericInstanceType gType = (GenericInstanceType)type;
if (gType.ElementType.Namespace == "System" && gType.ElementType.Name == "Nullable`1" && gType.GenericArguments.Count == 1) {
typeIndex++;
return new ComposedType {
BaseType = ConvertType(gType.GenericArguments[0], typeAttributes, ref typeIndex, options),
HasNullableSpecifier = true
};
}
AstType baseType = ConvertType(gType.ElementType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
List<AstType> typeArguments = new List<AstType>();
foreach (var typeArgument in gType.GenericArguments) {
typeIndex++;
typeArguments.Add(ConvertType(typeArgument, typeAttributes, ref typeIndex, options));
}
ApplyTypeArgumentsTo(baseType, typeArguments);
return baseType;
} else if (type is GenericParameter) {
return new SimpleType(type.Name);
} else if (type.IsNested) {
AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name);
MemberType memberType = new MemberType { Target = typeRef, MemberName = namepart };
memberType.AddAnnotation(type);
if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
AddTypeParameterDefininitionsTo(type, memberType);
}
return memberType;
} else {
string ns = type.Namespace ?? string.Empty;
string name = type.Name;
if (name == null)
throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString());
if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) {
return new Syntax.PrimitiveType("dynamic");
} else {
if (ns == "System") {
if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames)
!= ConvertTypeOptions.DoNotUsePrimitiveTypeNames) {
switch (name) {
case "SByte":
return new Syntax.PrimitiveType("sbyte");
case "Int16":
return new Syntax.PrimitiveType("short");
case "Int32":
return new Syntax.PrimitiveType("int");
case "Int64":
return new Syntax.PrimitiveType("long");
case "Byte":
return new Syntax.PrimitiveType("byte");
case "UInt16":
return new Syntax.PrimitiveType("ushort");
case "UInt32":
return new Syntax.PrimitiveType("uint");
case "UInt64":
return new Syntax.PrimitiveType("ulong");
case "String":
return new Syntax.PrimitiveType("string");
case "Single":
return new Syntax.PrimitiveType("float");
case "Double":
return new Syntax.PrimitiveType("double");
case "Decimal":
return new Syntax.PrimitiveType("decimal");
case "Char":
return new Syntax.PrimitiveType("char");
case "Boolean":
return new Syntax.PrimitiveType("bool");
case "Void":
return new Syntax.PrimitiveType("void");
case "Object":
return new Syntax.PrimitiveType("object");
}
}
}
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name);
AstType astType;
if ((options & ConvertTypeOptions.IncludeNamespace) == ConvertTypeOptions.IncludeNamespace && ns.Length > 0) {
string[] parts = ns.Split('.');
AstType nsType = new SimpleType(parts[0]);
for (int i = 1; i < parts.Length; i++) {
nsType = new MemberType { Target = nsType, MemberName = parts[i] };
}
astType = new MemberType { Target = nsType, MemberName = name };
} else {
astType = new SimpleType(name);
}
astType.AddAnnotation(type);
if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
AddTypeParameterDefininitionsTo(type, astType);
}
return astType;
}
}
}
static void AddTypeParameterDefininitionsTo(TypeReference type, AstType astType)
{
if (type.HasGenericParameters) {
List<AstType> typeArguments = new List<AstType>();
foreach (GenericParameter gp in type.GenericParameters) {
typeArguments.Add(new SimpleType(gp.Name));
}
ApplyTypeArgumentsTo(astType, typeArguments);
}
}
static void ApplyTypeArgumentsTo(AstType baseType, List<AstType> typeArguments)
{
SimpleType st = baseType as SimpleType;
if (st != null) {
st.TypeArguments.AddRange(typeArguments);
}
MemberType mt = baseType as MemberType;
if (mt != null) {
TypeReference type = mt.Annotation<TypeReference>();
if (type != null) {
int typeParameterCount;
ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
if (typeParameterCount > typeArguments.Count)
typeParameterCount = typeArguments.Count;
mt.TypeArguments.AddRange(typeArguments.GetRange(typeArguments.Count - typeParameterCount, typeParameterCount));
typeArguments.RemoveRange(typeArguments.Count - typeParameterCount, typeParameterCount);
if (typeArguments.Count > 0)
ApplyTypeArgumentsTo(mt.Target, typeArguments);
} else {
mt.TypeArguments.AddRange(typeArguments);
}
}
}
const string DynamicAttributeFullName = "System.Runtime.CompilerServices.DynamicAttribute";
static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex)
{
if (attributeProvider == null || !attributeProvider.HasCustomAttributes)
return false;
foreach (CustomAttribute a in attributeProvider.CustomAttributes) {
if (a.Constructor.DeclaringType.FullName == DynamicAttributeFullName) {
if (a.ConstructorArguments.Count == 1) {
CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[];
if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool)
return (bool)values[typeIndex].Value;
}
return true;
}
}
return false;
}
#endregion
}
[Flags]
public enum ConvertTypeOptions
{
None = 0,
IncludeNamespace = 1,
IncludeTypeParameterDefinitions = 2,
DoNotUsePrimitiveTypeNames = 4
}
}

47
ILSpy/Languages/CSharpLanguage.cs

@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy @@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy
bool showAllMembers = false;
int transformCount = int.MaxValue;
#if DEBUG
#if DEBUG
internal static IEnumerable<CSharpLanguage> GetDebugLanguages()
{
var decompiler = new CSharpDecompiler(ModuleDefinition.CreateModule("Dummy", ModuleKind.Dll), new DecompilerSettings());
@ -70,20 +70,17 @@ namespace ICSharpCode.ILSpy @@ -70,20 +70,17 @@ namespace ICSharpCode.ILSpy
showAllMembers = true
};
}
#endif
#endif
public override string Name
{
public override string Name {
get { return name; }
}
public override string FileExtension
{
public override string FileExtension {
get { return ".cs"; }
}
public override string ProjectFileExtension
{
public override string ProjectFileExtension {
get { return ".csproj"; }
}
@ -95,7 +92,7 @@ namespace ICSharpCode.ILSpy @@ -95,7 +92,7 @@ namespace ICSharpCode.ILSpy
decompiler.AstTransforms.RemoveAt(decompiler.AstTransforms.Count - 1);
return decompiler;
}
void WriteCode(ITextOutput output, DecompilerSettings settings, SyntaxTree syntaxTree, IDecompilerTypeSystem typeSystem)
{
syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
@ -103,7 +100,7 @@ namespace ICSharpCode.ILSpy @@ -103,7 +100,7 @@ namespace ICSharpCode.ILSpy
var formattingPolicy = settings.CSharpFormattingOptions;
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(outputFormatter, formattingPolicy));
}
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
AddReferenceWarningMessage(method.Module.Assembly, output);
@ -117,11 +114,11 @@ namespace ICSharpCode.ILSpy @@ -117,11 +114,11 @@ namespace ICSharpCode.ILSpy
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(method), decompiler.TypeSystem);
}
}
class SelectCtorTransform : IAstTransform
{
readonly IMethod ctor;
public SelectCtorTransform(IMethod ctor)
{
this.ctor = ctor;
@ -197,7 +194,7 @@ namespace ICSharpCode.ILSpy @@ -197,7 +194,7 @@ namespace ICSharpCode.ILSpy
sealed class SelectFieldTransform : IAstTransform
{
readonly IField field;
public SelectFieldTransform(IField field)
{
this.field = field;
@ -328,7 +325,7 @@ namespace ICSharpCode.ILSpy @@ -328,7 +325,7 @@ namespace ICSharpCode.ILSpy
output.WriteLine("// Runtime: " + runtimeName);
}
output.WriteLine();
// don't automatically load additional assemblies when an assembly node is selected in the tree view
using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad()) {
CSharpDecompiler decompiler = new CSharpDecompiler(assembly.ModuleDefinition, options.DecompilerSettings);
@ -343,25 +340,25 @@ namespace ICSharpCode.ILSpy @@ -343,25 +340,25 @@ namespace ICSharpCode.ILSpy
}
}
}
class ILSpyWholeProjectDecompiler : WholeProjectDecompiler
{
readonly LoadedAssembly assembly;
readonly DecompilationOptions options;
public ILSpyWholeProjectDecompiler(LoadedAssembly assembly, DecompilationOptions options)
{
this.assembly = assembly;
this.options = options;
base.Settings = options.DecompilerSettings;
}
protected override IEnumerable<Tuple<string, string>> WriteResourceToFile(string fileName, string resourceName, Stream entryStream)
{
if (fileName.EndsWith(".resource", StringComparison.OrdinalIgnoreCase)) {
using (ResourceReader reader = new ResourceReader(entryStream))
using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write))
using (ResXResourceWriter writer = new ResXResourceWriter(fs)) {
using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write))
using (ResXResourceWriter writer = new ResXResourceWriter(fs)) {
foreach (DictionaryEntry entry in reader) {
writer.AddResource((string)entry.Key, entry.Value);
}
@ -395,6 +392,7 @@ namespace ICSharpCode.ILSpy @@ -395,6 +392,7 @@ namespace ICSharpCode.ILSpy
Settings = settings
});
}
*/
public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes = null)
{
@ -407,7 +405,7 @@ namespace ICSharpCode.ILSpy @@ -407,7 +405,7 @@ namespace ICSharpCode.ILSpy
string TypeToString(ConvertTypeOptions options, TypeReference type, ICustomAttributeProvider typeAttributes = null)
{
AstType astType = AstBuilder.ConvertType(type, typeAttributes, options);
AstType astType = CSharpDecompiler.ConvertType(type, typeAttributes, options);
StringWriter w = new StringWriter();
if (type.IsByReference) {
@ -424,9 +422,9 @@ namespace ICSharpCode.ILSpy @@ -424,9 +422,9 @@ namespace ICSharpCode.ILSpy
astType.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
return w.ToString();
}
static readonly CSharpFormattingOptions TypeToStringFormattingOptions = FormattingOptionsFactory.CreateEmpty();
*/
public override string FormatPropertyName(PropertyDefinition property, bool? isIndexer)
{
if (property == null)
@ -466,15 +464,14 @@ namespace ICSharpCode.ILSpy @@ -466,15 +464,14 @@ namespace ICSharpCode.ILSpy
return (method.IsConstructor) ? method.DeclaringType.Name : method.Name;
}
/*
public override string FormatTypeName(TypeDefinition type)
{
if (type == null)
throw new ArgumentNullException("type");
return TypeToString(ConvertTypeOptions.DoNotUsePrimitiveTypeNames | ConvertTypeOptions.IncludeTypeParameterDefinitions, type);
}
*/
public override bool ShowMember(MemberReference member)
{
return showAllMembers || !CSharpDecompiler.MemberIsHidden(member, new DecompilationOptions().DecompilerSettings);

Loading…
Cancel
Save