/// <summary> /// Mark all base types and externally visible members reachable /// </summary> private static void Walk(ReachableContext context, TypeReference type) { // Generic parameters Walk(context, (IGenericParameterProvider)type); TypeDefinition typeDef; TypeSpecification typeSpec; GenericParameter genericParam; if ((typeDef = type as TypeDefinition) != null) { var isUsedInSerialization = typeDef.IsUsedInSerialization && !type.IsPrimitive && !typeDef.IsEnum && !type.Namespace.StartsWith("System"); // Mark base type reachable typeDef.BaseType.MarkReachable(context, isUsedInSerialization); // Mark declaring type reachable typeDef.DeclaringType.MarkReachable(context); // Mark implemented interfaces reachable if (typeDef.HasInterfaces) { foreach (var intf in typeDef.Interfaces.Select(x => x.Interface)) { intf.MarkReachable(context); } } // If this is an attribute, include related types if (typeDef.IsAttribute()) { GetDot42InternalType(context, "IAttribute").MarkReachable(context); GetDot42InternalType(context, "IAttributes").MarkReachable(context); } else if (typeDef.IsEnum) { var boxingType = GetDot42InternalType(context, "Boxing"); boxingType.Methods.Where(x => (x.Name == "UnboxInteger" || x.Name == "UnboxLong")).ForEach(x => x.MarkReachable(context)); } // Default & class ctor typeDef.FindDefaultCtor().MarkReachable(context); typeDef.GetClassCtor().MarkReachable(context); // Visit externally visible members if (typeDef.HasEvents) { foreach (var evt in typeDef.Events) { if ((!evt.IsReachable) && context.Include(evt)) { evt.MarkReachable(context); } } } if (typeDef.HasFields) { foreach (var field in typeDef.Fields) { // only public fields, so we don't pull any compiler generated stuff. var isSerializable = isUsedInSerialization && !field.IsStatic && field.IsPublic; if ((!field.IsReachable && context.Include(field)) || (!field.IsUsedInSerialization && isSerializable)) { field.MarkReachable(context, isUsedInSerialization); } } } if (typeDef.HasMethods) { foreach (var method in typeDef.Methods) { if ((!method.IsReachable) && context.Include(method)) { method.MarkReachable(context); } } } if (typeDef.HasProperties) { foreach (var prop in typeDef.Properties) { var isSerializable = isUsedInSerialization && prop.HasThis; if ((!prop.IsReachable && context.Include(prop) || (!prop.IsUsedInSerialization && isSerializable))) { prop.MarkReachable(context, isUsedInSerialization); } } } // Custom attributes Walk(context, (ICustomAttributeProvider)typeDef); // Walk imported java classes CustomAttribute javaImportAttr; if ((javaImportAttr = typeDef.GetJavaImportAttribute()) != null) { var javaClassName = (string)javaImportAttr.ConstructorArguments[0].Value; ClassFile javaClass; if (context.TryLoadClass(javaClassName, out javaClass)) { javaClass.MarkReachable(context); } } // Dex imported interfaces should have all their methods marked reachable. if (typeDef.IsInterface && typeDef.HasDexImportAttribute()) { typeDef.Methods.ForEach(x => x.MarkReachable(context)); } // Record in context context.RecordReachableType(typeDef); } else if ((typeSpec = type as TypeSpecification) != null) { // Element typeSpec.ElementType.MarkReachable(context, typeSpec.IsUsedInSerialization); // Generic instance GenericInstanceType git; FunctionPointerType fpt; RequiredModifierType reqModType; OptionalModifierType optModType; if ((git = typeSpec as GenericInstanceType) != null) { if (git.ElementType.IsNullableT()) { var typeofT = git.GenericArguments[0].Resolve(context); if (typeofT != null && !typeofT.UsedInNullableT) { typeofT.UsedInNullableT = true; DLog.Debug(DContext.CompilerAssemblyResolver, "found System.Nullable<{0}>", typeofT.FullName); } } Walk(context, (IGenericInstance)git); } else if ((fpt = typeSpec as FunctionPointerType) != null) { Walk(context, fpt.ReturnType); } else if ((reqModType = typeSpec as RequiredModifierType) != null) { reqModType.ModifierType.MarkReachable(context); } else if ((optModType = typeSpec as OptionalModifierType) != null) { optModType.ModifierType.MarkReachable(context); } } else if ((genericParam = type as GenericParameter) != null) { genericParam.IsSerializedParameter = genericParam.HasSerializedParameterAttribute(); // Owner var owner = (MemberReference)genericParam.Owner; owner.MarkReachable(context); // Constraints if (genericParam.HasConstraints) { foreach (TypeReference constraint in genericParam.Constraints) { constraint.MarkReachable(context); } } } else { // Try to resolve type.Resolve(context).MarkReachable(context, type.IsUsedInSerialization); } }
/// <summary> /// Mark all base types and externally visible members reachable /// </summary> private static void Walk(ReachableContext context, TypeReference type) { // Generic parameters Walk(context, (IGenericParameterProvider)type); TypeDefinition typeDef; TypeSpecification typeSpec; GenericParameter genericParam; if ((typeDef = type as TypeDefinition) != null) { // Mark base type reachable typeDef.BaseType.MarkReachable(context); // Mark declaring type reachable typeDef.DeclaringType.MarkReachable(context); // Mark implemented interfaces reachable if (typeDef.HasInterfaces) { foreach (var intf in typeDef.Interfaces.Select(x => x.Interface)) { intf.MarkReachable(context); } } // If is an an attribute include related types if (typeDef.IsAttribute()) { GetDot42InternalType(context, "IAttribute").MarkReachable(context); GetDot42InternalType(context, "IAttributes").MarkReachable(context); GetDot42InternalType(context, "IAnnotationType").MarkReachable(context); } else if (typeDef.IsEnum) { var boxingType = GetDot42InternalType(context, "Boxing"); boxingType.Methods.Where(x => (x.Name == "UnboxInteger" || x.Name == "UnboxLong")).ForEach(x => x.MarkReachable(context)); } // Default & class ctor typeDef.FindDefaultCtor().MarkReachable(context); typeDef.GetClassCtor().MarkReachable(context); // Visit externally visible members if (typeDef.HasEvents) { foreach (var evt in typeDef.Events) { if ((!evt.IsReachable) && context.Include(evt)) { evt.MarkReachable(context); } } } if (typeDef.HasFields) { foreach (var field in typeDef.Fields) { if ((!field.IsReachable) && context.Include(field)) { field.MarkReachable(context); } } } if (typeDef.HasMethods) { foreach (var method in typeDef.Methods) { if ((!method.IsReachable) && context.Include(method)) { method.MarkReachable(context); } } } if (typeDef.HasProperties) { foreach (var prop in typeDef.Properties) { if ((!prop.IsReachable) && context.Include(prop)) { prop.MarkReachable(context); } } } // Custom attributes Walk(context, (ICustomAttributeProvider)typeDef); // Walk imported java classes CustomAttribute javaImportAttr; if ((javaImportAttr = typeDef.GetJavaImportAttribute()) != null) { var javaClassName = (string)javaImportAttr.ConstructorArguments[0].Value; ClassFile javaClass; if (context.TryLoadClass(javaClassName, out javaClass)) { javaClass.MarkReachable(context); } } // Dex imported interfaces should have all their methods marked reachable. if (typeDef.IsInterface && typeDef.HasDexImportAttribute()) { typeDef.Methods.ForEach(x => x.MarkReachable(context)); } // Record in context and create class builder context.RecordReachableType(typeDef); } else if ((typeSpec = type as TypeSpecification) != null) { // Element typeSpec.ElementType.MarkReachable(context); // Generic instance GenericInstanceType git; FunctionPointerType fpt; RequiredModifierType reqModType; OptionalModifierType optModType; if ((git = typeSpec as GenericInstanceType) != null) { if (git.ElementType.IsNullableT()) { var typeofT = git.GenericArguments[0].Resolve(context); if (typeofT != null) { typeofT.UsedInNullableT = true; } } Walk(context, (IGenericInstance)git); } else if ((fpt = typeSpec as FunctionPointerType) != null) { Walk(context, fpt.ReturnType); } else if ((reqModType = typeSpec as RequiredModifierType) != null) { reqModType.ModifierType.MarkReachable(context); } else if ((optModType = typeSpec as OptionalModifierType) != null) { optModType.ModifierType.MarkReachable(context); } } else if ((genericParam = type as GenericParameter) != null) { // Owner var owner = (MemberReference)genericParam.Owner; owner.MarkReachable(context); // Constraints if (genericParam.HasConstraints) { foreach (TypeReference constraint in genericParam.Constraints) { constraint.MarkReachable(context); } } } else { // Try to resolve type.Resolve(context).MarkReachable(context); } }
/// <summary> /// Mark all base types and externally visible members reachable /// </summary> private static void Walk(ReachableContext context, TypeReference type) { // Generic parameters Walk(context, (IGenericParameterProvider)type); TypeDefinition typeDef; TypeSpecification typeSpec; GenericParameter genericParam; if ((typeDef = type as TypeDefinition) != null) { var isUsedInSerialization = typeDef.IsUsedInSerialization && !type.IsPrimitive && !typeDef.IsEnum && !type.Namespace.StartsWith("System"); // Mark base type reachable typeDef.BaseType.MarkReachable(context, isUsedInSerialization); // Mark declaring type reachable typeDef.DeclaringType.MarkReachable(context); // Mark implemented interfaces reachable if (typeDef.HasInterfaces) { foreach (var intf in typeDef.Interfaces.Select(x => x.InterfaceType)) { intf.MarkReachable(context); } } // If this is an attribute, include related types if (typeDef.IsAttribute()) { GetDot42InternalType(context, "IAttribute").MarkReachable(context); GetDot42InternalType(context, "IAttributes").MarkReachable(context); } else if (typeDef.IsEnum) { var boxingType = GetDot42InternalType(context, "Boxing"); boxingType.Methods.Where(x => (x.Name == "UnboxInteger" || x.Name == "UnboxLong")).ForEach(x => x.MarkReachable(context)); } // Default & class ctor typeDef.FindDefaultCtor().MarkReachable(context); typeDef.GetClassCtor().MarkReachable(context); // Visit externally visible members if (typeDef.HasEvents) { foreach (var evt in typeDef.Events) { if ((!evt.IsReachable) && context.Include(evt)) { evt.MarkReachable(context); } } } if (typeDef.HasFields) { foreach (var field in typeDef.Fields) { // only public fields, so we don't pull any compiler generated stuff. var isSerializable = isUsedInSerialization && !field.IsStatic && field.IsPublic; if ((!field.IsReachable && context.Include(field)) || (!field.IsUsedInSerialization && isSerializable)) { field.MarkReachable(context, isUsedInSerialization); } } } if (typeDef.HasMethods) { foreach (var method in typeDef.Methods) { if ((!method.IsReachable) && context.Include(method)) { method.MarkReachable(context); } } } if (typeDef.HasProperties) { foreach (var prop in typeDef.Properties) { var isSerializable = isUsedInSerialization && prop.HasThis; if ((!prop.IsReachable && context.Include(prop) || (!prop.IsUsedInSerialization && isSerializable))) { prop.MarkReachable(context, isUsedInSerialization); } } } // Custom attributes Walk(context, (ICustomAttributeProvider)typeDef); // Walk imported java classes CustomAttribute javaImportAttr; if ((javaImportAttr = typeDef.GetJavaImportAttribute()) != null) { var javaClassName = (string)javaImportAttr.ConstructorArguments[0].Value; ClassFile javaClass; if (context.TryLoadClass(javaClassName, out javaClass)) { javaClass.MarkReachable(context); } } // Dex imported interfaces should have all their methods marked reachable. if (typeDef.IsInterface && typeDef.HasDexImportAttribute()) { typeDef.Methods.ForEach(x => x.MarkReachable(context)); } // Record in context context.RecordReachableType(typeDef); } else if ((typeSpec = type as TypeSpecification) != null) { // Element typeSpec.ElementType.MarkReachable(context, typeSpec.IsUsedInSerialization); // Generic instance GenericInstanceType git; FunctionPointerType fpt; RequiredModifierType reqModType; OptionalModifierType optModType; if ((git = typeSpec as GenericInstanceType) != null) { if (git.ElementType.IsNullableT()) { var typeofT = git.GenericArguments[0].Resolve(context); if (typeofT != null && !typeofT.UsedInNullableT) { typeofT.UsedInNullableT = true; DLog.Debug(DContext.CompilerAssemblyResolver, "found System.Nullable<{0}>", typeofT.FullName); } } Walk(context, (IGenericInstance)git); } else if ((fpt = typeSpec as FunctionPointerType) != null) { Walk(context, fpt.ReturnType); } else if ((reqModType = typeSpec as RequiredModifierType) != null) { reqModType.ModifierType.MarkReachable(context); } else if ((optModType = typeSpec as OptionalModifierType) != null) { optModType.ModifierType.MarkReachable(context); } } else if ((genericParam = type as GenericParameter) != null) { genericParam.IsSerializedParameter = genericParam.HasSerializedParameterAttribute(); // Owner var owner = (MemberReference)genericParam.Owner; owner.MarkReachable(context); // Constraints if (genericParam.HasConstraints) { foreach (TypeReference constraint in genericParam.Constraints) { constraint.MarkReachable(context); } } } else { // Try to resolve type.Resolve(context).MarkReachable(context, type.IsUsedInSerialization); } }