summaryrefslogtreecommitdiffstats
path: root/tools/gn/err.cc
diff options
context:
space:
mode:
authorbauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-30 10:17:07 +0000
committerbauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-30 10:17:07 +0000
commit96ea63d0d101ebbdbb08f79a80f3fa38bfb27ced (patch)
treef33c8f6fa3ae9fbba0178ba0cbf4f291fd3ec11e /tools/gn/err.cc
parentfb68e6c9f20785ccd0024f14b09c200060931953 (diff)
downloadchromium_src-96ea63d0d101ebbdbb08f79a80f3fa38bfb27ced.zip
chromium_src-96ea63d0d101ebbdbb08f79a80f3fa38bfb27ced.tar.gz
chromium_src-96ea63d0d101ebbdbb08f79a80f3fa38bfb27ced.tar.bz2
Revert 214325 "Revert 214254 "Add initial prototype for the GN m..."
The issue was already fixed :) > Revert 214254 "Add initial prototype for the GN meta-buildsystem." > > It broke the check_licenses step on Android (see http://build.chromium.org/p/chromium.linux/builders/Android%20Builder%20%28dbg%29/builds/39904/steps/check_licenses/logs/stdio): > > @@@BUILD_STEP check_licenses@@@ > > /b/build/slave/Android_Builder__dbg_/build/src/android_webview/tools/webview_licenses.py scan > Got LicenseError "missing README.chromium or licenses.py SPECIAL_CASES entry" while scanning tools/gn/secondary/base/third_party/dynamic_annotations > Got LicenseError "missing README.chromium or licenses.py SPECIAL_CASES entry" while scanning tools/gn/secondary/third_party/modp_b64 > < /b/build/slave/Android_Builder__dbg_/build/src/android_webview/tools/webview_licenses.py scan > ERROR: process exited with code 2 > @@@STEP_FAILURE@@@ > > > > Add initial prototype for the GN meta-buildsystem. > > > > This is currently not hooked into the build. To build, add a reference to the > > gn.gyp file to build/all.gyp > > > > R=darin@chromium.org, scottmg@chromium.org > > > > Review URL: https://codereview.chromium.org/21114002 > > TBR=brettw@chromium.org > > Review URL: https://codereview.chromium.org/21084010 TBR=bauerb@chromium.org Review URL: https://codereview.chromium.org/21204003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214333 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/gn/err.cc')
-rw-r--r--tools/gn/err.cc196
1 files changed, 196 insertions, 0 deletions
diff --git a/tools/gn/err.cc b/tools/gn/err.cc
new file mode 100644
index 0000000..068ea6d
--- /dev/null
+++ b/tools/gn/err.cc
@@ -0,0 +1,196 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/err.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/standard_out.h"
+#include "tools/gn/tokenizer.h"
+#include "tools/gn/value.h"
+
+namespace {
+
+std::string GetNthLine(const base::StringPiece& data, int n) {
+ size_t line_off = Tokenizer::ByteOffsetOfNthLine(data, n);
+ size_t end = line_off + 1;
+ while (end < data.size() && !Tokenizer::IsNewline(data, end))
+ end++;
+ return data.substr(line_off, end - line_off).as_string();
+}
+
+void FillRangeOnLine(const LocationRange& range, int line_number,
+ std::string* line) {
+ // Only bother if the range's begin or end overlaps the line. If the entire
+ // line is highlighted as a result of this range, it's not very helpful.
+ if (range.begin().line_number() != line_number &&
+ range.end().line_number() != line_number)
+ return;
+
+ // Watch out, the char offsets in the location are 1-based, so we have to
+ // subtract 1.
+ int begin_char;
+ if (range.begin().line_number() < line_number)
+ begin_char = 0;
+ else
+ begin_char = range.begin().char_offset() - 1;
+
+ int end_char;
+ if (range.end().line_number() > line_number)
+ end_char = line->size(); // Ending is non-inclusive.
+ else
+ end_char = range.end().char_offset() - 1;
+
+ CHECK(end_char >= begin_char);
+ CHECK(begin_char >= 0 && begin_char <= static_cast<int>(line->size()));
+ CHECK(end_char >= 0 && end_char <= static_cast<int>(line->size()));
+ for (int i = begin_char; i < end_char; i++)
+ line->at(i) = '-';
+}
+
+// The line length is used to clip the maximum length of the markers we'll
+// make if the error spans more than one line (like unterminated literals).
+void OutputHighlighedPosition(const Location& location,
+ const Err::RangeList& ranges,
+ size_t line_length) {
+ // Make a buffer of the line in spaces.
+ std::string highlight;
+ highlight.resize(line_length);
+ for (size_t i = 0; i < line_length; i++)
+ highlight[i] = ' ';
+
+ // Highlight all the ranges on the line.
+ for (size_t i = 0; i < ranges.size(); i++)
+ FillRangeOnLine(ranges[i], location.line_number(), &highlight);
+
+ // Allow the marker to be one past the end of the line for marking the end.
+ highlight.push_back(' ');
+ CHECK(location.char_offset() - 1 >= 0 &&
+ location.char_offset() - 1 < static_cast<int>(highlight.size()));
+ highlight[location.char_offset() - 1] = '^';
+
+ // Trim unused spaces from end of line.
+ while (!highlight.empty() && highlight[highlight.size() - 1] == ' ')
+ highlight.resize(highlight.size() - 1);
+
+ highlight += "\n";
+ OutputString(highlight, DECORATION_BLUE);
+}
+
+} // namespace
+
+Err::Err() : has_error_(false) {
+}
+
+Err::Err(const Location& location,
+ const std::string& msg,
+ const std::string& help)
+ : has_error_(true),
+ location_(location),
+ message_(msg),
+ help_text_(help) {
+}
+
+Err::Err(const LocationRange& range,
+ const std::string& msg,
+ const std::string& help)
+ : has_error_(true),
+ location_(range.begin()),
+ message_(msg),
+ help_text_(help) {
+ ranges_.push_back(range);
+}
+
+Err::Err(const Token& token,
+ const std::string& msg,
+ const std::string& help)
+ : has_error_(true),
+ location_(token.location()),
+ message_(msg),
+ help_text_(help) {
+ ranges_.push_back(token.range());
+}
+
+Err::Err(const ParseNode* node,
+ const std::string& msg,
+ const std::string& help_text)
+ : has_error_(true),
+ message_(msg),
+ help_text_(help_text) {
+ // Node will be null in certain tests.
+ if (node) {
+ LocationRange range = node->GetRange();
+ location_ = range.begin();
+ ranges_.push_back(range);
+ }
+}
+
+Err::Err(const Value& value,
+ const std::string msg,
+ const std::string& help_text)
+ : has_error_(true),
+ message_(msg),
+ help_text_(help_text) {
+ if (value.origin()) {
+ LocationRange range = value.origin()->GetRange();
+ location_ = range.begin();
+ ranges_.push_back(range);
+ }
+}
+
+Err::~Err() {
+}
+
+void Err::PrintToStdout() const {
+ InternalPrintToStdout(false);
+}
+
+void Err::AppendSubErr(const Err& err) {
+ sub_errs_.push_back(err);
+}
+
+void Err::InternalPrintToStdout(bool is_sub_err) const {
+ DCHECK(has_error_);
+
+ if (!is_sub_err)
+ OutputString("ERROR ", DECORATION_RED);
+
+ // File name and location.
+ const InputFile* input_file = location_.file();
+ std::string loc_str;
+ if (input_file) {
+ std::string path8;
+ path8.assign(input_file->name().value());
+
+ if (is_sub_err)
+ loc_str = "See ";
+ else
+ loc_str = "at ";
+ loc_str += path8 + ": " +
+ base::IntToString(location_.line_number()) + ":" +
+ base::IntToString(location_.char_offset()) + ": ";
+ }
+ OutputString(loc_str + message_ + "\n");
+
+ // Quoted line.
+ if (input_file) {
+ std::string line = GetNthLine(input_file->contents(),
+ location_.line_number());
+ if (!ContainsOnlyWhitespaceASCII(line)) {
+ OutputString(line + "\n", DECORATION_BOLD);
+ OutputHighlighedPosition(location_, ranges_, line.size());
+ }
+ }
+
+ // Optional help text.
+ if (!help_text_.empty())
+ OutputString(help_text_ + "\n");
+
+ // Sub errors.
+ for (size_t i = 0; i < sub_errs_.size(); i++)
+ sub_errs_[i].InternalPrintToStdout(true);
+}