Deal with missing nested type as well
[mono.git] / mcs / mcs / ikvm.cs
1 //
2 // ikvm.cs: IKVM.Reflection and IKVM.Reflection.Emit specific implementations
3 //
4 // Author: Marek Safar (marek.safar@gmail.com)
5 //
6 // Dual licensed under the terms of the MIT X11 or GNU GPL
7 //
8 // Copyright 2009-2010 Novell, Inc. 
9 //
10 //
11
12 using System;
13 using System.Collections.Generic;
14 using MetaType = IKVM.Reflection.Type;
15 using IKVM.Reflection;
16 using IKVM.Reflection.Emit;
17 using System.IO;
18 using System.Configuration.Assemblies;
19
20 namespace Mono.CSharp
21 {
22 #if !STATIC
23         public class StaticImporter
24         {
25                 public StaticImporter (BuildinTypes buildin)
26                 {
27                         throw new NotSupportedException ();
28                 }
29
30                 public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
31                 {
32                         throw new NotSupportedException ();
33                 }
34
35                 public void ImportModule (Module module, RootNamespace targetNamespace)
36                 {
37                         throw new NotSupportedException ();
38                 }
39
40                 public TypeSpec ImportType (System.Type type)
41                 {
42                         throw new NotSupportedException ();
43                 }
44         }
45
46 #else
47
48         sealed class StaticImporter : MetadataImporter
49         {
50                 public StaticImporter ()
51                 {
52                 }
53
54                 protected override MemberKind DetermineKindFromBaseType (MetaType baseType)
55                 {
56                         string name = baseType.Name;
57
58                         if (name == "ValueType" && baseType.Namespace == "System")
59                                 return MemberKind.Struct;
60
61                         if (name == "Enum" && baseType.Namespace == "System")
62                                 return MemberKind.Enum;
63
64                         if (name == "MulticastDelegate" && baseType.Namespace == "System")
65                                 return MemberKind.Delegate;
66
67                         return MemberKind.Class;
68                 }
69
70                 protected override bool HasVolatileModifier (MetaType[] modifiers)
71                 {
72                         foreach (var t in modifiers) {
73                                 if (t.Name == "IsVolatile" && t.Namespace == CompilerServicesNamespace)
74                                         return true;
75                         }
76
77                         return false;
78                 }
79
80                 public override void GetCustomAttributeTypeName (CustomAttributeData cad, out string typeNamespace, out string typeName)
81                 {
82                         cad.__ReadTypeName (out typeNamespace, out typeName);
83                 }
84
85                 public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
86                 {
87                         // It can be used more than once when importing same assembly
88                         // into 2 or more global aliases
89                         var definition = GetAssemblyDefinition (assembly);
90
91                         var all_types = assembly.GetTypes ();
92                         ImportTypes (all_types, targetNamespace, definition.HasExtensionMethod);
93                 }
94
95                 public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
96                 {
97                         var module_definition = new ImportedModuleDefinition (module, this);
98                         module_definition.ReadAttributes ();
99
100                         var all_types = module.GetTypes ();
101                         ImportTypes (all_types, targetNamespace, false);
102
103                         return module_definition;
104                 }
105
106                 public void InitializeBuildinTypes (BuildinTypes buildin, Assembly corlib)
107                 {
108                         //
109                         // Setup mapping for build-in types to avoid duplication of their definition
110                         //
111                         foreach (var type in buildin.AllTypes) {
112                                 buildin_types.Add (corlib.GetType (type.FullName), type);
113                         }
114                 }
115         }
116 #endif
117
118         class AssemblyDefinitionStatic : AssemblyDefinition
119         {
120                 //
121                 // Assembly container with file output
122                 //
123                 public AssemblyDefinitionStatic (ModuleContainer module, string name, string fileName)
124                         : base (module, name, fileName)
125                 {
126                 }
127
128                 //
129                 // Initializes the code generator
130                 //
131                 public bool Create (StaticLoader loader)
132                 {
133                         ResolveAssemblySecurityAttributes ();
134                         var an = CreateAssemblyName ();
135
136                         Builder = loader.Domain.DefineDynamicAssembly (an, AssemblyBuilderAccess.Save, Path.GetDirectoryName (file_name));
137
138                         if (loader.Corlib != null) {
139                                 Builder.__SetImageRuntimeVersion (loader.Corlib.ImageRuntimeVersion, 0x20000);
140                         } else {
141                                 // Sets output file metadata version when there is no mscorlib
142                                 switch (RootContext.StdLibRuntimeVersion) {
143                                 case RuntimeVersion.v4:
144                                         Builder.__SetImageRuntimeVersion ("v4.0.30319", 0x20000);
145                                         break;
146                                 case RuntimeVersion.v2:
147                                         Builder.__SetImageRuntimeVersion ("v2.0.50727", 0x20000);
148                                         break;
149                                 case RuntimeVersion.v1:
150                                         // Compiler does not do any checks whether the produced metadata
151                                         // are valid in the context of 1.0 stream version
152                                         Builder.__SetImageRuntimeVersion ("v1.1.4322", 0x10000);
153                                         break;
154                                 default:
155                                         throw new NotImplementedException ();
156                                 }
157                         }
158
159                         builder_extra = new AssemblyBuilderIKVM (Builder, Compiler);
160                         return true;
161                 }
162
163                 public Module IncludeModule (RawModule moduleFile)
164                 {
165                         return Builder.__AddModule (moduleFile);
166                 }
167
168                 protected override void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine)
169                 {
170                         module.Builder.__Save (pekind, machine);
171                 }
172         }
173
174         class StaticLoader : AssemblyReferencesLoader<Assembly>, IDisposable
175         {
176                 readonly StaticImporter importer;
177                 readonly Universe domain;
178                 Assembly corlib;
179
180                 public StaticLoader (StaticImporter importer, CompilerContext compiler)
181                         : base (compiler)
182                 {
183                         this.importer = importer;
184                         domain = new Universe ();
185                         domain.AssemblyResolve += AssemblyReferenceResolver;
186
187                         // TODO: profile specific
188                         paths.Add (Path.GetDirectoryName (typeof (object).Assembly.Location));
189                 }
190
191                 public Assembly Corlib {
192                         get {
193                                 return corlib;
194                         }
195                         set {
196                                 corlib = value;
197                         }
198                 }
199
200                 public Universe Domain {
201                         get {
202                                 return domain;
203                         }
204                 }
205
206                 Assembly AssemblyReferenceResolver (object sender, IKVM.Reflection.ResolveEventArgs args)
207                 {
208                         if (args.Name == "mscorlib")
209                                 return corlib;
210
211                         // AssemblyReference has not been found in the domain
212                         // create missing reference and continue
213                         return new MissingAssembly (domain, args.Name);
214                 }
215
216                 public void Dispose ()
217                 {
218                         domain.Dispose ();
219                 }
220
221                 protected override string[] GetDefaultReferences ()
222                 {
223                         //
224                         // For now the "default config" is harcoded into the compiler
225                         // we can move this outside later
226                         //
227                         var default_references = new List<string> (4);
228
229                         default_references.Add ("System.dll");
230                         default_references.Add ("System.Xml.dll");
231
232                         if (RootContext.Version > LanguageVersion.ISO_2)
233                                 default_references.Add ("System.Core.dll");
234                         if (RootContext.Version > LanguageVersion.V_3)
235                                 default_references.Add ("Microsoft.CSharp.dll");
236
237                         return default_references.ToArray ();
238                 }
239
240                 public override bool HasObjectType (Assembly assembly)
241                 {
242                         return assembly.GetType (compiler.BuildinTypes.Object.FullName) != null;
243                 }
244
245                 public override Assembly LoadAssemblyFile (string fileName)
246                 {
247                         bool? has_extension = null;
248                         foreach (var path in paths) {
249                                 var file = Path.Combine (path, fileName);
250                                 if (!File.Exists (file)) {
251                                         if (!has_extension.HasValue)
252                                                 has_extension = fileName.EndsWith (".dll", StringComparison.Ordinal) || fileName.EndsWith (".exe", StringComparison.Ordinal);
253
254                                         if (has_extension.Value)
255                                                 continue;
256
257                                         file += ".dll";
258                                         if (!File.Exists (file))
259                                                 continue;
260                                 }
261
262                                 try {
263                                         using (RawModule module = domain.OpenRawModule (file)) {
264                                                 if (!module.IsManifestModule) {
265                                                         Error_AssemblyIsModule (fileName);
266                                                         return null;
267                                                 }
268
269                                                 return domain.LoadAssembly (module);
270                                         }
271                                 } catch {
272                                         Error_FileCorrupted (file);
273                                         return null;
274                                 }
275                         }
276
277                         Error_FileNotFound (fileName);
278                         return null;
279                 }
280
281                 public RawModule LoadModuleFile (string moduleName)
282                 {
283                         foreach (var path in paths) {
284                                 var file = Path.Combine (path, moduleName);
285                                 if (!File.Exists (file)) {
286                                         if (moduleName.EndsWith (".netmodule", StringComparison.Ordinal))
287                                                 continue;
288
289                                         file += ".netmodule";
290                                         if (!File.Exists (file))
291                                                 continue;
292                                 }
293
294                                 try {
295                                         return domain.OpenRawModule (file);
296                                 } catch {
297                                         Error_FileCorrupted (file);
298                                         return null;
299                                 }
300                         }
301
302                         Error_FileNotFound (moduleName);
303                         return null;                            
304                 }
305
306                 //
307                 // Optimized default assembly loader version
308                 //
309                 public override Assembly LoadAssemblyDefault (string assembly)
310                 {
311                         foreach (var path in paths) {
312                                 var file = Path.Combine (path, assembly);
313                                 if (!File.Exists (file))
314                                         continue;
315
316                                 try {
317                                         return domain.LoadFile (file);
318                                 } catch {
319                                         // Default assemblies can fail to load without error
320                                         return null;
321                                 }
322                         }
323
324                         return null;
325                 }
326
327                 public override void LoadReferences (ModuleContainer module)
328                 {
329                         List<Tuple<RootNamespace, Assembly>> loaded;
330                         base.LoadReferencesCore (module, out corlib, out loaded);
331
332                         if (corlib != null) {
333                                 importer.InitializeBuildinTypes (compiler.BuildinTypes, corlib);
334                                 importer.ImportAssembly (corlib, module.GlobalRootNamespace);
335                         }
336
337                         foreach (var entry in loaded) {
338                                 importer.ImportAssembly (entry.Item2, entry.Item1);
339                         }
340                 }
341
342                 public void LoadModules (AssemblyDefinitionStatic assembly, RootNamespace targetNamespace)
343                 {
344                         if (RootContext.Modules.Count == 0)
345                                 return;
346
347                         foreach (var moduleName in RootContext.Modules) {
348                                 var m = LoadModuleFile (moduleName);
349                                 if (m == null)
350                                         continue;
351
352                                 if (m.IsManifestModule) {
353                                         Error_FileCorrupted (moduleName);
354                                         continue;
355                                 }
356
357                                 var md = importer.ImportModule (assembly.IncludeModule (m), targetNamespace);
358                                 assembly.AddModule (md);
359                         }
360                 }
361         }
362
363         //
364         // Represents missing assembly reference
365         //
366         public class MissingAssembly : Assembly
367         {
368                 class MissingModule : Module
369                 {
370                         readonly Assembly assembly;
371
372                         public MissingModule (Universe universe, Assembly assembly)
373                                 : base (universe)
374                         {
375                                 this.assembly = assembly;
376                         }
377
378                         public override int MDStreamVersion {
379                                 get {
380                                         throw new NotImplementedException ();
381                                 }
382                         }
383
384                         public override Assembly Assembly {
385                                 get {
386                                         return assembly;
387                                 }
388                         }
389
390                         public override string FullyQualifiedName {
391                                 get {
392                                         throw new NotImplementedException ();
393                                 }
394                         }
395
396                         public override string Name {
397                                 get {
398                                         throw new NotImplementedException ();
399                                 }
400                         }
401
402                         public override Guid ModuleVersionId {
403                                 get {
404                                         throw new NotImplementedException ();
405                                 }
406                         }
407
408                         public override MetaType ResolveType (int metadataToken, MetaType[] genericTypeArguments, MetaType[] genericMethodArguments)
409                         {
410                                 throw new NotImplementedException ();
411                         }
412
413                         public override MethodBase ResolveMethod (int metadataToken, MetaType[] genericTypeArguments, MetaType[] genericMethodArguments)
414                         {
415                                 throw new NotImplementedException ();
416                         }
417
418                         public override FieldInfo ResolveField (int metadataToken, MetaType[] genericTypeArguments, MetaType[] genericMethodArguments)
419                         {
420                                 throw new NotImplementedException ();
421                         }
422
423                         public override MemberInfo ResolveMember (int metadataToken, MetaType[] genericTypeArguments, MetaType[] genericMethodArguments)
424                         {
425                                 throw new NotImplementedException ();
426                         }
427
428                         public override string ResolveString (int metadataToken)
429                         {
430                                 throw new NotImplementedException ();
431                         }
432
433                         public override MetaType[] __ResolveOptionalParameterTypes (int metadataToken)
434                         {
435                                 throw new NotImplementedException ();
436                         }
437
438                         public override string ScopeName {
439                                 get {
440                                         throw new NotImplementedException ();
441                                 }
442                         }
443
444                         internal override MetaType GetTypeImpl (string typeName)
445                         {
446                                 throw new NotImplementedException ();
447                         }
448
449                         internal override void GetTypesImpl (List<MetaType> list)
450                         {
451                                 throw new NotImplementedException ();
452                         }
453
454                         public override AssemblyName[] __GetReferencedAssemblies ()
455                         {
456                                 throw new NotImplementedException ();
457                         }
458
459                         internal override MetaType GetModuleType ()
460                         {
461                                 throw new NotImplementedException ();
462                         }
463
464                         internal override IKVM.Reflection.Reader.ByteReader GetBlob (int blobIndex)
465                         {
466                                 throw new NotImplementedException ();
467                         }
468                 }
469
470                 readonly string full_name;
471                 readonly Module module;
472                 Dictionary<string, MetaType> types;
473
474                 public MissingAssembly (Universe universe, string fullName)
475                         : base (universe)
476                 {
477                         this.full_name = fullName;
478                         this.module = new MissingModule (universe, this);
479                         types = new Dictionary<string, MetaType> ();
480                 }
481
482                 public override MetaType[] GetTypes ()
483                 {
484                         throw new NotImplementedException ();
485                 }
486
487                 public override string FullName {
488                         get {
489                                 return full_name;
490                         }
491                 }
492
493                 public override AssemblyName GetName ()
494                 {
495                         return new AssemblyName (full_name);
496                 }
497
498                 public override string ImageRuntimeVersion {
499                         get {
500                                 throw new NotImplementedException ();
501                         }
502                 }
503
504                 public override Module ManifestModule {
505                         get {
506                                 return module;
507                         }
508                 }
509
510                 public override MethodInfo EntryPoint {
511                         get {
512                                 throw new NotImplementedException ();
513                         }
514                 }
515
516                 public override string Location {
517                         get {
518                                 throw new NotImplementedException ();
519                         }
520                 }
521
522                 public override AssemblyName[] GetReferencedAssemblies ()
523                 {
524                         throw new NotImplementedException ();
525                 }
526
527                 public override Module[] GetModules (bool getResourceModules)
528                 {
529                         throw new NotImplementedException ();
530                 }
531
532                 public override Module[] GetLoadedModules (bool getResourceModules)
533                 {
534                         throw new NotImplementedException ();
535                 }
536
537                 public override Module GetModule (string name)
538                 {
539                         throw new NotImplementedException ();
540                 }
541
542                 public override string[] GetManifestResourceNames ()
543                 {
544                         throw new NotImplementedException ();
545                 }
546
547                 public override ManifestResourceInfo GetManifestResourceInfo (string resourceName)
548                 {
549                         throw new NotImplementedException ();
550                 }
551
552                 public override Stream GetManifestResourceStream (string resourceName)
553                 {
554                         throw new NotImplementedException ();
555                 }
556
557                 internal override MetaType GetTypeImpl (string typeName)
558                 {
559                         //
560                         // We are loading a type from missing reference
561                         // this itself is fine. The error will be reported
562                         // later when the type is actually used
563                         //
564                         MetaType t;
565                         if (!types.TryGetValue (typeName, out t)) {
566                                 t = new MissingType (typeName, this);
567                                 types.Add (typeName, t);
568                         }
569
570                         return t;
571                 }
572
573                 internal override IList<CustomAttributeData> GetCustomAttributesData (MetaType attributeType)
574                 {
575                         throw new NotImplementedException ();
576                 }
577         }
578
579         public class MissingType : MetaType
580         {
581                 readonly string full_name;
582                 readonly MissingAssembly assembly;
583
584                 public MissingType (string typeName, MissingAssembly assembly)
585                 {
586                         this.full_name = typeName;
587                         this.assembly = assembly;
588                 }
589
590                 public override TypeAttributes Attributes {
591                         get {
592                                 // TODO: Don't know yet
593                                 return TypeAttributes.Public;
594                         }
595                 }
596
597                 public override MetaType BaseType {
598                         get {
599                                 return null;
600                         }
601                 }
602
603                 public override string FullName {
604                         get {
605                                 return full_name;
606                         }
607                 }
608
609                 internal override MetaType GetGenericTypeArgument (int index)
610                 {
611                         return new MissingType ("#" + index.ToString (), assembly);
612                 }
613
614                 public override MetaType GetNestedType (string name, BindingFlags bindingAttr)
615                 {
616                         return new MissingType (full_name + name, assembly);
617                 }
618
619                 public override bool IsGenericTypeDefinition {
620                         get {
621                                 return full_name.IndexOf ('`') > 0;
622                         }
623                 }
624
625                 public override Module Module {
626                         get {
627                                 return assembly.ManifestModule;
628                         }
629                 }
630         }
631
632         class AssemblyBuilderIKVM : AssemblyBuilderExtension
633         {
634                 readonly AssemblyBuilder builder;
635
636                 public AssemblyBuilderIKVM (AssemblyBuilder builder, CompilerContext ctx)
637                         : base (ctx)
638                 {
639                         this.builder = builder;
640                 }
641
642                 public override void AddTypeForwarder (TypeSpec type, Location loc)
643                 {
644                         builder.__AddTypeForwarder (type.GetMetaInfo ());
645                 }
646
647                 public override void DefineWin32IconResource (string fileName)
648                 {
649                         builder.__DefineIconResource (File.ReadAllBytes (fileName));
650                 }
651
652                 public override void SetAlgorithmId (uint value, Location loc)
653                 {
654                         builder.__SetAssemblyAlgorithmId ((AssemblyHashAlgorithm) value);
655                 }
656
657                 public override void SetCulture (string culture, Location loc)
658                 {
659                         builder.__SetAssemblyCulture (culture);
660                 }
661
662                 public override void SetFlags (uint flags, Location loc)
663                 {
664                         builder.__SetAssemblyFlags ((AssemblyNameFlags) flags);
665                 }
666
667                 public override void SetVersion (Version version, Location loc)
668                 {
669                         builder.__SetAssemblyVersion (version);
670                 }
671         }
672 }