Home | History | Annotate | Line # | Download | only in Dynamic
      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 
     26 namespace clang {
     27 namespace ast_matchers {
     28 namespace dynamic {
     29 
     30 struct SourceLocation {
     31   SourceLocation() : Line(), Column() {}
     32   unsigned Line;
     33   unsigned Column;
     34 };
     35 
     36 struct SourceRange {
     37   SourceLocation Start;
     38   SourceLocation End;
     39 };
     40 
     41 /// A VariantValue instance annotated with its parser context.
     42 struct ParserValue {
     43   ParserValue() : Text(), Range(), Value() {}
     44   StringRef Text;
     45   SourceRange Range;
     46   VariantValue Value;
     47 };
     48 
     49 /// Helper class to manage error messages.
     50 class Diagnostics {
     51 public:
     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<<(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 
    177 private:
    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_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
    190