mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-23 14:36:16 +02:00
4feb7d9f71
Also move `SourcePath` into `libutil`. These changes allow `error.hh` and `error.cc` to access source path and position information, which we can use to produce better error messages (for example, we could consider omitting filenames when two or more consecutive stack frames originate from the same file).
112 lines
2.7 KiB
C++
112 lines
2.7 KiB
C++
#include "position.hh"
|
|
|
|
namespace nix {
|
|
|
|
Pos::Pos(const Pos * other)
|
|
{
|
|
if (!other) {
|
|
return;
|
|
}
|
|
line = other->line;
|
|
column = other->column;
|
|
origin = std::move(other->origin);
|
|
}
|
|
|
|
Pos::operator std::shared_ptr<Pos>() const
|
|
{
|
|
return std::make_shared<Pos>(&*this);
|
|
}
|
|
|
|
bool Pos::operator<(const Pos &rhs) const
|
|
{
|
|
return std::forward_as_tuple(line, column, origin)
|
|
< std::forward_as_tuple(rhs.line, rhs.column, rhs.origin);
|
|
}
|
|
|
|
std::optional<LinesOfCode> Pos::getCodeLines() const
|
|
{
|
|
if (line == 0)
|
|
return std::nullopt;
|
|
|
|
if (auto source = getSource()) {
|
|
|
|
std::istringstream iss(*source);
|
|
// count the newlines.
|
|
int count = 0;
|
|
std::string curLine;
|
|
int pl = line - 1;
|
|
|
|
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);
|
|
|
|
return loc;
|
|
}
|
|
|
|
return std::nullopt;
|
|
}
|
|
|
|
|
|
std::optional<std::string> Pos::getSource() const
|
|
{
|
|
return std::visit(overloaded {
|
|
[](const std::monostate &) -> std::optional<std::string> {
|
|
return std::nullopt;
|
|
},
|
|
[](const Pos::Stdin & s) -> std::optional<std::string> {
|
|
// Get rid of the null terminators added by the parser.
|
|
return std::string(s.source->c_str());
|
|
},
|
|
[](const Pos::String & s) -> std::optional<std::string> {
|
|
// Get rid of the null terminators added by the parser.
|
|
return std::string(s.source->c_str());
|
|
},
|
|
[](const SourcePath & path) -> std::optional<std::string> {
|
|
try {
|
|
return path.readFile();
|
|
} catch (Error &) {
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
}, origin);
|
|
}
|
|
|
|
void Pos::print(std::ostream & out, bool showOrigin) const
|
|
{
|
|
if (showOrigin) {
|
|
std::visit(overloaded {
|
|
[&](const std::monostate &) { out << "«none»"; },
|
|
[&](const Pos::Stdin &) { out << "«stdin»"; },
|
|
[&](const Pos::String & s) { out << "«string»"; },
|
|
[&](const SourcePath & path) { out << path; }
|
|
}, origin);
|
|
out << ":";
|
|
}
|
|
out << line;
|
|
if (column > 0)
|
|
out << ":" << column;
|
|
}
|
|
|
|
std::ostream & operator<<(std::ostream & str, const Pos & pos)
|
|
{
|
|
pos.print(str, true);
|
|
return str;
|
|
}
|
|
|
|
}
|