[mcs] Add pathmap option
authorMarek Safar <marek.safar@gmail.com>
Wed, 26 Oct 2016 09:22:52 +0000 (11:22 +0200)
committerMarek Safar <marek.safar@gmail.com>
Wed, 26 Oct 2016 09:53:11 +0000 (11:53 +0200)
man/mcs.1
mcs/class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs
mcs/errors/cs8101.cs [new file with mode: 0644]
mcs/mcs/context.cs
mcs/mcs/ecore.cs
mcs/mcs/location.cs
mcs/mcs/namespace.cs
mcs/mcs/settings.cs
mcs/tools/csharp/repl.cs

index 377c445cb095c3479199002d4a1461bc3bdaf7d1..644b85a6e4f123c8987dae19825eeb2f34778196 100644 (file)
--- a/man/mcs.1
+++ b/man/mcs.1
@@ -238,6 +238,9 @@ Names the output file to be generated.
 .I \-\-parse
 Used for benchmarking.  The compiler will only parse its input files.
 .TP
+.I \-pathmap:K=V[,Kn=Vn]
+Sets a mapping for source path names used in generated output.
+.TP
 .I \-pkg:package1[,packageN]
 Reference assemblies for the given packages.
 .Sp
index 4d142314b9efb96d53d59d4ab4b061ccf22d780d..acd269f5c4e3dcec29a7524fc9fecfa536c17d41 100644 (file)
@@ -682,6 +682,7 @@ namespace Mono.CompilerServices.SymbolWriter
                byte[] hash;
                bool creating;
                bool auto_generated;
+               readonly string sourceFile;
 
                public static int Size {
                        get { return 8; }
@@ -696,11 +697,17 @@ namespace Mono.CompilerServices.SymbolWriter
                        creating = true;
                }
 
-               public SourceFileEntry (MonoSymbolFile file, string file_name, byte[] guid, byte[] checksum)
-                       : this (file, file_name)
+               public SourceFileEntry (MonoSymbolFile file, string sourceFile, byte [] guid, byte [] checksum)
+                       : this (file, sourceFile, sourceFile, guid, checksum)
+               {
+               }
+
+               public SourceFileEntry (MonoSymbolFile file, string fileName, string sourceFile, byte[] guid, byte[] checksum)
+                       : this (file, fileName)
                {
                        this.guid = guid;
                        this.hash = checksum;
+                       this.sourceFile = sourceFile;
                }
 
                public byte[] Checksum {
@@ -719,7 +726,7 @@ namespace Mono.CompilerServices.SymbolWriter
 
                        if (hash == null) {
                                try {
-                                   using (FileStream fs = new FileStream (file_name, FileMode.Open, FileAccess.Read)) {
+                                   using (FileStream fs = new FileStream (sourceFile, FileMode.Open, FileAccess.Read)) {
                                        MD5 md5 = MD5.Create ();
                                        hash = md5.ComputeHash (fs);
                                    }
@@ -749,7 +756,7 @@ namespace Mono.CompilerServices.SymbolWriter
                        int old_pos = (int) reader.BaseStream.Position;
                        reader.BaseStream.Position = DataOffset;
 
-                       file_name = reader.ReadString ();
+                       sourceFile = file_name = reader.ReadString ();
                        guid = reader.ReadBytes (16);
                        hash = reader.ReadBytes (16);
                        auto_generated = reader.ReadByte () == 1;
@@ -778,7 +785,7 @@ namespace Mono.CompilerServices.SymbolWriter
                public bool CheckChecksum ()
                {
                        try {
-                               using (FileStream fs = new FileStream (file_name, FileMode.Open)) {
+                               using (FileStream fs = new FileStream (sourceFile, FileMode.Open)) {
                                        MD5 md5 = MD5.Create ();
                                        byte[] data = md5.ComputeHash (fs);
                                        for (int i = 0; i < 16; i++)
diff --git a/mcs/errors/cs8101.cs b/mcs/errors/cs8101.cs
new file mode 100644 (file)
index 0000000..eea62fd
--- /dev/null
@@ -0,0 +1,7 @@
+// CS8101: The pathmap option was incorrectly formatted
+// Line: 0
+// Compiler options: -pathmap:a=
+
+class X
+{
+}
\ No newline at end of file
index 33b05ff809b320ddcb69813f7fbc448007e81153..ddcb149f942a7c818e78b848558ae693882132d1 100644 (file)
@@ -674,13 +674,13 @@ namespace Mono.CSharp
                        if (all_source_files == null) {
                                all_source_files = new Dictionary<string, SourceFile> ();
                                foreach (var source in SourceFiles)
-                                       all_source_files[source.FullPathName] = source;
+                                       all_source_files[source.OriginalFullPathName] = source;
                        }
 
                        string path;
                        if (!Path.IsPathRooted (name)) {
                                var loc = comp_unit.SourceFile;
-                               string root = Path.GetDirectoryName (loc.FullPathName);
+                               string root = Path.GetDirectoryName (loc.OriginalFullPathName);
                                path = Path.GetFullPath (Path.Combine (root, name));
                                var dir = Path.GetDirectoryName (loc.Name);
                                if (!string.IsNullOrEmpty (dir))
index 2077f26bf2cf99d835fed105bbf4503bfeeae1d5..6f1b80596d04cf30d046b1c8439575558d1e2283 100644 (file)
@@ -5222,7 +5222,7 @@ namespace Mono.CSharp {
                                                if ((fp.ModFlags & Parameter.Modifier.CallerLineNumber) != 0) {
                                                        e = new IntLiteral (ec.BuiltinTypes, loc.Row, loc);
                                                } else if ((fp.ModFlags & Parameter.Modifier.CallerFilePath) != 0) {
-                                                       e = new StringLiteral (ec.BuiltinTypes, loc.NameFullPath, loc);
+                                                       e = new StringLiteral (ec.BuiltinTypes, loc.SourceFile.GetFullPathName (ec.Module.Compiler.Settings.PathMap), loc);
                                                } else if (ec.MemberContext.CurrentMemberDefinition != null) {
                                                        e = new StringLiteral (ec.BuiltinTypes, ec.MemberContext.CurrentMemberDefinition.GetCallerMemberName (), loc);
                                                }
index 79cee3cbf7db1dc87fb77e5acfa57ccfa3259f10..658f3b765fa4f48f4e9e1bce1787cca9a387e215 100644 (file)
@@ -15,6 +15,7 @@ using System.Collections.Generic;
 using Mono.CompilerServices.SymbolWriter;
 using System.Diagnostics;
 using System.Linq;
+using System.IO;
 
 namespace Mono.CSharp
 {
@@ -55,7 +56,7 @@ namespace Mono.CSharp
                static readonly byte[] MD5Algorith = { 96, 166, 110, 64, 207, 100, 130, 76, 182, 240, 66, 212, 129, 114, 167, 153 };
 
                public readonly string Name;
-               public readonly string FullPathName;
+               public readonly string OriginalFullPathName;
                public readonly int Index;
                public bool AutoGenerated;
 
@@ -67,7 +68,7 @@ namespace Mono.CSharp
                {
                        this.Index = index;
                        this.Name = name;
-                       this.FullPathName = path;
+                       this.OriginalFullPathName = path;
                }
 
                public byte[] Checksum {
@@ -99,21 +100,43 @@ namespace Mono.CSharp
                        this.checksum = checksum;
                }
 
-               public SourceFileEntry CreateSymbolInfo (MonoSymbolFile symwriter)
+               public SourceFileEntry CreateSymbolInfo (MonoSymbolFile symwriter, List<KeyValuePair<string, string>> pathMap)
                {
                        if (hidden_lines != null)
                                hidden_lines.Sort ();
 
-                       file = new SourceFileEntry (symwriter, FullPathName, algGuid, checksum);
+                       file = new SourceFileEntry (symwriter, GetFullPathName (pathMap), OriginalFullPathName, algGuid, checksum);
                        if (AutoGenerated)
                                file.SetAutoGenerated ();
 
                        return file;
                }
 
+               public string GetFullPathName (List<KeyValuePair<string, string>> pathMap)
+               {
+                       var path = OriginalFullPathName;
+                       if (pathMap != null) {
+                               foreach (var map in pathMap) {
+                                       var prefix = map.Key;
+                                       if (path.Length <= prefix.Length)
+                                               continue;
+
+                                       if (path [prefix.Length] != Path.DirectorySeparatorChar)
+                                               continue;
+
+                                       if (!path.StartsWith (prefix, StringComparison.Ordinal))
+                                               continue;
+
+                                       path = map.Value + path.Substring (prefix.Length);
+                               }
+                       }
+
+                       return path;
+               }
+
                public bool Equals (SourceFile other)
                {
-                       return FullPathName == other.FullPathName;
+                       return OriginalFullPathName == other.OriginalFullPathName;
                }
 
                public bool IsHiddenLocation (Location loc)
@@ -142,7 +165,7 @@ namespace Mono.CSharp
 
                public override string ToString ()
                {
-                       return String.Format ("SourceFile ({0}:{1}:{2})", Name, FullPathName, Index);
+                       return String.Format ("SourceFile ({0}:{1}:{2})", Name, OriginalFullPathName, Index);
                }
        }
 
@@ -326,10 +349,10 @@ namespace Mono.CSharp
                public string NameFullPath {
                        get {
                                int index = File;
-                               if (token == 0 || index <= 0)
+                               if (index <= 0)
                                        return null;
 
-                               return source_list[index - 1].FullPathName;
+                               return source_list[index - 1].OriginalFullPathName;
                        }
                }
 
@@ -369,18 +392,6 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("
                        }
                }
 
-               // The ISymbolDocumentWriter interface is used by the symbol writer to
-               // describe a single source file - for each source file there's exactly
-               // one corresponding ISymbolDocumentWriter instance.
-               //
-               // This class has an internal hash table mapping source document names
-               // to such ISymbolDocumentWriter instances - so there's exactly one
-               // instance per document.
-               //
-               // This property returns the ISymbolDocumentWriter instance which belongs
-               // to the location's source file.
-               //
-               // If we don't have a symbol writer, this property is always null.
                public SourceFile SourceFile {
                        get {
                                int index = File;
index b5379056ee7f9ae38bc0166c9c8f191465762f2f..5384ee1368607a30ea61290b5f19610aa15349e0 100644 (file)
@@ -624,8 +624,8 @@ namespace Mono.CSharp {
                        if (include_files == null)
                                include_files = new Dictionary<string, SourceFile> ();
 
-                       if (!include_files.ContainsKey (file.FullPathName))
-                               include_files.Add (file.FullPathName, file);
+                       if (!include_files.ContainsKey (file.OriginalFullPathName))
+                               include_files.Add (file.OriginalFullPathName, file);
                }
 
                public void AddDefine (string value)
@@ -648,7 +648,7 @@ namespace Mono.CSharp {
                {
                        var sw = Module.DeclaringAssembly.SymbolWriter;
                        if (sw != null) {
-                               CreateUnitSymbolInfo (sw);
+                               CreateUnitSymbolInfo (sw, Compiler.Settings.PathMap);
                        }
 
                        base.PrepareEmit ();
@@ -657,14 +657,14 @@ namespace Mono.CSharp {
                //
                // Creates symbol file index in debug symbol file
                //
-               void CreateUnitSymbolInfo (MonoSymbolFile symwriter)
+               void CreateUnitSymbolInfo (MonoSymbolFile symwriter, List<KeyValuePair<string, string>> pathMap)
                {
-                       var si = file.CreateSymbolInfo (symwriter);
+                       var si = file.CreateSymbolInfo (symwriter, pathMap);
                        comp_unit = new CompileUnitEntry (symwriter, si);
 
                        if (include_files != null) {
                                foreach (SourceFile include in include_files.Values) {
-                                       si = include.CreateSymbolInfo (symwriter);
+                                       si = include.CreateSymbolInfo (symwriter, pathMap);
                                        comp_unit.AddFile (si);
                                }
                        }
index 5a76b965889697d1462b92b3b08540348942ee71..63c6c41d516971168f969c39e4c1f75b1e73ba36 100644 (file)
@@ -87,6 +87,8 @@ namespace Mono.CSharp {
                //
                public List<Tuple<string, string>> AssemblyReferencesAliases;
 
+               public List<KeyValuePair<string, string>> PathMap;
+
                //
                // Modules to be embedded
                //
@@ -1210,6 +1212,31 @@ namespace Mono.CSharp {
                                settings.RuntimeMetadataVersion = value;
                                return ParseResult.Success;
 
+                       case "/pathmap":
+                               if (value.Length == 0) {
+                                       return ParseResult.Success;
+                               }
+
+                               foreach (var pair in value.Split (',')) {
+                                       var kv = pair.Split ('=');
+                                       if (kv.Length != 2) {
+                                               report.Error (8101, "The pathmap option was incorrectly formatted");
+                                               return ParseResult.Error;
+                                       }
+
+                                       if (settings.PathMap == null)
+                                               settings.PathMap = new List<KeyValuePair<string, string>> ();
+
+                                       var key = kv [0].TrimEnd (Path.DirectorySeparatorChar);
+                                       var path = kv [1].TrimEnd (Path.DirectorySeparatorChar);
+                                       if (key.Length == 0 || path.Length == 0)
+                                               report.Error (8101, "The pathmap option was incorrectly formatted");
+
+                                       settings.PathMap.Add (new KeyValuePair<string, string> (key, path));
+                               }
+
+                               return ParseResult.Success;
+
                        // csc options that we don't support
                        case "/analyzer":
                        case "/appconfig":
@@ -1224,7 +1251,6 @@ namespace Mono.CSharp {
                        case "/link":
                        case "/moduleassemblyname":
                        case "/nowin32manifest":
-                       case "/pathmap":
                        case "/pdb":
                        case "/preferreduilang":
                        case "/publicsign":
@@ -1595,7 +1621,7 @@ namespace Mono.CSharp {
                                "   -help                Lists all compiler options (short: -?)\n" +
                                "   -keycontainer:NAME   The key pair container used to sign the output assembly\n" +
                                "   -keyfile:FILE        The key file used to strongname the ouput assembly\n" +
-                               "   -langversion:TEXT    Specifies language version: ISO-1, ISO-2, 3, 4, 5, Default or Experimental\n" +
+                               "   -langversion:TEXT    Specifies language version: ISO-1, ISO-2, 3, 4, 5, 6, Default or Experimental\n" +
                                "   -lib:PATH1[,PATHn]   Specifies the location of referenced assemblies\n" +
                                "   -main:CLASS          Specifies the class with the Main method (short: -m)\n" +
                                "   -noconfig            Disables implicitly referenced assemblies\n" +
@@ -1603,6 +1629,7 @@ namespace Mono.CSharp {
                                "   -nowarn:W1[,Wn]      Suppress one or more compiler warnings\n" +
                                "   -optimize[+|-]       Enables advanced compiler optimizations (short: -o)\n" +
                                "   -out:FILE            Specifies output assembly name\n" +
+                               "   -pathmap:K=V[,Kn=Vn] Sets a mapping for source path names used in generated output\n" +
                                "   -pkg:P1[,Pn]         References packages P1..Pn\n" +
                                "   -platform:ARCH       Specifies the target platform of the output assembly\n" +
                                "                        ARCH can be one of: anycpu, anycpu32bitpreferred, arm,\n" +
index 75b22b934c83c16f46c9d255ce384d5ab8b53368..567c766e6cb5092bce1e1803a64f8e78e1647eb7 100644 (file)
@@ -55,7 +55,7 @@ namespace Mono {
                        var startup_files = new string [settings.SourceFiles.Count];
                        int i = 0;
                        foreach (var source in settings.SourceFiles)
-                               startup_files [i++] = source.FullPathName;
+                               startup_files [i++] = source.OriginalFullPathName;
                        settings.SourceFiles.Clear ();
 
                        TextWriter agent_stderr = null;