Merge pull request dotnet/corert#3601 from dotnet/nmirror
authorJan Kotas <jkotas@microsoft.com>
Fri, 12 May 2017 14:56:00 +0000 (07:56 -0700)
committerAtsushi Kanamori <AtsushiKan@users.noreply.github.com>
Fri, 12 May 2017 19:21:40 +0000 (12:21 -0700)
Merge nmirror to master

Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
src/mscorlib/shared/System/Reflection/AssemblyNameFormatter.cs [new file with mode: 0644]

index 921354b..716ed69 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyKeyNameAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyMetadataAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyNameFlags.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyNameFormatter.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyProductAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblySignatureKeyAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyTitleAttribute.cs" />
diff --git a/src/mscorlib/shared/System/Reflection/AssemblyNameFormatter.cs b/src/mscorlib/shared/System/Reflection/AssemblyNameFormatter.cs
new file mode 100644 (file)
index 0000000..7c4a980
--- /dev/null
@@ -0,0 +1,156 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.IO;
+using System.Text;
+using System.Globalization;
+using System.Collections.Generic;
+
+namespace System.Reflection
+{
+    internal static class AssemblyNameFormatter
+    {
+        public static string ComputeDisplayName(string name, Version version, string cultureName, byte[] pkt, AssemblyNameFlags flags, AssemblyContentType contentType)
+        {
+            const int PUBLIC_KEY_TOKEN_LEN = 8;
+
+            if (name == string.Empty)
+                throw new FileLoadException();
+
+            StringBuilder sb = new StringBuilder();
+            if (name != null)
+            {
+                sb.AppendQuoted(name);
+            }
+
+            if (version != null)
+            {
+                Version canonicalizedVersion = version.CanonicalizeVersion();
+                if (canonicalizedVersion.Major != ushort.MaxValue)
+                {
+                    sb.Append(", Version=");
+                    sb.Append(canonicalizedVersion.Major);
+
+                    if (canonicalizedVersion.Minor != ushort.MaxValue)
+                    {
+                        sb.Append('.');
+                        sb.Append(canonicalizedVersion.Minor);
+
+                        if (canonicalizedVersion.Build != ushort.MaxValue)
+                        {
+                            sb.Append('.');
+                            sb.Append(canonicalizedVersion.Build);
+
+                            if (canonicalizedVersion.Revision != ushort.MaxValue)
+                            {
+                                sb.Append('.');
+                                sb.Append(canonicalizedVersion.Revision);
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (cultureName != null)
+            {
+                if (cultureName == string.Empty)
+                    cultureName = "neutral";
+                sb.Append(", Culture=");
+                sb.AppendQuoted(cultureName);
+            }
+
+            if (pkt != null)
+            {
+                if (pkt.Length > PUBLIC_KEY_TOKEN_LEN)
+                    throw new ArgumentException();
+
+                sb.Append(", PublicKeyToken=");
+                if (pkt.Length == 0)
+                    sb.Append("null");
+                else
+                {
+                    foreach (byte b in pkt)
+                    {
+                        sb.Append(b.ToString("x2", CultureInfo.InvariantCulture));
+                    }
+                }
+            }
+
+            if (0 != (flags & AssemblyNameFlags.Retargetable))
+                sb.Append(", Retargetable=Yes");
+
+            if (contentType == AssemblyContentType.WindowsRuntime)
+                sb.Append(", ContentType=WindowsRuntime");
+
+            // NOTE: By design (desktop compat) AssemblyName.FullName and ToString() do not include ProcessorArchitecture.
+
+            return sb.ToString();
+        }
+
+        private static void AppendQuoted(this StringBuilder sb, string s)
+        {
+            bool needsQuoting = false;
+            const char quoteChar = '\"';
+
+            //@todo: App-compat: You can use double or single quotes to quote a name, and Fusion (or rather the IdentityAuthority) picks one
+            // by some algorithm. Rather than guess at it, I'll just use double-quote consistently.
+            if (s != s.Trim() || s.Contains("\"") || s.Contains("\'"))
+                needsQuoting = true;
+
+            if (needsQuoting)
+                sb.Append(quoteChar);
+
+            for (int i = 0; i < s.Length; i++)
+            {
+                bool addedEscape = false;
+                foreach (KeyValuePair<char, string> kv in EscapeSequences)
+                {
+                    string escapeReplacement = kv.Value;
+                    if (!(s[i] == escapeReplacement[0]))
+                        continue;
+                    if ((s.Length - i) < escapeReplacement.Length)
+                        continue;
+                    string prefix = s.Substring(i, escapeReplacement.Length);
+                    if (prefix == escapeReplacement)
+                    {
+                        sb.Append('\\');
+                        sb.Append(kv.Key);
+                        addedEscape = true;
+                    }
+                }
+
+                if (!addedEscape)
+                    sb.Append(s[i]);
+            }
+
+            if (needsQuoting)
+                sb.Append(quoteChar);
+        }
+
+        private static Version CanonicalizeVersion(this Version version)
+        {
+            ushort major = (ushort)version.Major;
+            ushort minor = (ushort)version.Minor;
+            ushort build = (ushort)version.Build;
+            ushort revision = (ushort)version.Revision;
+
+            if (major == version.Major && minor == version.Minor && build == version.Build && revision == version.Revision)
+                return version;
+
+            return new Version(major, minor, build, revision);
+        }
+
+        public static KeyValuePair<char, string>[] EscapeSequences =
+        {
+            new KeyValuePair<char, string>('\\', "\\"),
+            new KeyValuePair<char, string>(',', ","),
+            new KeyValuePair<char, string>('=', "="),
+            new KeyValuePair<char, string>('\'', "'"),
+            new KeyValuePair<char, string>('\"', "\""),
+            new KeyValuePair<char, string>('n', Environment.NewLine),
+            new KeyValuePair<char, string>('t', "\t"),
+        };
+    }
+}
+