~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/mcs/location.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// location.cs: Keeps track of the location of source code entity
 
3
//
 
4
// Author:
 
5
//   Miguel de Icaza
 
6
//   Atsushi Enomoto  <atsushi@ximian.com>
 
7
//   Marek Safar (marek.safar@gmail.com)
 
8
//
 
9
// Copyright 2001 Ximian, Inc.
 
10
// Copyright 2005 Novell, Inc.
 
11
//
 
12
 
 
13
using System;
 
14
using System.IO;
 
15
using System.Collections.Generic;
 
16
using Mono.CompilerServices.SymbolWriter;
 
17
using System.Diagnostics;
 
18
using System.Linq;
 
19
 
 
20
namespace Mono.CSharp {
 
21
        /// <summary>
 
22
        ///   This is one single source file.
 
23
        /// </summary>
 
24
        /// <remarks>
 
25
        ///   This is intentionally a class and not a struct since we need
 
26
        ///   to pass this by reference.
 
27
        /// </remarks>
 
28
        public class SourceFile : ISourceFile, IEquatable<SourceFile>
 
29
        {
 
30
                public readonly string Name;
 
31
                public readonly string FullPathName;
 
32
                public readonly int Index;
 
33
                public bool AutoGenerated;
 
34
 
 
35
                SourceFileEntry file;
 
36
                byte[] guid, checksum;
 
37
 
 
38
                public SourceFile (string name, string path, int index)
 
39
                {
 
40
                        this.Index = index;
 
41
                        this.Name = name;
 
42
                        this.FullPathName = path;
 
43
                }
 
44
 
 
45
                public SourceFileEntry SourceFileEntry {
 
46
                        get { return file; }
 
47
                }
 
48
 
 
49
                SourceFileEntry ISourceFile.Entry {
 
50
                        get { return file; }
 
51
                }
 
52
 
 
53
                public void SetChecksum (byte[] guid, byte[] checksum)
 
54
                {
 
55
                        this.guid = guid;
 
56
                        this.checksum = checksum;
 
57
                }
 
58
 
 
59
                public virtual void DefineSymbolInfo (MonoSymbolWriter symwriter)
 
60
                {
 
61
                        if (guid != null)
 
62
                                file = symwriter.DefineDocument (FullPathName, guid, checksum);
 
63
                        else {
 
64
                                file = symwriter.DefineDocument (FullPathName);
 
65
                                if (AutoGenerated)
 
66
                                        file.SetAutoGenerated ();
 
67
                        }
 
68
                }
 
69
 
 
70
                public bool Equals (SourceFile other)
 
71
                {
 
72
                        return FullPathName == other.FullPathName;
 
73
                }
 
74
 
 
75
                public override string ToString ()
 
76
                {
 
77
                        return String.Format ("SourceFile ({0}:{1}:{2}:{3})",
 
78
                                                  Name, FullPathName, Index, SourceFileEntry);
 
79
                }
 
80
        }
 
81
 
 
82
        public class CompilationSourceFile : SourceFile, ICompileUnit
 
83
        {
 
84
                CompileUnitEntry comp_unit;
 
85
                Dictionary<string, SourceFile> include_files;
 
86
                Dictionary<string, bool> conditionals;
 
87
                NamespaceContainer ns_container;
 
88
 
 
89
                public CompilationSourceFile (string name, string fullPathName, int index)
 
90
                        : base (name, fullPathName, index)
 
91
                {
 
92
                }
 
93
 
 
94
                CompileUnitEntry ICompileUnit.Entry {
 
95
                        get { return comp_unit; }
 
96
                }
 
97
 
 
98
                public CompileUnitEntry CompileUnitEntry {
 
99
                        get { return comp_unit; }
 
100
                }
 
101
 
 
102
                public NamespaceContainer NamespaceContainer {
 
103
                        get {
 
104
                                return ns_container;
 
105
                        }
 
106
                        set {
 
107
                                ns_container = value;
 
108
                        }
 
109
                }
 
110
 
 
111
                public void AddIncludeFile (SourceFile file)
 
112
                {
 
113
                        if (file == this)
 
114
                                return;
 
115
                        
 
116
                        if (include_files == null)
 
117
                                include_files = new Dictionary<string, SourceFile> ();
 
118
 
 
119
                        if (!include_files.ContainsKey (file.FullPathName))
 
120
                                include_files.Add (file.FullPathName, file);
 
121
                }
 
122
 
 
123
                public void AddDefine (string value)
 
124
                {
 
125
                        if (conditionals == null)
 
126
                                conditionals = new Dictionary<string, bool> (2);
 
127
 
 
128
                        conditionals [value] = true;
 
129
                }
 
130
 
 
131
                public void AddUndefine (string value)
 
132
                {
 
133
                        if (conditionals == null)
 
134
                                conditionals = new Dictionary<string, bool> (2);
 
135
 
 
136
                        conditionals [value] = false;
 
137
                }
 
138
 
 
139
                public override void DefineSymbolInfo (MonoSymbolWriter symwriter)
 
140
                {
 
141
                        base.DefineSymbolInfo (symwriter);
 
142
 
 
143
                        comp_unit = symwriter.DefineCompilationUnit (SourceFileEntry);
 
144
 
 
145
                        if (include_files != null) {
 
146
                                foreach (SourceFile include in include_files.Values) {
 
147
                                        include.DefineSymbolInfo (symwriter);
 
148
                                        comp_unit.AddFile (include.SourceFileEntry);
 
149
                                }
 
150
                        }
 
151
                }
 
152
 
 
153
                public bool IsConditionalDefined (CompilerContext ctx, string value)
 
154
                {
 
155
                        if (conditionals != null) {
 
156
                                bool res;
 
157
                                if (conditionals.TryGetValue (value, out res))
 
158
                                        return res;
 
159
                                
 
160
                                // When conditional was undefined
 
161
                                if (conditionals.ContainsKey (value))
 
162
                                        return false;                                   
 
163
                        }
 
164
 
 
165
                        return ctx.Settings.IsConditionalSymbolDefined (value);
 
166
                }
 
167
        }
 
168
 
 
169
        /// <summary>
 
170
        ///   Keeps track of the location in the program
 
171
        /// </summary>
 
172
        ///
 
173
        /// <remarks>
 
174
        ///   This uses a compact representation and a couple of auxiliary
 
175
        ///   structures to keep track of tokens to (file,line and column) 
 
176
        ///   mappings. The usage of the bits is:
 
177
        ///   
 
178
        ///     - 16 bits for "checkpoint" which is a mixed concept of
 
179
        ///       file and "line segment"
 
180
        ///     - 8 bits for line delta (offset) from the line segment
 
181
        ///     - 8 bits for column number.
 
182
        ///
 
183
        ///   http://lists.ximian.com/pipermail/mono-devel-list/2004-December/009508.html
 
184
        /// </remarks>
 
185
        public struct Location : IEquatable<Location>
 
186
        {
 
187
                struct Checkpoint {
 
188
                        public readonly int LineOffset;
 
189
                        public readonly int CompilationUnit;
 
190
                        public readonly int File;
 
191
 
 
192
                        public Checkpoint (int compile_unit, int file, int line)
 
193
                        {
 
194
                                File = file;
 
195
                                CompilationUnit = compile_unit;
 
196
                                LineOffset = line - (int) (line % (1 << line_delta_bits));
 
197
                        }
 
198
                }
 
199
 
 
200
#if FULL_AST
 
201
                long token;
 
202
 
 
203
                const int column_bits = 24;
 
204
                const int line_delta_bits = 24;
 
205
#else
 
206
                int token;
 
207
 
 
208
                const int column_bits = 8;
 
209
                const int line_delta_bits = 8;
 
210
#endif
 
211
                const int checkpoint_bits = 16;
 
212
 
 
213
                // -2 because the last one is used for hidden
 
214
                const int max_column = (1 << column_bits) - 2;
 
215
                const int column_mask = (1 << column_bits) - 1;
 
216
 
 
217
                static List<SourceFile> source_list;
 
218
                static int current_source;
 
219
                static int current_compile_unit;
 
220
                static Checkpoint [] checkpoints;
 
221
                static int checkpoint_index;
 
222
                
 
223
                public readonly static Location Null = new Location (-1);
 
224
                public static bool InEmacs;
 
225
                
 
226
                static Location ()
 
227
                {
 
228
                        Reset ();
 
229
                }
 
230
 
 
231
                public static void Reset ()
 
232
                {
 
233
                        source_list = new List<SourceFile> ();
 
234
                        current_source = 0;
 
235
                        current_compile_unit = 0;
 
236
                        checkpoint_index = 0;
 
237
                }
 
238
 
 
239
                public static SourceFile AddFile (string name, string fullName)
 
240
                {
 
241
                        var source = new SourceFile (name, fullName, source_list.Count + 1);
 
242
                        source_list.Add (source);
 
243
                        return source;
 
244
                }
 
245
 
 
246
                // <summary>
 
247
                //   After adding all source files we want to compile with AddFile(), this method
 
248
                //   must be called to `reserve' an appropriate number of bits in the token for the
 
249
                //   source file.  We reserve some extra space for files we encounter via #line
 
250
                //   directives while parsing.
 
251
                // </summary>
 
252
                static public void Initialize (List<CompilationSourceFile> files)
 
253
                {
 
254
#if NET_4_0
 
255
                        source_list.AddRange (files);
 
256
#else
 
257
                        source_list.AddRange (files.ToArray ());
 
258
#endif
 
259
 
 
260
                        checkpoints = new Checkpoint [source_list.Count * 2];
 
261
                        if (checkpoints.Length > 0)
 
262
                                checkpoints [0] = new Checkpoint (0, 0, 0);
 
263
                }
 
264
 
 
265
                static public void Push (CompilationSourceFile compile_unit, SourceFile file)
 
266
                {
 
267
                        current_source = file != null ? file.Index : -1;
 
268
                        current_compile_unit = compile_unit != null ? compile_unit.Index : -1;
 
269
                        // File is always pushed before being changed.
 
270
                }
 
271
                
 
272
                public Location (int row)
 
273
                        : this (row, 0)
 
274
                {
 
275
                }
 
276
 
 
277
                public Location (int row, int column)
 
278
                {
 
279
                        if (row <= 0)
 
280
                                token = 0;
 
281
                        else {
 
282
                                if (column > max_column)
 
283
                                        column = max_column;
 
284
                                else if (column < 0)
 
285
                                        column = max_column + 1;
 
286
 
 
287
                                long target = -1;
 
288
                                long delta = 0;
 
289
 
 
290
                                // FIXME: This value is certainly wrong but what was the intension
 
291
                                int max = checkpoint_index < 10 ?
 
292
                                        checkpoint_index : 10;
 
293
                                for (int i = 0; i < max; i++) {
 
294
                                        int offset = checkpoints [checkpoint_index - i].LineOffset;
 
295
                                        delta = row - offset;
 
296
                                        if (delta >= 0 &&
 
297
                                                delta < (1 << line_delta_bits) &&
 
298
                                                checkpoints [checkpoint_index - i].File == current_source) {
 
299
                                                target = checkpoint_index - i;
 
300
                                                break;
 
301
                                        }
 
302
                                }
 
303
                                if (target == -1) {
 
304
                                        AddCheckpoint (current_compile_unit, current_source, row);
 
305
                                        target = checkpoint_index;
 
306
                                        delta = row % (1 << line_delta_bits);
 
307
                                }
 
308
 
 
309
                                long l = column +
 
310
                                        (delta << column_bits) +
 
311
                                        (target << (line_delta_bits + column_bits));
 
312
#if FULL_AST
 
313
                                token = l;
 
314
#else
 
315
                                token = l > 0xFFFFFFFF ? 0 : (int) l;
 
316
#endif
 
317
                        }
 
318
                }
 
319
 
 
320
                public static Location operator - (Location loc, int columns)
 
321
                {
 
322
                        return new Location (loc.Row, loc.Column - columns);
 
323
                }
 
324
 
 
325
                static void AddCheckpoint (int compile_unit, int file, int row)
 
326
                {
 
327
                        if (checkpoints.Length == ++checkpoint_index) {
 
328
                                Array.Resize (ref checkpoints, checkpoint_index * 2);
 
329
                        }
 
330
                        checkpoints [checkpoint_index] = new Checkpoint (compile_unit, file, row);
 
331
                }
 
332
 
 
333
                string FormatLocation (string fileName)
 
334
                {
 
335
                        if (column_bits == 0 || InEmacs)
 
336
                                return fileName + "(" + Row.ToString () + "):";
 
337
 
 
338
                        return fileName + "(" + Row.ToString () + "," + Column.ToString () +
 
339
                                (Column == max_column ? "+):" : "):");
 
340
                }
 
341
                
 
342
                public override string ToString ()
 
343
                {
 
344
                        return FormatLocation (Name);
 
345
                }
 
346
 
 
347
                public string ToStringFullName ()
 
348
                {
 
349
                        return FormatLocation (NameFullPath);
 
350
                }
 
351
                
 
352
                /// <summary>
 
353
                ///   Whether the Location is Null
 
354
                /// </summary>
 
355
                public bool IsNull {
 
356
                        get { return token == 0; }
 
357
                }
 
358
 
 
359
                public string Name {
 
360
                        get {
 
361
                                int index = File;
 
362
                                if (token == 0 || index == 0)
 
363
                                        return "Internal";
 
364
                                if (source_list == null || index - 1 >= source_list.Count)
 
365
                                        return "unknown_file";
 
366
 
 
367
                                SourceFile file = source_list [index - 1];
 
368
                                return file.Name;
 
369
                        }
 
370
                }
 
371
 
 
372
                public string NameFullPath {
 
373
                        get {
 
374
                                int index = File;
 
375
                                if (token == 0 || index == 0)
 
376
                                        return "Internal";
 
377
 
 
378
                                return source_list[index - 1].FullPathName;
 
379
                        }
 
380
                }
 
381
 
 
382
                int CheckpointIndex {
 
383
                        get {
 
384
                                const int checkpoint_mask = (1 << checkpoint_bits) - 1;
 
385
                                return ((int) (token >> (line_delta_bits + column_bits))) & checkpoint_mask;
 
386
                        }
 
387
                }
 
388
 
 
389
                public int Row {
 
390
                        get {
 
391
                                if (token == 0)
 
392
                                        return 1;
 
393
 
 
394
                                int offset = checkpoints[CheckpointIndex].LineOffset;
 
395
 
 
396
                                const int line_delta_mask = (1 << column_bits) - 1;
 
397
                                return offset + (((int)(token >> column_bits)) & line_delta_mask);
 
398
                        }
 
399
                }
 
400
 
 
401
                public int Column {
 
402
                        get {
 
403
                                if (token == 0)
 
404
                                        return 1;
 
405
                                int col = (int) (token & column_mask);
 
406
                                return col > max_column ? 1 : col;
 
407
                        }
 
408
                }
 
409
 
 
410
                public bool Hidden {
 
411
                        get {
 
412
                                return (int) (token & column_mask) == max_column + 1;
 
413
                        }
 
414
                }
 
415
 
 
416
                public int CompilationUnitIndex {
 
417
                        get {
 
418
                                if (token == 0)
 
419
                                        return 0;
 
420
if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("Should not happen. Token is {0:X04}, checkpoints are {1}, index is {2}", token, checkpoints.Length, CheckpointIndex));
 
421
                                return checkpoints [CheckpointIndex].CompilationUnit;
 
422
                        }
 
423
                }
 
424
 
 
425
                public int File {
 
426
                        get {
 
427
                                if (token == 0)
 
428
                                        return 0;
 
429
if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("Should not happen. Token is {0:X04}, checkpoints are {1}, index is {2}", token, checkpoints.Length, CheckpointIndex));
 
430
                                return checkpoints [CheckpointIndex].File;
 
431
                        }
 
432
                }
 
433
 
 
434
                // The ISymbolDocumentWriter interface is used by the symbol writer to
 
435
                // describe a single source file - for each source file there's exactly
 
436
                // one corresponding ISymbolDocumentWriter instance.
 
437
                //
 
438
                // This class has an internal hash table mapping source document names
 
439
                // to such ISymbolDocumentWriter instances - so there's exactly one
 
440
                // instance per document.
 
441
                //
 
442
                // This property returns the ISymbolDocumentWriter instance which belongs
 
443
                // to the location's source file.
 
444
                //
 
445
                // If we don't have a symbol writer, this property is always null.
 
446
                public SourceFile SourceFile {
 
447
                        get {
 
448
                                int index = File;
 
449
                                if (index == 0)
 
450
                                        return null;
 
451
                                return (SourceFile) source_list [index - 1];
 
452
                        }
 
453
                }
 
454
 
 
455
                public CompilationSourceFile CompilationUnit {
 
456
                        get {
 
457
                                int index = CompilationUnitIndex;
 
458
                                if (index == 0)
 
459
                                        return null;
 
460
                                return (CompilationSourceFile) source_list [index - 1];
 
461
                        }
 
462
                }
 
463
 
 
464
                #region IEquatable<Location> Members
 
465
 
 
466
                public bool Equals (Location other)
 
467
                {
 
468
                        return this.token == other.token;
 
469
                }
 
470
 
 
471
                #endregion
 
472
        }
 
473
        
 
474
        public class SpecialsBag
 
475
        {
 
476
                public enum CommentType
 
477
                {
 
478
                        Single,
 
479
                        Multi,
 
480
                        Documentation
 
481
                }
 
482
                
 
483
                public class Comment
 
484
                {
 
485
                        public readonly CommentType CommentType;
 
486
                        public readonly bool StartsLine;
 
487
                        public readonly int Line;
 
488
                        public readonly int Col;
 
489
                        public readonly int EndLine;
 
490
                        public readonly int EndCol;
 
491
                        public readonly string Content;
 
492
                        
 
493
                        public Comment (CommentType commentType, bool startsLine, int line, int col, int endLine, int endCol, string content)
 
494
                        {
 
495
                                this.CommentType = commentType;
 
496
                                this.StartsLine = startsLine;
 
497
                                this.Line = line;
 
498
                                this.Col = col;
 
499
                                this.EndLine = endLine;
 
500
                                this.EndCol = endCol;
 
501
                                this.Content = content;
 
502
                        }
 
503
 
 
504
                        public override string ToString ()
 
505
                        {
 
506
                                return string.Format ("[Comment: CommentType={0}, Line={1}, Col={2}, EndLine={3}, EndCol={4}, Content={5}]", CommentType, Line, Col, EndLine, EndCol, Content);
 
507
                        }
 
508
                }
 
509
                
 
510
                public class PreProcessorDirective
 
511
                {
 
512
                        public readonly int Line;
 
513
                        public readonly int Col;
 
514
                        public readonly int EndLine;
 
515
                        public readonly int EndCol;
 
516
 
 
517
                        public readonly Tokenizer.PreprocessorDirective Cmd;
 
518
                        public readonly string Arg;
 
519
 
 
520
                        public PreProcessorDirective (int line, int col, int endLine, int endCol, Tokenizer.PreprocessorDirective cmd, string arg)
 
521
                        {
 
522
                                this.Line = line;
 
523
                                this.Col = col;
 
524
                                this.EndLine = endLine;
 
525
                                this.EndCol = endCol;
 
526
                                this.Cmd = cmd;
 
527
                                this.Arg = arg;
 
528
                        }
 
529
                        
 
530
                        public override string ToString ()
 
531
                        {
 
532
                                return string.Format ("[PreProcessorDirective: Line={0}, Col={1}, EndLine={2}, EndCol={3}, Cmd={4}, Arg={5}]", Line, Col, EndLine, EndCol, Cmd, Arg);
 
533
                        }
 
534
                }
 
535
                
 
536
                public readonly List<object> Specials = new List<object> ();
 
537
                
 
538
                CommentType curComment;
 
539
                bool startsLine;
 
540
                int startLine, startCol;
 
541
                System.Text.StringBuilder contentBuilder = new System.Text.StringBuilder ();
 
542
                
 
543
                [Conditional ("FULL_AST")]
 
544
                public void StartComment (CommentType type, bool startsLine, int startLine, int startCol)
 
545
                {
 
546
                        curComment = type;
 
547
                        this.startsLine = startsLine;
 
548
                        this.startLine = startLine;
 
549
                        this.startCol = startCol;
 
550
                        contentBuilder.Length = 0;
 
551
                }
 
552
                
 
553
                [Conditional ("FULL_AST")]
 
554
                public void PushCommentChar (int ch)
 
555
                {
 
556
                        if (ch < 0)
 
557
                                return;
 
558
                        contentBuilder.Append ((char)ch);
 
559
                }
 
560
                [Conditional ("FULL_AST")]
 
561
                public void PushCommentString (string str)
 
562
                {
 
563
                        contentBuilder.Append (str);
 
564
                }
 
565
                
 
566
                [Conditional ("FULL_AST")]
 
567
                public void EndComment (int endLine, int endColumn)
 
568
                {
 
569
                        Specials.Add (new Comment (curComment, startsLine, startLine, startCol, endLine, endColumn, contentBuilder.ToString ()));
 
570
                }
 
571
                
 
572
                [Conditional ("FULL_AST")]
 
573
                public void AddPreProcessorDirective (int startLine, int startCol, int endLine, int endColumn, Tokenizer.PreprocessorDirective cmd, string arg)
 
574
                {
 
575
                        Specials.Add (new PreProcessorDirective (startLine, startCol, endLine, endColumn, cmd, arg));
 
576
                }
 
577
        }
 
578
 
 
579
        //
 
580
        // A bag of additional locations to support full ast tree
 
581
        //
 
582
        public class LocationsBag
 
583
        {
 
584
                public class MemberLocations
 
585
                {
 
586
                        public IList<Tuple<Modifiers, Location>> Modifiers { get; internal set; }
 
587
                        List<Location> locations;
 
588
                        
 
589
                        public MemberLocations (IList<Tuple<Modifiers, Location>> mods, IEnumerable<Location> locs)
 
590
                        {
 
591
                                Modifiers = mods;
 
592
                                locations = locs != null ?  new List<Location> (locs) : null;
 
593
                        }
 
594
 
 
595
                        #region Properties
 
596
 
 
597
                        public Location this [int index] {
 
598
                                get {
 
599
                                        return locations [index];
 
600
                                }
 
601
                        }
 
602
                        
 
603
                        public int Count {
 
604
                                get {
 
605
                                        return locations != null ? locations.Count : 0;
 
606
                                }
 
607
                        }
 
608
 
 
609
                        #endregion
 
610
 
 
611
                        public void AddLocations (params Location[] additional)
 
612
 
 
613
                        {
 
614
 
 
615
                                AddLocations ((IEnumerable<Location>)additional);
 
616
 
 
617
                        }
 
618
                        public void AddLocations (IEnumerable<Location> additional)
 
619
                        {
 
620
                                if (additional == null)
 
621
                                        return;
 
622
                                if (locations == null) {
 
623
                                        locations = new List<Location>(additional);
 
624
                                } else {
 
625
                                        locations.AddRange (additional);
 
626
                                }
 
627
                        }
 
628
                }
 
629
                
 
630
                public MemberCore LastMember {
 
631
                        get;
 
632
                        private set;
 
633
                }
 
634
 
 
635
                Dictionary<object, List<Location>> simple_locs = new Dictionary<object,  List<Location>> (ReferenceEquality<object>.Default);
 
636
                Dictionary<MemberCore, MemberLocations> member_locs = new Dictionary<MemberCore, MemberLocations> (ReferenceEquality<MemberCore>.Default);
 
637
 
 
638
                [Conditional ("FULL_AST")]
 
639
                public void AddLocation (object element, params Location[] locations)
 
640
                {
 
641
                        AddLocation (element, (IEnumerable<Location>)locations);
 
642
                }
 
643
 
 
644
                [Conditional ("FULL_AST")]
 
645
                public void AddLocation (object element, IEnumerable<Location> locations)
 
646
                {
 
647
                        if (element == null || locations == null)
 
648
                                return;
 
649
                        simple_locs.Add (element, new List<Location> (locations));
 
650
                }
 
651
 
 
652
                [Conditional ("FULL_AST")]
 
653
                public void AddStatement (object element, params Location[] locations)
 
654
                {
 
655
                        if (element == null)
 
656
                                return;
 
657
                        if (locations.Length == 0)
 
658
                                throw new ArgumentException ("Statement is missing semicolon location");
 
659
                        simple_locs.Add (element, new List<Location>(locations));
 
660
                }
 
661
 
 
662
                [Conditional ("FULL_AST")]
 
663
                public void AddMember (MemberCore member, IList<Tuple<Modifiers, Location>> modLocations, params Location[] locations)
 
664
                {
 
665
                        LastMember = member;
 
666
                        if (member == null)
 
667
                                return;
 
668
                        
 
669
                        MemberLocations existing;
 
670
                        if (member_locs.TryGetValue (member, out existing)) {
 
671
                                existing.Modifiers = modLocations;
 
672
                                existing.AddLocations (locations);
 
673
                                return;
 
674
                        }
 
675
                        member_locs.Add (member, new MemberLocations (modLocations, locations));
 
676
                }
 
677
                [Conditional ("FULL_AST")]
 
678
                public void AddMember (MemberCore member, IList<Tuple<Modifiers, Location>> modLocations, IEnumerable<Location> locations)
 
679
                {
 
680
                        LastMember = member;
 
681
                        if (member == null)
 
682
                                return;
 
683
                        
 
684
                        MemberLocations existing;
 
685
                        if (member_locs.TryGetValue (member, out existing)) {
 
686
                                existing.Modifiers = modLocations;
 
687
                                existing.AddLocations (locations);
 
688
                                return;
 
689
                        }
 
690
                        member_locs.Add (member, new MemberLocations (modLocations, locations));
 
691
                }
 
692
 
 
693
                [Conditional ("FULL_AST")]
 
694
                public void AppendTo (object existing, params Location[] locations)
 
695
                {
 
696
                        AppendTo (existing, (IEnumerable<Location>)locations);
 
697
 
 
698
                }
 
699
 
 
700
                [Conditional ("FULL_AST")]
 
701
                public void AppendTo (object existing, IEnumerable<Location> locations)
 
702
                {
 
703
                        if (existing == null)
 
704
                                return;
 
705
                        List<Location> locs;
 
706
                        if (simple_locs.TryGetValue (existing, out locs)) {
 
707
                                simple_locs [existing].AddRange (locations);
 
708
                                return;
 
709
                        }
 
710
                        AddLocation (existing, locations);
 
711
                }
 
712
                
 
713
                [Conditional ("FULL_AST")]
 
714
                public void AppendToMember (MemberCore existing, params Location[] locations)
 
715
                {
 
716
                        AppendToMember (existing, (IEnumerable<Location>)locations);
 
717
 
 
718
                }
 
719
                
 
720
                [Conditional ("FULL_AST")]
 
721
                public void AppendToMember (MemberCore existing, IEnumerable<Location> locations)
 
722
                {
 
723
                        if (existing == null)
 
724
                                return;
 
725
                        MemberLocations member;
 
726
                        if (member_locs.TryGetValue (existing, out member)) {
 
727
                                member.AddLocations (locations);
 
728
                                return;
 
729
                        }
 
730
                        member_locs.Add (existing, new MemberLocations (null, locations));
 
731
                }
 
732
 
 
733
                public List<Location> GetLocations (object element)
 
734
                {
 
735
                        List<Location> found;
 
736
                        simple_locs.TryGetValue (element, out found);
 
737
                        return found;
 
738
                }
 
739
 
 
740
                public MemberLocations GetMemberLocation (MemberCore element)
 
741
                {
 
742
                        MemberLocations found;
 
743
                        member_locs.TryGetValue (element, out found);
 
744
                        return found;
 
745
                }
 
746
        }
 
747
        
 
748
        public class UsingsBag
 
749
        {
 
750
                public class Namespace {
 
751
                        public Location NamespaceLocation { get; set; }
 
752
                        public MemberName Name { get; set; }
 
753
                        
 
754
                        public Location OpenBrace { get; set; }
 
755
                        public Location CloseBrace { get; set; }
 
756
                        public Location OptSemicolon { get; set; }
 
757
                        
 
758
                        public List<object> usings = new List<object> ();
 
759
                        public List<object> members = new List<object> ();
 
760
                        
 
761
                        
 
762
                        public virtual void Accept (StructuralVisitor visitor)
 
763
                        {
 
764
                                visitor.Visit (this);
 
765
                        }
 
766
                }
 
767
                
 
768
                public class AliasUsing
 
769
                {
 
770
                        public readonly Location UsingLocation;
 
771
                        public readonly Tokenizer.LocatedToken Identifier;
 
772
                        public readonly Location AssignLocation;
 
773
                        public readonly MemberName Nspace;
 
774
                        public readonly Location SemicolonLocation;
 
775
                        
 
776
                        public AliasUsing (Location usingLocation, Tokenizer.LocatedToken identifier, Location assignLocation, MemberName nspace, Location semicolonLocation)
 
777
                        {
 
778
                                this.UsingLocation = usingLocation;
 
779
                                this.Identifier = identifier;
 
780
                                this.AssignLocation = assignLocation;
 
781
                                this.Nspace = nspace;
 
782
                                this.SemicolonLocation = semicolonLocation;
 
783
                        }
 
784
                        
 
785
                        public virtual void Accept (StructuralVisitor visitor)
 
786
                        {
 
787
                                visitor.Visit (this);
 
788
                        }
 
789
                }
 
790
                
 
791
                public class Using
 
792
                {
 
793
                        public readonly Location UsingLocation;
 
794
                        public readonly MemberName NSpace;
 
795
                        public readonly Location SemicolonLocation;
 
796
 
 
797
                        public Using (Location usingLocation, MemberName nSpace, Location semicolonLocation)
 
798
                        {
 
799
                                this.UsingLocation = usingLocation;
 
800
                                this.NSpace = nSpace;
 
801
                                this.SemicolonLocation = semicolonLocation;
 
802
                        }
 
803
 
 
804
                        public virtual void Accept (StructuralVisitor visitor)
 
805
                        {
 
806
                                visitor.Visit (this);
 
807
                        }
 
808
                }
 
809
                
 
810
                public class ExternAlias 
 
811
                {
 
812
                        public readonly Location ExternLocation;
 
813
                        public readonly Location AliasLocation;
 
814
                        public readonly Tokenizer.LocatedToken Identifier;
 
815
                        public readonly Location SemicolonLocation;
 
816
                        
 
817
                        public ExternAlias (Location externLocation, Location aliasLocation, Tokenizer.LocatedToken identifier, Location semicolonLocation)
 
818
                        {
 
819
                                this.ExternLocation = externLocation;
 
820
                                this.AliasLocation = aliasLocation;
 
821
                                this.Identifier = identifier;
 
822
                                this.SemicolonLocation = semicolonLocation;
 
823
                        }
 
824
 
 
825
                        public virtual void Accept (StructuralVisitor visitor)
 
826
                        {
 
827
                                visitor.Visit (this);
 
828
                        }
 
829
                }
 
830
                
 
831
                public Namespace Global {
 
832
                        get;
 
833
                        set;
 
834
                }
 
835
                Stack<Namespace> curNamespace = new Stack<Namespace> ();
 
836
                
 
837
                public UsingsBag ()
 
838
                {
 
839
                        Global = new Namespace ();
 
840
                        Global.OpenBrace = new Location (1, 1);
 
841
                        Global.CloseBrace = new Location (int.MaxValue, int.MaxValue);
 
842
                        curNamespace.Push (Global);
 
843
                }
 
844
                
 
845
                [Conditional ("FULL_AST")]
 
846
                public void AddUsingAlias (Location usingLocation, Tokenizer.LocatedToken identifier, Location assignLocation, MemberName nspace, Location semicolonLocation)
 
847
                {
 
848
                        curNamespace.Peek ().usings.Add (new AliasUsing (usingLocation, identifier, assignLocation, nspace, semicolonLocation));
 
849
                }
 
850
                
 
851
                [Conditional ("FULL_AST")]
 
852
                public void AddUsing (Location usingLocation, MemberName nspace, Location semicolonLocation)
 
853
                {
 
854
                        curNamespace.Peek ().usings.Add (new Using (usingLocation, nspace, semicolonLocation));
 
855
                }
 
856
 
 
857
                [Conditional ("FULL_AST")]
 
858
                public void AddExternAlias (Location externLocation, Location aliasLocation, Tokenizer.LocatedToken identifier, Location semicolonLocation)
 
859
                {
 
860
                        curNamespace.Peek ().usings.Add (new ExternAlias (externLocation, aliasLocation, identifier, semicolonLocation));
 
861
                }
 
862
                
 
863
                [Conditional ("FULL_AST")]
 
864
                public void DeclareNamespace (Location namespaceLocation, MemberName nspace)
 
865
                {
 
866
                        var newNamespace = new Namespace () { NamespaceLocation = namespaceLocation, Name = nspace };
 
867
                        curNamespace.Peek ().members.Add (newNamespace);
 
868
                        curNamespace.Push (newNamespace);
 
869
                }
 
870
                
 
871
                int typeLevel = 0;
 
872
                [Conditional ("FULL_AST")]
 
873
                public void PushTypeDeclaration (object type)
 
874
                {
 
875
                        if (typeLevel == 0)
 
876
                                curNamespace.Peek ().members.Add (type);
 
877
                        typeLevel++;
 
878
                }
 
879
                
 
880
                [Conditional ("FULL_AST")]
 
881
                public void PopTypeDeclaration ()
 
882
                {
 
883
                        typeLevel--;
 
884
                }
 
885
                
 
886
                [Conditional ("FULL_AST")]
 
887
                public void EndNamespace (Location optSemicolon)
 
888
                {
 
889
                        curNamespace.Peek ().OptSemicolon = optSemicolon;
 
890
                        curNamespace.Pop ();
 
891
                }
 
892
                
 
893
                [Conditional ("FULL_AST")]
 
894
                public void OpenNamespace (Location bracketLocation)
 
895
                {
 
896
                        curNamespace.Peek ().OpenBrace = bracketLocation;
 
897
                }
 
898
                
 
899
                [Conditional ("FULL_AST")]
 
900
                public void CloseNamespace (Location bracketLocation)
 
901
                {
 
902
                        curNamespace.Peek ().CloseBrace = bracketLocation;
 
903
                }
 
904
        }
 
905
}