[fidl][errors] Print column numbers and underline unexpected tokens
Change-Id: I1c15e58e23c7bdf7c92b6e7691db9242e5cd06cb
diff --git a/system/host/fidl/include/fidl/source_file.h b/system/host/fidl/include/fidl/source_file.h
index 644f405..8b9f9d5 100644
--- a/system/host/fidl/include/fidl/source_file.h
+++ b/system/host/fidl/include/fidl/source_file.h
@@ -21,7 +21,14 @@
StringView filename() const { return filename_; }
StringView data() const { return data_; }
- StringView LineContaining(StringView view, int* line_number_out) const;
+ // This is in the coordinates that most editors use. Lines start
+ // at 1 but columns start at 0.
+ struct Position {
+ int line;
+ int column;
+ };
+
+ StringView LineContaining(StringView view, Position* position_out) const;
private:
std::string filename_;
diff --git a/system/host/fidl/include/fidl/source_location.h b/system/host/fidl/include/fidl/source_location.h
index 198282d..6f98918 100644
--- a/system/host/fidl/include/fidl/source_location.h
+++ b/system/host/fidl/include/fidl/source_location.h
@@ -29,7 +29,7 @@
const StringView& data() const { return data_; }
const SourceFile& source_file() const { return *source_file_; }
- StringView SourceLine(int* line_number_out) const;
+ StringView SourceLine(SourceFile::Position* position_out) const;
private:
StringView data_;
diff --git a/system/host/fidl/lib/parser.cpp b/system/host/fidl/lib/parser.cpp
index 2077c24..84ae72c 100644
--- a/system/host/fidl/lib/parser.cpp
+++ b/system/host/fidl/lib/parser.cpp
@@ -79,15 +79,23 @@
decltype(nullptr) Parser::Fail() {
if (ok_) {
- int line_number;
- auto surrounding_line = last_token_.location().SourceLine(&line_number);
+ auto token_location = last_token_.location();
+ auto token_data = token_location.data();
- std::string error = "found unexpected token: ";
- error += last_token_.data();
- error += "\n";
- error += "on line #" + std::to_string(line_number) + ":\n\n";
+ SourceFile::Position position;
+ std::string surrounding_line = token_location.SourceLine(&position);
+ auto line_number = std::to_string(position.line);
+ auto column_number = std::to_string(position.column);
+
+ std::string squiggle(position.column, ' ');
+ squiggle +="^";
+ squiggle += std::string(token_data.size() - 1, '~');
+
+ std::string error = "found unexpected token on ";
+ error += "line " + line_number;
+ error += " column " + column_number + ":\n";
error += surrounding_line;
- error += "\n";
+ error += squiggle + "\n";
error_reporter_->ReportError(error);
ok_ = false;
diff --git a/system/host/fidl/lib/source_file.cpp b/system/host/fidl/lib/source_file.cpp
index 974892c..5eed0f4 100644
--- a/system/host/fidl/lib/source_file.cpp
+++ b/system/host/fidl/lib/source_file.cpp
@@ -31,7 +31,7 @@
SourceFile::~SourceFile() = default;
-StringView SourceFile::LineContaining(StringView view, int* line_number_out) const {
+StringView SourceFile::LineContaining(StringView view, Position* position_out) const {
auto ptr_order = [](const char* left, const char* right) {
return std::less_equal<const char*>()(left, right);
};
@@ -50,9 +50,12 @@
auto line = std::find_if(lines_.cbegin(), lines_.cend(), is_in_line);
assert(line != lines_.cend());
- if (line_number_out != nullptr) {
+ if (position_out != nullptr) {
// Humans number lines from 1.
- *line_number_out = (line - lines_.cbegin()) + 1;
+ int line_number = (line - lines_.cbegin()) + 1;
+ // But columns from 0!
+ int column_number = view.data() - line->data();
+ *position_out = {line_number, column_number};
}
return *line;
}
diff --git a/system/host/fidl/lib/source_location.cpp b/system/host/fidl/lib/source_location.cpp
index abe0718..ae7c6c2 100644
--- a/system/host/fidl/lib/source_location.cpp
+++ b/system/host/fidl/lib/source_location.cpp
@@ -6,8 +6,8 @@
namespace fidl {
-StringView SourceLocation::SourceLine(int* line_number_out) const {
- return source_file_->LineContaining(data(), line_number_out);
+StringView SourceLocation::SourceLine(SourceFile::Position* position_out) const {
+ return source_file_->LineContaining(data(), position_out);
}
} // namespace fidl