[bcl] Add .NET 4.7 reference assemblies (#4791)
[mono.git] / mcs / mcs / typespec.cs
index 8337ce59b8d91eb89391baa3908d53184c1b6659..696bde556c820ad00f9d206bac897e80c10ee470 100644 (file)
@@ -12,6 +12,7 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using System.Linq;
 
 #if STATIC
 using MetaType = IKVM.Reflection.Type;
@@ -91,8 +92,25 @@ namespace Mono.CSharp
                        }
                }
 
+               //
+               // Returns a list of all interfaces including
+               // interfaces from base type or base interfaces
+               //
                public virtual IList<TypeSpec> Interfaces {
                        get {
+                               if ((state & StateFlags.InterfacesImported) == 0) {
+                                       state |= StateFlags.InterfacesImported;
+
+                                       //
+                                       // Delay interfaces expansion to save memory and once all
+                                       // base types has been imported to avoid problems where
+                                       // interface references type before its base was imported
+                                       //
+                                       var imported = MemberDefinition as ImportedTypeDefinition;
+                                       if (imported != null && Kind != MemberKind.MissingType)
+                                               imported.DefineInterfaces (this);
+                               }
+
                                return ifaces;
                        }
                        set {
@@ -192,7 +210,7 @@ namespace Mono.CSharp
                //
                // Returns true for instances of IList<T>, IEnumerable<T>, ICollection<T>
                //
-               public virtual bool IsGenericIterateInterface {
+               public virtual bool IsArrayGenericInterface {
                        get {
                                return false;
                        }
@@ -276,6 +294,12 @@ namespace Mono.CSharp
                        }
                }
 
+               public bool IsStructOrEnum {
+                       get {
+                               return (Kind & (MemberKind.Struct | MemberKind.Enum)) != 0;
+                       }
+               }
+
                public bool IsTypeBuilder {
                        get {
 #if STATIC
@@ -302,6 +326,9 @@ namespace Mono.CSharp
                                if (Kind == MemberKind.Void)
                                        return true;
 
+                               if (Kind == MemberKind.TypeParameter)
+                                       return false;
+
                                if (IsNested && DeclaringType.IsGenericOrParentIsGeneric)
                                        return false;
 
@@ -350,13 +377,13 @@ namespace Mono.CSharp
 
                #endregion
 
-               public bool AddInterface (TypeSpec iface)
+               public virtual bool AddInterface (TypeSpec iface)
                {
                        if ((state & StateFlags.InterfacesExpanded) != 0)
                                throw new InternalErrorException ("Modifying expanded interface list");
 
                        if (ifaces == null) {
-                               ifaces = new List<TypeSpec> () { iface };
+                               ifaces = new List<TypeSpec> { iface };
                                return true;
                        }
 
@@ -385,11 +412,16 @@ namespace Mono.CSharp
                        // When resolving base class of X`1 we inflate context type A`1
                        // All this happens before we even hit IFoo resolve. Without
                        // additional expansion any inside usage of A<T> would miss IFoo
-                       // interface because it comes from early inflated TypeSpec
+                       // interface because it comes from early inflated A`1 definition.
                        //
                        if (inflated_instances != null) {
-                               foreach (var inflated in inflated_instances) {
-                                       inflated.Value.AddInterface (iface);
+                               //
+                               // Inflate only existing instances not any new instances added
+                               // during AddInterface
+                               //
+                               var inflated_existing = inflated_instances.Values.ToArray ();
+                               foreach (var inflated in inflated_existing) {
+                                       inflated.AddInterface (iface);
                                }
                        }
 
@@ -457,17 +489,22 @@ namespace Mono.CSharp
                //
                // Text representation of type used by documentation writer
                //
-               public override string GetSignatureForDocumentation ()
+               public sealed override string GetSignatureForDocumentation ()
+               {
+                       return GetSignatureForDocumentation (false);
+               }
+
+               public virtual string GetSignatureForDocumentation (bool explicitName)
                {
                        StringBuilder sb = new StringBuilder ();
                        if (IsNested) {
-                               sb.Append (DeclaringType.GetSignatureForDocumentation ());
-                       } else {
-                               sb.Append (MemberDefinition.Namespace);
+                               sb.Append (DeclaringType.GetSignatureForDocumentation (explicitName));
+                       } else if (MemberDefinition.Namespace != null) {
+                               sb.Append (explicitName ? MemberDefinition.Namespace.Replace ('.', '#') : MemberDefinition.Namespace);
                        }
 
                        if (sb.Length != 0)
-                               sb.Append (".");
+                               sb.Append (explicitName ? "#" : ".");
 
                        sb.Append (Name);
                        if (Arity > 0) {
@@ -477,7 +514,7 @@ namespace Mono.CSharp
                                        if (i > 0)
                                            sb.Append (",");
 
-                                       sb.Append (TypeArguments[i].GetSignatureForDocumentation ());
+                                               sb.Append (TypeArguments[i].GetSignatureForDocumentation (explicitName));
                                    }
                                    sb.Append ("}");
                                } else {
@@ -489,33 +526,6 @@ namespace Mono.CSharp
                        return sb.ToString ();
                }
 
-               public string GetExplicitNameSignatureForDocumentation ()
-               {
-                       StringBuilder sb = new StringBuilder ();
-                       if (IsNested) {
-                               sb.Append (DeclaringType.GetExplicitNameSignatureForDocumentation ());
-                       } else if (MemberDefinition.Namespace != null) {
-                               sb.Append (MemberDefinition.Namespace.Replace ('.', '#'));
-                       }
-
-                       if (sb.Length != 0)
-                               sb.Append ("#");
-
-                       sb.Append (Name);
-                       if (Arity > 0) {
-                               sb.Append ("{");
-                               for (int i = 0; i < Arity; ++i) {
-                                       if (i > 0)
-                                               sb.Append (",");
-
-                                       sb.Append (TypeArguments[i].GetExplicitNameSignatureForDocumentation ());
-                               }
-                               sb.Append ("}");
-                       }
-
-                       return sb.ToString ();
-               }
-
                public override string GetSignatureForError ()
                {
                        string s;
@@ -536,7 +546,15 @@ namespace Mono.CSharp
 
                public string GetSignatureForErrorIncludingAssemblyName ()
                {
-                       return string.Format ("{0} [{1}]", GetSignatureForError (), MemberDefinition.DeclaringAssembly.FullName);
+                       var imported = MemberDefinition.DeclaringAssembly as ImportedAssemblyDefinition;
+
+                       var location = imported != null ?
+                               System.IO.Path.GetFullPath (imported.Location) :
+                           ((MemberCore)MemberDefinition).Location.NameFullPath;
+
+                       return string.Format ("{0} [{1} -- {2}]", GetSignatureForError (),
+                                                                 MemberDefinition.DeclaringAssembly.FullName,
+                                                                 location);
                }
 
                protected virtual string GetTypeNameSignature ()
@@ -549,22 +567,16 @@ namespace Mono.CSharp
 
                public bool ImplementsInterface (TypeSpec iface, bool variantly)
                {
-                       var t = this;
-                       do {
-                               var ifaces = t.Interfaces;
-                               if (ifaces != null) {
-                                       for (int i = 0; i < ifaces.Count; ++i) {
-                                               if (TypeSpecComparer.IsEqual (ifaces[i], iface))
-                                                       return true;
-
-                                               if (variantly && TypeSpecComparer.Variant.IsEqual (ifaces[i], iface))
-                                                       return true;
-                                       }
-                               }
+                       var ifaces = Interfaces;
+                       if (ifaces != null) {
+                               for (int i = 0; i < ifaces.Count; ++i) {
+                                       if (TypeSpecComparer.IsEqual (ifaces[i], iface))
+                                               return true;
 
-                               // TODO: Why is it needed when we do it during import
-                               t = t.BaseType;
-                       } while (t != null);
+                                       if (variantly && TypeSpecComparer.Variant.IsEqual (ifaces[i], iface))
+                                               return true;
+                               }
+                       }
 
                        return false;
                }
@@ -624,6 +636,7 @@ namespace Mono.CSharp
                        case MemberKind.Struct:
                        case MemberKind.Enum:
                        case MemberKind.Void:
+                       case MemberKind.PointerType:
                                return false;
                        case MemberKind.InternalCompilerType:
                                //
@@ -635,6 +648,20 @@ namespace Mono.CSharp
                        }
                }
 
+               public static bool IsNonNullableValueType (TypeSpec t)
+               {
+                       switch (t.Kind) {
+                       case MemberKind.TypeParameter:
+                               return ((TypeParameterSpec) t).IsValueType;
+                       case MemberKind.Struct:
+                               return !t.IsNullableType;
+                       case MemberKind.Enum:
+                               return true;
+                       default:
+                               return false;
+                       }
+               }
+
                public static bool IsValueType (TypeSpec t)
                {
                        switch (t.Kind) {
@@ -706,22 +733,22 @@ namespace Mono.CSharp
                        return this;
                }
 
-               public override List<TypeSpec> ResolveMissingDependencies ()
+               public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
                {
-                       List<TypeSpec> missing = null;
+                       List<MissingTypeSpecReference> missing = null;
 
                        if (Kind == MemberKind.MissingType) {
-                               missing = new List<TypeSpec> ();
-                               missing.Add (this);
+                               missing = new List<MissingTypeSpecReference> ();
+                               missing.Add (new MissingTypeSpecReference (this, caller));
                                return missing;
                        }
 
                        foreach (var targ in TypeArguments) {
                                if (targ.Kind == MemberKind.MissingType) {
                                        if (missing == null)
-                                               missing = new List<TypeSpec> ();
+                                               missing = new List<MissingTypeSpecReference> ();
 
-                                       missing.Add (targ);
+                                       missing.Add (new MissingTypeSpecReference (targ, caller));
                                }
                        }
 
@@ -729,19 +756,19 @@ namespace Mono.CSharp
                                foreach (var iface in Interfaces) {
                                        if (iface.Kind == MemberKind.MissingType) {
                                                if (missing == null)
-                                                       missing = new List<TypeSpec> ();
+                                                       missing = new List<MissingTypeSpecReference> ();
 
-                                               missing.Add (iface);
+                                               missing.Add (new MissingTypeSpecReference (iface, caller));
                                        }
                                }
                        }
 
                        if (MemberDefinition.TypeParametersCount > 0) {
                                foreach (var tp in MemberDefinition.TypeParameters) {
-                                       var tp_missing = tp.GetMissingDependencies ();
+                                       var tp_missing = tp.GetMissingDependencies (this);
                                        if (tp_missing != null) {
                                                if (missing == null)
-                                                       missing = new List<TypeSpec> ();
+                                                       missing = new List<MissingTypeSpecReference> ();
 
                                                missing.AddRange (tp_missing);
                                        }
@@ -751,7 +778,7 @@ namespace Mono.CSharp
                        if (missing != null || BaseType == null)
                                return missing;
 
-                       return BaseType.ResolveMissingDependencies ();
+                       return BaseType.ResolveMissingDependencies (this);
                }
 
                public void SetMetaInfo (MetaType info)
@@ -766,6 +793,31 @@ namespace Mono.CSharp
                {
                        modifiers |= Modifiers.METHOD_EXTENSION;
                }
+
+               public void UpdateInflatedInstancesBaseType ()
+               {
+                       //
+                       // When nested class has a partial part the situation where parent type
+                       // is inflated before its base type is defined can occur. In such case
+                       // all inflated (should be only 1) instansted need to be updated
+                       //
+                       // partial class A<T> {
+                       //   partial class B : A<int> { }
+                       // }
+                       //
+                       // partial class A<T> : X {}
+                       //
+                       if (inflated_instances == null)
+                               return;
+
+                       foreach (var inflated in inflated_instances) {
+                               //
+                               // Don't need to inflate possible generic type because for now the method
+                               // is always used from within the nested type
+                               //
+                               inflated.Value.BaseType = base_type;
+                       }
+               }
        }
 
        //
@@ -1056,6 +1108,23 @@ namespace Mono.CSharp
                                return true;
                        }
 
+                       public static bool IsEqual (TypeSpec[] a, TypeSpec[] b)
+                       {
+                               if (a == b)
+                                       return true;
+
+                               if (a.Length != b.Length)
+                                       return false;
+
+                               for (int i = 0; i < a.Length; ++i) {
+                                       if (!IsEqual (a[i], b[i]))
+                                               return false;
+                               }
+
+                               return true;
+                       }
+
+
                        //
                        // Compares unordered arrays
                        //
@@ -1176,6 +1245,9 @@ namespace Mono.CSharp
                                                return false;
                                }
 
+                               if (a.IsNested && b.IsNested)
+                                       return IsEqual (a.DeclaringType, b.DeclaringType);
+
                                return true;
                        }
 
@@ -1337,6 +1409,9 @@ namespace Mono.CSharp
                IAssemblyDefinition DeclaringAssembly { get; }
                string Namespace { get; }
                bool IsPartial { get; }
+               bool IsComImport { get; }
+               bool IsTypeForwarder { get; }
+               bool IsCyclicTypeForwarder { get; }
                int TypeParametersCount { get; }
                TypeParameterSpec[] TypeParameters { get; }
 
@@ -1356,6 +1431,7 @@ namespace Mono.CSharp
                public static readonly InternalType FakeInternalType = new InternalType ("<fake$type>");
                public static readonly InternalType Namespace = new InternalType ("<namespace>");
                public static readonly InternalType ErrorType = new InternalType ("<error>");
+               public static readonly InternalType VarOutType = new InternalType ("var out");
 
                readonly string name;
 
@@ -1384,6 +1460,12 @@ namespace Mono.CSharp
                        }
                }
 
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return false;
+                       }
+               }
+
                bool IMemberDefinition.IsImported {
                        get {
                                return false;
@@ -1396,6 +1478,18 @@ namespace Mono.CSharp
                        }
                }
 
+               bool ITypeDefinition.IsTypeForwarder {
+                       get {
+                               return false;
+                       }
+               }
+
+               bool ITypeDefinition.IsCyclicTypeForwarder {
+                       get {
+                               return false;
+                       }
+               }
+
                public override string Name {
                        get {
                                return name;
@@ -1508,12 +1602,36 @@ namespace Mono.CSharp
 
                public TypeSpec Element { get; private set; }
 
+               public override IList<TypeSpec> Interfaces {
+                       set {
+                               throw new NotSupportedException ();
+                       }
+               }
+
+               bool ITypeDefinition.IsComImport {
+                       get {
+                               return false;
+                       }
+               }
+
                bool ITypeDefinition.IsPartial {
                        get {
                                return false;
                        }
                }
 
+               bool ITypeDefinition.IsTypeForwarder {
+                       get {
+                               return false;
+                       }
+               }
+
+               bool ITypeDefinition.IsCyclicTypeForwarder {
+                       get {
+                               return false;
+                       }
+               }
+
                public override string Name {
                        get {
                                throw new NotSupportedException ();
@@ -1522,6 +1640,11 @@ namespace Mono.CSharp
 
                #endregion
 
+               public override void CheckObsoleteness (IMemberContext mc, Location loc)
+               {
+                       Element.CheckObsoleteness (mc, loc);
+               }
+
                public override ObsoleteAttribute GetAttributeObsolete ()
                {
                        return Element.GetAttributeObsolete ();
@@ -1532,9 +1655,9 @@ namespace Mono.CSharp
                        return null;
                }
 
-               public override string GetSignatureForDocumentation ()
+               public override string GetSignatureForDocumentation (bool explicitName)
                {
-                       return Element.GetSignatureForDocumentation () + GetPostfixSignature ();
+                       return Element.GetSignatureForDocumentation (explicitName) + GetPostfixSignature ();
                }
 
                public override string GetSignatureForError ()
@@ -1659,13 +1782,19 @@ namespace Mono.CSharp
                readonly int rank;
                readonly ModuleContainer module;
 
-               private ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
+               ArrayContainer (ModuleContainer module, TypeSpec element, int rank)
                        : base (MemberKind.ArrayType, element, null)
                {
                        this.module = module;
                        this.rank = rank;
                }
 
+               public override IList<TypeSpec> Interfaces {
+                       get {
+                               return BaseType.Interfaces;
+                       }
+               }
+
                public int Rank {
                        get {
                                return rank;
@@ -1767,29 +1896,33 @@ namespace Mono.CSharp
                        return sb.ToString ();
                }
 
-               public override string GetSignatureForDocumentation ()
+               public override string GetSignatureForDocumentation (bool explicitName)
                {
                        StringBuilder sb = new StringBuilder ();
-                       GetElementSignatureForDocumentation (sb);
+                       GetElementSignatureForDocumentation (sb, explicitName);
                        return sb.ToString ();
                }
 
-               void GetElementSignatureForDocumentation (StringBuilder sb)
+               void GetElementSignatureForDocumentation (StringBuilder sb, bool explicitName)
                {
                        var ac = Element as ArrayContainer;
                        if (ac == null)
-                               sb.Append (Element.GetSignatureForDocumentation ());
+                               sb.Append (Element.GetSignatureForDocumentation (explicitName));
                        else
-                               ac.GetElementSignatureForDocumentation (sb);
+                               ac.GetElementSignatureForDocumentation (sb, explicitName);
 
-                       sb.Append ("[");
-                       for (int i = 1; i < rank; i++) {
-                               if (i == 1)
-                                       sb.Append ("0:");
+                       if (explicitName) {
+                               sb.Append (GetPostfixSignature (rank));
+                       } else {
+                               sb.Append ("[");
+                               for (int i = 1; i < rank; i++) {
+                                       if (i == 1)
+                                               sb.Append ("0:");
 
-                               sb.Append (",0:");
+                                       sb.Append (",0:");
+                               }
+                               sb.Append ("]");
                        }
-                       sb.Append ("]");
                }
 
                public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element)
@@ -1802,24 +1935,34 @@ namespace Mono.CSharp
                        ArrayContainer ac;
                        var key = new TypeRankPair (element, rank);
                        if (!module.ArrayTypesCache.TryGetValue (key, out ac)) {
-                               ac = new ArrayContainer (module, element, rank) {
-                                       BaseType = module.Compiler.BuiltinTypes.Array
-                               };
+                               ac = new ArrayContainer (module, element, rank);
+                               ac.BaseType = module.Compiler.BuiltinTypes.Array;
 
                                module.ArrayTypesCache.Add (key, ac);
                        }
 
                        return ac;
                }
+
+               public override List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller)
+               {
+                       return Element.ResolveMissingDependencies (caller);
+               }
        }
 
        class ReferenceContainer : ElementTypeSpec
        {
-               private ReferenceContainer (TypeSpec element)
+               ReferenceContainer (TypeSpec element)
                        : base (MemberKind.Class, element, null)        // TODO: Kind.Class is most likely wrong
                {
                }
 
+               public override IList<TypeSpec> Interfaces {
+                       get {
+                               return null;
+                       }
+               }
+
                public override MetaType GetMetaInfo ()
                {
                        if (info == null) {
@@ -1850,6 +1993,12 @@ namespace Mono.CSharp
                        state &= ~StateFlags.CLSCompliant_Undetected;
                }
 
+               public override IList<TypeSpec> Interfaces {
+                       get {
+                               return null;
+                       }
+               }
+
                public override MetaType GetMetaInfo ()
                {
                        if (info == null) {
@@ -1875,4 +2024,16 @@ namespace Mono.CSharp
                        return pc;
                }
        }
+
+       public class MissingTypeSpecReference
+       {
+               public MissingTypeSpecReference (TypeSpec type, MemberSpec caller)
+               {
+                       Type = type;
+                       Caller = caller;
+               }
+
+               public TypeSpec Type { get; private set; }
+               public MemberSpec Caller { get; private set; }
+       }
 }