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

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

Issue 2224343003: GN: Throw an error overwriting a nonempty scope. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comment Created 4 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
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/operators.h" 5 #include "tools/gn/operators.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <algorithm> 8 #include <algorithm>
9 9
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 } 202 }
203 203
204 void ValueDestination::MakeUndefinedIdentifierForModifyError(Err* err) { 204 void ValueDestination::MakeUndefinedIdentifierForModifyError(Err* err) {
205 // When Init() succeeds, the base of any accessor has already been resolved 205 // When Init() succeeds, the base of any accessor has already been resolved
206 // and that list indices are in-range. This means any undefined identifiers 206 // and that list indices are in-range. This means any undefined identifiers
207 // are for scope accesses. 207 // are for scope accesses.
208 DCHECK(type_ == SCOPE); 208 DCHECK(type_ == SCOPE);
209 *err = Err(*name_token_, "Undefined identifier."); 209 *err = Err(*name_token_, "Undefined identifier.");
210 } 210 }
211 211
212 // Computes an error message for overwriting a nonempty list/scope with another.
213 Err MakeOverwriteError(const BinaryOpNode* op_node,
214 const Value& old_value) {
215 std::string type_name;
216 std::string empty_def;
217
218 if (old_value.type() == Value::LIST) {
219 type_name = "list";
220 empty_def = "[]";
221 } else if (old_value.type() == Value::SCOPE) {
222 type_name = "scope";
223 empty_def = "{}";
224 } else {
225 NOTREACHED();
226 }
227
228 Err result(op_node->left()->GetRange(),
229 "Replacing nonempty " + type_name + ".",
230 "This overwrites a previously-defined nonempty " + type_name +
231 "with another nonempty " + type_name + ".");
232 result.AppendSubErr(Err(old_value, "for previous definition",
233 "Did you mean to append/modify instead? If you really want to overwrite, "
234 "do:\n"
235 " foo = " + empty_def + "\nbefore reassigning."));
236 return result;
237 }
238
212 // ----------------------------------------------------------------------------- 239 // -----------------------------------------------------------------------------
213 240
214 Err MakeIncompatibleTypeError(const BinaryOpNode* op_node, 241 Err MakeIncompatibleTypeError(const BinaryOpNode* op_node,
215 const Value& left, 242 const Value& left,
216 const Value& right) { 243 const Value& right) {
217 std::string msg = 244 std::string msg =
218 std::string("You can't do <") + Value::DescribeType(left.type()) + "> " + 245 std::string("You can't do <") + Value::DescribeType(left.type()) + "> " +
219 op_node->op().value().as_string() + 246 op_node->op().value().as_string() +
220 " <" + Value::DescribeType(right.type()) + ">."; 247 " <" + Value::DescribeType(right.type()) + ">.";
221 if (left.type() == Value::LIST) { 248 if (left.type() == Value::LIST) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 317
291 // We return a null value from this rather than the result of doing the append. 318 // We return a null value from this rather than the result of doing the append.
292 // See ValuePlusEquals for rationale. 319 // See ValuePlusEquals for rationale.
293 Value ExecuteEquals(Scope* exec_scope, 320 Value ExecuteEquals(Scope* exec_scope,
294 const BinaryOpNode* op_node, 321 const BinaryOpNode* op_node,
295 ValueDestination* dest, 322 ValueDestination* dest,
296 Value right, 323 Value right,
297 Err* err) { 324 Err* err) {
298 const Value* old_value = dest->GetExistingValue(); 325 const Value* old_value = dest->GetExistingValue();
299 if (old_value) { 326 if (old_value) {
300 // Throw an error when overwriting a nonempty list with another nonempty 327 // Check for overwriting nonempty scopes or lists with other nonempty
301 // list item. This is to detect the case where you write 328 // scopes or lists. This prevents mistakes that clobber a value rather than
302 // defines = ["FOO"] 329 // appending to it. For cases where a user meant to clear a value, allow
303 // and you overwrote inherited ones, when instead you mean to append: 330 // overwriting a nonempty list/scope with an empty one, which can then be
304 // defines += ["FOO"] 331 // modified.
305 if (old_value->type() == Value::LIST && 332 if (old_value->type() == Value::LIST && right.type() == Value::LIST &&
scottmg 2016/08/09 22:20:33 Something else will catch it if I try to overwrite
brettw 2016/08/09 23:00:48 Presumably that will just be wrong. If changing th
306 !old_value->list_value().empty() && 333 !old_value->list_value().empty() && !right.list_value().empty()) {
307 right.type() == Value::LIST && 334 *err = MakeOverwriteError(op_node, *old_value);
308 !right.list_value().empty()) { 335 return Value();
309 *err = Err(op_node->left()->GetRange(), "Replacing nonempty list.", 336 } else if (old_value->type() == Value::SCOPE &&
310 std::string("This overwrites a previously-defined nonempty list ") + 337 right.type() == Value::SCOPE &&
311 "(length " + 338 old_value->scope_value()->HasValues(Scope::SEARCH_CURRENT) &&
312 base::IntToString(static_cast<int>(old_value->list_value().size())) 339 right.scope_value()->HasValues(Scope::SEARCH_CURRENT)) {
313 + ")."); 340 *err = MakeOverwriteError(op_node, *old_value);
314 err->AppendSubErr(Err(*old_value, "for previous definition",
315 "with another one (length " +
316 base::IntToString(static_cast<int>(right.list_value().size())) +
317 "). Did you mean " +
318 "\"+=\" to append instead? If you\nreally want to do this, do\n"
319 " foo = []\nbefore reassigning."));
320 return Value(); 341 return Value();
321 } 342 }
322 } 343 }
323 if (err->has_error())
324 return Value();
325 344
326 Value* written_value = dest->SetValue(std::move(right), op_node->right()); 345 Value* written_value = dest->SetValue(std::move(right), op_node->right());
327 346
328 // Optionally apply the assignment filter in-place. 347 // Optionally apply the assignment filter in-place.
329 const PatternList* filter = dest->GetAssignmentFilter(exec_scope); 348 const PatternList* filter = dest->GetAssignmentFilter(exec_scope);
330 if (filter) { 349 if (filter) {
331 std::vector<Value>& list_value = written_value->list_value(); 350 std::vector<Value>& list_value = written_value->list_value();
332 auto first_deleted = std::remove_if( 351 auto first_deleted = std::remove_if(
333 list_value.begin(), list_value.end(), 352 list_value.begin(), list_value.end(),
334 [filter](const Value& v) { 353 [filter](const Value& v) {
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 return ExecuteGreaterEquals(scope, op_node, left_value, right_value, err); 774 return ExecuteGreaterEquals(scope, op_node, left_value, right_value, err);
756 if (op.type() == Token::LESS_EQUAL) 775 if (op.type() == Token::LESS_EQUAL)
757 return ExecuteLessEquals(scope, op_node, left_value, right_value, err); 776 return ExecuteLessEquals(scope, op_node, left_value, right_value, err);
758 if (op.type() == Token::GREATER_THAN) 777 if (op.type() == Token::GREATER_THAN)
759 return ExecuteGreater(scope, op_node, left_value, right_value, err); 778 return ExecuteGreater(scope, op_node, left_value, right_value, err);
760 if (op.type() == Token::LESS_THAN) 779 if (op.type() == Token::LESS_THAN)
761 return ExecuteLess(scope, op_node, left_value, right_value, err); 780 return ExecuteLess(scope, op_node, left_value, right_value, err);
762 781
763 return Value(); 782 return Value();
764 } 783 }
OLDNEW
« no previous file with comments | « mojo/public/tools/bindings/chromium_bindings_configuration.gni ('k') | tools/gn/operators_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698