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

« back to all changes in this revision

Viewing changes to src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/mcs/report.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
// report.cs: report errors and warnings.
 
3
//
 
4
// Author: Miguel de Icaza (miguel@ximian.com)
 
5
//         Marek Safar (marek.safar@seznam.cz)         
 
6
//
 
7
// Copyright 2001 Ximian, Inc. (http://www.ximian.com)
 
8
//
 
9
 
 
10
using System;
 
11
using System.IO;
 
12
using System.Text;
 
13
using System.Collections.Generic;
 
14
using System.Diagnostics;
 
15
 
 
16
namespace Mono.CSharp {
 
17
 
 
18
        //
 
19
        // Errors and warnings manager
 
20
        //
 
21
        public class Report
 
22
        {
 
23
                /// <summary>  
 
24
                ///   Whether warnings should be considered errors
 
25
                /// </summary>
 
26
                public bool WarningsAreErrors;
 
27
                List<int> warnings_as_error;
 
28
                List<int> warnings_only;
 
29
 
 
30
                public const int RuntimeErrorId = 10000;
 
31
 
 
32
                //
 
33
                // Keeps track of the warnings that we are ignoring
 
34
                //
 
35
                HashSet<int> warning_ignore_table;
 
36
 
 
37
                Dictionary<int, WarningRegions> warning_regions_table;
 
38
 
 
39
                int warning_level;
 
40
 
 
41
                ReportPrinter printer;
 
42
 
 
43
                int reporting_disabled;
 
44
                
 
45
                /// <summary>
 
46
                /// List of symbols related to reported error/warning. You have to fill it before error/warning is reported.
 
47
                /// </summary>
 
48
                List<string> extra_information = new List<string> ();
 
49
 
 
50
                // 
 
51
                // IF YOU ADD A NEW WARNING YOU HAVE TO ADD ITS ID HERE
 
52
                //
 
53
                public static readonly int[] AllWarnings = new int[] {
 
54
                        28, 67, 78,
 
55
                        105, 108, 109, 114, 162, 164, 168, 169, 183, 184, 197,
 
56
                        219, 251, 252, 253, 278, 282,
 
57
                        402, 414, 419, 420, 429, 436, 437, 440, 458, 464, 465, 467, 469, 472, 473,
 
58
                        612, 618, 626, 628, 642, 649, 652, 657, 658, 659, 660, 661, 665, 672, 675, 693,
 
59
                        728,
 
60
                        809, 824,
 
61
                        1030, 1058, 1066,
 
62
                        1522, 1570, 1571, 1572, 1573, 1574, 1580, 1581, 1584, 1587, 1589, 1590, 1591, 1592,
 
63
                        1607, 1616, 1633, 1634, 1635, 1685, 1690, 1691, 1692, 1695, 1696, 1699,
 
64
                        1700, 1701, 1702, 1709, 1717, 1718, 1720,
 
65
                        1901, 1956, 1981,
 
66
                        2002, 2023, 2029,
 
67
                        3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009,
 
68
                        3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019,
 
69
                        3021, 3022, 3023, 3024, 3026, 3027
 
70
                };
 
71
 
 
72
                static HashSet<int> AllWarningsHashSet;
 
73
 
 
74
                public Report (ReportPrinter printer)
 
75
                {
 
76
                        if (printer == null)
 
77
                                throw new ArgumentNullException ("printer");
 
78
 
 
79
                        this.printer = printer;
 
80
                        warning_level = 4;
 
81
                }
 
82
 
 
83
                public void DisableReporting ()
 
84
                {
 
85
                        ++reporting_disabled;
 
86
                }
 
87
 
 
88
                public void EnableReporting ()
 
89
                {
 
90
                        --reporting_disabled;
 
91
                }
 
92
 
 
93
                public void FeatureIsNotAvailable (CompilerContext compiler, Location loc, string feature)
 
94
                {
 
95
                        string version;
 
96
                        switch (compiler.Settings.Version) {
 
97
                        case LanguageVersion.ISO_1:
 
98
                                version = "1.0";
 
99
                                break;
 
100
                        case LanguageVersion.ISO_2:
 
101
                                version = "2.0";
 
102
                                break;
 
103
                        case LanguageVersion.V_3:
 
104
                                version = "3.0";
 
105
                                break;
 
106
                        default:
 
107
                                throw new InternalErrorException ("Invalid feature version", compiler.Settings.Version);
 
108
                        }
 
109
 
 
110
                        Error (1644, loc,
 
111
                                "Feature `{0}' cannot be used because it is not part of the C# {1} language specification",
 
112
                                      feature, version);
 
113
                }
 
114
 
 
115
                public void FeatureIsNotSupported (Location loc, string feature)
 
116
                {
 
117
                        Error (1644, loc,
 
118
                                "Feature `{0}' is not supported in Mono mcs1 compiler. Consider using the `gmcs' compiler instead",
 
119
                                feature);
 
120
                }
 
121
                
 
122
                bool IsWarningEnabled (int code, int level, Location loc)
 
123
                {
 
124
                        if (WarningLevel < level)
 
125
                                return false;
 
126
 
 
127
                        if (IsWarningDisabledGlobally (code))
 
128
                                return false;
 
129
 
 
130
                        if (warning_regions_table == null || loc.IsNull)
 
131
                                return true;
 
132
 
 
133
                        WarningRegions regions;
 
134
                        if (!warning_regions_table.TryGetValue (loc.File, out regions))
 
135
                                return true;
 
136
 
 
137
                        return regions.IsWarningEnabled (code, loc.Row);
 
138
                }
 
139
 
 
140
                public bool IsWarningDisabledGlobally (int code)
 
141
                {
 
142
                        return warning_ignore_table != null && warning_ignore_table.Contains (code);
 
143
                }
 
144
 
 
145
                bool IsWarningAsError (int code)
 
146
                {
 
147
                        bool is_error = WarningsAreErrors;
 
148
 
 
149
                        // Check specific list
 
150
                        if (warnings_as_error != null)
 
151
                                is_error |= warnings_as_error.Contains (code);
 
152
 
 
153
                        // Ignore excluded warnings
 
154
                        if (warnings_only != null && warnings_only.Contains (code))
 
155
                                is_error = false;
 
156
 
 
157
                        return is_error;
 
158
                }
 
159
                        
 
160
                public void RuntimeMissingSupport (Location loc, string feature) 
 
161
                {
 
162
                        Error (-88, loc, "Your .NET Runtime does not support `{0}'. Please use the latest Mono runtime instead.", feature);
 
163
                }
 
164
 
 
165
                /// <summary>
 
166
                /// In most error cases is very useful to have information about symbol that caused the error.
 
167
                /// Call this method before you call Report.Error when it makes sense.
 
168
                /// </summary>
 
169
                public void SymbolRelatedToPreviousError (Location loc, string symbol)
 
170
                {
 
171
                        SymbolRelatedToPreviousError (loc.ToString ());
 
172
                }
 
173
 
 
174
                public void SymbolRelatedToPreviousError (MemberSpec ms)
 
175
                {
 
176
                        if (reporting_disabled > 0 || !printer.HasRelatedSymbolSupport)
 
177
                                return;
 
178
 
 
179
                        var mc = ms.MemberDefinition as MemberCore;
 
180
                        while (ms is ElementTypeSpec) {
 
181
                                ms = ((ElementTypeSpec) ms).Element;
 
182
                                mc = ms.MemberDefinition as MemberCore;
 
183
                        }
 
184
 
 
185
                        if (mc != null) {
 
186
                                SymbolRelatedToPreviousError (mc);
 
187
                        } else {
 
188
                                if (ms.DeclaringType != null)
 
189
                                        ms = ms.DeclaringType;
 
190
 
 
191
                                var imported_type = ms.MemberDefinition as ImportedTypeDefinition;
 
192
                                if (imported_type != null) {
 
193
                                        var iad = imported_type.DeclaringAssembly as ImportedAssemblyDefinition;
 
194
                                        SymbolRelatedToPreviousError (iad.Location);
 
195
                                }
 
196
                        }
 
197
                }
 
198
 
 
199
                public void SymbolRelatedToPreviousError (MemberCore mc)
 
200
                {
 
201
                        SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ());
 
202
                }
 
203
 
 
204
                public void SymbolRelatedToPreviousError (string loc)
 
205
                {
 
206
                        string msg = String.Format ("{0} (Location of the symbol related to previous ", loc);
 
207
                        if (extra_information.Contains (msg))
 
208
                                return;
 
209
 
 
210
                        extra_information.Add (msg);
 
211
                }
 
212
 
 
213
                public void AddWarningAsError (string warningId)
 
214
                {
 
215
                        int id;
 
216
                        try {
 
217
                                id = int.Parse (warningId);
 
218
                        } catch {
 
219
                                CheckWarningCode (warningId, Location.Null);
 
220
                                return;
 
221
                        }
 
222
 
 
223
                        if (!CheckWarningCode (id, Location.Null))
 
224
                                return;
 
225
 
 
226
                        if (warnings_as_error == null)
 
227
                                warnings_as_error = new List<int> ();
 
228
                        
 
229
                        warnings_as_error.Add (id);
 
230
                }
 
231
 
 
232
                public void RemoveWarningAsError (string warningId)
 
233
                {
 
234
                        int id;
 
235
                        try {
 
236
                                id = int.Parse (warningId);
 
237
                        } catch {
 
238
                                CheckWarningCode (warningId, Location.Null);
 
239
                                return;
 
240
                        }
 
241
 
 
242
                        if (!CheckWarningCode (id, Location.Null))
 
243
                                return;
 
244
 
 
245
                        if (warnings_only == null)
 
246
                                warnings_only = new List<int> ();
 
247
 
 
248
                        warnings_only.Add (id);
 
249
                }
 
250
 
 
251
                public bool CheckWarningCode (string code, Location loc)
 
252
                {
 
253
                        Warning (1691, 1, loc, "`{0}' is not a valid warning number", code);
 
254
                        return false;
 
255
                }
 
256
 
 
257
                public bool CheckWarningCode (int code, Location loc)
 
258
                {
 
259
                        if (AllWarningsHashSet == null)
 
260
                                AllWarningsHashSet = new HashSet<int> (AllWarnings);
 
261
 
 
262
                        if (AllWarningsHashSet.Contains (code))
 
263
                                return true;
 
264
 
 
265
                        return CheckWarningCode (code.ToString (), loc);
 
266
                }
 
267
 
 
268
                public void ExtraInformation (Location loc, string msg)
 
269
                {
 
270
                        extra_information.Add (String.Format ("{0} {1}", loc, msg));
 
271
                }
 
272
 
 
273
                public WarningRegions RegisterWarningRegion (Location location)
 
274
                {
 
275
                        WarningRegions regions;
 
276
                        if (warning_regions_table == null) {
 
277
                                regions = null;
 
278
                                warning_regions_table = new Dictionary<int, WarningRegions> ();
 
279
                        } else {
 
280
                                warning_regions_table.TryGetValue (location.File, out regions);
 
281
                        }
 
282
 
 
283
                        if (regions == null) {
 
284
                                regions = new WarningRegions ();
 
285
                                warning_regions_table.Add (location.File, regions);
 
286
                        }
 
287
 
 
288
                        return regions;
 
289
                }
 
290
 
 
291
                public void Warning (int code, int level, Location loc, string message)
 
292
                {
 
293
                        if (reporting_disabled > 0)
 
294
                                return;
 
295
 
 
296
                        if (!IsWarningEnabled (code, level, loc))
 
297
                                return;
 
298
 
 
299
                        AbstractMessage msg;
 
300
                        if (IsWarningAsError (code)) {
 
301
                                message = "Warning as Error: " + message;
 
302
                                msg = new ErrorMessage (code, loc, message, extra_information);
 
303
                        } else {
 
304
                                msg = new WarningMessage (code, loc, message, extra_information);
 
305
                        }
 
306
 
 
307
                        extra_information.Clear ();
 
308
                        printer.Print (msg);
 
309
                }
 
310
 
 
311
                public void Warning (int code, int level, Location loc, string format, string arg)
 
312
                {
 
313
                        Warning (code, level, loc, String.Format (format, arg));
 
314
                }
 
315
 
 
316
                public void Warning (int code, int level, Location loc, string format, string arg1, string arg2)
 
317
                {
 
318
                        Warning (code, level, loc, String.Format (format, arg1, arg2));
 
319
                }
 
320
 
 
321
                public void Warning (int code, int level, Location loc, string format, params object[] args)
 
322
                {
 
323
                        Warning (code, level, loc, String.Format (format, args));
 
324
                }
 
325
 
 
326
                public void Warning (int code, int level, string message)
 
327
                {
 
328
                        Warning (code, level, Location.Null, message);
 
329
                }
 
330
 
 
331
                public void Warning (int code, int level, string format, string arg)
 
332
                {
 
333
                        Warning (code, level, Location.Null, format, arg);
 
334
                }
 
335
 
 
336
                public void Warning (int code, int level, string format, string arg1, string arg2)
 
337
                {
 
338
                        Warning (code, level, Location.Null, format, arg1, arg2);
 
339
                }
 
340
 
 
341
                public void Warning (int code, int level, string format, params string[] args)
 
342
                {
 
343
                        Warning (code, level, Location.Null, String.Format (format, args));
 
344
                }
 
345
 
 
346
                //
 
347
                // Warnings encountered so far
 
348
                //
 
349
                public int Warnings {
 
350
                        get { return printer.WarningsCount; }
 
351
                }
 
352
 
 
353
                public void Error (int code, Location loc, string error)
 
354
                {
 
355
                        if (reporting_disabled > 0)
 
356
                                return;
 
357
 
 
358
                        ErrorMessage msg = new ErrorMessage (code, loc, error, extra_information);
 
359
                        extra_information.Clear ();
 
360
 
 
361
                        printer.Print (msg);
 
362
                }
 
363
 
 
364
                public void Error (int code, Location loc, string format, string arg)
 
365
                {
 
366
                        Error (code, loc, String.Format (format, arg));
 
367
                }
 
368
 
 
369
                public void Error (int code, Location loc, string format, string arg1, string arg2)
 
370
                {
 
371
                        Error (code, loc, String.Format (format, arg1, arg2));
 
372
                }
 
373
 
 
374
                public void Error (int code, Location loc, string format, params string[] args)
 
375
                {
 
376
                        Error (code, loc, String.Format (format, args));
 
377
                }
 
378
 
 
379
                public void Error (int code, string error)
 
380
                {
 
381
                        Error (code, Location.Null, error);
 
382
                }
 
383
 
 
384
                public void Error (int code, string format, string arg)
 
385
                {
 
386
                        Error (code, Location.Null, format, arg);
 
387
                }
 
388
 
 
389
                public void Error (int code, string format, string arg1, string arg2)
 
390
                {
 
391
                        Error (code, Location.Null, format, arg1, arg2);
 
392
                }
 
393
 
 
394
                public void Error (int code, string format, params string[] args)
 
395
                {
 
396
                        Error (code, Location.Null, String.Format (format, args));
 
397
                }
 
398
 
 
399
                //
 
400
                // Errors encountered so far
 
401
                //
 
402
                public int Errors {
 
403
                        get { return printer.ErrorsCount; }
 
404
                }
 
405
 
 
406
                public bool IsDisabled {
 
407
                        get {
 
408
                                return reporting_disabled > 0;
 
409
                        }
 
410
                }
 
411
 
 
412
                public ReportPrinter Printer {
 
413
                        get { return printer; }
 
414
                }
 
415
 
 
416
                public void SetIgnoreWarning (int code)
 
417
                {
 
418
                        if (warning_ignore_table == null)
 
419
                                warning_ignore_table = new HashSet<int> ();
 
420
 
 
421
                        warning_ignore_table.Add (code);
 
422
                }
 
423
 
 
424
                public ReportPrinter SetPrinter (ReportPrinter printer)
 
425
                {
 
426
                        ReportPrinter old = this.printer;
 
427
                        this.printer = printer;
 
428
                        return old;
 
429
                }
 
430
 
 
431
                public int WarningLevel {
 
432
                        get {
 
433
                                return warning_level;
 
434
                        }
 
435
                        set {
 
436
                                warning_level = value;
 
437
                        }
 
438
                }
 
439
 
 
440
                [Conditional ("MCS_DEBUG")]
 
441
                static public void Debug (string message, params object[] args)
 
442
                {
 
443
                        Debug (4, message, args);
 
444
                }
 
445
                        
 
446
                [Conditional ("MCS_DEBUG")]
 
447
                static public void Debug (int category, string message, params object[] args)
 
448
                {
 
449
//                      if ((category & DebugFlags) == 0)
 
450
//                              return;
 
451
 
 
452
                        StringBuilder sb = new StringBuilder (message);
 
453
 
 
454
                        if ((args != null) && (args.Length > 0)) {
 
455
                                sb.Append (": ");
 
456
 
 
457
                                bool first = true;
 
458
                                foreach (object arg in args) {
 
459
                                        if (first)
 
460
                                                first = false;
 
461
                                        else
 
462
                                                sb.Append (", ");
 
463
                                        if (arg == null)
 
464
                                                sb.Append ("null");
 
465
//                                      else if (arg is ICollection)
 
466
//                                              sb.Append (PrintCollection ((ICollection) arg));
 
467
                                        else
 
468
                                                sb.Append (arg);
 
469
                                }
 
470
                        }
 
471
 
 
472
                        Console.WriteLine (sb.ToString ());
 
473
                }
 
474
/*
 
475
                static public string PrintCollection (ICollection collection)
 
476
                {
 
477
                        StringBuilder sb = new StringBuilder ();
 
478
 
 
479
                        sb.Append (collection.GetType ());
 
480
                        sb.Append ("(");
 
481
 
 
482
                        bool first = true;
 
483
                        foreach (object o in collection) {
 
484
                                if (first)
 
485
                                        first = false;
 
486
                                else
 
487
                                        sb.Append (", ");
 
488
                                sb.Append (o);
 
489
                        }
 
490
 
 
491
                        sb.Append (")");
 
492
                        return sb.ToString ();
 
493
                }
 
494
*/ 
 
495
        }
 
496
 
 
497
        public abstract class AbstractMessage
 
498
        {
 
499
                readonly string[] extra_info;
 
500
                protected readonly int code;
 
501
                protected readonly Location location;
 
502
                readonly string message;
 
503
 
 
504
                protected AbstractMessage (int code, Location loc, string msg, List<string> extraInfo)
 
505
                {
 
506
                        this.code = code;
 
507
                        if (code < 0)
 
508
                                this.code = 8000 - code;
 
509
 
 
510
                        this.location = loc;
 
511
                        this.message = msg;
 
512
                        if (extraInfo.Count != 0) {
 
513
                                this.extra_info = extraInfo.ToArray ();
 
514
                        }
 
515
                }
 
516
 
 
517
                protected AbstractMessage (AbstractMessage aMsg)
 
518
                {
 
519
                        this.code = aMsg.code;
 
520
                        this.location = aMsg.location;
 
521
                        this.message = aMsg.message;
 
522
                        this.extra_info = aMsg.extra_info;
 
523
                }
 
524
 
 
525
                public int Code {
 
526
                        get { return code; }
 
527
                }
 
528
 
 
529
                public override bool Equals (object obj)
 
530
                {
 
531
                        AbstractMessage msg = obj as AbstractMessage;
 
532
                        if (msg == null)
 
533
                                return false;
 
534
 
 
535
                        return code == msg.code && location.Equals (msg.location) && message == msg.message;
 
536
                }
 
537
 
 
538
                public override int GetHashCode ()
 
539
                {
 
540
                        return code.GetHashCode ();
 
541
                }
 
542
 
 
543
                public abstract bool IsWarning { get; }
 
544
 
 
545
                public Location Location {
 
546
                        get { return location; }
 
547
                }
 
548
 
 
549
                public abstract string MessageType { get; }
 
550
 
 
551
                public string[] RelatedSymbols {
 
552
                        get { return extra_info; }
 
553
                }
 
554
 
 
555
                public string Text {
 
556
                        get { return message; }
 
557
                }
 
558
        }
 
559
 
 
560
        sealed class WarningMessage : AbstractMessage
 
561
        {
 
562
                public WarningMessage (int code, Location loc, string message, List<string> extra_info)
 
563
                        : base (code, loc, message, extra_info)
 
564
                {
 
565
                }
 
566
 
 
567
                public override bool IsWarning {
 
568
                        get { return true; }
 
569
                }
 
570
 
 
571
                public override string MessageType {
 
572
                        get {
 
573
                                return "warning";
 
574
                        }
 
575
                }
 
576
        }
 
577
 
 
578
        sealed class ErrorMessage : AbstractMessage
 
579
        {
 
580
                public ErrorMessage (int code, Location loc, string message, List<string> extraInfo)
 
581
                        : base (code, loc, message, extraInfo)
 
582
                {
 
583
                }
 
584
 
 
585
                public ErrorMessage (AbstractMessage aMsg)
 
586
                        : base (aMsg)
 
587
                {
 
588
                }
 
589
 
 
590
                public override bool IsWarning {
 
591
                        get { return false; }
 
592
                }
 
593
 
 
594
                public override string MessageType {
 
595
                        get {
 
596
                                return "error";
 
597
                        }
 
598
                }
 
599
        }
 
600
 
 
601
        //
 
602
        // Generic base for any message writer
 
603
        //
 
604
        public abstract class ReportPrinter
 
605
        {
 
606
                #region Properties
 
607
 
 
608
                public int FatalCounter { get; set; }
 
609
 
 
610
                public int ErrorsCount { get; protected set; }
 
611
        
 
612
                public bool ShowFullPaths { get; set; }
 
613
 
 
614
                //
 
615
                // Whether to dump a stack trace on errors. 
 
616
                //
 
617
                public bool Stacktrace { get; set; }
 
618
 
 
619
                public int WarningsCount { get; private set; }
 
620
        
 
621
                //
 
622
                // When (symbols related to previous ...) can be used
 
623
                //
 
624
                public virtual bool HasRelatedSymbolSupport {
 
625
                        get { return true; }
 
626
                }
 
627
 
 
628
                #endregion
 
629
 
 
630
 
 
631
                protected virtual string FormatText (string txt)
 
632
                {
 
633
                        return txt;
 
634
                }
 
635
 
 
636
                public virtual void Print (AbstractMessage msg)
 
637
                {
 
638
                        if (msg.IsWarning) {
 
639
                                ++WarningsCount;
 
640
                        } else {
 
641
                                ++ErrorsCount;
 
642
 
 
643
                                if (ErrorsCount == FatalCounter)
 
644
                                        throw new Exception (msg.Text);
 
645
                        }
 
646
                }
 
647
 
 
648
                protected void Print (AbstractMessage msg, TextWriter output)
 
649
                {
 
650
                        StringBuilder txt = new StringBuilder ();
 
651
                        if (!msg.Location.IsNull) {
 
652
                                if (ShowFullPaths)
 
653
                                        txt.Append (msg.Location.ToStringFullName ());
 
654
                                else
 
655
                                        txt.Append (msg.Location.ToString ());
 
656
 
 
657
                                txt.Append (" ");
 
658
                        }
 
659
 
 
660
                        txt.AppendFormat ("{0} CS{1:0000}: {2}", msg.MessageType, msg.Code, msg.Text);
 
661
 
 
662
                        if (!msg.IsWarning)
 
663
                                output.WriteLine (FormatText (txt.ToString ()));
 
664
                        else
 
665
                                output.WriteLine (txt.ToString ());
 
666
 
 
667
                        if (msg.RelatedSymbols != null) {
 
668
                                foreach (string s in msg.RelatedSymbols)
 
669
                                        output.WriteLine (s + msg.MessageType + ")");
 
670
                        }
 
671
                }
 
672
 
 
673
                public void Reset ()
 
674
                {
 
675
                        // HACK: Temporary hack for broken repl flow
 
676
                        ErrorsCount = WarningsCount = 0;
 
677
                }
 
678
        }
 
679
 
 
680
        sealed class NullReportPrinter : ReportPrinter
 
681
        {
 
682
        }
 
683
 
 
684
        //
 
685
        // Default message recorder, it uses two types of message groups.
 
686
        // Common messages: messages reported in all sessions.
 
687
        // Merged messages: union of all messages in all sessions. 
 
688
        //
 
689
        // Used by the Lambda expressions to compile the code with various
 
690
        // parameter values, or by attribute resolver
 
691
        //
 
692
        class SessionReportPrinter : ReportPrinter
 
693
        {
 
694
                List<AbstractMessage> session_messages;
 
695
                //
 
696
                // A collection of exactly same messages reported in all sessions
 
697
                //
 
698
                List<AbstractMessage> common_messages;
 
699
 
 
700
                //
 
701
                // A collection of unique messages reported in all sessions
 
702
                //
 
703
                List<AbstractMessage> merged_messages;
 
704
 
 
705
                public override void Print (AbstractMessage msg)
 
706
                {
 
707
                        //
 
708
                        // This line is useful when debugging recorded messages
 
709
                        //
 
710
                        // Console.WriteLine ("RECORDING: {0}", msg.ToString ());
 
711
 
 
712
                        if (session_messages == null)
 
713
                                session_messages = new List<AbstractMessage> ();
 
714
 
 
715
                        session_messages.Add (msg);
 
716
 
 
717
                        base.Print (msg);
 
718
                }
 
719
 
 
720
                public void EndSession ()
 
721
                {
 
722
                        if (session_messages == null)
 
723
                                return;
 
724
 
 
725
                        //
 
726
                        // Handles the first session
 
727
                        //
 
728
                        if (common_messages == null) {
 
729
                                common_messages = new List<AbstractMessage> (session_messages);
 
730
                                merged_messages = session_messages;
 
731
                                session_messages = null;
 
732
                                return;
 
733
                        }
 
734
 
 
735
                        //
 
736
                        // Store common messages if any
 
737
                        //
 
738
                        for (int i = 0; i < common_messages.Count; ++i) {
 
739
                                AbstractMessage cmsg = common_messages[i];
 
740
                                bool common_msg_found = false;
 
741
                                foreach (AbstractMessage msg in session_messages) {
 
742
                                        if (cmsg.Equals (msg)) {
 
743
                                                common_msg_found = true;
 
744
                                                break;
 
745
                                        }
 
746
                                }
 
747
 
 
748
                                if (!common_msg_found)
 
749
                                        common_messages.RemoveAt (i);
 
750
                        }
 
751
 
 
752
                        //
 
753
                        // Merge session and previous messages
 
754
                        //
 
755
                        for (int i = 0; i < session_messages.Count; ++i) {
 
756
                                AbstractMessage msg = session_messages[i];
 
757
                                bool msg_found = false;
 
758
                                for (int ii = 0; ii < merged_messages.Count; ++ii) {
 
759
                                        if (msg.Equals (merged_messages[ii])) {
 
760
                                                msg_found = true;
 
761
                                                break;
 
762
                                        }
 
763
                                }
 
764
 
 
765
                                if (!msg_found)
 
766
                                        merged_messages.Add (msg);
 
767
                        }
 
768
                }
 
769
 
 
770
                public bool IsEmpty {
 
771
                        get {
 
772
                                return merged_messages == null && common_messages == null;
 
773
                        }
 
774
                }
 
775
 
 
776
                //
 
777
                // Prints collected messages, common messages have a priority
 
778
                //
 
779
                public bool Merge (ReportPrinter dest)
 
780
                {
 
781
                        var messages_to_print = merged_messages;
 
782
                        if (common_messages != null && common_messages.Count > 0) {
 
783
                                messages_to_print = common_messages;
 
784
                        }
 
785
 
 
786
                        if (messages_to_print == null)
 
787
                                return false;
 
788
 
 
789
                        bool error_msg = false;
 
790
                        foreach (AbstractMessage msg in messages_to_print) {
 
791
                                dest.Print (msg);
 
792
                                error_msg |= !msg.IsWarning;
 
793
                        }
 
794
 
 
795
                        return error_msg;
 
796
                }
 
797
        }
 
798
 
 
799
        public class StreamReportPrinter : ReportPrinter
 
800
        {
 
801
                readonly TextWriter writer;
 
802
 
 
803
                public StreamReportPrinter (TextWriter writer)
 
804
                {
 
805
                        this.writer = writer;
 
806
                }
 
807
 
 
808
                public override void Print (AbstractMessage msg)
 
809
                {
 
810
                        Print (msg, writer);
 
811
                        base.Print (msg);
 
812
                }
 
813
        }
 
814
 
 
815
        public class ConsoleReportPrinter : StreamReportPrinter
 
816
        {
 
817
                static readonly string prefix, postfix;
 
818
 
 
819
                static ConsoleReportPrinter ()
 
820
                {
 
821
                        string term = Environment.GetEnvironmentVariable ("TERM");
 
822
                        bool xterm_colors = false;
 
823
                        
 
824
                        switch (term){
 
825
                        case "xterm":
 
826
                        case "rxvt":
 
827
                        case "rxvt-unicode": 
 
828
                                if (Environment.GetEnvironmentVariable ("COLORTERM") != null){
 
829
                                        xterm_colors = true;
 
830
                                }
 
831
                                break;
 
832
 
 
833
                        case "xterm-color":
 
834
                                xterm_colors = true;
 
835
                                break;
 
836
                        }
 
837
                        if (!xterm_colors)
 
838
                                return;
 
839
 
 
840
                        if (!(UnixUtils.isatty (1) && UnixUtils.isatty (2)))
 
841
                                return;
 
842
                        
 
843
                        string config = Environment.GetEnvironmentVariable ("MCS_COLORS");
 
844
                        if (config == null){
 
845
                                config = "errors=red";
 
846
                                //config = "brightwhite,red";
 
847
                        }
 
848
 
 
849
                        if (config == "disable")
 
850
                                return;
 
851
 
 
852
                        if (!config.StartsWith ("errors="))
 
853
                                return;
 
854
 
 
855
                        config = config.Substring (7);
 
856
                        
 
857
                        int p = config.IndexOf (",");
 
858
                        if (p == -1)
 
859
                                prefix = GetForeground (config);
 
860
                        else
 
861
                                prefix = GetBackground (config.Substring (p+1)) + GetForeground (config.Substring (0, p));
 
862
                        postfix = "\x001b[0m";
 
863
                }
 
864
 
 
865
                public ConsoleReportPrinter ()
 
866
                        : base (Console.Error)
 
867
                {
 
868
                }
 
869
 
 
870
                public ConsoleReportPrinter (TextWriter writer)
 
871
                        : base (writer)
 
872
                {
 
873
                }
 
874
 
 
875
                static int NameToCode (string s)
 
876
                {
 
877
                        switch (s) {
 
878
                        case "black":
 
879
                                return 0;
 
880
                        case "red":
 
881
                                return 1;
 
882
                        case "green":
 
883
                                return 2;
 
884
                        case "yellow":
 
885
                                return 3;
 
886
                        case "blue":
 
887
                                return 4;
 
888
                        case "magenta":
 
889
                                return 5;
 
890
                        case "cyan":
 
891
                                return 6;
 
892
                        case "grey":
 
893
                        case "white":
 
894
                                return 7;
 
895
                        }
 
896
                        return 7;
 
897
                }
 
898
 
 
899
                //
 
900
                // maps a color name to its xterm color code
 
901
                //
 
902
                static string GetForeground (string s)
 
903
                {
 
904
                        string highcode;
 
905
 
 
906
                        if (s.StartsWith ("bright")) {
 
907
                                highcode = "1;";
 
908
                                s = s.Substring (6);
 
909
                        } else
 
910
                                highcode = "";
 
911
 
 
912
                        return "\x001b[" + highcode + (30 + NameToCode (s)).ToString () + "m";
 
913
                }
 
914
 
 
915
                static string GetBackground (string s)
 
916
                {
 
917
                        return "\x001b[" + (40 + NameToCode (s)).ToString () + "m";
 
918
                }
 
919
 
 
920
                protected override string FormatText (string txt)
 
921
                {
 
922
                        if (prefix != null)
 
923
                                return prefix + txt + postfix;
 
924
 
 
925
                        return txt;
 
926
                }
 
927
 
 
928
                static string FriendlyStackTrace (StackTrace t)
 
929
                {               
 
930
                        StringBuilder sb = new StringBuilder ();
 
931
                        
 
932
                        bool foundUserCode = false;
 
933
                        
 
934
                        for (int i = 0; i < t.FrameCount; i++) {
 
935
                                StackFrame f = t.GetFrame (i);
 
936
                                var mb = f.GetMethod ();
 
937
                                
 
938
                                if (!foundUserCode && mb.ReflectedType == typeof (Report))
 
939
                                        continue;
 
940
                                
 
941
                                foundUserCode = true;
 
942
                                
 
943
                                sb.Append ("\tin ");
 
944
                                
 
945
                                if (f.GetFileLineNumber () > 0)
 
946
                                        sb.AppendFormat ("(at {0}:{1}) ", f.GetFileName (), f.GetFileLineNumber ());
 
947
                                
 
948
                                sb.AppendFormat ("{0}.{1} (", mb.ReflectedType.Name, mb.Name);
 
949
                                
 
950
                                bool first = true;
 
951
                                foreach (var pi in mb.GetParameters ()) {
 
952
                                        if (!first)
 
953
                                                sb.Append (", ");
 
954
                                        first = false;
 
955
 
 
956
                                        sb.Append (pi.ParameterType.FullName);
 
957
                                }
 
958
                                sb.Append (")\n");
 
959
                        }
 
960
        
 
961
                        return sb.ToString ();
 
962
                }
 
963
 
 
964
                public override void Print (AbstractMessage msg)
 
965
                {
 
966
                        base.Print (msg);
 
967
 
 
968
                        if (Stacktrace)
 
969
                                Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
 
970
                }
 
971
 
 
972
                public static string FriendlyStackTrace (Exception e)
 
973
                {
 
974
                        return FriendlyStackTrace (new StackTrace (e, true));
 
975
                }
 
976
 
 
977
                public static void StackTrace ()
 
978
                {
 
979
                        Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
 
980
                }
 
981
        }
 
982
 
 
983
        class TimeReporter
 
984
        {
 
985
                public enum TimerType
 
986
                {
 
987
                        ParseTotal,
 
988
                        AssemblyBuilderSetup,
 
989
                        CreateTypeTotal,
 
990
                        ReferencesLoading,
 
991
                        ReferencesImporting,
 
992
                        PredefinedTypesInit,
 
993
                        ModuleDefinitionTotal,
 
994
                        UsingResolve,
 
995
                        EmitTotal,
 
996
                        CloseTypes,
 
997
                        Resouces,
 
998
                        OutputSave,
 
999
                        DebugSave,
 
1000
                }
 
1001
 
 
1002
                readonly Stopwatch[] timers;
 
1003
                Stopwatch total;
 
1004
 
 
1005
                public TimeReporter (bool enabled)
 
1006
                {
 
1007
                        if (!enabled)
 
1008
                                return;
 
1009
 
 
1010
                        timers = new Stopwatch[System.Enum.GetValues(typeof (TimerType)).Length];
 
1011
                }
 
1012
 
 
1013
                public void Start (TimerType type)
 
1014
                {
 
1015
                        if (timers != null) {
 
1016
                                var sw = new Stopwatch ();
 
1017
                                timers[(int) type] = sw;
 
1018
                                sw.Start ();
 
1019
                        }
 
1020
                }
 
1021
 
 
1022
                public void StartTotal ()
 
1023
                {
 
1024
                        total = new Stopwatch ();
 
1025
                        total.Start ();
 
1026
                }
 
1027
 
 
1028
                public void Stop (TimerType type)
 
1029
                {
 
1030
                        if (timers != null) {
 
1031
                                timers[(int) type].Stop ();
 
1032
                        }
 
1033
                }
 
1034
 
 
1035
                public void StopTotal ()
 
1036
                {
 
1037
                        total.Stop ();
 
1038
                }
 
1039
 
 
1040
                public void ShowStats ()
 
1041
                {
 
1042
                        if (timers == null)
 
1043
                                return;
 
1044
 
 
1045
                        Dictionary<TimerType, string> timer_names = new Dictionary<TimerType,string> () {
 
1046
                                { TimerType.ParseTotal, "Parsing source files" },
 
1047
                                { TimerType.AssemblyBuilderSetup, "Assembly builder setup" },
 
1048
                                { TimerType.CreateTypeTotal, "Compiled types created" },
 
1049
                                { TimerType.ReferencesLoading, "Referenced assemblies loading" },
 
1050
                                { TimerType.ReferencesImporting, "Referenced assemblies importing" },
 
1051
                                { TimerType.PredefinedTypesInit, "Predefined types initialization" },
 
1052
                                { TimerType.ModuleDefinitionTotal, "Module definition" },
 
1053
                                { TimerType.UsingResolve, "Top-level usings resolve" },
 
1054
                                { TimerType.EmitTotal, "Resolving and emitting members blocks" },
 
1055
                                { TimerType.CloseTypes, "Module types closed" },
 
1056
                                { TimerType.Resouces, "Embedding resources" },
 
1057
                                { TimerType.OutputSave, "Writing output file" },
 
1058
                                { TimerType.DebugSave, "Writing debug symbols file" },
 
1059
                        };
 
1060
 
 
1061
                        int counter = 0;
 
1062
                        double percentage = (double) total.ElapsedMilliseconds / 100;
 
1063
                        long subtotal = total.ElapsedMilliseconds;
 
1064
                        foreach (var timer in timers) {
 
1065
                                string msg = timer_names[(TimerType) counter++];
 
1066
                                var ms = timer == null ? 0 : timer.ElapsedMilliseconds;
 
1067
                                Console.WriteLine ("{0,4:0.0}% {1,5}ms {2}", ms / percentage, ms, msg);
 
1068
                                subtotal -= ms;
 
1069
                        }
 
1070
 
 
1071
                        Console.WriteLine ("{0,4:0.0}% {1,5}ms Other tasks", subtotal / percentage, subtotal);
 
1072
                        Console.WriteLine ();
 
1073
                        Console.WriteLine ("Total elapsed time: {0}", total.Elapsed);
 
1074
                }
 
1075
        }
 
1076
 
 
1077
        public class InternalErrorException : Exception {
 
1078
                public InternalErrorException (MemberCore mc, Exception e)
 
1079
                        : base (mc.Location + " " + mc.GetSignatureForError (), e)
 
1080
                {
 
1081
                }
 
1082
 
 
1083
                public InternalErrorException ()
 
1084
                        : base ("Internal error")
 
1085
                {
 
1086
                }
 
1087
 
 
1088
                public InternalErrorException (string message)
 
1089
                        : base (message)
 
1090
                {
 
1091
                }
 
1092
 
 
1093
                public InternalErrorException (string message, params object[] args)
 
1094
                        : base (String.Format (message, args))
 
1095
                {
 
1096
                }
 
1097
 
 
1098
                public InternalErrorException (Exception exception, string message, params object[] args)
 
1099
                        : base (String.Format (message, args), exception)
 
1100
                {
 
1101
                }
 
1102
                
 
1103
                public InternalErrorException (Exception e, Location loc)
 
1104
                        : base (loc.ToString (), e)
 
1105
                {
 
1106
                }
 
1107
        }
 
1108
 
 
1109
        /// <summary>
 
1110
        /// Handles #pragma warning
 
1111
        /// </summary>
 
1112
        public class WarningRegions {
 
1113
 
 
1114
                abstract class PragmaCmd
 
1115
                {
 
1116
                        public int Line;
 
1117
 
 
1118
                        protected PragmaCmd (int line)
 
1119
                        {
 
1120
                                Line = line;
 
1121
                        }
 
1122
 
 
1123
                        public abstract bool IsEnabled (int code, bool previous);
 
1124
                }
 
1125
                
 
1126
                class Disable : PragmaCmd
 
1127
                {
 
1128
                        int code;
 
1129
                        public Disable (int line, int code)
 
1130
                                : base (line)
 
1131
                        {
 
1132
                                this.code = code;
 
1133
                        }
 
1134
 
 
1135
                        public override bool IsEnabled (int code, bool previous)
 
1136
                        {
 
1137
                                return this.code == code ? false : previous;
 
1138
                        }
 
1139
                }
 
1140
 
 
1141
                class DisableAll : PragmaCmd
 
1142
                {
 
1143
                        public DisableAll (int line)
 
1144
                                : base (line) {}
 
1145
 
 
1146
                        public override bool IsEnabled(int code, bool previous)
 
1147
                        {
 
1148
                                return false;
 
1149
                        }
 
1150
                }
 
1151
 
 
1152
                class Enable : PragmaCmd
 
1153
                {
 
1154
                        int code;
 
1155
                        public Enable (int line, int code)
 
1156
                                : base (line)
 
1157
                        {
 
1158
                                this.code = code;
 
1159
                        }
 
1160
 
 
1161
                        public override bool IsEnabled(int code, bool previous)
 
1162
                        {
 
1163
                                return this.code == code ? true : previous;
 
1164
                        }
 
1165
                }
 
1166
 
 
1167
                class EnableAll : PragmaCmd
 
1168
                {
 
1169
                        public EnableAll (int line)
 
1170
                                : base (line) {}
 
1171
 
 
1172
                        public override bool IsEnabled(int code, bool previous)
 
1173
                        {
 
1174
                                return true;
 
1175
                        }
 
1176
                }
 
1177
 
 
1178
 
 
1179
                List<PragmaCmd> regions = new List<PragmaCmd> ();
 
1180
 
 
1181
                public void WarningDisable (int line)
 
1182
                {
 
1183
                        regions.Add (new DisableAll (line));
 
1184
                }
 
1185
 
 
1186
                public void WarningDisable (Location location, int code, Report Report)
 
1187
                {
 
1188
                        if (Report.CheckWarningCode (code, location))
 
1189
                                regions.Add (new Disable (location.Row, code));
 
1190
                }
 
1191
 
 
1192
                public void WarningEnable (int line)
 
1193
                {
 
1194
                        regions.Add (new EnableAll (line));
 
1195
                }
 
1196
 
 
1197
                public void WarningEnable (Location location, int code, Report Report)
 
1198
                {
 
1199
                        if (!Report.CheckWarningCode (code, location))
 
1200
                                return;
 
1201
 
 
1202
                        if (Report.IsWarningDisabledGlobally (code))
 
1203
                                Report.Warning (1635, 1, location, "Cannot restore warning `CS{0:0000}' because it was disabled globally", code);
 
1204
 
 
1205
                        regions.Add (new Enable (location.Row, code));
 
1206
                }
 
1207
 
 
1208
                public bool IsWarningEnabled (int code, int src_line)
 
1209
                {
 
1210
                        bool result = true;
 
1211
                        foreach (PragmaCmd pragma in regions) {
 
1212
                                if (src_line < pragma.Line)
 
1213
                                        break;
 
1214
 
 
1215
                                result = pragma.IsEnabled (code, result);
 
1216
                        }
 
1217
                        return result;
 
1218
                }
 
1219
        }
 
1220
}