Restructure rules result to properly support multiple files

The old version of rules_result assumed that all errors/warnings were
related to a single file. That was generally correct for errors, as
rules parsing always stopped at the first error, so there is only one
relevant file.

However, for warnings that was not the case. When reading multiple
files A and B, you might get a warning from file A *only* after
reading file B. For example, B might redefine a rule in such a way
that you could get unused list/macro warnings from file A.

To properly address this, make some changes to how contexts are
managed:

- Instead of creating snippets at the time the error/warning was
  generated, create snippets at the time the error/warning is
  converted into a string. This requires passing all rules contents to
  as_string()/as_json(), so define a
  falco::load_result::rules_contents_t map from filename to rules
  content (reference) and pass it in as_string/as_json(). Snippets are
  now generated from the rules content matching the filename in the
  context.
- When creating warnings/errors, there's no need to pass along the
  rules content. This is only used when converting an error into a
  string/json.

Also change snippet() to handle potentially very long lines. Instead
of always printing the entire line matching a location, print up to
snippet_width(param, with default 160 chars)/2 characters surrounding
the column from the location.

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
This commit is contained in:
Mark Stemm
2022-08-08 16:25:21 -07:00
committed by poiana
parent 0828296abc
commit 98c1e3d3f1
4 changed files with 95 additions and 53 deletions

View File

@@ -36,6 +36,8 @@ public:
class context
{
public:
static const size_t default_snippet_width = 160;
struct location
{
// The original location in the document
@@ -51,7 +53,7 @@ public:
};
context(const std::string& name);
context(const YAML::Node& mark,
context(const YAML::Node& item,
const std::string item_type,
const std::string item_name,
const context& parent);
@@ -59,7 +61,9 @@ public:
// Return a snippet of the provided rules content
// corresponding to this context.
std::string snippet(const std::string& content) const;
// Uses the provided rules_contents to look up the original
// rules content for a given location name.
std::string snippet(const falco::load_result::rules_contents_t& rules_contents, size_t snippet_width = default_snippet_width) const;
std::string as_string();
nlohmann::json as_json();
@@ -77,7 +81,6 @@ public:
falco::load_result::warning_code wc;
std::string msg;
context ctx;
std::string snippet;
};
struct error
@@ -85,7 +88,6 @@ public:
falco::load_result::error_code ec;
std::string msg;
context ctx;
std::string snippet;
};
class rule_load_exception : public std::exception
@@ -113,22 +115,21 @@ public:
virtual bool successful() override;
virtual bool has_warnings() override;
virtual const std::string& as_string(bool verbose) override;
virtual const nlohmann::json& as_json() override;
virtual const std::string& as_string(bool verbose, const falco::load_result::rules_contents_t& contents) override;
virtual const nlohmann::json& as_json(const falco::load_result::rules_contents_t& contents) override;
void add_error(falco::load_result::error_code ec,
const std::string& msg,
const context& ctx,
const std::string& rules_content);
const context& ctx);
void add_warning(falco::load_result::warning_code ec,
const std::string& msg,
const context& ctx,
const std::string& rules_content);
const context& ctx);
protected:
const std::string& as_summary_string();
const std::string& as_verbose_string();
const std::string& as_verbose_string(const falco::load_result::rules_contents_t& contents);
std::string name;
bool success;