public static List <ITypeDefinitionMember> FindRelatedExternalMembers(ITypeDefinitionMember member, CanIncludeCheck canInclude) { List <ITypeDefinitionMember> relatedMembers = new List <ITypeDefinitionMember>(); Dictionary <uint, ITypeReference> participatingTypes = new Dictionary <uint, ITypeReference>(); ITypeDefinition currentType = member.ContainingTypeDefinition; do { // // add the type // if (!canInclude(Util.CanonicalizeTypeReference(currentType))) { participatingTypes.Add(currentType.InternedKey, currentType); } // // add any interfaces it implements that are part of the closure // foreach (ITypeReference iface in currentType.Interfaces) { INamedTypeReference ifaceTemplate = Util.CanonicalizeTypeReference(iface); // check the closure against the template type, but add // the specialized type to participatingTypes so that // argument matching works if (!canInclude(ifaceTemplate) && !participatingTypes.ContainsKey(iface.InternedKey)) { // Should we add ifaceTemplate or iface? participatingTypes.Add(iface.InternedKey, iface); } } // // go up to the base type // currentType = TypeHelper.BaseClass(currentType); }while (currentType != null); foreach (ITypeReference type in participatingTypes.Values) { ITypeDefinitionMember relatedMember = FindRelatedMember(type, member); if (null != relatedMember) { relatedMembers.Add(relatedMember); } } return(relatedMembers); }
private bool ShouldHideMember(ITypeDefinitionMember member) { bool shouldHide = false; INamedTypeDefinition type = Util.ContainingTypeDefinition(member); if (IsHiddenMemberCandidate(member)) { if (!TypeIsVisibleInApi(type)) { // Declaring type is hidden, only modify the visibility on a // member when its corresponding member on a public base type // was hidden. INamedTypeDefinition baseType = Util.CanonicalizeType(TypeHelper.BaseClass(type)); while (baseType != null && baseType != Dummy.Type) { if (TypeIsVisibleInApi(baseType)) { ITypeDefinitionMember relatedMember = Util.FindRelatedMember(baseType, member); if (relatedMember != null) { ITypeDefinitionMember canonicalizedRelatedMember = Util.CanonicalizeMember(relatedMember); if (_depot.ContainsMember(canonicalizedRelatedMember) && ShouldHideMember(canonicalizedRelatedMember)) { shouldHide = true; break; } } } baseType = Util.CanonicalizeType(TypeHelper.BaseClass(baseType)); } } else { // declaring type is public, we must hide the member. shouldHide = true; } } return(shouldHide); }
public static List <ITypeDefinitionMember> FindRelatedMembers(ITypeDefinitionMember member, TypeIncluded includeType) { List <ITypeDefinitionMember> relatedMembers = new List <ITypeDefinitionMember>(); Dictionary <uint, ITypeReference> participatingTypes = new Dictionary <uint, ITypeReference>(); ITypeDefinition currentType = member.ContainingTypeDefinition; do { // // add the type // participatingTypes.Add(currentType.InternedKey, currentType); // // add any interfaces it implements that are part of the closure // foreach (ITypeReference iface in currentType.Interfaces) { INamedTypeReference ifaceTemplate = Util.CanonicalizeTypeReference(iface); // check the closure against the template type, but add // the specialized type to participatingTypes so that // argument matching works if (includeType(ifaceTemplate) && !participatingTypes.ContainsKey(iface.InternedKey)) { // Should we add ifaceTemplate or iface? participatingTypes.Add(iface.InternedKey, iface); } } // // go up to the base type // currentType = TypeHelper.BaseClass(currentType); }while (currentType != null); foreach (ITypeReference type in participatingTypes.Values) { ITypeDefinitionMember relatedMember = FindRelatedMember(type, member); if (null != relatedMember) { relatedMembers.Add(relatedMember); } // TODO: Review foreach (IMethodImplementation methodImpl in Util.CanonicalizeType(type).ExplicitImplementationOverrides) { ITypeDefinitionMember implementingMethod = Util.CanonicalizeMember(methodImpl.ImplementingMethod); ITypeDefinitionMember implementedMethod = Util.CanonicalizeMember(methodImpl.ImplementedMethod); bool implementedTypeIncluded = includeType(Util.CanonicalizeType(implementedMethod.ContainingType)); if ((implementedMethod == member) || (implementingMethod == member && implementedTypeIncluded)) { if (!relatedMembers.Contains(implementingMethod)) { relatedMembers.Add(implementingMethod); } if (!relatedMembers.Contains(implementedMethod)) { relatedMembers.Add(implementedMethod); } } } } return(relatedMembers); }
// Special case: If closureStatus == ApiRoot this will automatically // convert it to ImplRoot for internal types // TODO: Visitor should set status instead of this. public ThinModel ExportModel(IncludeStatus closureStatus) { _closureStatus = closureStatus; int nApiTypes = 0; int nApiTypeForwarders = 0; int nApiMembers = 0; ThinModel thinModel = new ThinModel(_thinModel.Options); Dictionary <String, ThinAssembly> assemblies = new Dictionary <String, ThinAssembly>(_depot.AssembliesClosure.Count); Dictionary <INamedTypeDefinition, ThinType> types = new Dictionary <INamedTypeDefinition, ThinType>(_depot.TypesClosure.Count); foreach (IAssembly assembly in _depot.AssembliesClosure.Values) { ThinAssembly thinAsm = new ThinAssembly(_thinModel, assembly.Name.Value, GetIncludeStatus(assembly), assembly); thinModel.Assemblies.Add(thinAsm.Name, thinAsm); assemblies.Add(assembly.Name.Value, thinAsm); } foreach (INamedTypeDefinition type in _depot.TypesClosure.Values) { IAssembly asm = TypeHelper.GetDefiningUnit(type) as IAssembly; if (asm != null && assemblies.ContainsKey(asm.Name.Value)) { VisibilityOverride vis = VisibilityOverride.None; if (ShouldHideType(type)) { vis = VisibilityOverride.Internal; } if (closureStatus != IncludeStatus.ApiRoot) { if (TypeIsVisibleInApi(type)) { INamedTypeDefinition curType = type; while (curType != null && curType != Dummy.Type && // TODO: Remove dummy check? CanInclude(curType)) { if (WeHidThisType(curType)) { throw new Exception("API closure error! Base type " + curType + " was hidden, but " + type + " is in the public API"); } ITypeReference curTypeRef = TypeHelper.BaseClass(curType); curType = curTypeRef != null?Util.CanonicalizeType(curTypeRef) : null; } } } ThinAssembly declaringAssembly = assemblies[asm.Name.Value]; ThinType thinType = new ThinType(declaringAssembly, Util.FullyQualifiedTypeNameFromType(type), GetIncludeStatus(type), type, vis); declaringAssembly.Types.Add(thinType.Name, thinType); types.Add(type, thinType); if (thinType.IncludeStatus == IncludeStatus.ApiClosure || thinType.IncludeStatus == IncludeStatus.ApiRoot || thinType.IncludeStatus == IncludeStatus.ApiFxInternal) { nApiTypes++; } } else { Console.Error.WriteLine("BclRewriter : warning BR5004 : couldn't find declaring module of type {0} in closure", type); } } foreach (IAliasForType typeForwarder in _depot.TypeForwardersClosure.Values) { // TODO: Why is this getting an immutable copy of the assembly? IAssembly asm = Util.GetDefiningAssembly(typeForwarder); if (asm != null && assemblies.ContainsKey(asm.Name.Value)) { ThinAssembly declaringAssembly = assemblies[asm.Name.Value]; ITypeReference aliasedType = typeForwarder.AliasedType; ThinTypeForwarder thinTypeForwarder = new ThinTypeForwarder(declaringAssembly, Util.GetDefiningAssembly(aliasedType).Name.Value, Util.GetTypeName(aliasedType), GetIncludeStatus(typeForwarder), typeForwarder); declaringAssembly.TypeForwarders.Add(thinTypeForwarder.Key, thinTypeForwarder); if (thinTypeForwarder.IncludeStatus == IncludeStatus.ApiClosure || thinTypeForwarder.IncludeStatus == IncludeStatus.ApiRoot || thinTypeForwarder.IncludeStatus == IncludeStatus.ApiFxInternal) { nApiTypeForwarders++; } } else { Console.Error.WriteLine("BclRewriter : warning BR5001 : couldn't find declaring module of type forwarder {0} in closure", typeForwarder); } } foreach (ITypeDefinitionMember member in _depot.MembersClosure.Keys) { INamedTypeDefinition type = Util.ContainingTypeDefinition(member); if (types.ContainsKey(type)) { ThinType declaringType = types[type]; IncludeStatus status = GetIncludeStatus(member); VisibilityOverride vis = VisibilityOverride.None; if (ShouldHideMember(member)) { vis = VisibilityOverride.Internal; } if ((type.IsInterface) && TypeIsVisibleInApi(type) && vis == VisibilityOverride.Internal) { throw new Exception(string.Format("Implementation required non-public member on public interface: {0} on {1}. This usually means you added a property to model.xml without adding the corresponding getter or setter.", member.Name, Util.FullyQualifiedTypeNameFromType(member.ContainingType))); } ThinMember thinMember = new ThinMember(declaringType, member, status, vis); declaringType.Members.Add(thinMember.Key, thinMember); if (thinMember.IncludeStatus == IncludeStatus.ApiClosure || thinMember.IncludeStatus == IncludeStatus.ApiRoot || thinMember.IncludeStatus == IncludeStatus.ApiFxInternal) { nApiMembers++; } } else { Console.Error.WriteLine("BclRewriter : warning BR5002 : couldn't find declaring type of member {0} in closure", member); } } foreach (IMethodDefinition method in _depot.MethodsClosure.Values) { INamedTypeDefinition type = Util.ContainingTypeDefinition(method); if (types.ContainsKey(type)) { ThinType declaringType = types[type]; IncludeStatus status = GetIncludeStatus(method); VisibilityOverride vis = VisibilityOverride.None; if (ShouldHideMember(method)) { vis = VisibilityOverride.Internal; } if ((type.IsInterface) && TypeIsVisibleInApi(type) && vis == VisibilityOverride.Internal) { //throw new Exception(string.Format("WARNING: implementation required non-public member on public interface: {0} on {1}. This usually means you added a property to model.xml without adding the corresponding getter or setter.", // method.Name, // Util.FullyQualifiedTypeNameFromType(method.ContainingType))); } ThinMember thinMember = new ThinMember(declaringType, method, status, vis); if (declaringType.Members.ContainsKey(thinMember.Key)) { throw new Exception(String.Format("Found two members with the same signature: {0}", thinMember.Key)); } declaringType.Members.Add(thinMember.Key, thinMember); if (thinMember.IncludeStatus == IncludeStatus.ApiClosure || thinMember.IncludeStatus == IncludeStatus.ApiRoot || thinMember.IncludeStatus == IncludeStatus.ApiFxInternal) { nApiMembers++; } } else { Console.Error.WriteLine("BclRewriter : warning BR5003 : couldn't find declaring type of method {0} in closure", method); } } foreach (ThinMember thinMember in _missingMembers) { ThinType typeToExtend = types[thinMember.DeclaringType.Metadata]; ThinMember newThinMember = new ThinMember(typeToExtend, thinMember); if (!typeToExtend.Members.ContainsKey(newThinMember.Key)) { typeToExtend.Members.Add(newThinMember.Key, newThinMember); } } return(thinModel); }
public CalledBaseCtorFinder(IMethodDefinition ctor) { _targetType = Util.CanonicalizeType(TypeHelper.BaseClass(Util.ContainingTypeDefinition(ctor))); _baseCtor = null; }
// // Some types may have base types with no default ctors // and no ctors themselves. In those cases, the compiler // cannot instantiate the type without an explicit ctor // that calls one of the included base type ctors. // private void GenerateWorkForCtors(INamedTypeDefinition type, IClosureVisitor visitor) { if (TypeHelper.BaseClass(type) == null) { return; } List <IMethodDefinition> ctors = GetCtors(type, true); if (ctors.Count != 0) { return; } List <IMethodDefinition> baseCtors = GetCtors(Util.CanonicalizeType(TypeHelper.BaseClass(type)), true); if (baseCtors.Count == 0) { return; } int nDefaultCtors = 0; foreach (IMethodDefinition ctor in baseCtors) { if (Util.ParameterCount(ctor) == 0) { nDefaultCtors++; } } if (nDefaultCtors != 0) { return; } // TODO: Shouldn't this be part of implclosure? ctors = GetCtors(type, false); foreach (IMethodDefinition baseCtor in baseCtors) { foreach (IMethodDefinition ctor in ctors) { if (MethodCallsMethod(ctor, baseCtor)) { AddMemberReference(ctor); return; // @TODO: we may need to add more than just the first one we find.. } } } // at this point, no included ctor in the base type is // being called by any of the ctors in the derived type // so we have to get a little more creative if (ctors.Count > 0) { IMethodDefinition fallback = FindCalledBaseCtor(ctors[0]); if (null != fallback) { AddMemberReference(ctors[0]); AddMemberReference(fallback); } } }
public override void Visit(ITypeDefinition type) { // prevent cycles if (_visitedTypes.ContainsKey(type.InternedKey)) { return; } _visitedTypes.Add(type.InternedKey, null); AddTypeReference(Util.CanonicalizeTypeReference(type)); INestedTypeDefinition nestedType = type as INestedTypeDefinition; if (nestedType != null) { Visit(nestedType.ContainingTypeDefinition); } Visit(type.Attributes); if (type.HasDeclarativeSecurity) { Visit(type.SecurityAttributes); } Visit(type.BaseClasses); // Don't visit type.Interfaces here, since we might not need to include all those interfaces in the closure. // We will include any interfaces used elsewhere in the api/implementation if (type.IsGeneric) { Visit(type.GenericParameters); } foreach (ITypeDefinitionMember member in type.Members) { List <ITypeDefinitionMember> members = Util.FindRelatedExternalMembers(member, m_implModel.CanInclude); if (members.Count != 0) { // This member is related to an external member, so we need to add it here. AddMemberReference(member); // TODO: Only add if the related member is abstract? } } // Instead of visiting all the members, let's just add the things that are implied foreach (IMethodDefinition meth in type.Methods) { // visit .cctor for the type if (meth.IsStaticConstructor) { AddMemberReference(meth); } // @TODO: this is lame--a base type of this type may not have // a default constructor and we may not ever encounter code // that actually creates *this* type, so we may end up in a // situation where we cannot compile this type because we // don't have a ctor that satisfies the base type's ctor(s). // // for now, just add any default .ctor and hope that's good enough if (meth.IsConstructor && TypeHelper.BaseClass(type) != null && Util.ParameterCount(meth) == 0) { AddMemberReference(meth); } } // TODO: _options.FieldOptions == FieldOptions.KeepAll needs to be checked for api closure as well? if (_options.FieldOptions == FieldOptions.KeepAll || (_options.FieldOptions == FieldOptions.KeepAllValueTypeFields && type.IsValueType)) { foreach (IFieldDefinition field in type.Fields) { // Include all static literal fields. if (!field.IsStatic || field.IsCompileTimeConstant) { AddMemberReference(field); } } } //Visit(type.TemplateArguments); //Visit(type.TemplateParameters); }