Ejemplo n.º 1
0
        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;
        }
Ejemplo n.º 2
0
        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;
        }