1//===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// Diagnostics class to manage error messages.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
15#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
16
17#include "clang/ASTMatchers/Dynamic/VariantValue.h"
18#include "clang/Basic/LLVM.h"
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/Twine.h"
22#include "llvm/Support/raw_ostream.h"
23#include <string>
24#include <vector>
25
26namespace clang {
27namespace ast_matchers {
28namespace dynamic {
29
30struct SourceLocation {
31 SourceLocation() = default;
32 unsigned Line = 0;
33 unsigned Column = 0;
34};
35
36struct SourceRange {
37 SourceLocation Start;
38 SourceLocation End;
39};
40
41/// A VariantValue instance annotated with its parser context.
42struct ParserValue {
43 ParserValue() {}
44 StringRef Text;
45 SourceRange Range;
46 VariantValue Value;
47};
48
49/// Helper class to manage error messages.
50class Diagnostics {
51public:
52 /// Parser context types.
53 enum ContextType {
54 CT_MatcherArg = 0,
55 CT_MatcherConstruct = 1
56 };
57
58 /// All errors from the system.
59 enum ErrorType {
60 ET_None = 0,
61
62 ET_RegistryMatcherNotFound = 1,
63 ET_RegistryWrongArgCount = 2,
64 ET_RegistryWrongArgType = 3,
65 ET_RegistryNotBindable = 4,
66 ET_RegistryAmbiguousOverload = 5,
67 ET_RegistryValueNotFound = 6,
68 ET_RegistryUnknownEnumWithReplace = 7,
69 ET_RegistryNonNodeMatcher = 8,
70 ET_RegistryMatcherNoWithSupport = 9,
71
72 ET_ParserStringError = 100,
73 ET_ParserNoOpenParen = 101,
74 ET_ParserNoCloseParen = 102,
75 ET_ParserNoComma = 103,
76 ET_ParserNoCode = 104,
77 ET_ParserNotAMatcher = 105,
78 ET_ParserInvalidToken = 106,
79 ET_ParserMalformedBindExpr = 107,
80 ET_ParserTrailingCode = 108,
81 ET_ParserNumberError = 109,
82 ET_ParserOverloadedType = 110,
83 ET_ParserMalformedChainedExpr = 111,
84 ET_ParserFailedToBuildMatcher = 112
85 };
86
87 /// Helper stream class.
88 class ArgStream {
89 public:
90 ArgStream(std::vector<std::string> *Out) : Out(Out) {}
91 template <class T> ArgStream &operator<<(const T &Arg) {
92 return operator<<(Arg: Twine(Arg));
93 }
94 ArgStream &operator<<(const Twine &Arg);
95
96 private:
97 std::vector<std::string> *Out;
98 };
99
100 /// Class defining a parser context.
101 ///
102 /// Used by the parser to specify (possibly recursive) contexts where the
103 /// parsing/construction can fail. Any error triggered within a context will
104 /// keep information about the context chain.
105 /// This class should be used as a RAII instance in the stack.
106 struct Context {
107 public:
108 /// About to call the constructor for a matcher.
109 enum ConstructMatcherEnum { ConstructMatcher };
110 Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName,
111 SourceRange MatcherRange);
112 /// About to recurse into parsing one argument for a matcher.
113 enum MatcherArgEnum { MatcherArg };
114 Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName,
115 SourceRange MatcherRange, unsigned ArgNumber);
116 ~Context();
117
118 private:
119 Diagnostics *const Error;
120 };
121
122 /// Context for overloaded matcher construction.
123 ///
124 /// This context will take care of merging all errors that happen within it
125 /// as "candidate" overloads for the same matcher.
126 struct OverloadContext {
127 public:
128 OverloadContext(Diagnostics* Error);
129 ~OverloadContext();
130
131 /// Revert all errors that happened within this context.
132 void revertErrors();
133
134 private:
135 Diagnostics *const Error;
136 unsigned BeginIndex;
137 };
138
139 /// Add an error to the diagnostics.
140 ///
141 /// All the context information will be kept on the error message.
142 /// \return a helper class to allow the caller to pass the arguments for the
143 /// error message, using the << operator.
144 ArgStream addError(SourceRange Range, ErrorType Error);
145
146 /// Information stored for one frame of the context.
147 struct ContextFrame {
148 ContextType Type;
149 SourceRange Range;
150 std::vector<std::string> Args;
151 };
152
153 /// Information stored for each error found.
154 struct ErrorContent {
155 std::vector<ContextFrame> ContextStack;
156 struct Message {
157 SourceRange Range;
158 ErrorType Type;
159 std::vector<std::string> Args;
160 };
161 std::vector<Message> Messages;
162 };
163 ArrayRef<ErrorContent> errors() const { return Errors; }
164
165 /// Returns a simple string representation of each error.
166 ///
167 /// Each error only shows the error message without any context.
168 void printToStream(llvm::raw_ostream &OS) const;
169 std::string toString() const;
170
171 /// Returns the full string representation of each error.
172 ///
173 /// Each error message contains the full context.
174 void printToStreamFull(llvm::raw_ostream &OS) const;
175 std::string toStringFull() const;
176
177private:
178 /// Helper function used by the constructors of ContextFrame.
179 ArgStream pushContextFrame(ContextType Type, SourceRange Range);
180
181 std::vector<ContextFrame> ContextStack;
182 std::vector<ErrorContent> Errors;
183};
184
185} // namespace dynamic
186} // namespace ast_matchers
187} // namespace clang
188
189#endif // LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
190

source code of clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h