#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() const { return std::make_shared(&*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 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 Pos::getSource() const { return std::visit(overloaded { [](const std::monostate &) -> std::optional { return std::nullopt; }, [](const Pos::Stdin & s) -> std::optional { // Get rid of the null terminators added by the parser. return std::string(s.source->c_str()); }, [](const Pos::String & s) -> std::optional { // Get rid of the null terminators added by the parser. return std::string(s.source->c_str()); }, [](const SourcePath & path) -> std::optional { 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 << ":"; } } std::ostream & operator<<(std::ostream & str, const Pos & pos) { pos.print(str, true); return str; } }