Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Side by Side Diff: tools/gn/err.cc

Issue 21114002: Add initial prototype for the GN meta-buildsystem. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add owners and readme Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/gn/err.h ('k') | tools/gn/escape.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium 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 "tools/gn/err.h"
6
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/string_util.h"
9 #include "tools/gn/filesystem_utils.h"
10 #include "tools/gn/input_file.h"
11 #include "tools/gn/parse_tree.h"
12 #include "tools/gn/standard_out.h"
13 #include "tools/gn/tokenizer.h"
14 #include "tools/gn/value.h"
15
16 namespace {
17
18 std::string GetNthLine(const base::StringPiece& data, int n) {
19 size_t line_off = Tokenizer::ByteOffsetOfNthLine(data, n);
20 size_t end = line_off + 1;
21 while (end < data.size() && !Tokenizer::IsNewline(data, end))
22 end++;
23 return data.substr(line_off, end - line_off).as_string();
24 }
25
26 void FillRangeOnLine(const LocationRange& range, int line_number,
27 std::string* line) {
28 // Only bother if the range's begin or end overlaps the line. If the entire
29 // line is highlighted as a result of this range, it's not very helpful.
30 if (range.begin().line_number() != line_number &&
31 range.end().line_number() != line_number)
32 return;
33
34 // Watch out, the char offsets in the location are 1-based, so we have to
35 // subtract 1.
36 int begin_char;
37 if (range.begin().line_number() < line_number)
38 begin_char = 0;
39 else
40 begin_char = range.begin().char_offset() - 1;
41
42 int end_char;
43 if (range.end().line_number() > line_number)
44 end_char = line->size(); // Ending is non-inclusive.
45 else
46 end_char = range.end().char_offset() - 1;
47
48 CHECK(end_char >= begin_char);
49 CHECK(begin_char >= 0 && begin_char <= static_cast<int>(line->size()));
50 CHECK(end_char >= 0 && end_char <= static_cast<int>(line->size()));
51 for (int i = begin_char; i < end_char; i++)
52 line->at(i) = '-';
53 }
54
55 // The line length is used to clip the maximum length of the markers we'll
56 // make if the error spans more than one line (like unterminated literals).
57 void OutputHighlighedPosition(const Location& location,
58 const Err::RangeList& ranges,
59 size_t line_length) {
60 // Make a buffer of the line in spaces.
61 std::string highlight;
62 highlight.resize(line_length);
63 for (size_t i = 0; i < line_length; i++)
64 highlight[i] = ' ';
65
66 // Highlight all the ranges on the line.
67 for (size_t i = 0; i < ranges.size(); i++)
68 FillRangeOnLine(ranges[i], location.line_number(), &highlight);
69
70 // Allow the marker to be one past the end of the line for marking the end.
71 highlight.push_back(' ');
72 CHECK(location.char_offset() - 1 >= 0 &&
73 location.char_offset() - 1 < static_cast<int>(highlight.size()));
74 highlight[location.char_offset() - 1] = '^';
75
76 // Trim unused spaces from end of line.
77 while (!highlight.empty() && highlight[highlight.size() - 1] == ' ')
78 highlight.resize(highlight.size() - 1);
79
80 highlight += "\n";
81 OutputString(highlight, DECORATION_BLUE);
82 }
83
84 } // namespace
85
86 Err::Err() : has_error_(false) {
87 }
88
89 Err::Err(const Location& location,
90 const std::string& msg,
91 const std::string& help)
92 : has_error_(true),
93 location_(location),
94 message_(msg),
95 help_text_(help) {
96 }
97
98 Err::Err(const LocationRange& range,
99 const std::string& msg,
100 const std::string& help)
101 : has_error_(true),
102 location_(range.begin()),
103 message_(msg),
104 help_text_(help) {
105 ranges_.push_back(range);
106 }
107
108 Err::Err(const Token& token,
109 const std::string& msg,
110 const std::string& help)
111 : has_error_(true),
112 location_(token.location()),
113 message_(msg),
114 help_text_(help) {
115 ranges_.push_back(token.range());
116 }
117
118 Err::Err(const ParseNode* node,
119 const std::string& msg,
120 const std::string& help_text)
121 : has_error_(true),
122 message_(msg),
123 help_text_(help_text) {
124 // Node will be null in certain tests.
125 if (node) {
126 LocationRange range = node->GetRange();
127 location_ = range.begin();
128 ranges_.push_back(range);
129 }
130 }
131
132 Err::Err(const Value& value,
133 const std::string msg,
134 const std::string& help_text)
135 : has_error_(true),
136 message_(msg),
137 help_text_(help_text) {
138 if (value.origin()) {
139 LocationRange range = value.origin()->GetRange();
140 location_ = range.begin();
141 ranges_.push_back(range);
142 }
143 }
144
145 Err::~Err() {
146 }
147
148 void Err::PrintToStdout() const {
149 InternalPrintToStdout(false);
150 }
151
152 void Err::AppendSubErr(const Err& err) {
153 sub_errs_.push_back(err);
154 }
155
156 void Err::InternalPrintToStdout(bool is_sub_err) const {
157 DCHECK(has_error_);
158
159 if (!is_sub_err)
160 OutputString("ERROR ", DECORATION_RED);
161
162 // File name and location.
163 const InputFile* input_file = location_.file();
164 std::string loc_str;
165 if (input_file) {
166 std::string path8;
167 path8.assign(input_file->name().value());
168
169 if (is_sub_err)
170 loc_str = "See ";
171 else
172 loc_str = "at ";
173 loc_str += path8 + ": " +
174 base::IntToString(location_.line_number()) + ":" +
175 base::IntToString(location_.char_offset()) + ": ";
176 }
177 OutputString(loc_str + message_ + "\n");
178
179 // Quoted line.
180 if (input_file) {
181 std::string line = GetNthLine(input_file->contents(),
182 location_.line_number());
183 if (!ContainsOnlyWhitespaceASCII(line)) {
184 OutputString(line + "\n", DECORATION_BOLD);
185 OutputHighlighedPosition(location_, ranges_, line.size());
186 }
187 }
188
189 // Optional help text.
190 if (!help_text_.empty())
191 OutputString(help_text_ + "\n");
192
193 // Sub errors.
194 for (size_t i = 0; i < sub_errs_.size(); i++)
195 sub_errs_[i].InternalPrintToStdout(true);
196 }
OLDNEW
« no previous file with comments | « tools/gn/err.h ('k') | tools/gn/escape.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698