📄 attribute.cs
字号:
public void AddAttributes (ArrayList attrs) { Attrs.AddRange (attrs); } /// <summary> /// Checks whether attribute target is valid for the current element /// </summary> public bool CheckTargets (Attributable member) { string[] valid_targets = member.ValidAttributeTargets; foreach (Attribute a in Attrs) { if (a.ExplicitTarget == null || a.ExplicitTarget == valid_targets [0]) { a.Target = member.AttributeTargets; continue; } // TODO: we can skip the first item if (((IList) valid_targets).Contains (a.ExplicitTarget)) { switch (a.ExplicitTarget) { case "return": a.Target = AttributeTargets.ReturnValue; continue; case "param": a.Target = AttributeTargets.Parameter; continue; case "field": a.Target = AttributeTargets.Field; continue; case "method": a.Target = AttributeTargets.Method; continue; case "property": a.Target = AttributeTargets.Property; continue; } throw new InternalErrorException ("Unknown explicit target: " + a.ExplicitTarget); } StringBuilder sb = new StringBuilder (); foreach (string s in valid_targets) { sb.Append (s); sb.Append (", "); } sb.Remove (sb.Length - 2, 2); Report.Error (657, a.Location, "`{0}' is not a valid attribute location for this declaration. " + "Valid attribute locations for this declaration are `{1}'", a.ExplicitTarget, sb.ToString ()); return false; } return true; } public Attribute Search (Type t, EmitContext ec) { foreach (Attribute a in Attrs) { if (a.ResolveType (ec) == t) return a; } return null; } /// <summary> /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true /// </summary> public Attribute[] SearchMulti (Type t, EmitContext ec) { ArrayList ar = null; foreach (Attribute a in Attrs) { if (a.ResolveType (ec) == t) { if (ar == null) ar = new ArrayList (); ar.Add (a); } } return ar == null ? null : ar.ToArray (typeof (Attribute)) as Attribute[]; } public void Emit (EmitContext ec, Attributable ias) { CheckTargets (ias); ListDictionary ld = new ListDictionary (); foreach (Attribute a in Attrs) a.Emit (ec, ias, ld); } public bool Contains (Type t, EmitContext ec) { return Search (t, ec) != null; } } /// <summary> /// Helper class for attribute verification routine. /// </summary> sealed class AttributeTester { static PtrHashtable analyzed_types = new PtrHashtable (); static PtrHashtable analyzed_types_obsolete = new PtrHashtable (); static PtrHashtable analyzed_member_obsolete = new PtrHashtable (); static PtrHashtable analyzed_method_excluded = new PtrHashtable ();#if NET_2_0 static PtrHashtable fixed_buffer_cache = new PtrHashtable ();#endif static object TRUE = new object (); static object FALSE = new object (); private AttributeTester () { } public enum Result { Ok, RefOutArrayError, ArrayArrayError } /// <summary> /// Returns true if parameters of two compared methods are CLS-Compliant. /// It tests differing only in ref or out, or in array rank. /// </summary> public static Result AreOverloadedMethodParamsClsCompliant (Type[] types_a, Type[] types_b) { if (types_a == null || types_b == null) return Result.Ok; if (types_a.Length != types_b.Length) return Result.Ok; Result result = Result.Ok; for (int i = 0; i < types_b.Length; ++i) { Type aType = types_a [i]; Type bType = types_b [i]; if (aType.IsArray && bType.IsArray) { Type a_el_type = aType.GetElementType (); Type b_el_type = bType.GetElementType (); if (aType.GetArrayRank () != bType.GetArrayRank () && a_el_type == b_el_type) { result = Result.RefOutArrayError; continue; } if (a_el_type.IsArray || b_el_type.IsArray) { result = Result.ArrayArrayError; continue; } } Type aBaseType = aType; bool is_either_ref_or_out = false; if (aType.IsByRef || aType.IsPointer) { aBaseType = aType.GetElementType (); is_either_ref_or_out = true; } Type bBaseType = bType; if (bType.IsByRef || bType.IsPointer) { bBaseType = bType.GetElementType (); is_either_ref_or_out = !is_either_ref_or_out; } if (aBaseType != bBaseType) return Result.Ok; if (is_either_ref_or_out) result = Result.RefOutArrayError; } return result; } /// <summary> /// Goes through all parameters and test if they are CLS-Compliant. /// </summary> public static bool AreParametersCompliant (Parameter[] fixedParameters, Location loc) { if (fixedParameters == null) return true; foreach (Parameter arg in fixedParameters) { if (!AttributeTester.IsClsCompliant (arg.ParameterType)) { Report.Error (3001, loc, "Argument type `{0}' is not CLS-compliant", arg.GetSignatureForError ()); return false; } } return true; } /// <summary> /// This method tests the CLS compliance of external types. It doesn't test type visibility. /// </summary> public static bool IsClsCompliant (Type type) { if (type == null) return true; object type_compliance = analyzed_types[type]; if (type_compliance != null) return type_compliance == TRUE; if (type.IsPointer) { analyzed_types.Add (type, null); return false; } bool result; if (type.IsArray || type.IsByRef) { result = IsClsCompliant (TypeManager.GetElementType (type)); } else { result = AnalyzeTypeCompliance (type); } analyzed_types.Add (type, result ? TRUE : FALSE); return result; } /// <summary> /// Returns IFixedBuffer implementation if field is fixed buffer else null. /// </summary> public static IFixedBuffer GetFixedBuffer (FieldInfo fi) { FieldBase fb = TypeManager.GetField (fi); if (fb != null) { return fb as IFixedBuffer; }#if NET_2_0 object o = fixed_buffer_cache [fi]; if (o == null) { if (System.Attribute.GetCustomAttribute (fi, TypeManager.fixed_buffer_attr_type) == null) { fixed_buffer_cache.Add (fi, FALSE); return null; } IFixedBuffer iff = new FixedFieldExternal (fi); fixed_buffer_cache.Add (fi, iff); return iff; } if (o == FALSE) return null; return (IFixedBuffer)o;#else return null;#endif } public static void VerifyModulesClsCompliance () { Module[] modules = RootNamespace.Global.Modules; if (modules == null) return; // The first module is generated assembly for (int i = 1; i < modules.Length; ++i) { Module module = modules [i]; if (!IsClsCompliant (module)) { Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " + "to match the assembly", module.Name); return; } } } public static Type GetImportedIgnoreCaseClsType (string name) { foreach (Assembly a in RootNamespace.Global.Assemblies) { Type t = a.GetType (name, false, true); if (t == null) continue; if (IsClsCompliant (t)) return t; } return null; } static bool IsClsCompliant (ICustomAttributeProvider attribute_provider) { object[] CompliantAttribute = attribute_provider.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false); if (CompliantAttribute.Length == 0) return false; return ((CLSCompliantAttribute)CompliantAttribute[0]).IsCompliant; } static bool AnalyzeTypeCompliance (Type type) { DeclSpace ds = TypeManager.LookupDeclSpace (type); if (ds != null) { return ds.IsClsCompliaceRequired (ds.Parent); } object[] CompliantAttribute = type.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false); if (CompliantAttribute.Length == 0) return IsClsCompliant (type.Assembly); return ((CLSCompliantAttribute)CompliantAttribute[0]).IsCompliant; } /// <summary> /// Returns instance of ObsoleteAttribute when type is obsolete /// </summary> public static ObsoleteAttribute GetObsoleteAttribute (Type type) { object type_obsolete = analyzed_types_obsolete [type]; if (type_obsolete == FALSE) return null; if (type_obsolete != null) return (ObsoleteAttribute)type_obsolete; ObsoleteAttribute result = null; if (type.IsByRef || type.IsArray || type.IsPointer) { result = GetObsoleteAttribute (TypeManager.GetElementType (type)); } else { DeclSpace type_ds = TypeManager.LookupDeclSpace (type); // Type is external, we can get attribute directly if (type_ds == null) { object[] attribute = type.GetCustomAttributes (TypeManager.obsolete_attribute_type, false); if (attribute.Length == 1) result = (ObsoleteAttribute)attribute [0]; } else { result = type_ds.GetObsoleteAttribute (); } } // Cannot use .Add because of corlib bootstrap analyzed_types_obsolete [type] = result == null ? FALSE : result; return result; } /// <summary> /// Returns instance of ObsoleteAttribute when method is obsolete /// </summary> public static ObsoleteAttribute GetMethodObsoleteAttribute (MethodBase mb) { IMethodData mc = TypeManager.GetMethod (mb); if (mc != null) return mc.GetObsoleteAttribute (); // compiler generated methods are not registered by AddMethod if (mb.DeclaringType is TypeBuilder) return null; if (mb.IsSpecialName) { PropertyInfo pi = PropertyExpr.AccessorTable [mb] as PropertyInfo; if (pi != null) { // FIXME: This is buggy as properties from this assembly are included as well return null; //return GetMemberObsoleteAttribute (pi); } } return GetMemberObsoleteAttribute (mb); } /// <summary> /// Returns instance of ObsoleteAttribute when member is obsolete /// </summary> public static ObsoleteAttribute GetMemberObsoleteAttribute (MemberInfo mi) { object type_obsolete = analyzed_member_obsolete [mi]; if (type_obsolete == FALSE) return null; if (type_obsolete != null) return (ObsoleteAttribute)type_obsolete; ObsoleteAttribute oa = System.Attribute.GetCustomAttribute (mi, TypeManager.obsolete_attribute_type, false) as ObsoleteAttribute; analyzed_member_obsolete.Add (mi, oa == null ? FALSE : oa); return oa; } /// <summary> /// Common method for Obsolete error/warning reporting. /// </summary> public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc) { if (oa.IsError) { Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message); return; } if (oa.Message == null) { Report.Warning (612, loc, "`{0}' is obsolete", member); return; } if (RootContext.WarningLevel >= 2) Report.Warning (618, loc, "`{0}' is obsolete: `{1}'", member, oa.Message); } public static bool IsConditionalMethodExcluded (MethodBase mb) { object excluded = analyzed_method_excluded [mb]; if (excluded != null) return excluded == TRUE ? true : false; ConditionalAttribute[] attrs = mb.GetCustomAttributes (TypeManager.conditional_attribute_type, true) as ConditionalAttribute[]; if (attrs.Length == 0) { analyzed_method_excluded.Add (mb, FALSE); return false; } foreach (ConditionalAttribute a in attrs) { if (RootContext.AllDefines.Contains (a.ConditionString)) { analyzed_method_excluded.Add (mb, FALSE); return false; } } analyzed_method_excluded.Add (mb, TRUE); return true; } /// <summary> /// Analyzes class whether it has attribute which has ConditionalAttribute /// and its condition is not defined. /// </summary> public static bool IsAttributeExcluded (Type type) { if (!type.IsClass) return false; Class class_decl = TypeManager.LookupDeclSpace (type) as Class; // TODO: add caching // TODO: merge all Type bases attribute caching to one cache to save memory if (class_decl == null) { object[] attributes = type.GetCustomAttributes (TypeManager.conditional_attribute_type, false); foreach (ConditionalAttribute ca in attributes) { if (RootContext.AllDefines.Contains (ca.ConditionString)) return false; } return attributes.Length > 0; } return class_decl.IsExcluded (); } public static Type GetCoClassAttribute (Type type) { TypeContainer tc = TypeManager.LookupInterface (type); if (tc == null) { object[] o = type.GetCustomAttributes (TypeManager.coclass_attr_type, false); return ((System.Runtime.InteropServices.CoClassAttribute)o[0]).CoClass; } if (tc.OptAttributes == null) return null; Attribute a = tc.OptAttributes.Search (TypeManager.coclass_attr_type, tc.EmitContext); if (a == null) return null; return a.GetCoClassAttributeValue (tc.EmitContext); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -