1 /**
2  * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved.
3  * Authors: Jacob Carlborg
4  * Version: Initial created: Oct 6, 2011
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  */
7 module clang.Diagnostic;
8 
9 import std.typecons : RefCounted;
10 
11 import clang.c.Index;
12 import clang.Util;
13 
14 struct Diagnostic
15 {
16     mixin CX;
17 
18     string format (uint options = clang_defaultDiagnosticDisplayOptions)
19     {
20         return toD(clang_formatDiagnostic(cx, options));
21     }
22 
23     @property CXDiagnosticSeverity severity ()
24     {
25         return clang_getDiagnosticSeverity(cx);
26     }
27 
28     @property toString()
29     {
30         return format;
31     }
32 }
33 
34 struct DiagnosticSet
35 {
36     private struct Container
37     {
38         CXDiagnosticSet set;
39 
40         ~this()
41         {
42             if (set != null)
43             {
44                 clang_disposeDiagnosticSet(set);
45             }
46         }
47     }
48 
49     private RefCounted!Container container;
50     private size_t begin;
51     private size_t end;
52 
53     private static RefCounted!Container makeContainer(
54         CXDiagnosticSet set)
55     {
56         RefCounted!Container result;
57         result.set = set;
58         return result;
59     }
60 
61     private this(
62         RefCounted!Container container,
63         size_t begin,
64         size_t end)
65     {
66         this.container = container;
67         this.begin = begin;
68         this.end = end;
69     }
70 
71     this(CXDiagnosticSet set)
72     {
73         container = makeContainer(set);
74         begin = 0;
75         end = clang_getNumDiagnosticsInSet(container.set);
76     }
77 
78     @property bool empty() const
79     {
80         return begin >= end;
81     }
82 
83     @property Diagnostic front()
84     {
85         return Diagnostic(clang_getDiagnosticInSet(container.set, cast(uint) begin));
86     }
87 
88     @property Diagnostic back()
89     {
90         return Diagnostic(clang_getDiagnosticInSet(container.set, cast(uint) (end - 1)));
91     }
92 
93     @property void popFront()
94     {
95         ++begin;
96     }
97 
98     @property void popBack()
99     {
100         --end;
101     }
102 
103     @property DiagnosticSet save()
104     {
105         return this;
106     }
107 
108     @property size_t length() const
109     {
110         return end - begin;
111     }
112 
113     Diagnostic opIndex(size_t index)
114     {
115         return Diagnostic(clang_getDiagnosticInSet(container.set, cast(uint) (begin + index)));
116     }
117 
118     DiagnosticSet opSlice(size_t begin, size_t end)
119     {
120         return DiagnosticSet(container, this.begin + begin, this.begin + end);
121     }
122 
123     size_t opDollar() const
124     {
125         return length;
126     }
127 }
128 
129 CXDiagnosticSeverity severity(DiagnosticSet diagnostics)
130 {
131     import std.algorithm.searching : minPos;
132     import std.algorithm.iteration : map;
133 
134     alias less = (a, b) => cast(uint) a > cast(uint) b;
135 
136     if (diagnostics.empty)
137         return CXDiagnosticSeverity.ignored;
138     else
139         return diagnostics.map!(diagnostic => diagnostic.severity).minPos!less.front;
140 }
141 
142 bool hasError(DiagnosticSet diagnostics)
143 {
144     auto severity = diagnostics.severity;
145 
146     return severity == CXDiagnosticSeverity.error ||
147         severity == CXDiagnosticSeverity.fatal;
148 }