2002-09-16 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / location.cs
1 //
2 // location.cs: Keeps track of the location of source code entity
3 //
4 // Author:
5 //   Miguel de Icaza
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9
10 using System;
11 using System.IO;
12 using System.Collections;
13 using System.Diagnostics.SymbolStore;
14
15 namespace Mono.CSharp {
16         /// <summary>
17         ///   Keeps track of the location in the program
18         /// </summary>
19         ///
20         /// <remarks>
21         ///   This uses a compact representation and a couple of auxiliary
22         ///   structures to keep track of tokens to (file,line) mappings.
23         ///
24         ///   We could probably also keep track of columns by storing those
25         ///   in 8 bits (and say, map anything after char 255 to be `255+').
26         /// </remarks>
27         public struct Location {
28                 public int token; 
29
30                 static Hashtable map;
31                 static Hashtable sym_docs;
32                 static ArrayList list;
33                 static int global_count;
34                 static int module_base;
35
36                 public readonly static Location Null;
37                 
38                 static Location ()
39                 {
40                         map = new Hashtable ();
41                         list = new ArrayList ();
42                         sym_docs = new Hashtable ();
43                         global_count = 0;
44                         module_base = 0;
45                         Null.token = -1;
46                 }
47
48                 static public void Push (string name)
49                 {
50                         map.Remove (global_count);
51                         map.Add (global_count, name);
52                         list.Add (global_count);
53                         module_base = global_count;
54                 }
55                 
56                 public Location (int row)
57                 {
58                         if (row < 0)
59                                 token = -1;
60                         else {
61                                 token = module_base + row;
62                                 if (global_count < token)
63                                         global_count = token;
64                         }
65                 }
66
67                 public override string ToString ()
68                 {
69                         return Name + ": (" + Row + ")";
70                 }
71                 
72                 /// <summary>
73                 ///   Whether the Location is Null
74                 /// </summary>
75                 static public bool IsNull (Location l)
76                 {
77                         return l.token == -1;
78                 }
79
80                 public string Name {
81                         get {
82                                 int best = 0;
83                                 
84                                 if (token < 0)
85                                         return "Internal";
86
87                                 foreach (int b in list){
88                                         if (token > b)
89                                                 best = b;
90                                 }
91                                 return (string) map [best];
92                         }
93                 }
94
95                 public int Row {
96                         get {
97                                 int best = 0;
98                                 
99                                 if (token < 0)
100                                         return 1;
101                                 
102                                 foreach (int b in list){
103                                         if (token > b)
104                                                 best = b;
105                                 }
106                                 return token - best;
107                         }
108                 }
109
110                 // The ISymbolDocumentWriter interface is used by the symbol writer to
111                 // describe a single source file - for each source file there's exactly
112                 // one corresponding ISymbolDocumentWriter instance.
113                 //
114                 // This class has an internal hash table mapping source document names
115                 // to such ISymbolDocumentWriter instances - so there's exactly one
116                 // instance per document.
117                 //
118                 // This property returns the ISymbolDocumentWriter instance which belongs
119                 // to the location's source file.
120                 //
121                 // If we don't have a symbol writer, this property is always null.
122                 public ISymbolDocumentWriter SymbolDocument {
123                         get {
124                                 ISymbolWriter sw = CodeGen.SymbolWriter;
125                                 ISymbolDocumentWriter doc;
126
127                                 if (token < 0)
128                                         return null;
129
130                                 // If we don't have a symbol writer, return null.
131                                 if (sw == null)
132                                         return null;
133
134                                 string path = Path.GetFullPath (Name);
135
136                                 if (sym_docs.Contains (path))
137                                         // If we already created an ISymbolDocumentWriter
138                                         // instance for this document, return it.
139                                         doc = (ISymbolDocumentWriter) sym_docs [path];
140                                 else {
141                                         // Create a new ISymbolDocumentWriter instance and
142                                         // store it in the hash table.
143                                         doc = sw.DefineDocument (path, SymLanguageType.CSharp,
144                                                                  SymLanguageVendor.Microsoft,
145                                                                  SymDocumentType.Text);
146
147                                         sym_docs.Add (path, doc);
148                                 }
149
150                                 return doc;
151                         }
152                 }
153         }
154 }