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