[mcs] New property/indexer cannot have accessors implementing an interface in base...
[mono.git] / mcs / mcs / import.cs
index 98254207136904fa18e8867abc8b3fe401c1cf0e..dbec2c0469f603bce116c228d4a3252b2abc85be 100644 (file)
@@ -13,6 +13,7 @@ using System;
 using System.Runtime.CompilerServices;
 using System.Linq;
 using System.Collections.Generic;
+using System.IO;
 
 #if STATIC
 using MetaType = IKVM.Reflection.Type;
@@ -141,6 +142,7 @@ namespace Mono.CSharp
                        compiled_types = new Dictionary<MetaType, TypeSpec> (40, ReferenceEquality<MetaType>.Default);
                        assembly_2_definition = new Dictionary<Assembly, IAssemblyDefinition> (ReferenceEquality<Assembly>.Default);
                        IgnorePrivateMembers = true;
+                       IgnoreCompilerGeneratedField = true;
                }
 
                #region Properties
@@ -153,6 +155,8 @@ namespace Mono.CSharp
 
                public bool IgnorePrivateMembers { get; set; }
 
+               public bool IgnoreCompilerGeneratedField { get; set; }
+
                #endregion
 
                public abstract void AddCompiledType (TypeBuilder builder, TypeSpec spec);
@@ -178,8 +182,10 @@ namespace Mono.CSharp
                                        break;
                                default:
                                        // Ignore private fields (even for error reporting) to not require extra dependencies
-                                       if ((IgnorePrivateMembers && !declaringType.IsStruct) ||
-                                               HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
+                                       if (IgnorePrivateMembers && !declaringType.IsStruct)
+                                               return null;
+
+                                       if (IgnoreCompilerGeneratedField && HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace))
                                                return null;
 
                                        mod = Modifiers.PRIVATE;
@@ -189,7 +195,7 @@ namespace Mono.CSharp
                        TypeSpec field_type;
 
                        try {
-                               field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi));
+                               field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi), declaringType);
 
                                //
                                // Private field has private type which is not fixed buffer
@@ -209,14 +215,14 @@ namespace Mono.CSharp
                                Constant c = field_type.Kind == MemberKind.MissingType ?
                                        new NullConstant (InternalType.ErrorType, Location.Null) :
                                        CreateConstantFromValue (field_type, fi);
-                               return new ConstSpec (declaringType, definition, field_type, fi, mod, c);
+                               return new ConstSpec (declaringType, definition, field_type, fi, mod | Modifiers.STATIC, c);
                        }
 
                        if ((fa & FieldAttributes.InitOnly) != 0) {
                                if (field_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
                                        var dc = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (fi));
                                        if (dc != null)
-                                               return new ConstSpec (declaringType, definition, field_type, fi, mod, dc);
+                                               return new ConstSpec (declaringType, definition, field_type, fi, mod | Modifiers.STATIC, dc);
                                }
 
                                mod |= Modifiers.READONLY;
@@ -269,7 +275,7 @@ namespace Mono.CSharp
                        if (add.Modifiers != remove.Modifiers)
                                throw new NotImplementedException ("Different accessor modifiers " + ei.Name);
 
-                       var event_type = ImportType (ei.EventHandlerType, new DynamicTypeReader (ei));
+                       var event_type = ImportType (ei.EventHandlerType, new DynamicTypeReader (ei), declaringType);
                        var definition = new ImportedMemberDefinition (ei, event_type,  this);
                        return new EventSpec (declaringType, definition, event_type, add.Modifiers, add, remove);
                }
@@ -340,7 +346,7 @@ namespace Mono.CSharp
                                if (type.HasElementType) {
                                        var element = type.GetElementType ();
                                        ++dtype.Position;
-                                       spec = ImportType (element, dtype);
+                                       spec = ImportType (element, dtype, null);
 
                                        if (!type.IsArray) {
                                                throw new NotImplementedException ("Unknown element type " + type.ToString ());
@@ -359,7 +365,7 @@ namespace Mono.CSharp
                                        // }
                                        //
                                        if (!IsMissingType (type) && type.IsGenericTypeDefinition) {
-                                               var start_pos = spec.DeclaringType == null ? 0 : spec.DeclaringType.MemberDefinition.TypeParametersCount;
+                                               var start_pos = GetDeclaringTypesTypeParametersCount (spec);
                                                var targs = CreateGenericArguments (start_pos, type.GetGenericArguments (), dtype);
                                                spec = spec.MakeGenericType (module, targs);
                                        }
@@ -375,6 +381,17 @@ namespace Mono.CSharp
                        return tspec;
                }
 
+               static int GetDeclaringTypesTypeParametersCount (TypeSpec spec)
+               {
+                       int total = 0;
+                       while (spec.DeclaringType != null) {
+                               total += spec.DeclaringType.MemberDefinition.TypeParametersCount;
+                               spec = spec.DeclaringType;
+                       }
+
+                       return total;
+               }
+
                public MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType)
                {
                        Modifiers mod = ReadMethodModifiers (mb, declaringType);
@@ -397,6 +414,9 @@ namespace Mono.CSharp
                                kind = MemberKind.Constructor;
                                returnType = module.Compiler.BuiltinTypes.Void;
                        } else {
+                               var mi = (MethodInfo)mb;
+                               returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter), declaringType);
+
                                //
                                // Detect operators and destructors
                                //
@@ -410,7 +430,7 @@ namespace Mono.CSharp
                                                                kind = MemberKind.Operator;
                                                        }
                                                }
-                                       } else if (parameters.IsEmpty && name == Destructor.MetadataName) {
+                                       } else if (parameters.IsEmpty && name == Destructor.MetadataName && returnType.Kind == MemberKind.Void) {
                                                kind = MemberKind.Destructor;
                                                if (declaringType.BuiltinType == BuiltinTypeSpec.Type.Object) {
                                                        mod &= ~Modifiers.OVERRIDE;
@@ -419,9 +439,6 @@ namespace Mono.CSharp
                                        }
                                }
 
-                               var mi = (MethodInfo) mb;
-                               returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter));
-
                                // Cannot set to OVERRIDE without full hierarchy checks
                                // this flag indicates that the method could be override
                                // but further validation is needed
@@ -528,13 +545,13 @@ namespace Mono.CSharp
                                        // Strip reference wrapping
                                        //
                                        var el = p.ParameterType.GetElementType ();
-                                       types[i] = ImportType (el, new DynamicTypeReader (p));  // TODO: 1-based positio to be csc compatible
+                                       types[i] = ImportType (el, new DynamicTypeReader (p), parent);  // TODO: 1-based positio to be csc compatible
                                } else if (i == 0 && method.IsStatic && (parent.Modifiers & Modifiers.METHOD_EXTENSION) != 0 &&
                                        HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) {
                                        mod = Parameter.Modifier.This;
-                                       types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p));
+                                       types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p), parent);
                                } else {
-                                       types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p));
+                                       types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p), parent);
 
                                        if (i >= pi.Length - 2 && types[i] is ArrayContainer) {
                                                if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) {
@@ -628,14 +645,7 @@ namespace Mono.CSharp
                                        if (set_param_count == 0) {
                                                set_based_param = ParametersCompiled.EmptyReadOnlyParameters;
                                        } else {
-                                               //
-                                               // Create indexer parameters based on setter method parameters (the last parameter has to be removed)
-                                               //
-                                               var data = new IParameterData[set_param_count];
-                                               var types = new TypeSpec[set_param_count];
-                                               Array.Copy (set.Parameters.FixedParameters, data, set_param_count);
-                                               Array.Copy (set.Parameters.Types, types, set_param_count);
-                                               set_based_param = new ParametersImported (data, types, set.Parameters.HasParams);
+                                               set_based_param = IndexerSpec.CreateParametersFromSetter (set, set_param_count);
                                        }
 
                                        mod = set.Modifiers;
@@ -675,20 +685,16 @@ namespace Mono.CSharp
                        if (!param.IsEmpty) {
                                if (is_valid_property) {
                                        var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember ();
-                                       if (index_name == null) {
+                                       if (index_name == null || index_name != pi.Name) {
                                                is_valid_property = false;
                                        } else {
                                                if (get != null) {
                                                        if (get.IsStatic)
                                                                is_valid_property = false;
-                                                       if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
-                                                               is_valid_property = false;
                                                }
                                                if (set != null) {
                                                        if (set.IsStatic)
                                                                is_valid_property = false;
-                                                       if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4)
-                                                               is_valid_property = false;
                                                }
                                        }
 
@@ -817,7 +823,7 @@ namespace Mono.CSharp
                                                if (t.Kind == MemberKind.MissingType)
                                                        spec = t;
                                                else
-                                                       spec = MemberCache.FindNestedType (spec, t.Name, t.Arity);
+                                                       spec = MemberCache.FindNestedType (spec, t.Name, t.Arity, false);
 
                                                if (t.Arity > 0) {
                                                        spec = spec.MakeGenericType (module, targs.Skip (targs_pos).Take (spec.Arity).ToArray ());
@@ -837,7 +843,7 @@ namespace Mono.CSharp
                                                if (index > 0)
                                                        name = name.Substring (0, index);
 
-                                               spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos);
+                                               spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos, false);
 
                                                if (spec.Arity > 0) {
                                                        spec = spec.MakeGenericType (module, targs.Skip (targs_pos).ToArray ());
@@ -979,6 +985,21 @@ namespace Mono.CSharp
                        return found;
                }
 
+               public ImportedAssemblyDefinition GetImportedAssemblyDefinition (AssemblyName assemblyName)
+               {
+                       foreach (var a in Assemblies) {
+                               var ia = a as ImportedAssemblyDefinition;
+                               if (ia == null)
+                                       continue;
+                               
+                               if (a.Name == assemblyName.Name)
+                                       return ia;
+                       }
+
+                       return null;
+               }
+
+
                public void ImportTypeBase (MetaType type)
                {
                        TypeSpec spec = import_cache[type];
@@ -1064,7 +1085,7 @@ namespace Mono.CSharp
                        }
                }
 
-               protected void ImportTypes (MetaType[] types, Namespace targetNamespace, bool importExtensionTypes)
+               public void ImportTypes (MetaType[] types, Namespace targetNamespace, bool importExtensionTypes)
                {
                        Namespace ns = targetNamespace;
                        string prev_namespace = null;
@@ -1171,15 +1192,15 @@ namespace Mono.CSharp
 
                public TypeSpec ImportType (MetaType type)
                {
-                       return ImportType (type, new DynamicTypeReader (type));
+                       return ImportType (type, new DynamicTypeReader (type), null);
                }
 
-               TypeSpec ImportType (MetaType type, DynamicTypeReader dtype)
+               TypeSpec ImportType (MetaType type, DynamicTypeReader dtype, TypeSpec currentType)
                {
                        if (type.HasElementType) {
                                var element = type.GetElementType ();
                                ++dtype.Position;
-                               var spec = ImportType (element, dtype);
+                               var spec = ImportType (element, dtype, currentType);
 
                                if (type.IsArray)
                                        return ArrayContainer.MakeType (module, spec, type.GetArrayRank ());
@@ -1195,11 +1216,19 @@ namespace Mono.CSharp
                        if (compiled_types.TryGetValue (type, out compiled_type)) {
                                if (compiled_type.BuiltinType == BuiltinTypeSpec.Type.Object && dtype.IsDynamicObject ())
                                        return module.Compiler.BuiltinTypes.Dynamic;
+                       } else {
+                               compiled_type = CreateType (type, dtype, true);
+                       }
 
-                               return compiled_type;
+                       if (currentType == compiled_type && currentType?.IsGeneric == true) {
+                               //
+                               // Inflates current type to match behaviour of TypeDefinition::CurrentType used by compiled types
+                               //
+                               var targs = compiled_type.MemberDefinition.TypeParameters;
+                               compiled_type = compiled_type.MakeGenericType (module, targs);
                        }
 
-                       return CreateType (type, dtype, true);
+                       return compiled_type;
                }
 
                static bool IsMissingType (MetaType type)
@@ -1678,7 +1707,7 @@ namespace Mono.CSharp
                                token = null;
 
                        foreach (var internals in internals_visible_to) {
-                               if (internals.Name != assembly.Name)
+                               if (!String.Equals(internals.Name, assembly.Name, StringComparison.OrdinalIgnoreCase))
                                        continue;
 
                                if (token == null && assembly is AssemblyDefinition) {
@@ -1724,7 +1753,14 @@ namespace Mono.CSharp
                                        if (s == null)
                                                continue;
 
-                                       var an = new AssemblyName (s);
+                                       AssemblyName an;
+                                       try {
+                                               an = new AssemblyName (s);
+                                       } catch (FileLoadException) {
+                                               // Invalid assembly name reuses FileLoadException
+                                               continue;
+                                       }
+
                                        if (internals_visible_to == null)
                                                internals_visible_to = new List<AssemblyName> ();