PageRenderTime 60ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/mcs/import.cs

https://bitbucket.org/danipen/mono
C# | 2237 lines | 1654 code | 377 blank | 206 comment | 595 complexity | a436000ff0cfbb869a127d9454dce319 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. //
  2. // import.cs: System.Reflection conversions
  3. //
  4. // Authors: Marek Safar (marek.safar@gmail.com)
  5. //
  6. // Dual licensed under the terms of the MIT X11 or GNU GPL
  7. //
  8. // Copyright 2009-2011 Novell, Inc
  9. // Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
  10. //
  11. using System;
  12. using System.Runtime.CompilerServices;
  13. using System.Linq;
  14. using System.Collections.Generic;
  15. #if STATIC
  16. using MetaType = IKVM.Reflection.Type;
  17. using IKVM.Reflection;
  18. using IKVM.Reflection.Emit;
  19. #else
  20. using MetaType = System.Type;
  21. using System.Reflection;
  22. using System.Reflection.Emit;
  23. #endif
  24. namespace Mono.CSharp
  25. {
  26. public abstract class MetadataImporter
  27. {
  28. //
  29. // Dynamic types reader with additional logic to reconstruct a dynamic
  30. // type using DynamicAttribute values
  31. //
  32. protected struct DynamicTypeReader
  33. {
  34. static readonly bool[] single_attribute = { true };
  35. public int Position;
  36. bool[] flags;
  37. // There is no common type for CustomAttributeData and we cannot
  38. // use ICustomAttributeProvider
  39. object provider;
  40. //
  41. // A member provider which can be used to get CustomAttributeData
  42. //
  43. public DynamicTypeReader (object provider)
  44. {
  45. Position = 0;
  46. flags = null;
  47. this.provider = provider;
  48. }
  49. //
  50. // Returns true when object at local position has dynamic attribute flag
  51. //
  52. public bool IsDynamicObject (MetadataImporter importer)
  53. {
  54. if (provider != null)
  55. ReadAttribute (importer);
  56. return flags != null && Position < flags.Length && flags[Position];
  57. }
  58. //
  59. // Returns true when DynamicAttribute exists
  60. //
  61. public bool HasDynamicAttribute (MetadataImporter importer)
  62. {
  63. if (provider != null)
  64. ReadAttribute (importer);
  65. return flags != null;
  66. }
  67. void ReadAttribute (MetadataImporter importer)
  68. {
  69. IList<CustomAttributeData> cad;
  70. if (provider is MemberInfo) {
  71. cad = CustomAttributeData.GetCustomAttributes ((MemberInfo) provider);
  72. } else if (provider is ParameterInfo) {
  73. cad = CustomAttributeData.GetCustomAttributes ((ParameterInfo) provider);
  74. } else {
  75. provider = null;
  76. return;
  77. }
  78. if (cad.Count > 0) {
  79. foreach (var ca in cad) {
  80. var dt = ca.Constructor.DeclaringType;
  81. if (dt.Name != "DynamicAttribute" || dt.Namespace != CompilerServicesNamespace)
  82. continue;
  83. if (ca.ConstructorArguments.Count == 0) {
  84. flags = single_attribute;
  85. break;
  86. }
  87. var arg_type = ca.ConstructorArguments[0].ArgumentType;
  88. if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) {
  89. var carg = (IList<CustomAttributeTypedArgument>) ca.ConstructorArguments[0].Value;
  90. flags = new bool[carg.Count];
  91. for (int i = 0; i < flags.Length; ++i) {
  92. if (MetaType.GetTypeCode (carg[i].ArgumentType) == TypeCode.Boolean)
  93. flags[i] = (bool) carg[i].Value;
  94. }
  95. break;
  96. }
  97. }
  98. }
  99. provider = null;
  100. }
  101. }
  102. protected readonly Dictionary<MetaType, TypeSpec> import_cache;
  103. protected readonly Dictionary<MetaType, TypeSpec> compiled_types;
  104. protected readonly Dictionary<Assembly, IAssemblyDefinition> assembly_2_definition;
  105. protected readonly ModuleContainer module;
  106. public static readonly string CompilerServicesNamespace = "System.Runtime.CompilerServices";
  107. protected MetadataImporter (ModuleContainer module)
  108. {
  109. this.module = module;
  110. import_cache = new Dictionary<MetaType, TypeSpec> (1024, ReferenceEquality<MetaType>.Default);
  111. compiled_types = new Dictionary<MetaType, TypeSpec> (40, ReferenceEquality<MetaType>.Default);
  112. assembly_2_definition = new Dictionary<Assembly, IAssemblyDefinition> (ReferenceEquality<Assembly>.Default);
  113. IgnorePrivateMembers = true;
  114. }
  115. #region Properties
  116. public ICollection<IAssemblyDefinition> Assemblies {
  117. get {
  118. return assembly_2_definition.Values;
  119. }
  120. }
  121. public bool IgnorePrivateMembers { get; set; }
  122. #endregion
  123. public abstract void AddCompiledType (TypeBuilder builder, TypeSpec spec);
  124. protected abstract MemberKind DetermineKindFromBaseType (MetaType baseType);
  125. protected abstract bool HasVolatileModifier (MetaType[] modifiers);
  126. public FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType)
  127. {
  128. Modifiers mod = 0;
  129. var fa = fi.Attributes;
  130. switch (fa & FieldAttributes.FieldAccessMask) {
  131. case FieldAttributes.Public:
  132. mod = Modifiers.PUBLIC;
  133. break;
  134. case FieldAttributes.Assembly:
  135. mod = Modifiers.INTERNAL;
  136. break;
  137. case FieldAttributes.Family:
  138. mod = Modifiers.PROTECTED;
  139. break;
  140. case FieldAttributes.FamORAssem:
  141. mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
  142. break;
  143. default:
  144. // Ignore private fields (even for error reporting) to not require extra dependencies
  145. if ((IgnorePrivateMembers && !declaringType.IsStruct) ||
  146. HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
  147. return null;
  148. mod = Modifiers.PRIVATE;
  149. break;
  150. }
  151. TypeSpec field_type;
  152. try {
  153. field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi));
  154. } catch (Exception e) {
  155. // TODO: I should construct fake TypeSpec based on TypeRef signature
  156. // but there is no way to do it with System.Reflection
  157. throw new InternalErrorException (e, "Cannot import field `{0}.{1}' referenced in assembly `{2}'",
  158. declaringType.GetSignatureForError (), fi.Name, declaringType.MemberDefinition.DeclaringAssembly);
  159. }
  160. var definition = new ImportedMemberDefinition (fi, field_type, this);
  161. if ((fa & FieldAttributes.Literal) != 0) {
  162. Constant c = field_type.Kind == MemberKind.MissingType ?
  163. new NullConstant (InternalType.ErrorType, Location.Null) :
  164. Constant.CreateConstantFromValue (field_type, fi.GetRawConstantValue (), Location.Null);
  165. return new ConstSpec (declaringType, definition, field_type, fi, mod, c);
  166. }
  167. if ((fa & FieldAttributes.InitOnly) != 0) {
  168. if (field_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
  169. var dc = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (fi));
  170. if (dc != null)
  171. return new ConstSpec (declaringType, definition, field_type, fi, mod, dc);
  172. }
  173. mod |= Modifiers.READONLY;
  174. } else {
  175. var req_mod = fi.GetRequiredCustomModifiers ();
  176. if (req_mod.Length > 0 && HasVolatileModifier (req_mod))
  177. mod |= Modifiers.VOLATILE;
  178. }
  179. if ((fa & FieldAttributes.Static) != 0) {
  180. mod |= Modifiers.STATIC;
  181. } else {
  182. // Fixed buffers cannot be static
  183. if (declaringType.IsStruct && field_type.IsStruct && field_type.IsNested &&
  184. HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "FixedBufferAttribute", CompilerServicesNamespace)) {
  185. // TODO: Sanity check on field_type (only few types are allowed)
  186. var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType);
  187. return new FixedFieldSpec (module, declaringType, definition, fi, element_field, mod);
  188. }
  189. }
  190. return new FieldSpec (declaringType, definition, field_type, fi, mod);
  191. }
  192. public EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove)
  193. {
  194. add.IsAccessor = true;
  195. remove.IsAccessor = true;
  196. if (add.Modifiers != remove.Modifiers)
  197. throw new NotImplementedException ("Different accessor modifiers " + ei.Name);
  198. var event_type = ImportType (ei.EventHandlerType, new DynamicTypeReader (ei));
  199. var definition = new ImportedMemberDefinition (ei, event_type, this);
  200. return new EventSpec (declaringType, definition, event_type, add.Modifiers, add, remove);
  201. }
  202. TypeParameterSpec[] CreateGenericParameters (MetaType type, TypeSpec declaringType)
  203. {
  204. var tparams = type.GetGenericArguments ();
  205. int parent_owned_count;
  206. if (type.IsNested) {
  207. parent_owned_count = type.DeclaringType.GetGenericArguments ().Length;
  208. //
  209. // System.Reflection duplicates parent type parameters for each
  210. // nested type with slightly modified properties (eg. different owner)
  211. // This just makes things more complicated (think of cloned constraints)
  212. // therefore we remap any nested type owned by parent using `type_cache'
  213. // to the single TypeParameterSpec
  214. //
  215. if (declaringType != null && parent_owned_count > 0) {
  216. int read_count = 0;
  217. while (read_count != parent_owned_count) {
  218. var tparams_count = declaringType.Arity;
  219. if (tparams_count != 0) {
  220. var parent_tp = declaringType.MemberDefinition.TypeParameters;
  221. read_count += tparams_count;
  222. for (int i = 0; i < tparams_count; i++) {
  223. import_cache.Add (tparams[parent_owned_count - read_count + i], parent_tp[i]);
  224. }
  225. }
  226. declaringType = declaringType.DeclaringType;
  227. }
  228. }
  229. } else {
  230. parent_owned_count = 0;
  231. }
  232. if (tparams.Length - parent_owned_count == 0)
  233. return null;
  234. return CreateGenericParameters (parent_owned_count, tparams);
  235. }
  236. TypeParameterSpec[] CreateGenericParameters (int first, MetaType[] tparams)
  237. {
  238. var tspec = new TypeParameterSpec[tparams.Length - first];
  239. for (int pos = first; pos < tparams.Length; ++pos) {
  240. var type = tparams[pos];
  241. int index = pos - first;
  242. tspec[index] = (TypeParameterSpec) CreateType (type, new DynamicTypeReader (), false);
  243. }
  244. return tspec;
  245. }
  246. TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, DynamicTypeReader dtype)
  247. {
  248. ++dtype.Position;
  249. var tspec = new TypeSpec [tparams.Length - first];
  250. for (int pos = first; pos < tparams.Length; ++pos) {
  251. var type = tparams[pos];
  252. int index = pos - first;
  253. TypeSpec spec;
  254. if (type.HasElementType) {
  255. var element = type.GetElementType ();
  256. ++dtype.Position;
  257. spec = ImportType (element, dtype);
  258. if (!type.IsArray) {
  259. throw new NotImplementedException ("Unknown element type " + type.ToString ());
  260. }
  261. spec = ArrayContainer.MakeType (module, spec, type.GetArrayRank ());
  262. } else {
  263. spec = CreateType (type, dtype, true);
  264. //
  265. // We treat nested generic types as inflated internally where
  266. // reflection uses type definition
  267. //
  268. // class A<T> {
  269. // IFoo<A<T>> foo; // A<T> is definition in this case
  270. // }
  271. //
  272. // TODO: Is full logic from CreateType needed here as well?
  273. //
  274. if (!IsMissingType (type) && type.IsGenericTypeDefinition) {
  275. var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype);
  276. spec = spec.MakeGenericType (module, targs);
  277. }
  278. }
  279. ++dtype.Position;
  280. tspec[index] = spec;
  281. }
  282. return tspec;
  283. }
  284. public MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType)
  285. {
  286. Modifiers mod = ReadMethodModifiers (mb, declaringType);
  287. TypeParameterSpec[] tparams;
  288. var parameters = CreateParameters (declaringType, mb.GetParameters (), mb);
  289. if (mb.IsGenericMethod) {
  290. if (!mb.IsGenericMethodDefinition)
  291. throw new NotSupportedException ("assert");
  292. tparams = CreateGenericParameters (0, mb.GetGenericArguments ());
  293. } else {
  294. tparams = null;
  295. }
  296. MemberKind kind;
  297. TypeSpec returnType;
  298. if (mb.MemberType == MemberTypes.Constructor) {
  299. kind = MemberKind.Constructor;
  300. returnType = module.Compiler.BuiltinTypes.Void;
  301. } else {
  302. //
  303. // Detect operators and destructors
  304. //
  305. string name = mb.Name;
  306. kind = MemberKind.Method;
  307. if (tparams == null && !mb.DeclaringType.IsInterface && name.Length > 6) {
  308. if ((mod & (Modifiers.STATIC | Modifiers.PUBLIC)) == (Modifiers.STATIC | Modifiers.PUBLIC)) {
  309. if (name[2] == '_' && name[1] == 'p' && name[0] == 'o') {
  310. var op_type = Operator.GetType (name);
  311. if (op_type.HasValue && parameters.Count > 0 && parameters.Count < 3) {
  312. kind = MemberKind.Operator;
  313. }
  314. }
  315. } else if (parameters.IsEmpty && name == Destructor.MetadataName) {
  316. kind = MemberKind.Destructor;
  317. if (declaringType.BuiltinType == BuiltinTypeSpec.Type.Object) {
  318. mod &= ~Modifiers.OVERRIDE;
  319. mod |= Modifiers.VIRTUAL;
  320. }
  321. }
  322. }
  323. var mi = (MethodInfo) mb;
  324. returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter));
  325. // Cannot set to OVERRIDE without full hierarchy checks
  326. // this flag indicates that the method could be override
  327. // but further validation is needed
  328. if ((mod & Modifiers.OVERRIDE) != 0) {
  329. bool is_real_override = false;
  330. if (kind == MemberKind.Method && declaringType.BaseType != null) {
  331. var btype = declaringType.BaseType;
  332. if (IsOverrideMethodBaseTypeAccessible (btype)) {
  333. var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null);
  334. var candidate = MemberCache.FindMember (btype, filter, BindingRestriction.None);
  335. //
  336. // For imported class method do additional validation to be sure that metadata
  337. // override flag was correct
  338. //
  339. // Difference between protected internal and protected is ok
  340. //
  341. const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL;
  342. if (candidate != null && (candidate.Modifiers & conflict_mask) == (mod & conflict_mask) && !candidate.IsStatic) {
  343. is_real_override = true;
  344. }
  345. }
  346. }
  347. if (!is_real_override) {
  348. mod &= ~Modifiers.OVERRIDE;
  349. if ((mod & Modifiers.SEALED) != 0)
  350. mod &= ~Modifiers.SEALED;
  351. else
  352. mod |= Modifiers.VIRTUAL;
  353. }
  354. }
  355. }
  356. IMemberDefinition definition;
  357. if (tparams != null) {
  358. var gmd = new ImportedGenericMethodDefinition ((MethodInfo) mb, returnType, parameters, tparams, this);
  359. foreach (var tp in gmd.TypeParameters) {
  360. ImportTypeParameterTypeConstraints (tp, tp.GetMetaInfo ());
  361. }
  362. definition = gmd;
  363. } else {
  364. definition = new ImportedParameterMemberDefinition (mb, returnType, parameters, this);
  365. }
  366. MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod);
  367. if (tparams != null)
  368. ms.IsGeneric = true;
  369. return ms;
  370. }
  371. bool IsOverrideMethodBaseTypeAccessible (TypeSpec baseType)
  372. {
  373. switch (baseType.Modifiers & Modifiers.AccessibilityMask) {
  374. case Modifiers.PUBLIC:
  375. return true;
  376. case Modifiers.INTERNAL:
  377. //
  378. // Check whether imported method in base type is accessible from compiled
  379. // context
  380. //
  381. return baseType.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly);
  382. case Modifiers.PRIVATE:
  383. return false;
  384. default:
  385. // protected
  386. // protected internal
  387. //
  388. // Method accessibility checks will be done later based on context
  389. // where the method is called (CS0122 error will be reported for inaccessible)
  390. //
  391. return true;
  392. }
  393. }
  394. //
  395. // Imports System.Reflection parameters
  396. //
  397. AParametersCollection CreateParameters (TypeSpec parent, ParameterInfo[] pi, MethodBase method)
  398. {
  399. int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;
  400. if (pi.Length == 0 && varargs == 0)
  401. return ParametersCompiled.EmptyReadOnlyParameters;
  402. TypeSpec[] types = new TypeSpec[pi.Length + varargs];
  403. IParameterData[] par = new IParameterData[pi.Length + varargs];
  404. bool is_params = false;
  405. for (int i = 0; i < pi.Length; i++) {
  406. ParameterInfo p = pi[i];
  407. Parameter.Modifier mod = 0;
  408. Expression default_value = null;
  409. if (p.ParameterType.IsByRef) {
  410. if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out)
  411. mod = Parameter.Modifier.OUT;
  412. else
  413. mod = Parameter.Modifier.REF;
  414. //
  415. // Strip reference wrapping
  416. //
  417. var el = p.ParameterType.GetElementType ();
  418. types[i] = ImportType (el, new DynamicTypeReader (p)); // TODO: 1-based positio to be csc compatible
  419. } else if (i == 0 && method.IsStatic && (parent.Modifiers & Modifiers.METHOD_EXTENSION) != 0 &&
  420. HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) {
  421. mod = Parameter.Modifier.This;
  422. types[i] = ImportType (p.ParameterType);
  423. } else {
  424. types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p));
  425. if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
  426. if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) {
  427. mod = Parameter.Modifier.PARAMS;
  428. is_params = true;
  429. }
  430. }
  431. if (!is_params && p.IsOptional) {
  432. object value = p.RawDefaultValue;
  433. var ptype = types[i];
  434. if ((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter && (value != null || TypeSpec.IsReferenceType (ptype))) {
  435. if (value == null) {
  436. default_value = Constant.CreateConstantFromValue (ptype, null, Location.Null);
  437. } else {
  438. default_value = ImportParameterConstant (value);
  439. if (ptype.IsEnum) {
  440. default_value = new EnumConstant ((Constant) default_value, ptype);
  441. }
  442. }
  443. var attrs = CustomAttributeData.GetCustomAttributes (p);
  444. for (int ii = 0; ii < attrs.Count; ++ii) {
  445. var attr = attrs[ii];
  446. var dt = attr.Constructor.DeclaringType;
  447. if (dt.Namespace != CompilerServicesNamespace)
  448. continue;
  449. if (dt.Name == "CallerLineNumberAttribute" && (ptype.BuiltinType == BuiltinTypeSpec.Type.Int || Convert.ImplicitNumericConversionExists (module.Compiler.BuiltinTypes.Int, ptype)))
  450. mod |= Parameter.Modifier.CallerLineNumber;
  451. else if (dt.Name == "CallerFilePathAttribute" && Convert.ImplicitReferenceConversionExists (module.Compiler.BuiltinTypes.String, ptype))
  452. mod |= Parameter.Modifier.CallerFilePath;
  453. else if (dt.Name == "CallerMemberNameAttribute" && Convert.ImplicitReferenceConversionExists (module.Compiler.BuiltinTypes.String, ptype))
  454. mod |= Parameter.Modifier.CallerMemberName;
  455. }
  456. } else if (value == Missing.Value) {
  457. default_value = EmptyExpression.MissingValue;
  458. } else if (value == null) {
  459. default_value = new DefaultValueExpression (new TypeExpression (ptype, Location.Null), Location.Null);
  460. } else if (ptype.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
  461. default_value = ImportParameterConstant (value);
  462. }
  463. }
  464. }
  465. par[i] = new ParameterData (p.Name, mod, default_value);
  466. }
  467. if (varargs != 0) {
  468. par[par.Length - 1] = new ArglistParameter (Location.Null);
  469. types[types.Length - 1] = InternalType.Arglist;
  470. }
  471. return method != null ?
  472. new ParametersImported (par, types, varargs != 0, is_params) :
  473. new ParametersImported (par, types, is_params);
  474. }
  475. //
  476. // Returns null when the property is not valid C# property
  477. //
  478. public PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set)
  479. {
  480. Modifiers mod = 0;
  481. AParametersCollection param = null;
  482. TypeSpec type = null;
  483. if (get != null) {
  484. mod = get.Modifiers;
  485. param = get.Parameters;
  486. type = get.ReturnType;
  487. }
  488. bool is_valid_property = true;
  489. if (set != null) {
  490. if (set.ReturnType.Kind != MemberKind.Void)
  491. is_valid_property = false;
  492. var set_param_count = set.Parameters.Count - 1;
  493. if (set_param_count < 0) {
  494. set_param_count = 0;
  495. is_valid_property = false;
  496. }
  497. var set_type = set.Parameters.Types[set_param_count];
  498. if (mod == 0) {
  499. AParametersCollection set_based_param;
  500. if (set_param_count == 0) {
  501. set_based_param = ParametersCompiled.EmptyReadOnlyParameters;
  502. } else {
  503. //
  504. // Create indexer parameters based on setter method parameters (the last parameter has to be removed)
  505. //
  506. var data = new IParameterData[set_param_count];
  507. var types = new TypeSpec[set_param_count];
  508. Array.Copy (set.Parameters.FixedParameters, data, set_param_count);
  509. Array.Copy (set.Parameters.Types, types, set_param_count);
  510. set_based_param = new ParametersImported (data, types, set.Parameters.HasParams);
  511. }
  512. mod = set.Modifiers;
  513. param = set_based_param;
  514. type = set_type;
  515. } else {
  516. if (set_param_count != get.Parameters.Count)
  517. is_valid_property = false;
  518. if (get.ReturnType != set_type)
  519. is_valid_property = false;
  520. // Possible custom accessor modifiers
  521. if ((mod & Modifiers.AccessibilityMask) != (set.Modifiers & Modifiers.AccessibilityMask)) {
  522. var get_acc = mod & Modifiers.AccessibilityMask;
  523. if (get_acc != Modifiers.PUBLIC) {
  524. var set_acc = set.Modifiers & Modifiers.AccessibilityMask;
  525. // If the accessor modifiers are not same, do extra restriction checks
  526. if (get_acc != set_acc) {
  527. var get_restr = ModifiersExtensions.IsRestrictedModifier (get_acc, set_acc);
  528. var set_restr = ModifiersExtensions.IsRestrictedModifier (set_acc, get_acc);
  529. if (get_restr && set_restr) {
  530. is_valid_property = false; // Neither is more restrictive
  531. }
  532. if (get_restr) {
  533. mod &= ~Modifiers.AccessibilityMask;
  534. mod |= set_acc;
  535. }
  536. }
  537. }
  538. }
  539. }
  540. }
  541. PropertySpec spec = null;
  542. if (!param.IsEmpty) {
  543. if (is_valid_property) {
  544. var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember ();
  545. if (index_name == null) {
  546. is_valid_property = false;
  547. } else {
  548. if (get != null) {
  549. if (get.IsStatic)
  550. is_valid_property = false;
  551. if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
  552. is_valid_property = false;
  553. }
  554. if (set != null) {
  555. if (set.IsStatic)
  556. is_valid_property = false;
  557. if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
  558. is_valid_property = false;
  559. }
  560. }
  561. if (is_valid_property) {
  562. spec = new IndexerSpec (declaringType, new ImportedParameterMemberDefinition (pi, type, param, this), type, param, pi, mod);
  563. } else if (declaringType.MemberDefinition.IsComImport && param.FixedParameters[0].HasDefaultValue) {
  564. //
  565. // Enables support for properties with parameters (must have default value) of COM-imported types
  566. //
  567. is_valid_property = true;
  568. for (int i = 0; i < param.FixedParameters.Length; ++i) {
  569. if (!param.FixedParameters[i].HasDefaultValue) {
  570. is_valid_property = false;
  571. break;
  572. }
  573. }
  574. }
  575. }
  576. }
  577. if (spec == null)
  578. spec = new PropertySpec (MemberKind.Property, declaringType, new ImportedMemberDefinition (pi, type, this), type, pi, mod);
  579. if (!is_valid_property) {
  580. spec.IsNotCSharpCompatible = true;
  581. return spec;
  582. }
  583. if (set != null)
  584. spec.Set = set;
  585. if (get != null)
  586. spec.Get = get;
  587. return spec;
  588. }
  589. public TypeSpec CreateType (MetaType type)
  590. {
  591. return CreateType (type, new DynamicTypeReader (), true);
  592. }
  593. public TypeSpec CreateNestedType (MetaType type, TypeSpec declaringType)
  594. {
  595. return CreateType (type, declaringType, new DynamicTypeReader (type), false);
  596. }
  597. TypeSpec CreateType (MetaType type, DynamicTypeReader dtype, bool canImportBaseType)
  598. {
  599. TypeSpec declaring_type;
  600. if (type.IsNested && !type.IsGenericParameter)
  601. declaring_type = CreateType (type.DeclaringType, new DynamicTypeReader (type.DeclaringType), true);
  602. else
  603. declaring_type = null;
  604. return CreateType (type, declaring_type, dtype, canImportBaseType);
  605. }
  606. protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType)
  607. {
  608. TypeSpec spec;
  609. if (import_cache.TryGetValue (type, out spec)) {
  610. if (spec.BuiltinType == BuiltinTypeSpec.Type.Object) {
  611. if (dtype.IsDynamicObject (this))
  612. return module.Compiler.BuiltinTypes.Dynamic;
  613. return spec;
  614. }
  615. if (!spec.IsGeneric || type.IsGenericTypeDefinition)
  616. return spec;
  617. if (!dtype.HasDynamicAttribute (this))
  618. return spec;
  619. // We've found same object in the cache but this one has a dynamic custom attribute
  620. // and it's most likely dynamic version of same type IFoo<object> agains IFoo<dynamic>
  621. // Do type resolve process again in that case
  622. // TODO: Handle cases where they still unify
  623. }
  624. if (IsMissingType (type)) {
  625. spec = new TypeSpec (MemberKind.MissingType, declaringType, new ImportedTypeDefinition (type, this), type, Modifiers.PUBLIC);
  626. spec.MemberCache = MemberCache.Empty;
  627. import_cache.Add (type, spec);
  628. return spec;
  629. }
  630. if (type.IsGenericType && !type.IsGenericTypeDefinition) {
  631. var type_def = type.GetGenericTypeDefinition ();
  632. // Generic type definition can also be forwarded
  633. if (compiled_types.TryGetValue (type_def, out spec))
  634. return spec;
  635. var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype);
  636. if (declaringType == null) {
  637. // Simple case, no nesting
  638. spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType);
  639. spec = spec.MakeGenericType (module, targs);
  640. } else {
  641. //
  642. // Nested type case, converting .NET types like
  643. // A`1.B`1.C`1<int, long, string> to typespec like
  644. // A<int>.B<long>.C<string>
  645. //
  646. var nested_hierarchy = new List<TypeSpec> ();
  647. while (declaringType.IsNested) {
  648. nested_hierarchy.Add (declaringType);
  649. declaringType = declaringType.DeclaringType;
  650. }
  651. int targs_pos = 0;
  652. if (declaringType.Arity > 0) {
  653. spec = declaringType.MakeGenericType (module, targs.Skip (targs_pos).Take (declaringType.Arity).ToArray ());
  654. targs_pos = spec.Arity;
  655. } else {
  656. spec = declaringType;
  657. }
  658. for (int i = nested_hierarchy.Count; i != 0; --i) {
  659. var t = nested_hierarchy [i - 1];
  660. spec = MemberCache.FindNestedType (spec, t.Name, t.Arity);
  661. if (t.Arity > 0) {
  662. spec = spec.MakeGenericType (module, targs.Skip (targs_pos).Take (spec.Arity).ToArray ());
  663. targs_pos += t.Arity;
  664. }
  665. }
  666. string name = type.Name;
  667. int index = name.IndexOf ('`');
  668. if (index > 0)
  669. name = name.Substring (0, index);
  670. spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos);
  671. if (spec == null)
  672. return null;
  673. if (spec.Arity > 0) {
  674. spec = spec.MakeGenericType (module, targs.Skip (targs_pos).ToArray ());
  675. }
  676. }
  677. // Don't add generic type with dynamic arguments, they can interfere with same type
  678. // using object type arguments
  679. if (!spec.HasDynamicElement) {
  680. // Add to reading cache to speed up reading
  681. if (!import_cache.ContainsKey (type))
  682. import_cache.Add (type, spec);
  683. }
  684. return spec;
  685. }
  686. Modifiers mod;
  687. MemberKind kind;
  688. var ma = type.Attributes;
  689. switch (ma & TypeAttributes.VisibilityMask) {
  690. case TypeAttributes.Public:
  691. case TypeAttributes.NestedPublic:
  692. mod = Modifiers.PUBLIC;
  693. break;
  694. case TypeAttributes.NestedPrivate:
  695. mod = Modifiers.PRIVATE;
  696. break;
  697. case TypeAttributes.NestedFamily:
  698. mod = Modifiers.PROTECTED;
  699. break;
  700. case TypeAttributes.NestedFamORAssem:
  701. mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
  702. break;
  703. default:
  704. mod = Modifiers.INTERNAL;
  705. break;
  706. }
  707. if ((ma & TypeAttributes.Interface) != 0) {
  708. kind = MemberKind.Interface;
  709. } else if (type.IsGenericParameter) {
  710. kind = MemberKind.TypeParameter;
  711. } else {
  712. var base_type = type.BaseType;
  713. if (base_type == null || (ma & TypeAttributes.Abstract) != 0) {
  714. kind = MemberKind.Class;
  715. } else {
  716. kind = DetermineKindFromBaseType (base_type);
  717. if (kind == MemberKind.Struct || kind == MemberKind.Delegate) {
  718. mod |= Modifiers.SEALED;
  719. }
  720. }
  721. if (kind == MemberKind.Class) {
  722. if ((ma & TypeAttributes.Sealed) != 0) {
  723. mod |= Modifiers.SEALED;
  724. if ((ma & TypeAttributes.Abstract) != 0)
  725. mod |= Modifiers.STATIC;
  726. } else if ((ma & TypeAttributes.Abstract) != 0) {
  727. mod |= Modifiers.ABSTRACT;
  728. }
  729. }
  730. }
  731. var definition = new ImportedTypeDefinition (type, this);
  732. TypeSpec pt;
  733. if (kind == MemberKind.Enum) {
  734. const BindingFlags underlying_member = BindingFlags.DeclaredOnly |
  735. BindingFlags.Instance |
  736. BindingFlags.Public | BindingFlags.NonPublic;
  737. var type_members = type.GetFields (underlying_member);
  738. foreach (var type_member in type_members) {
  739. spec = new EnumSpec (declaringType, definition, CreateType (type_member.FieldType), type, mod);
  740. break;
  741. }
  742. if (spec == null)
  743. kind = MemberKind.Class;
  744. } else if (kind == MemberKind.TypeParameter) {
  745. spec = CreateTypeParameter (type, declaringType);
  746. } else if (type.IsGenericTypeDefinition) {
  747. definition.TypeParameters = CreateGenericParameters (type, declaringType);
  748. } else if (compiled_types.TryGetValue (type, out pt)) {
  749. //
  750. // Same type was found in inside compiled types. It's
  751. // either build-in type or forward referenced typed
  752. // which point into just compiled assembly.
  753. //
  754. spec = pt;
  755. BuiltinTypeSpec bts = pt as BuiltinTypeSpec;
  756. if (bts != null)
  757. bts.SetDefinition (definition, type, mod);
  758. }
  759. if (spec == null)
  760. spec = new TypeSpec (kind, declaringType, definition, type, mod);
  761. import_cache.Add (type, spec);
  762. if (kind == MemberKind.TypeParameter) {
  763. if (canImportBaseType)
  764. ImportTypeParameterTypeConstraints ((TypeParameterSpec) spec, type);
  765. return spec;
  766. }
  767. //
  768. // Two stage setup as the base type can be inflated declaring type or
  769. // another nested type inside same declaring type which has not been
  770. // loaded, therefore we can import a base type of nested types once
  771. // the types have been imported
  772. //
  773. if (canImportBaseType)
  774. ImportTypeBase (spec, type);
  775. return spec;
  776. }
  777. public IAssemblyDefinition GetAssemblyDefinition (Assembly assembly)
  778. {
  779. IAssemblyDefinition found;
  780. if (!assembly_2_definition.TryGetValue (assembly, out found)) {
  781. // This can happen in dynamic context only
  782. var def = new ImportedAssemblyDefinition (assembly);
  783. assembly_2_definition.Add (assembly, def);
  784. def.ReadAttributes ();
  785. found = def;
  786. }
  787. return found;
  788. }
  789. public void ImportTypeBase (MetaType type)
  790. {
  791. TypeSpec spec = import_cache[type];
  792. if (spec != null)
  793. ImportTypeBase (spec, type);
  794. }
  795. TypeParameterSpec CreateTypeParameter (MetaType type, TypeSpec declaringType)
  796. {
  797. Variance variance;
  798. switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) {
  799. case GenericParameterAttributes.Covariant:
  800. variance = Variance.Covariant;
  801. break;
  802. case GenericParameterAttributes.Contravariant:
  803. variance = Variance.Contravariant;
  804. break;
  805. default:
  806. variance = Variance.None;
  807. break;
  808. }
  809. SpecialConstraint special = SpecialConstraint.None;
  810. var import_special = type.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
  811. if ((import_special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) {
  812. special |= SpecialConstraint.Struct;
  813. } else if ((import_special & GenericParameterAttributes.DefaultConstructorConstraint) != 0) {
  814. special = SpecialConstraint.Constructor;
  815. }
  816. if ((import_special & GenericParameterAttributes.ReferenceTypeConstraint) != 0) {
  817. special |= SpecialConstraint.Class;
  818. }
  819. TypeParameterSpec spec;
  820. var def = new ImportedTypeParameterDefinition (type, this);
  821. if (type.DeclaringMethod != null) {
  822. spec = new TypeParameterSpec (type.GenericParameterPosition, def, special, variance, type);
  823. } else {
  824. spec = new TypeParameterSpec (declaringType, type.GenericParameterPosition, def, special, variance, type);
  825. }
  826. return spec;
  827. }
  828. //
  829. // Test for a custom attribute type match. Custom attributes are not really predefined globaly
  830. // they can be assembly specific therefore we do check based on names only
  831. //
  832. public static bool HasAttribute (IList<CustomAttributeData> attributesData, string attrName, string attrNamespace)
  833. {
  834. if (attributesData.Count == 0)
  835. return false;
  836. foreach (var attr in attributesData) {
  837. var dt = attr.Constructor.DeclaringType;
  838. if (dt.Name == attrName && dt.Namespace == attrNamespace)
  839. return true;
  840. }
  841. return false;
  842. }
  843. void ImportTypeBase (TypeSpec spec, MetaType type)
  844. {
  845. if (spec.Kind == MemberKind.Interface)
  846. spec.BaseType = module.Compiler.BuiltinTypes.Object;
  847. else if (type.BaseType != null) {
  848. TypeSpec base_type;
  849. if (!IsMissingType (type.BaseType) && type.BaseType.IsGenericType)
  850. base_type = CreateType (type.BaseType, new DynamicTypeReader (type), true);
  851. else
  852. base_type = CreateType (type.BaseType);
  853. spec.BaseType = base_type;
  854. }
  855. MetaType[] ifaces;
  856. #if STATIC
  857. ifaces = type.__GetDeclaredInterfaces ();
  858. if (ifaces.Length != 0) {
  859. foreach (var iface in ifaces) {
  860. var it = CreateType (iface);
  861. if (it == null)
  862. continue;
  863. spec.AddInterface (it);
  864. // Unfortunately not all languages expand inherited interfaces
  865. var bifaces = it.Interfaces;
  866. if (bifaces != null) {
  867. foreach (var biface in bifaces) {
  868. spec.AddInterface (biface);
  869. }
  870. }
  871. }
  872. }
  873. //
  874. // It's impossible to get declared interfaces only using System.Reflection
  875. // hence we need to mimic the behavior with ikvm-reflection too to keep
  876. // our type look-up logic same
  877. //
  878. if (spec.BaseType != null) {
  879. var bifaces = spec.BaseType.Interfaces;
  880. if (bifaces != null) {
  881. //
  882. // Before adding base class interfaces close defined interfaces
  883. // on type parameter
  884. //
  885. var tp = spec as TypeParameterSpec;
  886. if (tp != null && tp.InterfacesDefined == null) {
  887. tp.InterfacesDefined = TypeSpec.EmptyTypes;
  888. }
  889. foreach (var iface in bifaces)
  890. spec.AddInterface (iface);
  891. }
  892. }
  893. #else
  894. ifaces = type.GetInterfaces ();
  895. if (ifaces.Length > 0) {
  896. foreach (var iface in ifaces) {
  897. spec.AddInterface (CreateType (iface));
  898. }
  899. }
  900. #endif
  901. if (spec.MemberDefinition.TypeParametersCount > 0) {
  902. foreach (var tp in spec.MemberDefinition.TypeParameters) {
  903. ImportTypeParameterTypeConstraints (tp, tp.GetMetaInfo ());
  904. }
  905. }
  906. }
  907. protected void ImportTypes (MetaType[] types, Namespace targetNamespace, bool importExtensionTypes)
  908. {
  909. Namespace ns = targetNamespace;
  910. string prev_namespace = null;
  911. foreach (var t in types) {
  912. if (t == null)
  913. continue;
  914. // Be careful not to trigger full parent type loading
  915. if (t.MemberType == MemberTypes.NestedType)
  916. continue;
  917. if (t.Name[0] == '<')
  918. continue;
  919. var it = CreateType (t, null, new DynamicTypeReader (t), true);
  920. if (it == null)
  921. continue;
  922. if (prev_namespace != t.Namespace) {
  923. ns = t.Namespace == null ? targetNamespace : targetNamespace.GetNamespace (t.Namespace, true);
  924. prev_namespace = t.Namespace;
  925. }
  926. // Cannot rely on assembly level Extension attribute or static modifier because they
  927. // are not followed by other compilers (e.g. F#).
  928. if (it.IsClass && it.Arity == 0 && importExtensionTypes &&
  929. HasAttribute (CustomAttributeData.GetCustomAttributes (t), "ExtensionAttribute", CompilerServicesNamespace)) {
  930. it.SetExtensionMethodContainer ();
  931. }
  932. ns.AddType (module, it);
  933. }
  934. }
  935. void ImportTypeParameterTypeConstraints (TypeParameterSpec spec, MetaType type)
  936. {
  937. var constraints = type.GetGenericParameterConstraints ();
  938. List<TypeSpec> tparams = null;
  939. foreach (var ct in constraints) {
  940. if (ct.IsGenericParameter) {
  941. if (tparams == null)
  942. tparams = new List<TypeSpec> ();
  943. tparams.Add (CreateType (ct));
  944. continue;
  945. }
  946. var constraint_type = CreateType (ct);
  947. if (constraint_type.IsClass) {
  948. spec.BaseType = constraint_type;
  949. continue;
  950. }
  951. spec.AddInterface (constraint_type);
  952. }
  953. if (spec.BaseType == null)
  954. spec.BaseType = module.Compiler.BuiltinTypes.Object;
  955. if (tparams != null)
  956. spec.TypeArguments = tparams.ToArray ();
  957. }
  958. Constant ImportParameterConstant (object value)
  959. {
  960. //
  961. // Get type of underlying value as int constant can be used for object
  962. // parameter type. This is not allowed in C# but other languages can do that
  963. //
  964. var types = module.Compiler.BuiltinTypes;
  965. switch (System.Type.GetTypeCode (value.GetType ())) {
  966. case TypeCode.Boolean:
  967. return new BoolConstant (types, (bool) value, Location.Null);
  968. case TypeCode.Byte:
  969. return new ByteConstant (types, (byte) value, Location.Null);
  970. case TypeCode.Char:
  971. return new CharConstant (types, (char) value, Location.Null);
  972. case TypeCode.Decimal:
  973. return new DecimalConstant (types, (decimal) value, Location.Null);
  974. case TypeCode.Double:
  975. return new DoubleConstant (types, (double) value, Location.Null);
  976. case TypeCode.Int16:
  977. return new ShortConstant (types, (short) value, Location.Null);
  978. case TypeCode.Int32:
  979. return new IntConstant (types, (int) value, Location.Null);
  980. case TypeCode.Int64:
  981. return new LongConstant (types, (long) value, Location.Null);
  982. case TypeCode.SByte:
  983. return new SByteConstant (types, (sbyte) value, Location.Null);
  984. case TypeCode.Single:
  985. return new FloatConstant (types, (float) value, Location.Null);
  986. case TypeCode.String:
  987. return new StringConstant (types, (string) value, Location.Null);
  988. case TypeCode.UInt16:
  989. return new UShortConstant (types, (ushort) value, Location.Null);
  990. case TypeCode.UInt32:
  991. return new UIntConstant (types, (uint) value, Location.Null);
  992. case TypeCode.UInt64:
  993. return new ULongConstant (types, (ulong) value, Location.Null);
  994. }
  995. throw new NotImplementedException (value.GetType ().ToString ());
  996. }
  997. public TypeSpec ImportType (MetaType type)
  998. {
  999. return ImportType (type, new DynamicTypeReader (type));
  1000. }
  1001. TypeSpec ImportType (MetaType type, DynamicTypeReader dtype)
  1002. {
  1003. if (type.HasElementType) {
  1004. var element = type.GetElementType ();
  1005. ++dtype.Position;
  1006. var spec = ImportType (element, dtype);
  1007. if (type.IsArray)
  1008. return ArrayContainer.MakeType (module, spec, type.GetArrayRank ());
  1009. if (type.IsByRef)
  1010. return ReferenceContainer.MakeType (module, spec);
  1011. if (type.IsPointer)
  1012. return PointerContainer.MakeType (module, spec);
  1013. throw new NotImplementedException ("Unknown element type " + type.ToString ());
  1014. }
  1015. return CreateType (type, dtype, true);
  1016. }
  1017. static bool IsMissingType (MetaType type)
  1018. {
  1019. #if STATIC
  1020. return type.__IsMissing;
  1021. #else
  1022. return false;
  1023. #endif
  1024. }
  1025. //
  1026. // Decimal constants cannot be encoded in the constant blob, and thus are marked
  1027. // as IsInitOnly ('readonly' in C# parlance). We get its value from the
  1028. // DecimalConstantAttribute metadata.
  1029. //
  1030. Constant ReadDecimalConstant (IList<CustomAttributeData> attrs)
  1031. {
  1032. if (attrs.Count == 0)
  1033. return null;
  1034. foreach (var ca in attrs) {
  1035. var dt = ca.Constructor.DeclaringType;
  1036. if (dt.Name != "DecimalConstantAttribute" || dt.Namespace != CompilerServicesNamespace)
  1037. continue;
  1038. var value = new decimal (
  1039. (int) (uint) ca.ConstructorArguments[4].Value,
  1040. (int) (uint) ca.ConstructorArguments[3].Value,
  1041. (int) (uint) ca.ConstructorArguments[2].Value,
  1042. (byte) ca.ConstructorArguments[1].Value != 0,
  1043. (byte) ca.ConstructorArguments[0].Value);
  1044. return new DecimalConstant (module.Compiler.BuiltinTypes, value, Location.Null);
  1045. }
  1046. return null;
  1047. }
  1048. static Modifiers ReadMethodModifiers (MethodBase mb, TypeSpec declaringType)
  1049. {
  1050. Modifiers mod;
  1051. var ma = mb.Attributes;
  1052. switch (ma & MethodAttributes.MemberAccessMask) {
  1053. case MethodAttributes.Public:
  1054. mod = Modifiers.PUBLIC;
  1055. break;
  1056. case MethodAttributes.Assembly:
  1057. mod = Modifiers.INTERNAL;
  1058. break;
  1059. case MethodAttributes.Family:
  1060. mod = Modifiers.PROTECTED;
  1061. break;
  1062. case MethodAttributes.FamORAssem:
  1063. mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
  1064. break;
  1065. default:
  1066. mod = Modifiers.PRIVATE;
  1067. break;
  1068. }
  1069. if ((ma & MethodAttributes.Static) != 0) {
  1070. mod |= Modifiers.STATIC;
  1071. return mod;
  1072. }
  1073. if ((ma & MethodAttributes.Abstract) != 0 && declaringType.IsClass) {
  1074. mod |= Modifiers.ABSTRACT;
  1075. return mod;
  1076. }
  1077. // It can be sealed and override
  1078. if ((ma & MethodAttributes.Final) != 0)
  1079. mod |= Modifiers.SEALED;
  1080. if ((ma & MethodAttributes.Virtual) != 0) {
  1081. // Not every member can be detected based on MethodAttribute, we
  1082. // set virtual or non-virtual only when we are certain. Further checks
  1083. // to really find out what `virtual' means for this member are done
  1084. // later
  1085. if ((ma & MethodAttributes.NewSlot) != 0) {
  1086. if ((mod & Modifiers.SEALED) != 0) {
  1087. mod &= ~Modifiers.SEALED;
  1088. } else {
  1089. mod |= Modifiers.VIRTUAL;
  1090. }
  1091. } else {
  1092. mod |= Modifiers.OVERRIDE;
  1093. }
  1094. }
  1095. return mod;
  1096. }
  1097. }
  1098. abstract class ImportedDefinition : IMemberDefinition
  1099. {
  1100. protected class AttributesBag
  1101. {
  1102. public static readonly AttributesBag Default = new AttributesBag ();
  1103. public AttributeUsageAttribute AttributeUsage;
  1104. public ObsoleteAttribute Obsolete;
  1105. public string[] Conditionals;
  1106. public string DefaultIndexerName;
  1107. public bool? CLSAttributeValue;
  1108. public TypeSpec CoClass;
  1109. public static AttributesBag Read (MemberInfo mi, MetadataImporter importer)
  1110. {
  1111. AttributesBag bag = null;
  1112. List<string> conditionals = null;
  1113. // It should not throw any loading exception
  1114. IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (mi);
  1115. foreach (var a in attrs) {
  1116. var dt = a.Constructor.DeclaringType;
  1117. string name = dt.Name;
  1118. if (name == "ObsoleteAttribute") {
  1119. if (dt.Namespace != "System")
  1120. continue;
  1121. if (bag == null)
  1122. bag = new AttributesBag ();
  1123. var args = a.ConstructorArguments;
  1124. if (args.Count == 1) {
  1125. bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value);
  1126. } else if (args.Count == 2) {
  1127. bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value, (bool) args[1].Value);
  1128. } else {
  1129. bag.Obsolete = new ObsoleteAttribute ();
  1130. }
  1131. continue;
  1132. }
  1133. if (name == "ConditionalAttribute") {
  1134. if (dt.Namespace != "System.Diagnostics")
  1135. continue;
  1136. if (bag == null)
  1137. bag = new AttributesBag ();
  1138. if (conditionals == null)
  1139. conditionals = new List<string> (2);
  1140. conditionals.Add ((string) a.ConstructorArguments[0].Value);
  1141. continue;
  1142. }
  1143. if (name == "CLSCompliantAttribute") {
  1144. if (dt.Namespace != "System")
  1145. continue;
  1146. if (bag == null)
  1147. bag = new AttributesBag ();
  1148. bag.CLSAttributeValue = (bool) a.ConstructorArguments[0].Value;
  1149. continue;
  1150. }
  1151. // Type only attributes
  1152. if (mi.MemberType == MemberTypes.TypeInfo || mi.MemberType == MemberTypes.NestedType) {
  1153. if (name == "DefaultMemberAttribute") {
  1154. if (dt.Namespace != "System.Reflection")
  1155. continue;
  1156. if (bag == null)
  1157. bag = new AttributesBag ();
  1158. bag.DefaultIndexerName = (string) a.ConstructorArguments[0].Value;
  1159. continue;
  1160. }
  1161. if (name == "AttributeUsageAttribute") {
  1162. if (dt.Namespace != "System")
  1163. continue;
  1164. if (bag == null)
  1165. bag = new AttributesBag ();
  1166. bag.AttributeUsage = new AttributeUsageAttribute ((AttributeTargets) a.ConstructorArguments[0].Value);
  1167. foreach (var named in a.NamedArguments) {
  1168. if (named.MemberInfo.Name == "AllowMultiple")
  1169. bag.AttributeUsage.AllowMultiple = (bool) named.TypedValue.Value;
  1170. else if (named.MemberInfo.Name == "Inherited")
  1171. bag.AttributeUsage.Inherited = (bool) named.TypedValue.Value;
  1172. }
  1173. continue;
  1174. }
  1175. // Interface only attribute
  1176. if (name == "CoClassAttribute") {
  1177. if (dt.Namespace != "System.Runtime.InteropServices")
  1178. continue;
  1179. if (bag == null)
  1180. bag = new AttributesBag ();
  1181. bag.CoClass = importer.ImportType ((MetaType) a.ConstructorArguments[0].Value);
  1182. continue;
  1183. }
  1184. }
  1185. }
  1186. if (bag == null)
  1187. return Default;
  1188. if (conditionals != null)
  1189. bag.Conditionals = conditionals.ToArray ();
  1190. return bag;
  1191. }
  1192. }
  1193. protected readonly MemberInfo provider;
  1194. protected AttributesBag cattrs;
  1195. protected readonly MetadataImporter importer;
  1196. public ImportedDefinition (MemberInfo provider, MetadataImporter importer)
  1197. {
  1198. this.provider = provider;
  1199. this.importer = importer;
  1200. }
  1201. #region Properties
  1202. public bool IsImported {
  1203. get {
  1204. return true;
  1205. }
  1206. }
  1207. public virtual string Name {
  1208. get {
  1209. return provider.Name;
  1210. }
  1211. }
  1212. #endregion
  1213. public string[] ConditionalConditions ()
  1214. {
  1215. if (cattrs == null)
  1216. ReadAttributes ();
  1217. return cattrs.Conditionals;
  1218. }
  1219. public ObsoleteAttribute GetAttributeObsolete ()
  1220. {
  1221. if (cattrs == null)
  1222. ReadAttributes ();
  1223. return cattrs.Obsolete;
  1224. }
  1225. public bool? CLSAttributeValue {
  1226. get {
  1227. if (cattrs == null)
  1228. ReadAttributes ();
  1229. return cattrs.CLSAttributeValue;
  1230. }
  1231. }
  1232. protected void ReadAttributes ()
  1233. {
  1234. cattrs = AttributesBag.Read (provider, importer);
  1235. }
  1236. public void SetIsAssigned ()
  1237. {
  1238. // Unused for imported members
  1239. }
  1240. public void SetIsUsed ()
  1241. {
  1242. // Unused for imported members
  1243. }
  1244. }
  1245. public class ImportedModuleDefinition
  1246. {
  1247. readonly Module module;
  1248. bool cls_compliant;
  1249. public ImportedModuleDefinition (Module module)
  1250. {
  1251. this.module = module;
  1252. }
  1253. #region Properties
  1254. public bool IsCLSCompliant {
  1255. get {
  1256. return cls_compliant;
  1257. }
  1258. }
  1259. public string Name {
  1260. get {
  1261. return module.Name;
  1262. }
  1263. }
  1264. #endregion
  1265. public void ReadAttributes ()
  1266. {
  1267. IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (module);
  1268. foreach (var a in attrs) {
  1269. var dt = a.Constructor.DeclaringType;
  1270. if (dt.Name == "CLSCompliantAttribute") {
  1271. if (dt.Namespace != "System")
  1272. continue;
  1273. cls_compliant = (bool) a.ConstructorArguments[0].Value;
  1274. continue;
  1275. }
  1276. }
  1277. }
  1278. //
  1279. // Reads assembly attributes which where attached to a special type because
  1280. // module does have assembly manifest
  1281. //
  1282. public List<Attribute> ReadAssemblyAttributes ()
  1283. {
  1284. var t = module.GetType (AssemblyAttributesPlaceholder.GetGeneratedName (Name));
  1285. if (t == null)
  1286. return null;
  1287. var field = t.GetField (AssemblyAttributesPlaceholder.AssemblyFieldName, BindingFlags.NonPublic | BindingFlags.Static);
  1288. if (field == null)
  1289. return null;
  1290. // TODO: implement, the idea is to fabricate specil Attribute class and
  1291. // add it to OptAttributes before resolving the source code attributes
  1292. // Need to build module location as well for correct error reporting
  1293. //var assembly_attributes = CustomAttributeData.GetCustomAttributes (field);
  1294. //var attrs = new List<Attribute> (assembly_attributes.Count);
  1295. //foreach (var a in assembly_attributes)
  1296. //{
  1297. // var type = metaImporter.ImportType (a.Constructor.DeclaringType);
  1298. // var ctor = metaImporter.CreateMethod (a.Constructor, type);
  1299. // foreach (var carg in a.ConstructorArguments) {
  1300. // carg.Value
  1301. // }
  1302. // attrs.Add (new Attribute ("assembly", ctor, null, Location.Null, true));
  1303. //}
  1304. return null;
  1305. }
  1306. }
  1307. public class ImportedAssemblyDefinition : IAssemblyDefinition
  1308. {
  1309. readonly Assembly assembly;
  1310. readonly AssemblyName aname;
  1311. bool cls_compliant;
  1312. List<AssemblyName> internals_visible_to;
  1313. Dictionary<IAssemblyDefinition, AssemblyName> internals_visible_to_cache;
  1314. public ImportedAssemblyDefinition (Assembly assembly)
  1315. {
  1316. this.assembly = assembly;
  1317. this.aname = assembly.GetName ();
  1318. }
  1319. #region Properties
  1320. public Assembly Assembly {
  1321. get {
  1322. return assembly;
  1323. }
  1324. }
  1325. public string FullName {
  1326. get {
  1327. return aname.FullName;
  1328. }
  1329. }
  1330. public bool HasStrongName {
  1331. get {
  1332. return aname.GetPublicKey ().Length != 0;
  1333. }
  1334. }
  1335. public bool IsMissing {
  1336. get {
  1337. #if STATIC
  1338. return assembly.__IsMissing;
  1339. #else
  1340. return false;
  1341. #endif
  1342. }
  1343. }
  1344. public bool IsCLSCompliant {
  1345. get {
  1346. return cls_compliant;
  1347. }
  1348. }
  1349. public string Location {
  1350. get {
  1351. return assembly.Location;
  1352. }
  1353. }
  1354. public string Name {
  1355. get {
  1356. return aname.Name;
  1357. }
  1358. }
  1359. #endregion
  1360. public byte[] GetPublicKeyToken ()
  1361. {
  1362. return aname.GetPublicKeyToken ();
  1363. }
  1364. public AssemblyName GetAssemblyVisibleToName (IAssemblyDefinition assembly)
  1365. {
  1366. return internals_visible_to_cache [assembly];
  1367. }
  1368. public bool IsFriendAssemblyTo (IAssemblyDefinition assembly)
  1369. {
  1370. if (internals_visible_to == null)
  1371. return false;
  1372. AssemblyName is_visible = null;
  1373. if (internals_visible_to_cache == null) {
  1374. internals_visible_to_cache = new Dictionary<IAssemblyDefinition, AssemblyName> ();
  1375. } else {
  1376. if (internals_visible_to_cache.TryGetValue (assembly, out is_visible))
  1377. return is_visible != null;
  1378. }
  1379. var token = assembly.GetPublicKeyToken ();
  1380. if (token != null && token.Length == 0)
  1381. token = null;
  1382. foreach (var internals in internals_visible_to) {
  1383. if (internals.Name != assembly.Name)
  1384. continue;
  1385. if (token == null && assembly is AssemblyDefinition) {
  1386. is_visible = internals;
  1387. break;
  1388. }
  1389. if (!ArrayComparer.IsEqual (token, internals.GetPublicKeyToken ()))
  1390. continue;
  1391. is_visible = internals;
  1392. break;
  1393. }
  1394. internals_visible_to_cache.Add (assembly, is_visible);
  1395. return is_visible != null;
  1396. }
  1397. public void ReadAttributes ()
  1398. {
  1399. #if STATIC
  1400. if (assembly.__IsMissing)
  1401. return;
  1402. #endif
  1403. IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (assembly);
  1404. foreach (var a in attrs) {
  1405. var dt = a.Constructor.DeclaringType;
  1406. var name = dt.Name;
  1407. if (name == "CLSCompliantAttribute") {
  1408. if (dt.Namespace == "System") {
  1409. cls_co

Large files files are truncated, but you can click here to view the full file