Imported Upstream version 4.3.2.467

Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
Xamarin Public Jenkins
2016-02-22 11:00:01 -05:00
parent f302175246
commit f3e3aab35a
4097 changed files with 122406 additions and 82300 deletions

View File

@@ -0,0 +1,34 @@
//
// AppContext.cs
//
// Authors:
// Marek Safar <marek.safar@gmail.com>
//
// Copyright (C) 2015 Xamarin Inc (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace System
{
public static class AppContext
{
}
}

View File

@@ -983,6 +983,7 @@ namespace System {
return _process_guid;
}
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
public static AppDomain CreateDomain (string friendlyName)
{
return CreateDomain (friendlyName, null, null);
@@ -1061,6 +1062,25 @@ namespace System {
return ad;
}
#else
[Obsolete ("AppDomain.CreateDomain is not supported on the current platform.", true)]
public static AppDomain CreateDomain (string friendlyName)
{
throw new PlatformNotSupportedException ("AppDomain.CreateDomain is not supported on the current platform.");
}
[Obsolete ("AppDomain.CreateDomain is not supported on the current platform.", true)]
public static AppDomain CreateDomain (string friendlyName, Evidence securityInfo)
{
throw new PlatformNotSupportedException ("AppDomain.CreateDomain is not supported on the current platform.");
}
[Obsolete ("AppDomain.CreateDomain is not supported on the current platform.", true)]
public static AppDomain CreateDomain (string friendlyName, Evidence securityInfo, AppDomainSetup info)
{
throw new PlatformNotSupportedException ("AppDomain.CreateDomain is not supported on the current platform.");
}
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
#if !NET_2_1
[Serializable]
@@ -1098,13 +1118,23 @@ namespace System {
}
#endif
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
public static AppDomain CreateDomain (string friendlyName, Evidence securityInfo,string appBasePath,
string appRelativeSearchPath, bool shadowCopyFiles)
{
return CreateDomain (friendlyName, securityInfo, CreateDomainSetup (appBasePath, appRelativeSearchPath, shadowCopyFiles));
}
#else
[Obsolete ("AppDomain.CreateDomain is not supported on the current platform.", true)]
public static AppDomain CreateDomain (string friendlyName, Evidence securityInfo,string appBasePath,
string appRelativeSearchPath, bool shadowCopyFiles)
{
throw new PlatformNotSupportedException ("AppDomain.CreateDomain is not supported on the current platform.");
}
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
#if !NET_2_1
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
public static AppDomain CreateDomain (string friendlyName, Evidence securityInfo, AppDomainSetup info,
PermissionSet grantSet, params StrongName [] fullTrustAssemblies)
{
@@ -1114,8 +1144,17 @@ namespace System {
info.ApplicationTrust = new ApplicationTrust (grantSet, fullTrustAssemblies ?? EmptyArray<StrongName>.Value);
return CreateDomain (friendlyName, securityInfo, info);
}
#else
[Obsolete ("AppDomain.CreateDomain is not supported on the current platform.", true)]
public static AppDomain CreateDomain (string friendlyName, Evidence securityInfo, AppDomainSetup info,
PermissionSet grantSet, params StrongName [] fullTrustAssemblies)
{
throw new PlatformNotSupportedException ("AppDomain.CreateDomain is not supported on the current platform.");
}
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
#endif
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
static AppDomainSetup CreateDomainSetup (string appBasePath, string appRelativeSearchPath, bool shadowCopyFiles)
{
AppDomainSetup info = new AppDomainSetup ();
@@ -1130,6 +1169,7 @@ namespace System {
return info;
}
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private static extern bool InternalIsFinalizingForUnload (int domain_id);
@@ -1149,6 +1189,7 @@ namespace System {
return Thread.GetDomainID ();
}
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
[SecurityPermission (SecurityAction.Demand, ControlAppDomain = true)]
[ReliabilityContractAttribute (Consistency.MayCorruptAppDomain, Cer.MayFail)]
public static void Unload (AppDomain domain)
@@ -1158,6 +1199,13 @@ namespace System {
InternalUnload (domain.getDomainID());
}
#else
[Obsolete ("AppDomain.Unload is not supported on the current platform.", true)]
public static void Unload (AppDomain domain)
{
throw new PlatformNotSupportedException ("AppDomain.Unload is not supported on the current platform.");
}
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
[MethodImplAttribute (MethodImplOptions.InternalCall)]
[SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
@@ -1339,11 +1387,16 @@ namespace System {
return null;
}
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
private void DoDomainUnload ()
{
if (DomainUnload != null)
DomainUnload(this, null);
}
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern void DoUnhandledException (Exception e);
internal void DoUnhandledException (UnhandledExceptionEventArgs args) {
if (UnhandledException != null)
@@ -1386,7 +1439,11 @@ namespace System {
[method: SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
public event ResolveEventHandler AssemblyResolve;
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
[method: SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
#else
[Obsolete ("AppDomain.DomainUnload is not supported on the current platform.", true)]
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
public event EventHandler DomainUnload;
[method: SecurityPermission (SecurityAction.LinkDemand, ControlAppDomain = true)]
@@ -1421,10 +1478,17 @@ namespace System {
#endif
#pragma warning restore 649
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
// default is null
public AppDomainManager DomainManager {
get { return (AppDomainManager)_domain_manager; }
}
#else
[Obsolete ("AppDomain.DomainManager is not supported on this platform.", true)]
public AppDomainManager DomainManager {
get { throw new PlatformNotSupportedException ("AppDomain.DomainManager is not supported on this platform."); }
}
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
#if !MOBILE
public event ResolveEventHandler ReflectionOnlyAssemblyResolve;
@@ -1470,6 +1534,7 @@ namespace System {
// static methods
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
public static AppDomain CreateDomain (string friendlyName, Evidence securityInfo, string appBasePath,
string appRelativeSearchPath, bool shadowCopyFiles, AppDomainInitializer adInit, string[] adInitArgs)
{
@@ -1480,6 +1545,14 @@ namespace System {
return CreateDomain (friendlyName, securityInfo, info);
}
#else
[Obsolete ("AppDomain.CreateDomain is not supported on the current platform.", true)]
public static AppDomain CreateDomain (string friendlyName, Evidence securityInfo, string appBasePath,
string appRelativeSearchPath, bool shadowCopyFiles, AppDomainInitializer adInit, string[] adInitArgs)
{
throw new PlatformNotSupportedException ("AppDomain.CreateDomain is not supported on the current platform.");
}
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
public int ExecuteAssemblyByName (string assemblyName)
{

View File

@@ -27,8 +27,12 @@
//
namespace System {
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
[System.Runtime.InteropServices.ComVisible (true)]
[Serializable]
#else
[Obsolete ("AppDomainInitializer is not supported on the current platform.", true)]
#endif
public delegate void AppDomainInitializer (string[] args);
}

View File

@@ -36,6 +36,7 @@ using System.Threading;
namespace System {
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
[ComVisible (true)]
[SecurityPermission (SecurityAction.LinkDemand, Infrastructure = true)]
[SecurityPermission (SecurityAction.InheritanceDemand, Infrastructure = true)]
@@ -111,4 +112,55 @@ namespace System {
return AppDomain.CreateDomain (friendlyName, securityInfo, appDomainInfo);
}
}
#else
[Obsolete ("AppDomainManager is not supported on the current platform.", true)]
public class AppDomainManager : MarshalByRefObject {
public AppDomainManager ()
{
throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform.");
}
public virtual ApplicationActivator ApplicationActivator {
get { throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform."); }
}
public virtual Assembly EntryAssembly {
get { throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform."); }
}
public virtual HostExecutionContextManager HostExecutionContextManager {
get { throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform."); }
}
public virtual HostSecurityManager HostSecurityManager {
get { throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform."); }
}
public AppDomainManagerInitializationOptions InitializationFlags {
get { throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform."); }
set { throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform."); }
}
public virtual AppDomain CreateDomain (string friendlyName, Evidence securityInfo, AppDomainSetup appDomainInfo)
{
throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform.");
}
public virtual void InitializeNewDomain (AppDomainSetup appDomainInfo)
{
throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform.");
}
public virtual bool CheckSecuritySettings (SecurityState state)
{
throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform.");
}
protected static AppDomain CreateDomainHelper (string friendlyName, Evidence securityInfo, AppDomainSetup appDomainInfo)
{
throw new PlatformNotSupportedException ("AppDomainManager is not supported on the current platform.");
}
}
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
}

View File

@@ -309,6 +309,7 @@ namespace System
set { _activationArguments = value; }
}
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
[MonoLimitation ("it needs to be invoked within the created domain")]
public AppDomainInitializer AppDomainInitializer {
get {
@@ -319,6 +320,14 @@ namespace System
}
set { domain_initializer = value; }
}
#else
[Obsolete ("AppDomainSetup.AppDomainInitializer is not supported on this platform.", true)]
public AppDomainInitializer AppDomainInitializer {
get { throw new PlatformNotSupportedException ("AppDomainSetup.AppDomainInitializer is not supported on this platform."); }
set { throw new PlatformNotSupportedException ("AppDomainSetup.AppDomainInitializer is not supported on this platform."); }
}
#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
[MonoLimitation ("it needs to be used to invoke the initializer within the created domain")]
public string [] AppDomainInitializerArguments {
@@ -369,7 +378,9 @@ namespace System
object [] arr = (object []) bf.Deserialize (ms);
_activationArguments = (ActivationArguments) arr [0];
#if MONO_FEATURE_MULTIPLE_APPDOMAINS
domain_initializer = (AppDomainInitializer) arr [1];
#endif
application_trust = (ApplicationTrust) arr [2];
serialized_non_primitives = null;

View File

@@ -1689,10 +1689,10 @@ namespace System
if (keys == null)
throw new ArgumentNullException ("keys");
if (keys.Length != items.Length)
throw new ArgumentException ("Length of keys and items does not match.");
if (keys.Length > items.Length)
throw new ArgumentException ("Length of keys is larger than length of items.");
SortImpl<TKey, TValue> (keys, items, 0, keys.Length, comparer);
}
@@ -3102,6 +3102,12 @@ namespace System
return d;
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static T[] Empty<T>()
{
return EmptyArray<T>.Value;
}
public static bool Exists<T> (T [] array, Predicate <T> match)
{
if (array == null)
@@ -3183,6 +3189,19 @@ namespace System
//
// Moved value from instance into target of different type with no checks (JIT intristics)
//
// Restrictions:
//
// S and R must either:
// both be blitable valuetypes
// both be reference types (IOW, an unsafe cast)
// S and R cannot be float or double
// S and R must either:
// both be a struct
// both be a scalar
// S and R must either:
// be of same size
// both be a scalar of size <= 4
//
internal static R UnsafeMov<S,R> (S instance) {
return (R)(object) instance;
}

View File

@@ -207,7 +207,8 @@ namespace System
private static Stream Open (IntPtr handle, FileAccess access, int bufferSize)
{
try {
return new FileStream (handle, access, false, bufferSize, false, bufferSize == 0);
// TODO: Should use __ConsoleStream from reference sources
return new FileStream (handle, access, false, bufferSize, false, true);
} catch (IOException) {
return Stream.Null;
}

View File

@@ -60,7 +60,7 @@ namespace System
private object m_target;
private IntPtr method;
private IntPtr delegate_trampoline;
private IntPtr rgctx;
private IntPtr extra_arg;
private IntPtr method_code;
private MethodInfo method_info;

View File

@@ -57,7 +57,7 @@ namespace System {
* of icalls, do not require an increment.
*/
#pragma warning disable 169
private const int mono_corlib_version = 138;
private const int mono_corlib_version = 140;
#pragma warning restore 169
[ComVisible (true)]
@@ -375,7 +375,7 @@ namespace System {
/// </summary>
public static Version Version {
get {
return new Version (Consts.FxFileVersion);
return new Version (Consts.EnvironmentVersion);
}
}
@@ -736,6 +736,10 @@ namespace System {
return String.Empty;
// This is where data common to all users goes
case SpecialFolder.CommonApplicationData:
Version v = CreateVersionFromString (GetOSVersionString ());
if (Platform == PlatformID.MacOSX && v >= new Version(15, 0)) {
return "/usr/local/share";
}
return "/usr/share";
default:
throw new ArgumentException ("Invalid SpecialFolder");

View File

@@ -69,6 +69,7 @@ namespace System
IDictionary _data;
internal StackTrace[] captured_traces;
IntPtr[] native_trace_ips;
object dynamic_methods;
#endregion
#pragma warning restore 169, 649
@@ -247,7 +248,7 @@ namespace System
info.AddValue ("ClassName", ClassName);
info.AddValue ("Message", _message);
info.AddValue ("InnerException", inner_exception);
info.AddValue ("InnerException", inner_exception, typeof (Exception));
info.AddValue ("HelpURL", help_link);
info.AddValue ("StackTraceString", StackTrace);
info.AddValue ("RemoteStackTraceString", _remoteStackTraceString);

File diff suppressed because it is too large Load Diff

View File

@@ -51,6 +51,9 @@ namespace System
// Contains information about the type which is expensive to compute
[StructLayout (LayoutKind.Sequential)]
internal class MonoTypeInfo {
// this is the displayed form: special characters
// ,+*&*[]\ in the identifier portions of the names
// have been escaped with a leading backslash (\)
public string full_name;
public MonoCMethod default_ctor;
}

View File

@@ -75,6 +75,19 @@ namespace System
}
}
// Some high-performance applications use this internal property
// to avoid using a slow path to determine if there is more than one handler
// This brings an API that we removed in f410e545e2db0e0dc338673a6b10a5cfd2d3340f
// which some users depeneded on
//
// This is an example of code that used this:
// https://gist.github.com/migueldeicaza/cd99938c2a4372e7e5d5
//
// Do not remove this API
internal bool HasSingleTarget {
get { return delegates == null; }
}
// <remarks>
// Equals: two multicast delegates are equal if their base is equal
// and their invocations list is equal.

View File

@@ -266,7 +266,7 @@ namespace System {
return timeZoneInfo;
}
static void GetSystemTimeZones (List<TimeZoneInfo> systemTimeZones)
static void GetSystemTimeZonesCore (List<TimeZoneInfo> systemTimeZones)
{
foreach (string id in AndroidTimeZones.GetAvailableIds ()) {
var tz = AndroidTimeZones.GetTimeZone (id, id);

View File

@@ -58,7 +58,7 @@ namespace System {
}
}
static void GetSystemTimeZones (List<TimeZoneInfo> systemTimeZones)
static void GetSystemTimeZonesCore (List<TimeZoneInfo> systemTimeZones)
{
foreach (string name in GetMonoTouchNames ()) {
using (Stream stream = GetMonoTouchData (name, false)) {

View File

@@ -33,6 +33,7 @@ using System.Threading;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;
using System.Text;
using System.Globalization;
using System.IO;
@@ -89,6 +90,58 @@ namespace System
*/
private List<KeyValuePair<DateTime, TimeType>> transitions;
private static bool libcNotFound;
[DllImport ("libc")]
private static extern int readlink (string path, byte[] buffer, int buflen);
private static string readlink (string path)
{
if (libcNotFound)
return null;
byte[] buf = new byte [512];
int ret;
try {
ret = readlink (path, buf, buf.Length);
} catch (DllNotFoundException e) {
libcNotFound = true;
return null;
}
if (ret == -1) return null;
char[] cbuf = new char [512];
int chars = System.Text.Encoding.Default.GetChars (buf, 0, ret, cbuf, 0);
return new String (cbuf, 0, chars);
}
private static bool TryGetNameFromPath (string path, out string name)
{
name = null;
var linkPath = readlink (path);
if (linkPath != null)
path = linkPath;
path = Path.GetFullPath (path);
if (string.IsNullOrEmpty (TimeZoneDirectory))
return false;
var baseDir = TimeZoneDirectory;
if (baseDir [baseDir.Length-1] != Path.DirectorySeparatorChar)
baseDir += Path.DirectorySeparatorChar;
if (!path.StartsWith (baseDir, StringComparison.InvariantCulture))
return false;
name = path.Substring (baseDir.Length);
if (name == "localtime")
name = "Local";
return true;
}
#if !MOBILE || MOBILE_STATIC
static TimeZoneInfo CreateLocal ()
{
@@ -114,15 +167,22 @@ namespace System
}
}
try {
return FindSystemTimeZoneByFileName ("Local", "/etc/localtime");
} catch (TimeZoneNotFoundException) {
var tzFilePaths = new string [] {
"/etc/localtime",
Path.Combine (TimeZoneDirectory, "localtime")};
foreach (var tzFilePath in tzFilePaths) {
try {
return FindSystemTimeZoneByFileName ("Local", Path.Combine (TimeZoneDirectory, "localtime"));
string tzName = null;
if (!TryGetNameFromPath (tzFilePath, out tzName))
tzName = "Local";
return FindSystemTimeZoneByFileName (tzName, tzFilePath);
} catch (TimeZoneNotFoundException) {
return Utc;
continue;
}
}
return Utc;
}
static TimeZoneInfo FindSystemTimeZoneByIdCore (string id)
@@ -135,7 +195,7 @@ namespace System
#endif
}
static void GetSystemTimeZones (List<TimeZoneInfo> systemTimeZones)
static void GetSystemTimeZonesCore (List<TimeZoneInfo> systemTimeZones)
{
#if !MOBILE_STATIC
if (TimeZoneKey != null) {
@@ -150,7 +210,7 @@ namespace System
#endif
#if LIBC
string[] continents = new string [] {"Africa", "America", "Antarctica", "Arctic", "Asia", "Atlantic", "Brazil", "Canada", "Chile", "Europe", "Indian", "Mexico", "Mideast", "Pacific", "US"};
string[] continents = new string [] {"Africa", "America", "Antarctica", "Arctic", "Asia", "Atlantic", "Australia", "Brazil", "Canada", "Chile", "Europe", "Indian", "Mexico", "Mideast", "Pacific", "US"};
foreach (string continent in continents) {
try {
foreach (string zonepath in Directory.GetFiles (Path.Combine (TimeZoneDirectory, continent))) {
@@ -267,8 +327,13 @@ namespace System
private static bool TryAddTicks (DateTime date, long ticks, out DateTime result, DateTimeKind kind = DateTimeKind.Unspecified)
{
var resultTicks = date.Ticks + ticks;
if (resultTicks < DateTime.MinValue.Ticks || resultTicks > DateTime.MaxValue.Ticks) {
result = default (DateTime);
if (resultTicks < DateTime.MinValue.Ticks) {
result = DateTime.SpecifyKind (DateTime.MinValue, kind);
return false;
}
if (resultTicks > DateTime.MaxValue.Ticks) {
result = DateTime.SpecifyKind (DateTime.MaxValue, kind);
return false;
}
@@ -415,9 +480,7 @@ namespace System
var utcOffset = sourceTimeZone.GetUtcOffset (dateTime, out isDst);
DateTime utcDateTime;
if (!TryAddTicks (dateTime, -utcOffset.Ticks, out utcDateTime, DateTimeKind.Utc))
return DateTime.SpecifyKind (DateTime.MinValue, DateTimeKind.Utc);
TryAddTicks (dateTime, -utcOffset.Ticks, out utcDateTime, DateTimeKind.Utc);
return utcDateTime;
}
@@ -651,7 +714,7 @@ namespace System
{
if (systemTimeZones == null) {
var tz = new List<TimeZoneInfo> ();
GetSystemTimeZones (tz);
GetSystemTimeZonesCore (tz);
Interlocked.CompareExchange (ref systemTimeZones, new ReadOnlyCollection<TimeZoneInfo> (tz), null);
}
@@ -1175,7 +1238,7 @@ namespace System
return (((i >> 24) & 0xff)
| ((i >> 8) & 0xff00)
| ((i << 8) & 0xff0000)
| ((i << 24)));
| (((i & 0xff) << 24)));
}
static int ReadBigEndianInt32 (byte [] buffer, int start)

View File

@@ -0,0 +1,234 @@
//
// System.TypeIdentifier.cs
//
// Author:
// Aleksey Kliger <aleksey@xamarin.com>
//
//
// Copyright (C) 2015 Xamarin, Inc (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace System {
// A TypeName is wrapper around type names in display form
// (that is, with special characters escaped).
//
// Note that in general if you unescape a type name, you will
// lose information: If the type name's DisplayName is
// Foo\+Bar+Baz (outer class ``Foo+Bar``, inner class Baz)
// unescaping the first plus will give you (outer class Foo,
// inner class Bar, innermost class Baz).
//
// The correct way to take a TypeName apart is to feed its
// DisplayName to TypeSpec.Parse()
//
internal interface TypeName : System.IEquatable<TypeName> {
string DisplayName {
get;
}
// add a nested name under this one.
TypeName NestedName (TypeIdentifier innerName);
}
// A type identifier is a single component of a type name.
// Unlike a general typename, a type identifier can be be
// converted to internal form without loss of information.
internal interface TypeIdentifier : TypeName {
string InternalName {
get;
}
}
internal class TypeNames {
internal static TypeName FromDisplay (string displayName)
{
return new Display (displayName);
}
internal abstract class ATypeName : TypeName {
public abstract string DisplayName { get; }
public abstract TypeName NestedName (TypeIdentifier innerName);
public bool Equals(TypeName other)
{
return other != null && DisplayName == other.DisplayName;
}
public override int GetHashCode ()
{
return DisplayName.GetHashCode();
}
public override bool Equals(object other)
{
return Equals(other as TypeName);
}
}
private class Display : ATypeName {
string displayName;
internal Display (string displayName)
{
this.displayName = displayName;
}
public override string DisplayName { get { return displayName; } }
public override TypeName NestedName (TypeIdentifier innerName)
{
return new Display (DisplayName + "+" + innerName.DisplayName);
}
}
}
internal class TypeIdentifiers {
internal static TypeIdentifier FromDisplay (string displayName)
{
return new Display (displayName);
}
internal static TypeIdentifier FromInternal (string internalName)
{
return new Internal (internalName);
}
internal static TypeIdentifier FromInternal (string internalNameSpace, TypeIdentifier typeName)
{
return new Internal (internalNameSpace, typeName);
}
// Only use if simpleName is certain not to contain
// unexpected characters that ordinarily require
// escaping: ,+*&[]\
internal static TypeIdentifier WithoutEscape (string simpleName)
{
return new NoEscape (simpleName);
}
private class Display : TypeNames.ATypeName, TypeIdentifier {
string displayName;
string internal_name; //cached
internal Display (string displayName)
{
this.displayName = displayName;
internal_name = null;
}
public override string DisplayName {
get { return displayName; }
}
public string InternalName {
get {
if (internal_name == null)
internal_name = GetInternalName ();
return internal_name;
}
}
private string GetInternalName ()
{
return TypeSpec.UnescapeInternalName(displayName);
}
public override TypeName NestedName (TypeIdentifier innerName) {
return TypeNames.FromDisplay (DisplayName + "+" + innerName.DisplayName);
}
}
private class Internal : TypeNames.ATypeName, TypeIdentifier {
string internalName;
string display_name; //cached
internal Internal (string internalName)
{
this.internalName = internalName;
this.display_name = null;
}
internal Internal (string nameSpaceInternal, TypeIdentifier typeName)
{
this.internalName = nameSpaceInternal + "." + typeName.InternalName;
this.display_name = null;
}
public override string DisplayName {
get {
if (display_name == null)
display_name = GetDisplayName ();
return display_name;
}
}
public string InternalName {
get { return internalName; }
}
private string GetDisplayName ()
{
return TypeSpec.EscapeDisplayName (internalName);
}
public override TypeName NestedName (TypeIdentifier innerName)
{
return TypeNames.FromDisplay (DisplayName + "+" + innerName.DisplayName);
}
}
private class NoEscape : TypeNames.ATypeName, TypeIdentifier {
string simpleName;
internal NoEscape (string simpleName)
{
this.simpleName = simpleName;
#if DEBUG
checkNoBadChars(simpleName);
#endif
}
public override string DisplayName { get { return simpleName; } }
public string InternalName { get { return simpleName; } }
#if DEBUG
static private void checkNoBadChars (string s)
{
if (TypeSpec.NeedsEscaping (s))
throw new ArgumentException ("simpleName");
}
#endif
public override TypeName NestedName (TypeIdentifier innerName) {
return TypeNames.FromDisplay (DisplayName + "+" + innerName.DisplayName);
}
}
}
}

View File

@@ -32,8 +32,13 @@ using System.IO;
using System.Reflection;
namespace System {
internal class ArraySpec
internal interface ModifierSpec {
Type Resolve (Type type);
Text.StringBuilder Append (Text.StringBuilder sb);
}
internal class ArraySpec : ModifierSpec
{
// dimensions == 1 and bound, or dimensions > 1 and !bound
int dimensions;
bool bound;
@@ -43,7 +48,7 @@ namespace System {
this.bound = bound;
}
internal Type Resolve (Type type)
public Type Resolve (Type type)
{
if (bound)
return type.MakeArrayType (1);
@@ -52,70 +57,160 @@ namespace System {
return type.MakeArrayType (dimensions);
}
#if DEBUG
public override string ToString ()
public Text.StringBuilder Append (Text.StringBuilder sb)
{
if (bound)
return "[*]";
string str = "[";
for (int i = 1; i < dimensions; ++i)
str += ",";
return str + "]";
return sb.Append ("[*]");
return sb.Append ('[')
.Append (',', dimensions - 1)
.Append (']');
}
#endif
public override string ToString ()
{
return Append (new Text.StringBuilder ()).ToString ();
}
}
internal class PointerSpec : ModifierSpec
{
int pointer_level;
internal PointerSpec (int pointer_level) {
this.pointer_level = pointer_level;
}
public Type Resolve (Type type) {
for (int i = 0; i < pointer_level; ++i)
type = type.MakePointerType ();
return type;
}
public Text.StringBuilder Append (Text.StringBuilder sb)
{
return sb.Append ('*', pointer_level);
}
public override string ToString () {
return Append (new Text.StringBuilder ()).ToString ();
}
}
internal class TypeSpec
{
string name, assembly_name;
List<string> nested;
TypeIdentifier name;
string assembly_name;
List<TypeIdentifier> nested;
List<TypeSpec> generic_params;
List<ArraySpec> array_spec;
int pointer_level;
List<ModifierSpec> modifier_spec;
bool is_byref;
bool IsArray {
get { return array_spec != null; }
string display_fullname; // cache
internal bool HasModifiers {
get { return modifier_spec != null; }
}
internal bool IsNested {
get { return nested != null && nested.Count > 0; }
}
internal bool IsByRef {
get { return is_byref; }
}
internal TypeName Name {
get { return name; }
}
internal IEnumerable<TypeName> Nested {
get {
if (nested != null)
return nested;
else
return EmptyArray<TypeName>.Value;
}
}
internal IEnumerable<ModifierSpec> Modifiers {
get {
if (modifier_spec != null)
return modifier_spec;
else
return EmptyArray<ModifierSpec>.Value;
}
}
[Flags]
internal enum DisplayNameFormat {
Default = 0x0,
WANT_ASSEMBLY = 0x1,
NO_MODIFIERS = 0x2,
}
#if DEBUG
public override string ToString () {
string str = name;
return GetDisplayFullName (DisplayNameFormat.WANT_ASSEMBLY);
}
#endif
string GetDisplayFullName (DisplayNameFormat flags)
{
bool wantAssembly = (flags & DisplayNameFormat.WANT_ASSEMBLY) != 0;
bool wantModifiers = (flags & DisplayNameFormat.NO_MODIFIERS) == 0;
var sb = new Text.StringBuilder(name.DisplayName);
if (nested != null) {
foreach (var n in nested)
str += "+" + n;
sb.Append ('+').Append (n.DisplayName);
}
if (generic_params != null) {
str += "[";
sb.Append ('[');
for (int i = 0; i < generic_params.Count; ++i) {
if (i > 0)
str += ", ";
sb.Append (", ");
if (generic_params [i].assembly_name != null)
str += "[" + generic_params [i] + "]";
sb.Append ('[').Append (generic_params [i].DisplayFullName).Append (']');
else
str += generic_params [i];
sb.Append (generic_params [i].DisplayFullName);
}
str += "]";
sb.Append (']');
}
if (array_spec != null) {
foreach (var ar in array_spec)
str += ar;
}
if (wantModifiers)
GetModifierString (sb);
for (int i = 0; i < pointer_level; ++i)
str += "*";
if (assembly_name != null && wantAssembly)
sb.Append (", ").Append (assembly_name);
return sb.ToString();
}
internal string ModifierString ()
{
return GetModifierString (new Text.StringBuilder ()).ToString ();
}
private Text.StringBuilder GetModifierString (Text.StringBuilder sb)
{
if (modifier_spec != null) {
foreach (var md in modifier_spec)
md.Append (sb);
}
if (is_byref)
str += "&";
sb.Append ('&');
if (assembly_name != null)
str += ", " + assembly_name;
return str;
return sb;
}
internal string DisplayFullName {
get {
if (display_fullname == null)
display_fullname = GetDisplayFullName (DisplayNameFormat.Default);
return display_fullname;
}
}
#endif
internal static TypeSpec Parse (string typeName)
{
@@ -129,11 +224,70 @@ namespace System {
return res;
}
internal static string EscapeDisplayName(string internalName)
{
// initial capacity = length of internalName.
// Maybe we won't have to escape anything.
var res = new Text.StringBuilder (internalName.Length);
foreach (char c in internalName)
{
switch (c) {
case '+':
case ',':
case '[':
case ']':
case '*':
case '&':
case '\\':
res.Append ('\\').Append (c);
break;
default:
res.Append (c);
break;
}
}
return res.ToString ();
}
internal static string UnescapeInternalName(string displayName)
{
var res = new Text.StringBuilder (displayName.Length);
for (int i = 0; i < displayName.Length; ++i)
{
char c = displayName[i];
if (c == '\\')
if (++i < displayName.Length)
c = displayName[i];
res.Append (c);
}
return res.ToString ();
}
internal static bool NeedsEscaping (string internalName)
{
foreach (char c in internalName)
{
switch (c) {
case ',':
case '+':
case '*':
case '&':
case '[':
case ']':
case '\\':
return true;
default:
break;
}
}
return false;
}
internal Type Resolve (Func<AssemblyName,Assembly> assemblyResolver, Func<Assembly,string,bool,Type> typeResolver, bool throwOnError, bool ignoreCase)
{
Assembly asm = null;
if (assemblyResolver == null && typeResolver == null)
return Type.GetType (name, throwOnError, ignoreCase);
return Type.GetType (name.DisplayName, throwOnError, ignoreCase);
if (assembly_name != null) {
if (assemblyResolver != null)
@@ -150,9 +304,9 @@ namespace System {
Type type = null;
if (typeResolver != null)
type = typeResolver (asm, name, ignoreCase);
type = typeResolver (asm, name.DisplayName, ignoreCase);
else
type = asm.GetType (name, false, ignoreCase);
type = asm.GetType (name.DisplayName, false, ignoreCase);
if (type == null) {
if (throwOnError)
throw new TypeLoadException ("Could not resolve type '" + name + "'");
@@ -161,7 +315,7 @@ namespace System {
if (nested != null) {
foreach (var n in nested) {
var tmp = type.GetNestedType (n, BindingFlags.Public | BindingFlags.NonPublic);
var tmp = type.GetNestedType (n.DisplayName, BindingFlags.Public | BindingFlags.NonPublic);
if (tmp == null) {
if (throwOnError)
throw new TypeLoadException ("Could not resolve type '" + n + "'");
@@ -185,14 +339,11 @@ namespace System {
type = type.MakeGenericType (args);
}
if (array_spec != null) {
foreach (var arr in array_spec)
type = arr.Resolve (type);
if (modifier_spec != null) {
foreach (var md in modifier_spec)
type = md.Resolve (type);
}
for (int i = 0; i < pointer_level; ++i)
type = type.MakePointerType ();
if (is_byref)
type = type.MakeByRefType ();
@@ -202,19 +353,19 @@ namespace System {
void AddName (string type_name)
{
if (name == null) {
name = type_name;
name = ParsedTypeIdentifier(type_name);
} else {
if (nested == null)
nested = new List <string> ();
nested.Add (type_name);
nested = new List <TypeIdentifier> ();
nested.Add (ParsedTypeIdentifier(type_name));
}
}
void AddArray (ArraySpec array)
void AddModifier (ModifierSpec md)
{
if (array_spec == null)
array_spec = new List<ArraySpec> ();
array_spec.Add (array);
if (modifier_spec == null)
modifier_spec = new List<ModifierSpec> ();
modifier_spec.Add (md);
}
static void SkipSpace (string name, ref int pos)
@@ -225,6 +376,11 @@ namespace System {
pos = p;
}
static TypeIdentifier ParsedTypeIdentifier (string displayName)
{
return TypeIdentifiers.FromDisplay(displayName);
}
static TypeSpec Parse (string name, ref int p, bool is_recurse, bool allow_aqn)
{
int pos = p;
@@ -261,6 +417,9 @@ namespace System {
name_start = pos + 1;
in_modifiers = true;
break;
case '\\':
pos++;
break;
}
if (in_modifiers)
break;
@@ -282,7 +441,13 @@ namespace System {
case '*':
if (data.is_byref)
throw new ArgumentException ("Can't have a pointer to a byref type", "typeName");
++data.pointer_level;
// take subsequent '*'s too
int pointer_level = 1;
while (pos+1 < name.Length && name[pos+1] == '*') {
++pos;
++pointer_level;
}
data.AddModifier (new PointerSpec(pointer_level));
break;
case ',':
if (is_recurse) {
@@ -308,8 +473,8 @@ namespace System {
if (name [pos] != ',' && name [pos] != '*' && name [pos] != ']') {//generic args
List<TypeSpec> args = new List <TypeSpec> ();
if (data.IsArray)
throw new ArgumentException ("generic args after array spec", "typeName");
if (data.HasModifiers)
throw new ArgumentException ("generic args after array spec or pointer type", "typeName");
while (pos < name.Length) {
SkipSpace (name, ref pos);
@@ -348,11 +513,11 @@ namespace System {
++pos;
SkipSpace (name, ref pos);
}
if (name [pos] != ']')
if (pos >= name.Length || name [pos] != ']')
throw new ArgumentException ("Error parsing array spec", "typeName");
if (dimensions > 1 && bound)
throw new ArgumentException ("Invalid array spec, multi-dimensional array cannot be bound", "typeName");
data.AddArray (new ArraySpec (dimensions, bound));
data.AddModifier (new ArraySpec (dimensions, bound));
}
break;
@@ -371,6 +536,41 @@ namespace System {
p = pos;
return data;
}
internal TypeName TypeNameWithoutModifiers ()
{
return new TypeSpecTypeName (this, false);
}
internal TypeName TypeName {
get { return new TypeSpecTypeName (this, true); }
}
private class TypeSpecTypeName : TypeNames.ATypeName, TypeName {
TypeSpec ts;
bool want_modifiers;
internal TypeSpecTypeName (TypeSpec ts, bool wantModifiers)
{
this.ts = ts;
this.want_modifiers = wantModifiers;
}
public override string DisplayName {
get {
if (want_modifiers)
return ts.DisplayFullName;
else
return ts.GetDisplayFullName (DisplayNameFormat.NO_MODIFIERS);
}
}
public override TypeName NestedName (TypeIdentifier innerName)
{
return TypeNames.FromDisplay(DisplayName + "+" + innerName.DisplayName);
}
}
}
}