SpECTRE Documentation Coverage Report
Current view: top level - Options - Options.hpp Hit Total Coverage
Commit: ebec864322c50bab8dca0a90baf8d01875114261 Lines: 15 22 68.2 %
Date: 2020-11-25 20:28:50
Legend: Lines: hit not hit

          Line data    Source code
       1           1 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : /// \file
       5             : /// Defines classes and functions for making classes creatable from
       6             : /// input files.
       7             : 
       8             : #pragma once
       9             : 
      10             : #include <exception>
      11             : #include <memory>
      12             : #include <ostream>
      13             : #include <sstream>
      14             : #include <string>
      15             : #include <utility>
      16             : 
      17             : #include "ErrorHandling/Error.hpp"
      18             : #include "Utilities/NoSuchType.hpp"
      19             : #include "Utilities/PrettyType.hpp"
      20             : #include "Utilities/TMPL.hpp"
      21             : #include "Utilities/TypeTraits.hpp"
      22             : 
      23             : /// \cond
      24             : namespace YAML {
      25             : class Node;
      26             : }  // namespace YAML
      27             : /// \endcond
      28             : 
      29             : /// Utilities for parsing input files.
      30             : namespace Options {
      31             : /// The string used in option structs
      32           1 : using String = const char* const;
      33             : 
      34             : /// \ingroup OptionParsingGroup
      35             : /// Information about the nested operations being performed by the
      36             : /// parser, for use in printing errors.  A default-constructed
      37             : /// Context is printed as an empty string.  This struct is
      38             : /// primarily used as an argument to PARSE_ERROR for reporting input
      39             : /// file parsing errors.  Users outside of the core option parsing
      40             : /// code should not need to manipulate the contents.
      41           1 : struct Context {
      42           0 :   bool top_level{true};
      43             :   /// (Part of) the parsing "backtrace" printed with an error
      44           1 :   std::string context;
      45             :   /// File line number (0 based)
      46           1 :   int line{-1};
      47             :   /// File column number (0 based)
      48           1 :   int column{-1};
      49             : 
      50             :   /// Append a line to the context.  Automatically appends a colon.
      51           1 :   void append(const std::string& c) noexcept { context += c + ":\n"; }
      52             : };
      53             : 
      54           0 : inline std::ostream& operator<<(std::ostream& s, const Context& c) noexcept {
      55             :   s << c.context;
      56             :   if (c.line >= 0 and c.column >= 0) {
      57             :     s << "At line " << c.line + 1 << " column " << c.column + 1 << ":\n";
      58             :   }
      59             :   return s;
      60             : }
      61             : 
      62             : /// \ingroup OptionParsingGroup
      63             : /// Like ERROR("\n" << (context) << m), but instead throws an
      64             : /// exception that will be caught in a higher level Options if not
      65             : /// passed a top-level context.  This is used to print a parsing
      66             : /// "backtrace" since we can't pass any extra data through the
      67             : /// yaml-cpp code.
      68             : ///
      69             : /// \param context Context used to print a parsing traceback
      70             : /// \param m error message, as for ERROR
      71           1 : #define PARSE_ERROR(context, m)                                         \
      72             :   do {                                                                  \
      73             :     if ((context).top_level) {                                          \
      74             :       /* clang-tidy: macro arg in parentheses */                        \
      75             :       ERROR("\n" << (context) << m); /* NOLINT */                       \
      76             :     } else {                                                            \
      77             :       std::ostringstream avoid_name_collisions_PARSE_ERROR;             \
      78             :       /* clang-tidy: macro arg in parentheses */                        \
      79             :       avoid_name_collisions_PARSE_ERROR << (context) << m; /* NOLINT */ \
      80             :       throw ::Options::Options_detail::propagate_context(               \
      81             :           avoid_name_collisions_PARSE_ERROR.str());                     \
      82             :     }                                                                   \
      83             :   } while (false)
      84             : 
      85             : namespace Options_detail {
      86             : class propagate_context : public std::exception {
      87             :  public:
      88             :   // cppcheck-suppress passedByValue
      89             :   explicit propagate_context(std::string message) noexcept
      90             :       : message_(std::move(message)) {}
      91             : 
      92             :   const char* what() const noexcept override { return message_.c_str(); }
      93             :   const std::string& message() const noexcept { return message_; }
      94             : 
      95             :  private:
      96             :   std::string message_;
      97             : };
      98             : }  // namespace Options_detail
      99             : 
     100             : /// \ingroup OptionParsingGroup
     101             : /// The type that options are passed around as.  Contains YAML node
     102             : /// data and an Context.
     103             : ///
     104             : /// \note To use any methods on this class in a concrete function you
     105             : /// must include ParseOptions.hpp, but you do *not* need to include
     106             : /// that header to use this in an uninstantiated
     107             : /// `create_from_yaml::create` function.
     108           1 : class Option {
     109             :  public:
     110           0 :   const Context& context() const noexcept;
     111             : 
     112             :   /// Append a line to the contained context.
     113           1 :   void append_context(const std::string& context) noexcept;
     114             : 
     115             :   /// Convert to an object of type `T`.
     116             :   template <typename T, typename Metavariables = NoSuchType>
     117           1 :   T parse_as() const;
     118             : 
     119             :   /// \note This constructor overwrites the mark data in the supplied
     120             :   /// context with the one from the node.
     121             :   ///
     122             :   /// \warning This method is for internal use of the option parser.
     123           1 :   explicit Option(YAML::Node node, Context context = {}) noexcept;
     124             : 
     125             :   /// \warning This method is for internal use of the option parser.
     126           1 :   explicit Option(Context context) noexcept;
     127             : 
     128             :   /// \warning This method is for internal use of the option parser.
     129           1 :   const YAML::Node& node() const noexcept;
     130             : 
     131             :   /// Sets the node and updates the context's mark to correspond to it.
     132             :   ///
     133             :   /// \warning This method is for internal use of the option parser.
     134           1 :   void set_node(YAML::Node node) noexcept;
     135             : 
     136             :  private:
     137           0 :   std::unique_ptr<YAML::Node> node_;
     138           0 :   Context context_;
     139             : };
     140             : 
     141             : /// \ingroup OptionParsingGroup
     142             : /// Used by the parser to create an object.  The default action is to
     143             : /// parse options using `T::options`.  This struct may be specialized
     144             : /// to change that behavior for specific types.
     145             : ///
     146             : /// Do not call create directly.  Use Option::parse_as instead.
     147             : template <typename T>
     148             : struct create_from_yaml {
     149             :   template <typename Metavariables>
     150           0 :   static T create(const Option& options);
     151             : };
     152             : 
     153             : namespace Options_detail {
     154             : template <typename T, typename = std::void_t<>>
     155             : struct name_helper {
     156             :   static std::string name() noexcept { return pretty_type::short_name<T>(); }
     157             : };
     158             : 
     159             : template <typename T>
     160             : struct name_helper<T, std::void_t<decltype(T::name())>> {
     161             :   static std::string name() noexcept { return T::name(); }
     162             : };
     163             : }  // namespace Options_detail
     164             : 
     165             : // The name in the YAML file for a struct.
     166             : template <typename T>
     167           0 : std::string name() noexcept {
     168             :   return Options_detail::name_helper<T>::name();
     169             : }
     170             : }  // namespace Options

Generated by: LCOV version 1.14