[mcs] extend API for loading types and consuming source file from a stream (#4905)
[mono.git] / mcs / mcs / location.cs
index 85eb26c5a1941b47bff6b5272a38d061284e6aed..287aac0797a375b222d27470769e692f0dabefe7 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,9 +56,10 @@ 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;
+               public Func<SourceFile, SeekableStreamReader> GetInputStream;
 
                SourceFileEntry file;
                byte[] algGuid, checksum;
@@ -67,7 +69,12 @@ namespace Mono.CSharp
                {
                        this.Index = index;
                        this.Name = name;
-                       this.FullPathName = path;
+                       this.OriginalFullPathName = path;
+               }
+
+               public SourceFile (string name, string path, int index, Func<SourceFile, SeekableStreamReader> inputStreamDelegate) : this (name, path, index)
+               {
+                       this.GetInputStream = inputStreamDelegate;
                }
 
                public byte[] Checksum {
@@ -99,21 +106,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 +171,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);
                }
        }
 
@@ -222,11 +251,7 @@ namespace Mono.CSharp
                // </summary>
                static public void Initialize (List<SourceFile> files)
                {
-#if NET_4_0 || MONODROID
                        source_list.AddRange (files);
-#else
-                       source_list.AddRange (files.ToArray ());
-#endif
 
                        checkpoints = new Checkpoint [System.Math.Max (1, source_list.Count * 2)];
                        if (checkpoints.Length > 0)
@@ -330,10 +355,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;
                        }
                }
 
@@ -373,18 +398,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;
@@ -412,11 +425,28 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("
                public class MemberLocations
                {
                        public readonly IList<Tuple<Modifiers, Location>> Modifiers;
-                       Location[] locations;
+                       List<Location> locations;
 
-                       public MemberLocations (IList<Tuple<Modifiers, Location>> mods, Location[] locs)
+                       public MemberLocations (IList<Tuple<Modifiers, Location>> mods)
                        {
                                Modifiers = mods;
+                       }
+
+                       public MemberLocations (IList<Tuple<Modifiers, Location>> mods, Location loc)
+                               : this (mods)
+                       {
+                               AddLocations (loc);
+                       }
+
+                       public MemberLocations (IList<Tuple<Modifiers, Location>> mods, Location[] locs)
+                               : this (mods)
+                       {
+                               AddLocations (locs);
+                       }
+
+                       public MemberLocations (IList<Tuple<Modifiers, Location>> mods, List<Location> locs)
+                               : this (mods)
+                       {
                                locations = locs;
                        }
 
@@ -430,31 +460,50 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("
                        
                        public int Count {
                                get {
-                                       return locations.Length;
+                                       return locations.Count;
                                }
                        }
 
                        #endregion
 
+                       public void AddLocations (Location loc)
+                       {
+                               if (locations == null) {
+                                       locations = new List<Location> ();
+                               }
+
+                               locations.Add (loc);
+                       }
+
                        public void AddLocations (params Location[] additional)
                        {
                                if (locations == null) {
-                                       locations = additional;
+                                       locations = new List<Location> (additional);
                                } else {
-                                       int pos = locations.Length;
-                                       Array.Resize (ref locations, pos + additional.Length);
-                                       additional.CopyTo (locations, pos);
+                                       locations.AddRange (additional);
                                }
                        }
                }
 
-               Dictionary<object, Location[]> simple_locs = new Dictionary<object, Location[]> (ReferenceEquality<object>.Default);
+               Dictionary<object, List<Location>> simple_locs = new Dictionary<object, List<Location>> (ReferenceEquality<object>.Default);
                Dictionary<MemberCore, MemberLocations> member_locs = new Dictionary<MemberCore, MemberLocations> (ReferenceEquality<MemberCore>.Default);
 
                [Conditional ("FULL_AST")]
                public void AddLocation (object element, params Location[] locations)
                {
-                       simple_locs.Add (element, locations);
+                       simple_locs.Add (element, new List<Location> (locations));
+               }
+
+               [Conditional ("FULL_AST")]
+               public void InsertLocation (object element, int index, Location location)
+               {
+                       List<Location> found;
+                       if (!simple_locs.TryGetValue (element, out found)) {
+                               found = new List<Location> ();
+                               simple_locs.Add (element, found);
+                       }
+
+                       found.Insert (index, location);
                }
 
                [Conditional ("FULL_AST")]
@@ -463,7 +512,19 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("
                        if (locations.Length == 0)
                                throw new ArgumentException ("Statement is missing semicolon location");
 
-                       simple_locs.Add (element, locations);
+                       AddLocation (element, locations);
+               }
+
+               [Conditional ("FULL_AST")]
+               public void AddMember (MemberCore member, IList<Tuple<Modifiers, Location>> modLocations)
+               {
+                       member_locs.Add (member, new MemberLocations (modLocations));
+               }
+
+               [Conditional ("FULL_AST")]
+               public void AddMember (MemberCore member, IList<Tuple<Modifiers, Location>> modLocations, Location location)
+               {
+                       member_locs.Add (member, new MemberLocations (modLocations, location));
                }
 
                [Conditional ("FULL_AST")]
@@ -473,13 +534,21 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("
                }
 
                [Conditional ("FULL_AST")]
-               public void AppendTo (object existing, params Location[] locations)
+               public void AddMember (MemberCore member, IList<Tuple<Modifiers, Location>> modLocations, List<Location> locations)
                {
-                       Location[] locs;
-                       if (simple_locs.TryGetValue (existing, out locs)) {
-                               simple_locs [existing] = locs.Concat (locations).ToArray ();
-                               return;
+                       member_locs.Add (member, new MemberLocations (modLocations, locations));
+               }
+
+               [Conditional ("FULL_AST")]
+               public void AppendTo (object element, Location location)
+               {
+                       List<Location> found;
+                       if (!simple_locs.TryGetValue (element, out found)) {
+                               found = new List<Location> ();
+                               simple_locs.Add (element, found);
                        }
+
+                       found.Add (location);
                }
 
                [Conditional ("FULL_AST")]
@@ -492,9 +561,9 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("
                        }
                }
 
-               public Location[] GetLocations (object element)
+               public List<Location> GetLocations (object element)
                {
-                       Location[] found;
+                       List<Location> found;
                        simple_locs.TryGetValue (element, out found);
                        return found;
                }