public static TypeNode GetTemplateType(TypeNode type) { if (type == null) { throw new ArgumentNullException("type"); } // Console.WriteLine(type.FullName); // only generic types have templates if (!type.IsGeneric) { return(type); } if (type.DeclaringType == null) { // if the type is not nested, life is simpler // if the type is not specified, the type is the template if (type.TemplateArguments == null) { return(type); } // otherwise, construct the template type identifier and use it to fetch the template type Module templateModule = type.DeclaringModule; Identifier name = new Identifier(String.Format("{0}`{1}", type.GetUnmangledNameWithoutTypeParameters(), type.TemplateArguments.Count)); Identifier space = type.Namespace; TypeNode template = templateModule.GetType(space, name); return(template); } else { // if the type is nested, life is harder; we have to walk up the chain, constructing // un-specialized identifiers as we go, then walk back down the chain, fetching // template types as we go // create a stack to keep track of identifiers Stack <Identifier> identifiers = new Stack <Identifier>(); // populate the stack with the identifiers of all the types up to the outermost type TypeNode current = type; while (true) { int count = 0; if ((current.TemplateArguments != null) && (current.TemplateArguments.Count > count)) { count = current.TemplateArguments.Count; } if ((current.TemplateParameters != null) && (current.TemplateParameters.Count > count)) { count = current.TemplateParameters.Count; } TypeNodeList arguments = current.TemplateParameters; if (count == 0) { identifiers.Push(new Identifier(current.GetUnmangledNameWithoutTypeParameters())); } else { identifiers.Push(new Identifier(String.Format("{0}`{1}", current.GetUnmangledNameWithoutTypeParameters(), count))); } // Console.WriteLine("U {0} {1}", identifiers.Peek(), CountArguments(current)); if (current.DeclaringType == null) { break; } current = current.DeclaringType; } // fetch a TypeNode representing that outermost type Module module = current.DeclaringModule; Identifier space = current.Namespace; current = module.GetType(space, identifiers.Pop()); // move down the stack to the inner type we want while (identifiers.Count > 0) { current = (TypeNode)current.GetMembersNamed(identifiers.Pop())[0]; // Console.WriteLine("D {0} {1}", current.GetFullUnmangledNameWithTypeParameters(), CountArguments(current)); } // whew, finally we've got it return(current); } }
//===================================================================== /// <summary> /// Write out a type name /// </summary> /// <param name="type">The type for which to write out the name</param> /// <param name="sb">The string builder to which the name is written</param> private static void WriteType(TypeNode type, StringBuilder sb) { switch (type.NodeType) { case NodeType.ArrayType: ArrayType array = (ArrayType)type; WriteType(array.ElementType, sb); sb.Append("["); if (array.Rank > 1) { for (int i = 0; i < array.Rank; i++) { if (i > 0) { sb.Append(","); } sb.Append("0:"); } } sb.Append("]"); break; case NodeType.Reference: Reference reference = (Reference)type; WriteType(reference.ElementType, sb); sb.Append("@"); break; case NodeType.Pointer: Pointer pointer = (Pointer)type; WriteType(pointer.ElementType, sb); sb.Append("*"); break; case NodeType.OptionalModifier: TypeModifier optionalModifierClause = (TypeModifier)type; WriteType(optionalModifierClause.ModifiedType, sb); sb.Append("!"); WriteType(optionalModifierClause.Modifier, sb); break; case NodeType.RequiredModifier: TypeModifier requiredModifierClause = (TypeModifier)type; WriteType(requiredModifierClause.ModifiedType, sb); // !EFW - Skip writing out the modifier if it's an InAttribute. Not sure if this is the best // way to handle this so we'll have to wait and see. if (requiredModifierClause.Modifier.Name.Name != "InAttribute") { sb.Append("|"); WriteType(requiredModifierClause.Modifier, sb); } break; default: if (type.IsTemplateParameter) { ITypeParameter gtp = (ITypeParameter)type; if (gtp.DeclaringMember is TypeNode) { sb.Append("`"); } else if (gtp.DeclaringMember is Method) { sb.Append("``"); } else { throw new InvalidOperationException("Generic parameter not on type or method"); } sb.Append(gtp.ParameterListIndex); } else { // Namespace TypeNode declaringType = type.DeclaringType; if (declaringType != null) { // Names of nested types begin with outer type name WriteType(declaringType, sb); sb.Append("."); } else { // Otherwise just prefix with the namespace Identifier space = type.Namespace; if (space != null && !String.IsNullOrEmpty(space.Name)) { sb.Append(space.Name); sb.Append("."); } } // Name sb.Append(type.GetUnmangledNameWithoutTypeParameters()); // Generic parameters if (type.IsGeneric) { // Number of parameters TypeNodeList parameters = type.TemplateParameters; if (parameters != null) { sb.Append('`'); sb.Append(parameters.Count); } // Arguments TypeNodeList arguments = type.TemplateArguments; if (arguments != null && arguments.Count > 0) { sb.Append("{"); for (int i = 0; i < arguments.Count; i++) { if (i > 0) { sb.Append(","); } WriteType(arguments[i], sb); } sb.Append("}"); } } } break; } }
private static void WriteType(TypeNode type, TextWriter writer) { switch (type.NodeType) { case NodeType.ArrayType: ArrayType array = type as ArrayType; WriteType(array.ElementType, writer); writer.Write("["); if (array.Rank > 1) { for (int i = 0; i < array.Rank; i++) { if (i > 0) { writer.Write(","); } writer.Write("0:"); } } writer.Write("]"); break; case NodeType.Reference: Reference reference = type as Reference; TypeNode referencedType = reference.ElementType; WriteType(referencedType, writer); writer.Write("@"); break; case NodeType.Pointer: Pointer pointer = type as Pointer; WriteType(pointer.ElementType, writer); writer.Write("*"); break; case NodeType.OptionalModifier: TypeModifier optionalModifierClause = type as TypeModifier; WriteType(optionalModifierClause.ModifiedType, writer); writer.Write("!"); WriteType(optionalModifierClause.Modifier, writer); break; case NodeType.RequiredModifier: TypeModifier requiredModifierClause = type as TypeModifier; WriteType(requiredModifierClause.ModifiedType, writer); writer.Write("|"); WriteType(requiredModifierClause.Modifier, writer); break; default: if (type.IsTemplateParameter) { ITypeParameter gtp = (ITypeParameter)type; if (gtp.DeclaringMember is TypeNode) { writer.Write("`"); } else if (gtp.DeclaringMember is Method) { writer.Write("``"); } else { throw new InvalidOperationException("Generic parameter not on type or method."); } writer.Write(gtp.ParameterListIndex); } else { // namespace TypeNode declaringType = type.DeclaringType; if (declaringType != null) { // names of nested types begin with outer type name WriteType(declaringType, writer); writer.Write("."); } else { // otherwise just prepend the namespace Identifier space = type.Namespace; if ((space != null) && !String.IsNullOrEmpty(space.Name)) { //string space = type.Namespace.Name; //if (space != null && space.Length > 0) { writer.Write(space.Name); writer.Write("."); } } // name writer.Write(type.GetUnmangledNameWithoutTypeParameters()); // generic parameters if (type.IsGeneric) { // number of parameters TypeNodeList parameters = type.TemplateParameters; if (parameters != null) { writer.Write("`{0}", parameters.Count); } // arguments TypeNodeList arguments = type.TemplateArguments; if ((arguments != null) && (arguments.Count > 0)) { writer.Write("{"); for (int i = 0; i < arguments.Count; i++) { TypeNode argument = arguments[i]; if (i > 0) { writer.Write(","); } WriteType(arguments[i], writer); } writer.Write("}"); } } } break; } }
/// <summary> /// Get the template type for the given type /// </summary> /// <param name="type">The type for which to get the template type</param> /// <returns>The type itself if it is not generic or the template type if it is</returns> public static TypeNode GetTemplateType(this TypeNode type) { if (type == null) { throw new ArgumentNullException("type"); } // Only generic types have templates if (!type.IsGeneric) { return(type); } // If the type is not nested, life is simpler. if (type.DeclaringType == null) { // If the type is not specified, the type is the template if (type.TemplateArguments == null) { return(type); } // Otherwise, construct the template type identifier and use it to fetch the template type Identifier name = new Identifier(String.Format(CultureInfo.InvariantCulture, "{0}`{1}", type.GetUnmangledNameWithoutTypeParameters(), type.TemplateArguments.Count)); TypeNode template = type.DeclaringModule.GetType(type.Namespace, name); // !EFW - Added by ComponentOne if (template == null) { template = type; } return(template); } // If the type is nested, life is harder. We have to walk up the chain, constructing unspecialized // identifiers as we go, then walk back down the chain, fetching template types as we go. // Create a stack to keep track of identifiers Stack <Identifier> identifiers = new Stack <Identifier>(); // Populate the stack with the identifiers of all the types up to the outermost type TypeNode current = type; while (true) { int count = 0; if (current.TemplateArguments != null && current.TemplateArguments.Count > count) { count = current.TemplateArguments.Count; } if (current.TemplateParameters != null && current.TemplateParameters.Count > count) { count = current.TemplateParameters.Count; } if (count == 0) { identifiers.Push(new Identifier(current.GetUnmangledNameWithoutTypeParameters())); } else { identifiers.Push(new Identifier(String.Format(CultureInfo.InvariantCulture, "{0}`{1}", current.GetUnmangledNameWithoutTypeParameters(), count))); } if (current.DeclaringType == null) { break; } current = current.DeclaringType; } // Fetch a TypeNode representing the outermost type current = current.DeclaringModule.GetType(current.Namespace, identifiers.Pop()); // Move down the stack to the inner type we want while (identifiers.Count > 0 && current != null) { current = (TypeNode)current.GetMembersNamed(identifiers.Pop()).FirstOrDefault(); } // !EFW - Added by ComponentOne if (current == null) { return(type); } // Whew, finally we've got it return(current); }
//===================================================================== /// <summary> /// Write out a type name /// </summary> /// <param name="type">The type for which to write out the name</param> /// <param name="sb">The string builder to which the name is written</param> private static void WriteType(TypeNode type, StringBuilder sb) { switch (type.NodeType) { case NodeType.ArrayType: ArrayType array = (ArrayType)type; WriteType(array.ElementType, sb); sb.Append('['); if (array.Rank > 1) { for (int i = 0; i < array.Rank; i++) { if (i > 0) { sb.Append(','); } sb.Append("0:"); } } sb.Append(']'); break; case NodeType.Reference: Reference reference = (Reference)type; WriteType(reference.ElementType, sb); sb.Append('@'); break; case NodeType.Pointer: Pointer pointer = (Pointer)type; WriteType(pointer.ElementType, sb); sb.Append('*'); break; case NodeType.OptionalModifier: TypeModifier optionalModifierClause = (TypeModifier)type; WriteType(optionalModifierClause.ModifiedType, sb); sb.Append('!'); WriteType(optionalModifierClause.Modifier, sb); break; case NodeType.RequiredModifier: TypeModifier requiredModifierClause = (TypeModifier)type; WriteType(requiredModifierClause.ModifiedType, sb); sb.Append('|'); WriteType(requiredModifierClause.Modifier, sb); break; default: if (type.IsTemplateParameter) { ITypeParameter gtp = (ITypeParameter)type; if (gtp.DeclaringMember is TypeNode) { sb.Append('`'); } else if (gtp.DeclaringMember is Method) { sb.Append("``"); } else { throw new InvalidOperationException("Generic parameter not on type or method"); } sb.Append(gtp.ParameterListIndex); } else { // Namespace TypeNode declaringType = type.DeclaringType; if (declaringType != null) { // Names of nested types begin with outer type name WriteType(declaringType, sb); sb.Append('.'); } else { // Otherwise just prefix with the namespace Identifier space = type.Namespace; if (space != null && !String.IsNullOrEmpty(space.Name)) { sb.Append(space.Name); sb.Append('.'); } } // Name sb.Append(type.GetUnmangledNameWithoutTypeParameters()); RenameTypeIfNecessary(sb); // Generic parameters if (type.IsGeneric) { // Number of parameters TypeNodeList parameters = type.TemplateParameters; if (parameters != null) { sb.Append('`'); sb.Append(parameters.Count); } // Arguments TypeNodeList arguments = type.TemplateArguments; if (arguments != null && arguments.Count > 0) { sb.Append('{'); for (int i = 0; i < arguments.Count; i++) { if (i > 0) { sb.Append(','); } WriteType(arguments[i], sb); } sb.Append('}'); } } } break; } }