mirror of
https://github.com/NixOS/nix
synced 2025-07-06 05:01:48 +02:00
Merge pull request #9874 from pennae/error-reports
improve error reports somewhat
This commit is contained in:
commit
a200ee6bf7
37 changed files with 336 additions and 142 deletions
|
@ -29,32 +29,17 @@ std::optional<LinesOfCode> Pos::getCodeLines() const
|
|||
return std::nullopt;
|
||||
|
||||
if (auto source = getSource()) {
|
||||
|
||||
std::istringstream iss(*source);
|
||||
// count the newlines.
|
||||
int count = 0;
|
||||
std::string curLine;
|
||||
int pl = line - 1;
|
||||
|
||||
LinesIterator lines(*source), end;
|
||||
LinesOfCode loc;
|
||||
|
||||
do {
|
||||
std::getline(iss, curLine);
|
||||
++count;
|
||||
if (count < pl)
|
||||
;
|
||||
else if (count == pl) {
|
||||
loc.prevLineOfCode = curLine;
|
||||
} else if (count == pl + 1) {
|
||||
loc.errLineOfCode = curLine;
|
||||
} else if (count == pl + 2) {
|
||||
loc.nextLineOfCode = curLine;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!iss.good())
|
||||
break;
|
||||
} while (true);
|
||||
if (line > 1)
|
||||
std::advance(lines, line - 2);
|
||||
if (lines != end && line > 1)
|
||||
loc.prevLineOfCode = *lines++;
|
||||
if (lines != end)
|
||||
loc.errLineOfCode = *lines++;
|
||||
if (lines != end)
|
||||
loc.nextLineOfCode = *lines++;
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
@ -109,4 +94,26 @@ std::ostream & operator<<(std::ostream & str, const Pos & pos)
|
|||
return str;
|
||||
}
|
||||
|
||||
void Pos::LinesIterator::bump(bool atFirst)
|
||||
{
|
||||
if (!atFirst) {
|
||||
pastEnd = input.empty();
|
||||
if (!input.empty() && input[0] == '\r')
|
||||
input.remove_prefix(1);
|
||||
if (!input.empty() && input[0] == '\n')
|
||||
input.remove_prefix(1);
|
||||
}
|
||||
|
||||
// nix line endings are not only \n as eg std::getline assumes, but also
|
||||
// \r\n **and \r alone**. not treating them all the same causes error
|
||||
// reports to not match with line numbers as the parser expects them.
|
||||
auto eol = input.find_first_of("\r\n");
|
||||
|
||||
if (eol > input.size())
|
||||
eol = input.size();
|
||||
|
||||
curLine = input.substr(0, eol);
|
||||
input.remove_prefix(eol);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -67,6 +67,48 @@ struct Pos
|
|||
bool operator==(const Pos & rhs) const = default;
|
||||
bool operator!=(const Pos & rhs) const = default;
|
||||
bool operator<(const Pos & rhs) const;
|
||||
|
||||
struct LinesIterator {
|
||||
using difference_type = size_t;
|
||||
using value_type = std::string_view;
|
||||
using reference = const std::string_view &;
|
||||
using pointer = const std::string_view *;
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
|
||||
LinesIterator(): pastEnd(true) {}
|
||||
explicit LinesIterator(std::string_view input): input(input), pastEnd(input.empty()) {
|
||||
if (!pastEnd)
|
||||
bump(true);
|
||||
}
|
||||
|
||||
LinesIterator & operator++() {
|
||||
bump(false);
|
||||
return *this;
|
||||
}
|
||||
LinesIterator operator++(int) {
|
||||
auto result = *this;
|
||||
++*this;
|
||||
return result;
|
||||
}
|
||||
|
||||
reference operator*() const { return curLine; }
|
||||
pointer operator->() const { return &curLine; }
|
||||
|
||||
bool operator!=(const LinesIterator & other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
bool operator==(const LinesIterator & other) const {
|
||||
return (pastEnd && other.pastEnd)
|
||||
|| (std::forward_as_tuple(input.size(), input.data())
|
||||
== std::forward_as_tuple(other.input.size(), other.input.data()));
|
||||
}
|
||||
|
||||
private:
|
||||
std::string_view input, curLine;
|
||||
bool pastEnd = false;
|
||||
|
||||
void bump(bool atFirst);
|
||||
};
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & str, const Pos & pos);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue