1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "fidl/error_reporter.h" 6#include "fidl/source_location.h" 7#include "fidl/string_view.h" 8#include "fidl/token.h" 9 10namespace fidl { 11 12std::string MakeSquiggle(const std::string& surrounding_line, int column) { 13 std::string squiggle; 14 for (int i = 0; i < column; i++) { 15 switch (surrounding_line[i]) { 16 case '\t': 17 squiggle.push_back('\t'); 18 default: 19 squiggle.push_back(' '); 20 } 21 } 22 squiggle.push_back('^'); 23 return squiggle; 24} 25 26std::string FormatError(const SourceLocation& location, StringView message, size_t squiggle_size = 0u) { 27 SourceFile::Position position; 28 std::string surrounding_line = location.SourceLine(&position); 29 30 std::string squiggle = MakeSquiggle(surrounding_line, position.column); 31 if (squiggle_size != 0u) { 32 --squiggle_size; 33 } 34 squiggle += std::string(squiggle_size, '~'); 35 // Some tokens (like string literals) can span multiple 36 // lines. Truncate the string to just one line at most. The 37 // containing line contains a newline, so drop it when 38 // comparing sizes. 39 size_t line_size = surrounding_line.size() - 1; 40 if (squiggle.size() > line_size) { 41 squiggle.resize(line_size); 42 } 43 44 // Many editors and IDEs recognize errors in the form of 45 // filename:linenumber:column: error: descriptive-test-here\n 46 std::string error = location.position(); 47 error.append(": error: "); 48 error.append(message); 49 error.push_back('\n'); 50 error.append(surrounding_line); 51 error.append(squiggle); 52 53 return error; 54} 55 56// ReportError records an error with the location, message, source line, and 57// position indicator. 58// 59// filename:line:col: error: message 60// sourceline 61// ^ 62void ErrorReporter::ReportError(const SourceLocation& location, StringView message) { 63 auto error = FormatError(location, message); 64 errors_.push_back(std::move(error)); 65} 66 67// ReportError records an error with the location, message, source line, 68// position indicator, and tildes under the token reported. 69// 70// filename:line:col: error: message 71// sourceline 72// ^~~~ 73void ErrorReporter::ReportError(const Token& token, StringView message) { 74 auto token_location = token.location(); 75 auto token_data = token_location.data(); 76 auto error = FormatError(token_location, message, token_data.size()); 77 errors_.push_back(std::move(error)); 78} 79 80// ReportError records the provided message. 81void ErrorReporter::ReportError(StringView message) { 82 std::string error("error: "); 83 error.append(message); 84 errors_.push_back(std::move(error)); 85} 86 87void ErrorReporter::PrintReports() { 88 for (const auto& error : errors_) { 89 fprintf(stderr, "%s\n", error.data()); 90 } 91} 92 93} // namespace fidl 94