Browse Source

Add TypeSystemAstBuilder.ConvertAttributeType, which deals with all the special cases when referring to attribute types in attribute context.

pull/1213/head
Siegfried Pammer 7 years ago
parent
commit
c7c3801ff1
  1. 120
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  2. 11
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs

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

@ -227,7 +227,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} else if (typeWithElementType is ByReferenceType) {
return ConvertType(typeWithElementType.ElementType).MakeRefType();
} else {
// e.g. ByReferenceType; not supported as type in C#
// not supported as type in C#
return ConvertType(typeWithElementType.ElementType);
}
}
@ -324,9 +324,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
// Handle top-level types
if (string.IsNullOrEmpty(genericType.Namespace)) {
result.Target = new SimpleType("global");
if (AddResolveResultAnnotations)
result.Target.AddAnnotation(new NamespaceResolveResult(resolver.Compilation.RootNamespace));
result.IsDoubleColon = true;
} else {
result.Target = ConvertNamespace(genericType.Namespace);
result.Target = ConvertNamespace(genericType.Namespace, out _);
}
}
result.MemberName = genericType.Name;
@ -377,16 +379,20 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
public AstType ConvertNamespace(string namespaceName)
public AstType ConvertNamespace(string namespaceName, out NamespaceResolveResult nrr)
{
if (resolver != null) {
// Look if there's an alias to the target namespace
if (UseAliases) {
for (ResolvedUsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) {
foreach (var pair in usingScope.UsingAliases) {
NamespaceResolveResult nrr = pair.Value as NamespaceResolveResult;
if (nrr != null && nrr.NamespaceName == namespaceName)
return new SimpleType(pair.Key);
nrr = pair.Value as NamespaceResolveResult;
if (nrr != null && nrr.NamespaceName == namespaceName) {
var ns = new SimpleType(pair.Key);
if (AddResolveResultAnnotations)
ns.AddAnnotation(nrr);
return ns;
}
}
}
}
@ -394,30 +400,52 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
int pos = namespaceName.LastIndexOf('.');
if (pos < 0) {
if (IsValidNamespace(namespaceName)) {
return new SimpleType(namespaceName);
if (IsValidNamespace(namespaceName, out nrr)) {
var ns = new SimpleType(namespaceName);
if (AddResolveResultAnnotations && nrr != null)
ns.AddAnnotation(nrr);
return ns;
} else {
return new MemberType {
Target = new SimpleType("global"),
var target = new SimpleType("global");
if (AddResolveResultAnnotations)
target.AddAnnotation(new NamespaceResolveResult(resolver.Compilation.RootNamespace));
var ns = new MemberType {
Target = target,
IsDoubleColon = true,
MemberName = namespaceName
};
if (AddResolveResultAnnotations) {
var @namespace = resolver.Compilation.RootNamespace.GetChildNamespace(namespaceName);
if (@namespace != null)
ns.AddAnnotation(nrr = new NamespaceResolveResult(@namespace));
}
return ns;
}
} else {
string parentNamespace = namespaceName.Substring(0, pos);
string localNamespace = namespaceName.Substring(pos + 1);
return new MemberType {
Target = ConvertNamespace(parentNamespace),
var parentNS = ConvertNamespace(parentNamespace, out var parentNRR);
var ns = new MemberType {
Target = parentNS,
MemberName = localNamespace
};
nrr = null;
if (AddResolveResultAnnotations && parentNRR != null) {
var newNamespace = parentNRR.Namespace.GetChildNamespace(localNamespace);
if (newNamespace != null) {
ns.AddAnnotation(nrr = new NamespaceResolveResult(newNamespace));
}
}
return ns;
}
}
bool IsValidNamespace(string firstNamespacePart)
bool IsValidNamespace(string firstNamespacePart, out NamespaceResolveResult nrr)
{
nrr = null;
if (resolver == null)
return true; // just assume namespaces are valid if we don't have a resolver
NamespaceResolveResult nrr = resolver.ResolveSimpleName(firstNamespacePart, EmptyList<IType>.Instance) as NamespaceResolveResult;
nrr = resolver.ResolveSimpleName(firstNamespacePart, EmptyList<IType>.Instance) as NamespaceResolveResult;
return nrr != null && !nrr.IsError && nrr.NamespaceName == firstNamespacePart;
}
#endregion
@ -447,6 +475,70 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
#endregion
#region Convert Attribute Type
public AstType ConvertAttributeType(IType type)
{
if (type == null)
throw new ArgumentNullException("type");
AstType astType = ConvertTypeHelper(type);
string shortName = null;
if (type.Name.Length > 9 && type.Name.EndsWith("Attribute", StringComparison.Ordinal)) {
shortName = type.Name.Remove(type.Name.Length - 9);
}
switch (astType) {
case SimpleType st:
ResolveResult shortRR = null;
ResolveResult withExtraAttrSuffix = resolver.LookupSimpleNameOrTypeName(type.Name + "Attribute", EmptyList<IType>.Instance, NameLookupMode.Type);
if (shortName != null) {
shortRR = resolver.LookupSimpleNameOrTypeName(shortName, EmptyList<IType>.Instance, NameLookupMode.Type);
}
// short type is either unknown or not an attribute type -> we can use the short name.
if (shortRR != null && (shortRR is UnknownIdentifierResolveResult || !IsAttributeType(shortRR))) {
st.Identifier = shortName;
} else if (IsAttributeType(withExtraAttrSuffix)) {
// typeName + "Attribute" is an attribute type -> we cannot use long type name, add '@' to disable implicit "Attribute" suffix.
st.Identifier = '@' + st.Identifier;
}
break;
case MemberType mt:
if (type.DeclaringType != null) {
var declaringTypeDef = type.DeclaringType.GetDefinition();
if (declaringTypeDef != null) {
if (shortName != null && !declaringTypeDef.GetNestedTypes(t => t.TypeParameterCount == 0 && t.Name == shortName).Any(IsAttributeType)) {
mt.MemberName = shortName;
} else if (declaringTypeDef.GetNestedTypes(t => t.TypeParameterCount == 0 && t.Name == type.Name + "Attribute").Any(IsAttributeType)) {
mt.MemberName = '@' + mt.MemberName;
}
}
} else if (mt.Target.GetResolveResult() is NamespaceResolveResult nrr) {
if (shortName != null && !IsAttributeType(nrr.Namespace.GetTypeDefinition(shortName, 0))) {
mt.MemberName = shortName;
} else if (IsAttributeType(nrr.Namespace.GetTypeDefinition(type.Name + "Attribute", 0))) {
mt.MemberName = '@' + mt.MemberName;
}
}
break;
}
if (AddTypeReferenceAnnotations)
astType.AddAnnotation(type);
if (AddResolveResultAnnotations)
astType.AddAnnotation(new TypeResolveResult(type));
return astType;
}
private bool IsAttributeType(IType type)
{
return type != null && type.GetNonInterfaceBaseTypes().Any(t => t.IsKnownType(KnownTypeCode.Attribute));
}
private bool IsAttributeType(ResolveResult rr)
{
return rr is TypeResolveResult trr && IsAttributeType(trr.Type);
}
#endregion
#region Convert Constant Value
/// <summary>
/// Creates an Expression for the given constant value.

11
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs

@ -200,11 +200,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
base.VisitSimpleType(simpleType);
return;
}
// HACK : ignore type names in attributes (TypeSystemAstBuilder doesn't handle them correctly)
if (simpleType.Parent is Syntax.Attribute) {
base.VisitSimpleType(simpleType);
return;
}
astBuilder.NameLookupMode = simpleType.GetNameLookupMode();
if (astBuilder.NameLookupMode == NameLookupMode.Type) {
AstType outermostType = simpleType;
@ -217,7 +212,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
astBuilder.NameLookupMode = NameLookupMode.Expression;
}
}
simpleType.ReplaceWith(astBuilder.ConvertType(rr.Type));
if (simpleType.Parent is Syntax.Attribute) {
simpleType.ReplaceWith(astBuilder.ConvertAttributeType(rr.Type));
} else {
simpleType.ReplaceWith(astBuilder.ConvertType(rr.Type));
}
}
}
}

Loading…
Cancel
Save