public override TypeNode VisitTypeReference(TypeNode type) { if (type == null) return null; TypeNode dup = (TypeNode)this.DuplicateFor[type.UniqueKey]; if (dup != null && (dup.Template != type || this.RecordOriginalAsTemplate)) return dup; switch (type.NodeType) { case NodeType.ArrayType: ArrayType arrType = (ArrayType)type; TypeNode elemType = this.VisitTypeReference(arrType.ElementType); if (elemType == arrType.ElementType) return arrType; if (elemType == null) { Debug.Fail(""); return null; } this.TypesToBeDuplicated[arrType.UniqueKey] = arrType; dup = elemType.GetArrayType(arrType.Rank, arrType.Sizes, arrType.LowerBounds); break; case NodeType.ClassParameter: case NodeType.TypeParameter: if (this.RecordOriginalAsTemplate) return type; if (this.TypesToBeDuplicated[type.UniqueKey] == null) return type; dup = this.VisitTypeNode(type); break; case NodeType.DelegateNode: { FunctionType ftype = type as FunctionType; if (ftype == null) goto default; dup = FunctionType.For(this.VisitTypeReference(ftype.ReturnType), this.VisitParameterList(ftype.Parameters), this.TargetType); break; } case NodeType.Pointer: Pointer pType = (Pointer)type; elemType = this.VisitTypeReference(pType.ElementType); if (elemType == pType.ElementType) return pType; if (elemType == null) { Debug.Fail(""); return null; } dup = elemType.GetPointerType(); break; case NodeType.Reference: Reference rType = (Reference)type; elemType = this.VisitTypeReference(rType.ElementType); if (elemType == rType.ElementType) return rType; if (elemType == null) { Debug.Fail(""); return null; } dup = elemType.GetReferenceType(); break; //These types typically have only one reference and do not have pointer identity. Just duplicate them. case NodeType.ArrayTypeExpression: ArrayTypeExpression aExpr = (ArrayTypeExpression)type.Clone(); elemType = this.VisitTypeReference(aExpr.ElementType); if (elemType == null) { Debug.Fail(""); return aExpr; } aExpr.ElementType = elemType; return aExpr; case NodeType.BoxedTypeExpression: BoxedTypeExpression bExpr = (BoxedTypeExpression)type.Clone(); bExpr.ElementType = this.VisitTypeReference(bExpr.ElementType); return bExpr; case NodeType.ClassExpression: ClassExpression cExpr = (ClassExpression)type.Clone(); cExpr.Expression = this.VisitExpression(cExpr.Expression); cExpr.TemplateArguments = this.VisitTypeReferenceList(cExpr.TemplateArguments); return cExpr; case NodeType.FlexArrayTypeExpression: FlexArrayTypeExpression flExpr = (FlexArrayTypeExpression)type.Clone(); flExpr.ElementType = this.VisitTypeReference(flExpr.ElementType); return flExpr; case NodeType.FunctionPointer: FunctionPointer funcPointer = (FunctionPointer)type.Clone(); funcPointer.ParameterTypes = this.VisitTypeReferenceList(funcPointer.ParameterTypes); funcPointer.ReturnType = this.VisitTypeReference(funcPointer.ReturnType); return funcPointer; case NodeType.FunctionTypeExpression: FunctionTypeExpression ftExpr = (FunctionTypeExpression)type.Clone(); ftExpr.Parameters = this.VisitParameterList(ftExpr.Parameters); ftExpr.ReturnType = this.VisitTypeReference(ftExpr.ReturnType); return ftExpr; case NodeType.InvariantTypeExpression: InvariantTypeExpression invExpr = (InvariantTypeExpression)type.Clone(); invExpr.ElementType = this.VisitTypeReference(invExpr.ElementType); return invExpr; case NodeType.InterfaceExpression: InterfaceExpression iExpr = (InterfaceExpression)type.Clone(); iExpr.Expression = this.VisitExpression(iExpr.Expression); iExpr.TemplateArguments = this.VisitTypeReferenceList(iExpr.TemplateArguments); return iExpr; case NodeType.NonEmptyStreamTypeExpression: NonEmptyStreamTypeExpression neExpr = (NonEmptyStreamTypeExpression)type.Clone(); neExpr.ElementType = this.VisitTypeReference(neExpr.ElementType); return neExpr; case NodeType.NonNullTypeExpression: NonNullTypeExpression nnExpr = (NonNullTypeExpression)type.Clone(); nnExpr.ElementType = this.VisitTypeReference(nnExpr.ElementType); return nnExpr; case NodeType.NonNullableTypeExpression: NonNullableTypeExpression nbExpr = (NonNullableTypeExpression)type.Clone(); nbExpr.ElementType = this.VisitTypeReference(nbExpr.ElementType); return nbExpr; case NodeType.NullableTypeExpression: NullableTypeExpression nuExpr = (NullableTypeExpression)type.Clone(); nuExpr.ElementType = this.VisitTypeReference(nuExpr.ElementType); return nuExpr; case NodeType.OptionalModifier: TypeModifier modType = (TypeModifier)type; TypeNode modified = this.VisitTypeReference(modType.ModifiedType); TypeNode modifier = this.VisitTypeReference(modType.Modifier); if (modified == null || modifier == null) { Debug.Fail(""); return null; } return OptionalModifier.For(modifier, modified); case NodeType.RequiredModifier: modType = (TypeModifier)type; modified = this.VisitTypeReference(modType.ModifiedType); modifier = this.VisitTypeReference(modType.Modifier); if (modified == null || modifier == null) { Debug.Fail(""); return null; } return RequiredModifier.For(modifier, modified); case NodeType.OptionalModifierTypeExpression: OptionalModifierTypeExpression optmodType = (OptionalModifierTypeExpression)type.Clone(); optmodType.ModifiedType = this.VisitTypeReference(optmodType.ModifiedType); optmodType.Modifier = this.VisitTypeReference(optmodType.Modifier); return optmodType; case NodeType.RequiredModifierTypeExpression: RequiredModifierTypeExpression reqmodType = (RequiredModifierTypeExpression)type.Clone(); reqmodType.ModifiedType = this.VisitTypeReference(reqmodType.ModifiedType); reqmodType.Modifier = this.VisitTypeReference(reqmodType.Modifier); return reqmodType; case NodeType.PointerTypeExpression: PointerTypeExpression pExpr = (PointerTypeExpression)type.Clone(); elemType = this.VisitTypeReference(pExpr.ElementType); if (elemType == null) { Debug.Fail(""); return pExpr; } pExpr.ElementType = elemType; return pExpr; case NodeType.ReferenceTypeExpression: ReferenceTypeExpression rExpr = (ReferenceTypeExpression)type.Clone(); elemType = this.VisitTypeReference(rExpr.ElementType); if (elemType == null) { Debug.Fail(""); return rExpr; } rExpr.ElementType = elemType; return rExpr; case NodeType.StreamTypeExpression: StreamTypeExpression sExpr = (StreamTypeExpression)type.Clone(); sExpr.ElementType = this.VisitTypeReference(sExpr.ElementType); return sExpr; case NodeType.TupleTypeExpression: TupleTypeExpression tuExpr = (TupleTypeExpression)type.Clone(); tuExpr.Domains = this.VisitFieldList(tuExpr.Domains); return tuExpr; case NodeType.TypeExpression: TypeExpression tExpr = (TypeExpression)type.Clone(); tExpr.Expression = this.VisitExpression(tExpr.Expression); tExpr.TemplateArguments = this.VisitTypeReferenceList(tExpr.TemplateArguments); return tExpr; case NodeType.TypeIntersectionExpression: TypeIntersectionExpression tiExpr = (TypeIntersectionExpression)type.Clone(); tiExpr.Types = this.VisitTypeReferenceList(tiExpr.Types); return tiExpr; case NodeType.TypeUnionExpression: TypeUnionExpression tyuExpr = (TypeUnionExpression)type.Clone(); tyuExpr.Types = this.VisitTypeReferenceList(tyuExpr.Types); return tyuExpr; default: if (type.Template != null && type.Template != type && (type.TemplateArguments != null || (!this.RecordOriginalAsTemplate && type.ConsolidatedTemplateArguments != null && type.ConsolidatedTemplateArguments.Count > 0))) { TypeNode templ = this.VisitTypeReference(type.Template); //^ assume templ != null; if (TargetPlatform.UseGenerics) { if (templ.Template != null) { if (this.RecordOriginalAsTemplate) templ = templ.Template; else templ = this.VisitTypeReference(templ.Template); //^ assume templ != null; } if (type.DeclaringType != null) { TypeNode declType = this.VisitTypeReference(type.DeclaringType); if (declType != null) { TypeNode templDup = declType.GetNestedType(templ.Name); if (templDup == null) { //Can happen when templ is nested in a type that is still being duplicated templDup = (TypeNode)templ.Clone(); templDup.DeclaringModule = this.TargetModule; templDup.Template = templ; declType.NestedTypes.Add(templDup); templ = templDup; } else { templ = templDup; if (templ.Template != null) { if (this.RecordOriginalAsTemplate) templ = templ.Template; else { if (templ.Template.DeclaringType == null) templ.Template.DeclaringType = templ.DeclaringType.Template; templ = this.VisitTypeReference(templ.Template); } //^ assume templ != null; } } } } } else { if (templ.Template != null) return type; } bool duplicateReference = templ != type.Template; TypeNodeList targs = type.TemplateArguments == null ? new TypeNodeList() : new TypeNodeList(type.TemplateArguments); if(!this.RecordOriginalAsTemplate) targs = type.ConsolidatedTemplateArguments == null ? new TypeNodeList() : new TypeNodeList(type.ConsolidatedTemplateArguments); for(int i = 0, n = targs == null ? 0 : targs.Count; i < n; i++) { TypeNode targ = targs[i]; if(targ == null) continue; // !EFW - Okay, this is a REALLY ugly hack but I couldn't think of any other way // around it. If a type contains a nested type that itself implements a nested // type from within the containing type (still with me?), this gets into an // endless loop and eventually overflows the stack. As with the other case // similar to this (Nodes.cs), I'm assuming 20 levels of recursion is enough of // an indication that we've hit the problem. In this case, if it hits the // maximum level, we'll just return the current type. This seems to work okay. // // The abbreviated example: // // public abstract partial class MyClass<TD, TT> // { // public interface IBase // { // NestedClass<T> RequestElementsTyped<T>(); // } // // public class NestedClass<T> : IEquatable<NestedClass<T>> // { // public bool Equals(NestedClass<T> other) // { // throw new NotImplementedException(); // } // } // // public interface IAnother : IBase { } //} // if(recursionCounter > 20) return type; recursionCounter++; TypeNode targDup = this.VisitTypeReference(targ); recursionCounter--; if(targ != targDup) duplicateReference = true; targs[i] = targDup; } if(!duplicateReference) return type; if(!this.RecordOriginalAsTemplate) dup = templ.GetGenericTemplateInstance(this.TargetModule, targs); else dup = templ.GetTemplateInstance(this.TargetModule, this.TargetType, type.DeclaringType, targs); this.DuplicateFor[type.UniqueKey] = dup; return dup; } if (this.TypesToBeDuplicated[type.UniqueKey] == null) return type; TypeNode savedTargetType = this.TargetType; TypeNode declaringType = this.VisitTypeReference(type.DeclaringType); if (declaringType != null) { dup = (TypeNode)this.DuplicateFor[type.UniqueKey]; if (dup != null) return dup; if (declaringType == type.DeclaringType) { //Trying to duplicate a nested type into a type that is not the duplicate of the declaring type. //In this case, type is being duplicated into the original target type. declaringType = this.OriginalTargetType; } } this.TargetType = declaringType; dup = (TypeNode)this.Visit(type); this.TargetType = savedTargetType; break; } this.DuplicateFor[type.UniqueKey] = dup; return dup; }
internal TypeNode VisitTypeNode(TypeNode type, Identifier mangledName, TypeNodeList templateArguments, TypeNode template, bool delayVisitToNestedTypes) { if (type == null) return null; TypeNode dup = (TypeNode)this.DuplicateFor[type.UniqueKey]; if (dup != null) return dup; this.DuplicateFor[type.UniqueKey] = dup = (TypeNode)type.Clone(); if (mangledName != null) { this.TargetModule.StructurallyEquivalentType[mangledName.UniqueIdKey] = dup; dup.TemplateArguments = templateArguments; } dup.arrayTypes = null; dup.constructors = null; dup.consolidatedTemplateArguments = null; dup.consolidatedTemplateParameters = null; #if DEBUG dup.DebugLabel = null; #endif dup.DocumentationId = null; if (this.CopyDocumentation) dup.Documentation = type.Documentation; dup.defaultMembers = null; dup.explicitCoercionFromTable = null; dup.explicitCoercionMethods = null; dup.implicitCoercionFromTable = null; dup.implicitCoercionMethods = null; dup.implicitCoercionToTable = null; dup.memberCount = 0; dup.memberTable = null; dup.modifierTable = null; dup.NestedTypes = null; dup.pointerType = null; dup.ProviderHandle = null; dup.ProvideTypeAttributes = null; dup.ProvideTypeMembers = null; dup.ProvideNestedTypes = null; dup.referenceType = null; dup.runtimeType = null; dup.structurallyEquivalentMethod = null; TypeParameter tp = dup as TypeParameter; if (tp != null) tp.structuralElementTypes = null; ClassParameter cp = dup as ClassParameter; if (cp != null) cp.structuralElementTypes = null; dup.szArrayTypes = null; if (this.RecordOriginalAsTemplate) dup.Template = type; dup.TemplateArguments = null; dup.TemplateInstances = null; dup.DeclaringModule = this.TargetModule; dup.DeclaringType = this.TargetType; TypeNode savedTargetType = this.TargetType; this.TargetType = dup; dup.Attributes = this.VisitAttributeList(type.Attributes); dup.SecurityAttributes = this.VisitSecurityAttributeList(type.SecurityAttributes); Class c = dup as Class; if (c != null) c.BaseClass = (Class)this.VisitTypeReference(c.BaseClass); dup.Interfaces = this.VisitInterfaceReferenceList(dup.Interfaces); dup.TemplateParameters = this.VisitTypeReferenceList(type.TemplateParameters); dup.consolidatedTemplateParameters = null; if (dup is MethodScope) dup.members = this.VisitMemberList(type.members); else if (!this.RecordOriginalAsTemplate) { if (!delayVisitToNestedTypes) dup.nestedTypes = this.VisitNestedTypes(dup, type.NestedTypes); dup.members = null; dup.ProvideTypeMembers = new TypeNode.TypeMemberProvider(this.ProvideTypeMembers); dup.ProviderHandle = type; } else { dup.members = null; dup.ProvideNestedTypes = new TypeNode.NestedTypeProvider(this.ProvideNestedTypes); dup.ProvideTypeMembers = new TypeNode.TypeMemberProvider(this.ProvideTypeMembers); dup.ProviderHandle = type; } DelegateNode delegateNode = dup as DelegateNode; if (delegateNode != null) { if (!delegateNode.IsNormalized || !this.RecordOriginalAsTemplate) { if (!delegateNode.IsNormalized) ((DelegateNode)type).ProvideMembers(); delegateNode.Parameters = this.VisitParameterList(delegateNode.Parameters); delegateNode.ReturnType = this.VisitTypeReference(delegateNode.ReturnType); } else { delegateNode.Parameters = null; delegateNode.ReturnType = null; } } dup.membersBeingPopulated = false; this.TargetType = savedTargetType; return dup; }