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