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