Browse Source

Reimplement CSharpLanguage.TypeToString

pull/863/head
Siegfried Pammer 8 years ago
parent
commit
206497e6c1
  1. 201
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 25
      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
}
}

25
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"; }
}
@ -360,8 +357,8 @@ namespace ICSharpCode.ILSpy @@ -360,8 +357,8 @@ namespace ICSharpCode.ILSpy
{
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,8 +422,8 @@ namespace ICSharpCode.ILSpy @@ -424,8 +422,8 @@ 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)
{
@ -466,7 +464,6 @@ namespace ICSharpCode.ILSpy @@ -466,7 +464,6 @@ namespace ICSharpCode.ILSpy
return (method.IsConstructor) ? method.DeclaringType.Name : method.Name;
}
/*
public override string FormatTypeName(TypeDefinition type)
{
if (type == null)
@ -474,7 +471,7 @@ namespace ICSharpCode.ILSpy @@ -474,7 +471,7 @@ namespace ICSharpCode.ILSpy
return TypeToString(ConvertTypeOptions.DoNotUsePrimitiveTypeNames | ConvertTypeOptions.IncludeTypeParameterDefinitions, type);
}
*/
public override bool ShowMember(MemberReference member)
{
return showAllMembers || !CSharpDecompiler.MemberIsHidden(member, new DecompilationOptions().DecompilerSettings);

Loading…
Cancel
Save