• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gn/parse_tree.h"
6 
7 #include <stdint.h>
8 
9 #include <memory>
10 #include <string>
11 #include <tuple>
12 
13 #include "base/json/string_escape.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "gn/functions.h"
18 #include "gn/operators.h"
19 #include "gn/scope.h"
20 #include "gn/string_utils.h"
21 
22 // Dictionary keys used for JSON-formatted tree dump.
23 const char kJsonNodeChild[] = "child";
24 const char kJsonNodeType[] = "type";
25 const char kJsonNodeValue[] = "value";
26 const char kJsonBeforeComment[] = "before_comment";
27 const char kJsonSuffixComment[] = "suffix_comment";
28 const char kJsonAfterComment[] = "after_comment";
29 const char kJsonLocation[] = "location";
30 const char kJsonLocationBeginLine[] = "begin_line";
31 const char kJsonLocationBeginColumn[] = "begin_column";
32 const char kJsonLocationEndLine[] = "end_line";
33 const char kJsonLocationEndColumn[] = "end_column";
34 
35 // Used by Block and List.
36 const char kJsonBeginToken[] = "begin_token";
37 const char kJsonEnd[] = "end";
38 
39 namespace {
40 
41 enum DepsCategory {
42   DEPS_CATEGORY_LOCAL,
43   DEPS_CATEGORY_RELATIVE,
44   DEPS_CATEGORY_ABSOLUTE,
45   DEPS_CATEGORY_OTHER,
46 };
47 
GetDepsCategory(std::string_view deps)48 DepsCategory GetDepsCategory(std::string_view deps) {
49   if (deps.length() < 2 || deps[0] != '"' || deps[deps.size() - 1] != '"')
50     return DEPS_CATEGORY_OTHER;
51 
52   if (deps[1] == ':')
53     return DEPS_CATEGORY_LOCAL;
54 
55   if (deps[1] == '/')
56     return DEPS_CATEGORY_ABSOLUTE;
57 
58   return DEPS_CATEGORY_RELATIVE;
59 }
60 
SplitAtFirst(std::string_view str,char c)61 std::tuple<std::string_view, std::string_view> SplitAtFirst(
62     std::string_view str,
63     char c) {
64   if (!base::starts_with(str, "\"") || !base::ends_with(str, "\""))
65     return std::make_tuple(str, std::string_view());
66 
67   str = str.substr(1, str.length() - 2);
68   size_t index_of_first = str.find(c);
69   return std::make_tuple(str.substr(0, index_of_first),
70                          index_of_first != std::string_view::npos
71                              ? str.substr(index_of_first + 1)
72                              : std::string_view());
73 }
74 
IsSortRangeSeparator(const ParseNode * node,const ParseNode * prev)75 bool IsSortRangeSeparator(const ParseNode* node, const ParseNode* prev) {
76   // If it's a block comment, or has an attached comment with a blank line
77   // before it, then we break the range at this point.
78   return node->AsBlockComment() != nullptr ||
79          (prev && node->comments() && !node->comments()->before().empty() &&
80           (node->GetRange().begin().line_number() >
81            prev->GetRange().end().line_number() +
82                static_cast<int>(node->comments()->before().size() + 1)));
83 }
84 
GetStringRepresentation(const ParseNode * node)85 std::string_view GetStringRepresentation(const ParseNode* node) {
86   DCHECK(node->AsLiteral() || node->AsIdentifier() || node->AsAccessor());
87   if (node->AsLiteral())
88     return node->AsLiteral()->value().value();
89   else if (node->AsIdentifier())
90     return node->AsIdentifier()->value().value();
91   else if (node->AsAccessor())
92     return node->AsAccessor()->base().value();
93   return std::string_view();
94 }
95 
AddLocationJSONNodes(base::Value * dict,LocationRange location)96 void AddLocationJSONNodes(base::Value* dict, LocationRange location) {
97   base::Value loc(base::Value::Type::DICTIONARY);
98   loc.SetKey(kJsonLocationBeginLine,
99              base::Value(location.begin().line_number()));
100   loc.SetKey(kJsonLocationBeginColumn,
101              base::Value(location.begin().column_number()));
102   loc.SetKey(kJsonLocationEndLine, base::Value(location.end().line_number()));
103   loc.SetKey(kJsonLocationEndColumn,
104              base::Value(location.end().column_number()));
105   dict->SetKey(kJsonLocation, std::move(loc));
106 }
107 
GetBeginLocationFromJSON(const base::Value & value)108 Location GetBeginLocationFromJSON(const base::Value& value) {
109   int line =
110       value.FindKey(kJsonLocation)->FindKey(kJsonLocationBeginLine)->GetInt();
111   int column =
112       value.FindKey(kJsonLocation)->FindKey(kJsonLocationBeginColumn)->GetInt();
113   return Location(nullptr, line, column);
114 }
115 
GetCommentsFromJSON(ParseNode * node,const base::Value & value)116 void GetCommentsFromJSON(ParseNode* node, const base::Value& value) {
117   Comments* comments = node->comments_mutable();
118 
119   Location loc = GetBeginLocationFromJSON(value);
120 
121   auto loc_for = [&loc](int line) {
122     return Location(nullptr, loc.line_number() + line, loc.column_number());
123   };
124 
125   if (value.FindKey(kJsonBeforeComment)) {
126     int line = 0;
127     for (const auto& c : value.FindKey(kJsonBeforeComment)->GetList()) {
128       comments->append_before(
129           Token::ClassifyAndMake(loc_for(line), c.GetString()));
130       ++line;
131     }
132   }
133 
134   if (value.FindKey(kJsonSuffixComment)) {
135     int line = 0;
136     for (const auto& c : value.FindKey(kJsonSuffixComment)->GetList()) {
137       comments->append_suffix(
138           Token::ClassifyAndMake(loc_for(line), c.GetString()));
139       ++line;
140     }
141   }
142 
143   if (value.FindKey(kJsonAfterComment)) {
144     int line = 0;
145     for (const auto& c : value.FindKey(kJsonAfterComment)->GetList()) {
146       comments->append_after(
147           Token::ClassifyAndMake(loc_for(line), c.GetString()));
148       ++line;
149     }
150   }
151 }
152 
TokenFromValue(const base::Value & value)153 Token TokenFromValue(const base::Value& value) {
154   return Token::ClassifyAndMake(GetBeginLocationFromJSON(value),
155                                 value.FindKey(kJsonNodeValue)->GetString());
156 }
157 
158 }  // namespace
159 
160 Comments::Comments() = default;
161 
162 Comments::~Comments() = default;
163 
ReverseSuffix()164 void Comments::ReverseSuffix() {
165   for (int i = 0, j = static_cast<int>(suffix_.size() - 1); i < j; ++i, --j)
166     std::swap(suffix_[i], suffix_[j]);
167 }
168 
169 ParseNode::ParseNode() = default;
170 
171 ParseNode::~ParseNode() = default;
172 
AsAccessor() const173 const AccessorNode* ParseNode::AsAccessor() const {
174   return nullptr;
175 }
AsBinaryOp() const176 const BinaryOpNode* ParseNode::AsBinaryOp() const {
177   return nullptr;
178 }
AsBlockComment() const179 const BlockCommentNode* ParseNode::AsBlockComment() const {
180   return nullptr;
181 }
AsBlock() const182 const BlockNode* ParseNode::AsBlock() const {
183   return nullptr;
184 }
AsCondition() const185 const ConditionNode* ParseNode::AsCondition() const {
186   return nullptr;
187 }
AsEnd() const188 const EndNode* ParseNode::AsEnd() const {
189   return nullptr;
190 }
AsFunctionCall() const191 const FunctionCallNode* ParseNode::AsFunctionCall() const {
192   return nullptr;
193 }
AsIdentifier() const194 const IdentifierNode* ParseNode::AsIdentifier() const {
195   return nullptr;
196 }
AsList() const197 const ListNode* ParseNode::AsList() const {
198   return nullptr;
199 }
AsLiteral() const200 const LiteralNode* ParseNode::AsLiteral() const {
201   return nullptr;
202 }
AsUnaryOp() const203 const UnaryOpNode* ParseNode::AsUnaryOp() const {
204   return nullptr;
205 }
206 
comments_mutable()207 Comments* ParseNode::comments_mutable() {
208   if (!comments_)
209     comments_ = std::make_unique<Comments>();
210   return comments_.get();
211 }
212 
CreateJSONNode(const char * type,LocationRange location) const213 base::Value ParseNode::CreateJSONNode(const char* type,
214                                       LocationRange location) const {
215   base::Value dict(base::Value::Type::DICTIONARY);
216   dict.SetKey(kJsonNodeType, base::Value(type));
217   AddLocationJSONNodes(&dict, location);
218   AddCommentsJSONNodes(&dict);
219   return dict;
220 }
221 
CreateJSONNode(const char * type,std::string_view value,LocationRange location) const222 base::Value ParseNode::CreateJSONNode(const char* type,
223                                       std::string_view value,
224                                       LocationRange location) const {
225   base::Value dict(base::Value::Type::DICTIONARY);
226   dict.SetKey(kJsonNodeType, base::Value(type));
227   dict.SetKey(kJsonNodeValue, base::Value(value));
228   AddLocationJSONNodes(&dict, location);
229   AddCommentsJSONNodes(&dict);
230   return dict;
231 }
232 
AddCommentsJSONNodes(base::Value * out_value) const233 void ParseNode::AddCommentsJSONNodes(base::Value* out_value) const {
234   if (comments_) {
235     if (comments_->before().size()) {
236       base::Value comment_values(base::Value::Type::LIST);
237       for (const auto& token : comments_->before())
238         comment_values.GetList().push_back(base::Value(token.value()));
239       out_value->SetKey(kJsonBeforeComment, std::move(comment_values));
240     }
241     if (comments_->suffix().size()) {
242       base::Value comment_values(base::Value::Type::LIST);
243       for (const auto& token : comments_->suffix())
244         comment_values.GetList().push_back(base::Value(token.value()));
245       out_value->SetKey(kJsonSuffixComment, std::move(comment_values));
246     }
247     if (comments_->after().size()) {
248       base::Value comment_values(base::Value::Type::LIST);
249       for (const auto& token : comments_->after())
250         comment_values.GetList().push_back(base::Value(token.value()));
251       out_value->SetKey(kJsonAfterComment, std::move(comment_values));
252     }
253   }
254 }
255 
256 // static
BuildFromJSON(const base::Value & value)257 std::unique_ptr<ParseNode> ParseNode::BuildFromJSON(const base::Value& value) {
258   const std::string& str_type = value.FindKey(kJsonNodeType)->GetString();
259 
260 #define RETURN_IF_MATCHES_NAME(t)       \
261   do {                                  \
262     if (str_type == t::kDumpNodeName) { \
263       return t::NewFromJSON(value);     \
264     }                                   \
265   } while (0)
266 
267   RETURN_IF_MATCHES_NAME(AccessorNode);
268   RETURN_IF_MATCHES_NAME(BinaryOpNode);
269   RETURN_IF_MATCHES_NAME(BlockCommentNode);
270   RETURN_IF_MATCHES_NAME(BlockNode);
271   RETURN_IF_MATCHES_NAME(ConditionNode);
272   RETURN_IF_MATCHES_NAME(EndNode);
273   RETURN_IF_MATCHES_NAME(FunctionCallNode);
274   RETURN_IF_MATCHES_NAME(IdentifierNode);
275   RETURN_IF_MATCHES_NAME(ListNode);
276   RETURN_IF_MATCHES_NAME(LiteralNode);
277   RETURN_IF_MATCHES_NAME(UnaryOpNode);
278 
279 #undef RETURN_IF_MATCHES_NAME
280 
281   NOTREACHED() << str_type;
282   return std::unique_ptr<ParseNode>();
283 }
284 
285 // AccessorNode ---------------------------------------------------------------
286 
287 AccessorNode::AccessorNode() = default;
288 
289 AccessorNode::~AccessorNode() = default;
290 
AsAccessor() const291 const AccessorNode* AccessorNode::AsAccessor() const {
292   return this;
293 }
294 
Execute(Scope * scope,Err * err) const295 Value AccessorNode::Execute(Scope* scope, Err* err) const {
296   if (subscript_)
297     return ExecuteSubscriptAccess(scope, err);
298   else if (member_)
299     return ExecuteScopeAccess(scope, err);
300   NOTREACHED();
301   return Value();
302 }
303 
GetRange() const304 LocationRange AccessorNode::GetRange() const {
305   if (subscript_)
306     return LocationRange(base_.location(), subscript_->GetRange().end());
307   else if (member_)
308     return LocationRange(base_.location(), member_->GetRange().end());
309   NOTREACHED();
310   return LocationRange();
311 }
312 
MakeErrorDescribing(const std::string & msg,const std::string & help) const313 Err AccessorNode::MakeErrorDescribing(const std::string& msg,
314                                       const std::string& help) const {
315   return Err(GetRange(), msg, help);
316 }
317 
GetJSONNode() const318 base::Value AccessorNode::GetJSONNode() const {
319   base::Value dict(CreateJSONNode(kDumpNodeName, base_.value(), GetRange()));
320   base::Value child(base::Value::Type::LIST);
321   if (subscript_) {
322     child.GetList().push_back(subscript_->GetJSONNode());
323     dict.SetKey(kDumpAccessorKind, base::Value(kDumpAccessorKindSubscript));
324   } else if (member_) {
325     child.GetList().push_back(member_->GetJSONNode());
326     dict.SetKey(kDumpAccessorKind, base::Value(kDumpAccessorKindMember));
327   }
328   dict.SetKey(kJsonNodeChild, std::move(child));
329   return dict;
330 }
331 
332 #define DECLARE_CHILD_AS_LIST_OR_FAIL()                     \
333   const base::Value* child = value.FindKey(kJsonNodeChild); \
334   if (!child || !child->is_list()) {                        \
335     return nullptr;                                         \
336   }                                                         \
337   (void)(0)  // this is to supress extra semicolon warning.
338 
339 // static
NewFromJSON(const base::Value & value)340 std::unique_ptr<AccessorNode> AccessorNode::NewFromJSON(
341     const base::Value& value) {
342   auto ret = std::make_unique<AccessorNode>();
343   DECLARE_CHILD_AS_LIST_OR_FAIL();
344   ret->base_ = TokenFromValue(value);
345   const base::Value::ListStorage& children = child->GetList();
346   const std::string& kind = value.FindKey(kDumpAccessorKind)->GetString();
347   if (kind == kDumpAccessorKindSubscript) {
348     ret->subscript_ = ParseNode::BuildFromJSON(children[0]);
349   } else if (kind == kDumpAccessorKindMember) {
350     ret->member_ = IdentifierNode::NewFromJSON(children[0]);
351   }
352   GetCommentsFromJSON(ret.get(), value);
353   return ret;
354 }
355 
ExecuteSubscriptAccess(Scope * scope,Err * err) const356 Value AccessorNode::ExecuteSubscriptAccess(Scope* scope, Err* err) const {
357   const Value* base_value = scope->GetValue(base_.value(), true);
358   if (!base_value) {
359     *err = MakeErrorDescribing("Undefined identifier.");
360     return Value();
361   }
362   if (base_value->type() == Value::LIST) {
363     return ExecuteArrayAccess(scope, base_value, err);
364   } else if (base_value->type() == Value::SCOPE) {
365     return ExecuteScopeSubscriptAccess(scope, base_value, err);
366   } else {
367     *err = MakeErrorDescribing(
368         std::string("Expecting either a list or a scope for subscript, got ") +
369         Value::DescribeType(base_value->type()) + ".");
370     return Value();
371   }
372 }
373 
ExecuteArrayAccess(Scope * scope,const Value * base_value,Err * err) const374 Value AccessorNode::ExecuteArrayAccess(Scope* scope,
375                                        const Value* base_value,
376                                        Err* err) const {
377   size_t index = 0;
378   if (!ComputeAndValidateListIndex(scope, base_value->list_value().size(),
379                                    &index, err))
380     return Value();
381   return base_value->list_value()[index];
382 }
383 
ExecuteScopeSubscriptAccess(Scope * scope,const Value * base_value,Err * err) const384 Value AccessorNode::ExecuteScopeSubscriptAccess(Scope* scope,
385                                                 const Value* base_value,
386                                                 Err* err) const {
387   Value key_value = subscript_->Execute(scope, err);
388   if (err->has_error())
389     return Value();
390   if (!key_value.VerifyTypeIs(Value::STRING, err))
391     return Value();
392   const Value* result =
393       ExecuteScopeAccessForMember(scope, key_value.string_value(), err);
394   if (!result) {
395     *err =
396         Err(subscript_.get(), "No value named \"" + key_value.string_value() +
397                                   "\" in scope \"" + base_.value() + "\"");
398     return Value();
399   }
400   return *result;
401 }
402 
ExecuteScopeAccess(Scope * scope,Err * err) const403 Value AccessorNode::ExecuteScopeAccess(Scope* scope, Err* err) const {
404   const Value* result =
405       ExecuteScopeAccessForMember(scope, member_->value().value(), err);
406 
407   if (!result) {
408     *err = Err(member_.get(), "No value named \"" + member_->value().value() +
409                                   "\" in scope \"" + base_.value() + "\"");
410     return Value();
411   }
412   return *result;
413 }
414 
ExecuteScopeAccessForMember(Scope * scope,std::string_view member_str,Err * err) const415 const Value* AccessorNode::ExecuteScopeAccessForMember(
416     Scope* scope,
417     std::string_view member_str,
418     Err* err) const {
419   // We jump through some hoops here since ideally a.b will count "b" as
420   // accessed in the given scope. The value "a" might be in some normal nested
421   // scope and we can modify it, but it might also be inherited from the
422   // readonly root scope and we can't do used variable tracking on it. (It's
423   // not legal to const cast it away since the root scope will be in readonly
424   // mode and being accessed from multiple threads without locking.) So this
425   // code handles both cases.
426   const Value* result = nullptr;
427 
428   // Look up the value in the scope named by "base_".
429   Value* mutable_base_value =
430       scope->GetMutableValue(base_.value(), Scope::SEARCH_NESTED, true);
431   if (mutable_base_value) {
432     // Common case: base value is mutable so we can track variable accesses
433     // for unused value warnings.
434     if (!mutable_base_value->VerifyTypeIs(Value::SCOPE, err))
435       return nullptr;
436     result = mutable_base_value->scope_value()->GetValue(member_str, true);
437   } else {
438     // Fall back to see if the value is on a read-only scope.
439     const Value* const_base_value = scope->GetValue(base_.value(), true);
440     if (const_base_value) {
441       // Read only value, don't try to mark the value access as a "used" one.
442       if (!const_base_value->VerifyTypeIs(Value::SCOPE, err))
443         return nullptr;
444       result = const_base_value->scope_value()->GetValue(member_str);
445     } else {
446       *err = Err(base_, "Undefined identifier.");
447       return nullptr;
448     }
449   }
450   return result;
451 }
452 
SetNewLocation(int line_number)453 void AccessorNode::SetNewLocation(int line_number) {
454   Location old = base_.location();
455   base_.set_location(Location(old.file(), line_number, old.column_number()));
456 }
457 
ComputeAndValidateListIndex(Scope * scope,size_t max_len,size_t * computed_index,Err * err) const458 bool AccessorNode::ComputeAndValidateListIndex(Scope* scope,
459                                                size_t max_len,
460                                                size_t* computed_index,
461                                                Err* err) const {
462   Value index_value = subscript_->Execute(scope, err);
463   if (err->has_error())
464     return false;
465   if (!index_value.VerifyTypeIs(Value::INTEGER, err))
466     return false;
467 
468   int64_t index_int = index_value.int_value();
469   if (index_int < 0) {
470     *err = Err(subscript_->GetRange(), "Negative array subscript.",
471                "You gave me " + base::Int64ToString(index_int) + ".");
472     return false;
473   }
474   if (max_len == 0) {
475     *err = Err(subscript_->GetRange(), "Array subscript out of range.",
476                "You gave me " + base::Int64ToString(index_int) + " but the " +
477                    "array has no elements.");
478     return false;
479   }
480   size_t index_sizet = static_cast<size_t>(index_int);
481   if (index_sizet >= max_len) {
482     *err = Err(subscript_->GetRange(), "Array subscript out of range.",
483                "You gave me " + base::Int64ToString(index_int) +
484                    " but I was expecting something from 0 to " +
485                    base::NumberToString(max_len - 1) + ", inclusive.");
486     return false;
487   }
488 
489   *computed_index = index_sizet;
490   return true;
491 }
492 
493 // BinaryOpNode ---------------------------------------------------------------
494 
495 BinaryOpNode::BinaryOpNode() = default;
496 
497 BinaryOpNode::~BinaryOpNode() = default;
498 
AsBinaryOp() const499 const BinaryOpNode* BinaryOpNode::AsBinaryOp() const {
500   return this;
501 }
502 
Execute(Scope * scope,Err * err) const503 Value BinaryOpNode::Execute(Scope* scope, Err* err) const {
504   return ExecuteBinaryOperator(scope, this, left_.get(), right_.get(), err);
505 }
506 
GetRange() const507 LocationRange BinaryOpNode::GetRange() const {
508   return left_->GetRange().Union(right_->GetRange());
509 }
510 
MakeErrorDescribing(const std::string & msg,const std::string & help) const511 Err BinaryOpNode::MakeErrorDescribing(const std::string& msg,
512                                       const std::string& help) const {
513   return Err(op_, msg, help);
514 }
515 
GetJSONNode() const516 base::Value BinaryOpNode::GetJSONNode() const {
517   base::Value dict(CreateJSONNode(kDumpNodeName, op_.value(), GetRange()));
518   base::Value child(base::Value::Type::LIST);
519   child.GetList().push_back(left_->GetJSONNode());
520   child.GetList().push_back(right_->GetJSONNode());
521   dict.SetKey(kJsonNodeChild, std::move(child));
522   return dict;
523 }
524 
525 // static
NewFromJSON(const base::Value & value)526 std::unique_ptr<BinaryOpNode> BinaryOpNode::NewFromJSON(
527     const base::Value& value) {
528   auto ret = std::make_unique<BinaryOpNode>();
529   DECLARE_CHILD_AS_LIST_OR_FAIL();
530   const base::Value::ListStorage& children = child->GetList();
531   ret->left_ = ParseNode::BuildFromJSON(children[0]);
532   ret->right_ = ParseNode::BuildFromJSON(children[1]);
533   ret->op_ = TokenFromValue(value);
534   GetCommentsFromJSON(ret.get(), value);
535   return ret;
536 }
537 
538 // BlockNode ------------------------------------------------------------------
539 
BlockNode(ResultMode result_mode)540 BlockNode::BlockNode(ResultMode result_mode) : result_mode_(result_mode) {}
541 
542 BlockNode::~BlockNode() = default;
543 
AsBlock() const544 const BlockNode* BlockNode::AsBlock() const {
545   return this;
546 }
547 
Execute(Scope * enclosing_scope,Err * err) const548 Value BlockNode::Execute(Scope* enclosing_scope, Err* err) const {
549   std::unique_ptr<Scope> nested_scope;  // May be null.
550 
551   Scope* execution_scope;  // Either the enclosing_scope or nested_scope.
552   if (result_mode_ == RETURNS_SCOPE) {
553     // Create a nested scope to save the values for returning.
554     nested_scope = std::make_unique<Scope>(enclosing_scope);
555     execution_scope = nested_scope.get();
556   } else {
557     // Use the enclosing scope. Modifications will go into this also (for
558     // example, if conditions and loops).
559     execution_scope = enclosing_scope;
560   }
561 
562   for (size_t i = 0; i < statements_.size() && !err->has_error(); i++) {
563     // Check for trying to execute things with no side effects in a block.
564     //
565     // A BlockNode here means that somebody has a free-floating { }.
566     // Technically this can have side effects since it could generated targets,
567     // but we don't want to allow this since it creates ambiguity when
568     // immediately following a function call that takes no block. By not
569     // allowing free-floating blocks that aren't passed anywhere or assigned to
570     // anything, this ambiguity is resolved.
571     const ParseNode* cur = statements_[i].get();
572     if (cur->AsList() || cur->AsLiteral() || cur->AsUnaryOp() ||
573         cur->AsIdentifier() || cur->AsBlock()) {
574       *err = cur->MakeErrorDescribing(
575           "This statement has no effect.",
576           "Either delete it or do something with the result.");
577       return Value();
578     }
579     cur->Execute(execution_scope, err);
580   }
581 
582   if (result_mode_ == RETURNS_SCOPE) {
583     // Clear the reference to the containing scope. This will be passed in
584     // a value whose lifetime will not be related to the enclosing_scope passed
585     // to this function.
586     nested_scope->DetachFromContaining();
587     return Value(this, std::move(nested_scope));
588   }
589   return Value();
590 }
591 
GetRange() const592 LocationRange BlockNode::GetRange() const {
593   if (begin_token_.type() != Token::INVALID &&
594       end_->value().type() != Token::INVALID) {
595     return begin_token_.range().Union(end_->value().range());
596   } else if (!statements_.empty()) {
597     return statements_[0]->GetRange().Union(
598         statements_[statements_.size() - 1]->GetRange());
599   }
600   return LocationRange();
601 }
602 
MakeErrorDescribing(const std::string & msg,const std::string & help) const603 Err BlockNode::MakeErrorDescribing(const std::string& msg,
604                                    const std::string& help) const {
605   return Err(GetRange(), msg, help);
606 }
607 
GetJSONNode() const608 base::Value BlockNode::GetJSONNode() const {
609   base::Value dict(CreateJSONNode(kDumpNodeName, GetRange()));
610   base::Value statements(base::Value::Type::LIST);
611   for (const auto& statement : statements_)
612     statements.GetList().push_back(statement->GetJSONNode());
613   if (end_)
614     dict.SetKey(kJsonEnd, end_->GetJSONNode());
615 
616   dict.SetKey(kJsonNodeChild, std::move(statements));
617 
618   if (result_mode_ == BlockNode::RETURNS_SCOPE) {
619     dict.SetKey(kDumpResultMode, base::Value(kDumpResultModeReturnsScope));
620   } else if (result_mode_ == BlockNode::DISCARDS_RESULT) {
621     dict.SetKey(kDumpResultMode, base::Value(kDumpResultModeDiscardsResult));
622   } else {
623     NOTREACHED();
624   }
625 
626   dict.SetKey(kJsonBeginToken, base::Value(begin_token_.value()));
627 
628   return dict;
629 }
630 
631 // static
NewFromJSON(const base::Value & value)632 std::unique_ptr<BlockNode> BlockNode::NewFromJSON(const base::Value& value) {
633   const std::string& result_mode = value.FindKey(kDumpResultMode)->GetString();
634   std::unique_ptr<BlockNode> ret;
635 
636   if (result_mode == kDumpResultModeReturnsScope) {
637     ret.reset(new BlockNode(BlockNode::RETURNS_SCOPE));
638   } else if (result_mode == kDumpResultModeDiscardsResult) {
639     ret.reset(new BlockNode(BlockNode::DISCARDS_RESULT));
640   } else {
641     NOTREACHED();
642   }
643 
644   DECLARE_CHILD_AS_LIST_OR_FAIL();
645   for (const auto& elem : child->GetList()) {
646     ret->statements_.push_back(ParseNode::BuildFromJSON(elem));
647   }
648 
649   ret->begin_token_ =
650       Token::ClassifyAndMake(GetBeginLocationFromJSON(value),
651                              value.FindKey(kJsonBeginToken)->GetString());
652   if (value.FindKey(kJsonEnd)) {
653     ret->end_ = EndNode::NewFromJSON(*value.FindKey(kJsonEnd));
654   }
655 
656   GetCommentsFromJSON(ret.get(), value);
657   return ret;
658 }
659 
660 // ConditionNode --------------------------------------------------------------
661 
662 ConditionNode::ConditionNode() = default;
663 
664 ConditionNode::~ConditionNode() = default;
665 
AsCondition() const666 const ConditionNode* ConditionNode::AsCondition() const {
667   return this;
668 }
669 
Execute(Scope * scope,Err * err) const670 Value ConditionNode::Execute(Scope* scope, Err* err) const {
671   Value condition_result = condition_->Execute(scope, err);
672   if (err->has_error())
673     return Value();
674   if (condition_result.type() != Value::BOOLEAN) {
675     *err = condition_->MakeErrorDescribing(
676         "Condition does not evaluate to a boolean value.",
677         std::string("This is a value of type \"") +
678             Value::DescribeType(condition_result.type()) + "\" instead.");
679     err->AppendRange(if_token_.range());
680     return Value();
681   }
682 
683   if (condition_result.boolean_value()) {
684     if_true_->Execute(scope, err);
685   } else if (if_false_) {
686     // The else block is optional.
687     if_false_->Execute(scope, err);
688   }
689 
690   return Value();
691 }
692 
GetRange() const693 LocationRange ConditionNode::GetRange() const {
694   if (if_false_)
695     return if_token_.range().Union(if_false_->GetRange());
696   return if_token_.range().Union(if_true_->GetRange());
697 }
698 
MakeErrorDescribing(const std::string & msg,const std::string & help) const699 Err ConditionNode::MakeErrorDescribing(const std::string& msg,
700                                        const std::string& help) const {
701   return Err(if_token_, msg, help);
702 }
703 
GetJSONNode() const704 base::Value ConditionNode::GetJSONNode() const {
705   base::Value dict = CreateJSONNode(kDumpNodeName, GetRange());
706   base::Value child(base::Value::Type::LIST);
707   child.GetList().push_back(condition_->GetJSONNode());
708   child.GetList().push_back(if_true_->GetJSONNode());
709   if (if_false_) {
710     child.GetList().push_back(if_false_->GetJSONNode());
711   }
712   dict.SetKey(kJsonNodeChild, std::move(child));
713   return dict;
714 }
715 
716 // static
NewFromJSON(const base::Value & value)717 std::unique_ptr<ConditionNode> ConditionNode::NewFromJSON(
718     const base::Value& value) {
719   auto ret = std::make_unique<ConditionNode>();
720 
721   DECLARE_CHILD_AS_LIST_OR_FAIL();
722   const base::Value::ListStorage& children = child->GetList();
723 
724   ret->if_token_ =
725       Token::ClassifyAndMake(GetBeginLocationFromJSON(value), "if");
726   ret->condition_ = ParseNode::BuildFromJSON(children[0]);
727   ret->if_true_ = BlockNode::NewFromJSON(children[1]);
728   if (children.size() > 2) {
729     ret->if_false_ = ParseNode::BuildFromJSON(children[2]);
730   }
731   GetCommentsFromJSON(ret.get(), value);
732   return ret;
733 }
734 
735 // FunctionCallNode -----------------------------------------------------------
736 
737 FunctionCallNode::FunctionCallNode() = default;
738 
739 FunctionCallNode::~FunctionCallNode() = default;
740 
AsFunctionCall() const741 const FunctionCallNode* FunctionCallNode::AsFunctionCall() const {
742   return this;
743 }
744 
Execute(Scope * scope,Err * err) const745 Value FunctionCallNode::Execute(Scope* scope, Err* err) const {
746   return functions::RunFunction(scope, this, args_.get(), block_.get(), err);
747 }
748 
GetRange() const749 LocationRange FunctionCallNode::GetRange() const {
750   if (function_.type() == Token::INVALID)
751     return LocationRange();  // This will be null in some tests.
752   if (block_)
753     return function_.range().Union(block_->GetRange());
754   return function_.range().Union(args_->GetRange());
755 }
756 
MakeErrorDescribing(const std::string & msg,const std::string & help) const757 Err FunctionCallNode::MakeErrorDescribing(const std::string& msg,
758                                           const std::string& help) const {
759   return Err(function_, msg, help);
760 }
761 
GetJSONNode() const762 base::Value FunctionCallNode::GetJSONNode() const {
763   base::Value dict =
764       CreateJSONNode(kDumpNodeName, function_.value(), GetRange());
765   base::Value child(base::Value::Type::LIST);
766   child.GetList().push_back(args_->GetJSONNode());
767   if (block_) {
768     child.GetList().push_back(block_->GetJSONNode());
769   }
770   dict.SetKey(kJsonNodeChild, std::move(child));
771   return dict;
772 }
773 
774 // static
NewFromJSON(const base::Value & value)775 std::unique_ptr<FunctionCallNode> FunctionCallNode::NewFromJSON(
776     const base::Value& value) {
777   auto ret = std::make_unique<FunctionCallNode>();
778 
779   DECLARE_CHILD_AS_LIST_OR_FAIL();
780   const base::Value::ListStorage& children = child->GetList();
781   ret->function_ = TokenFromValue(value);
782   ret->args_ = ListNode::NewFromJSON(children[0]);
783   if (children.size() > 1)
784     ret->block_ = BlockNode::NewFromJSON(children[1]);
785 
786   GetCommentsFromJSON(ret.get(), value);
787   return ret;
788 }
789 
SetNewLocation(int line_number)790 void FunctionCallNode::SetNewLocation(int line_number) {
791   Location func_old_loc = function_.location();
792   Location func_new_loc =
793       Location(func_old_loc.file(), line_number, func_old_loc.column_number());
794   function_.set_location(func_new_loc);
795 
796   Location args_old_loc = args_->Begin().location();
797   Location args_new_loc =
798       Location(args_old_loc.file(), line_number, args_old_loc.column_number());
799   const_cast<Token&>(args_->Begin()).set_location(args_new_loc);
800   const_cast<Token&>(args_->End()->value()).set_location(args_new_loc);
801 }
802 
803 // IdentifierNode --------------------------------------------------------------
804 
805 IdentifierNode::IdentifierNode() = default;
806 
IdentifierNode(const Token & token)807 IdentifierNode::IdentifierNode(const Token& token) : value_(token) {}
808 
809 IdentifierNode::~IdentifierNode() = default;
810 
AsIdentifier() const811 const IdentifierNode* IdentifierNode::AsIdentifier() const {
812   return this;
813 }
814 
Execute(Scope * scope,Err * err) const815 Value IdentifierNode::Execute(Scope* scope, Err* err) const {
816   const Scope* found_in_scope = nullptr;
817   const Value* value =
818       scope->GetValueWithScope(value_.value(), true, &found_in_scope);
819   Value result;
820   if (!value) {
821     *err = MakeErrorDescribing("Undefined identifier");
822     return result;
823   }
824 
825   if (!EnsureNotReadingFromSameDeclareArgs(this, scope, found_in_scope, err))
826     return result;
827 
828   result = *value;
829   result.set_origin(this);
830   return result;
831 }
832 
GetRange() const833 LocationRange IdentifierNode::GetRange() const {
834   return value_.range();
835 }
836 
MakeErrorDescribing(const std::string & msg,const std::string & help) const837 Err IdentifierNode::MakeErrorDescribing(const std::string& msg,
838                                         const std::string& help) const {
839   return Err(value_, msg, help);
840 }
841 
GetJSONNode() const842 base::Value IdentifierNode::GetJSONNode() const {
843   return CreateJSONNode(kDumpNodeName, value_.value(), GetRange());
844 }
845 
846 // static
NewFromJSON(const base::Value & value)847 std::unique_ptr<IdentifierNode> IdentifierNode::NewFromJSON(
848     const base::Value& value) {
849   auto ret = std::make_unique<IdentifierNode>();
850   ret->set_value(TokenFromValue(value));
851   GetCommentsFromJSON(ret.get(), value);
852   return ret;
853 }
854 
SetNewLocation(int line_number)855 void IdentifierNode::SetNewLocation(int line_number) {
856   Location old = value_.location();
857   value_.set_location(Location(old.file(), line_number, old.column_number()));
858 }
859 
860 // ListNode -------------------------------------------------------------------
861 
ListNode()862 ListNode::ListNode() {}
863 
864 ListNode::~ListNode() = default;
865 
AsList() const866 const ListNode* ListNode::AsList() const {
867   return this;
868 }
869 
Execute(Scope * scope,Err * err) const870 Value ListNode::Execute(Scope* scope, Err* err) const {
871   Value result_value(this, Value::LIST);
872   std::vector<Value>& results = result_value.list_value();
873   results.reserve(contents_.size());
874 
875   for (const auto& cur : contents_) {
876     if (cur->AsBlockComment())
877       continue;
878     results.push_back(cur->Execute(scope, err));
879     if (err->has_error())
880       return Value();
881     if (results.back().type() == Value::NONE) {
882       *err = cur->MakeErrorDescribing("This does not evaluate to a value.",
883                                       "I can't do something with nothing.");
884       return Value();
885     }
886   }
887   return result_value;
888 }
889 
GetRange() const890 LocationRange ListNode::GetRange() const {
891   return LocationRange(begin_token_.location(), end_->value().location());
892 }
893 
MakeErrorDescribing(const std::string & msg,const std::string & help) const894 Err ListNode::MakeErrorDescribing(const std::string& msg,
895                                   const std::string& help) const {
896   return Err(begin_token_, msg, help);
897 }
898 
GetJSONNode() const899 base::Value ListNode::GetJSONNode() const {
900   base::Value dict(CreateJSONNode(kDumpNodeName, GetRange()));
901   base::Value child(base::Value::Type::LIST);
902   for (const auto& cur : contents_) {
903     child.GetList().push_back(cur->GetJSONNode());
904   }
905   if (end_)
906     dict.SetKey(kJsonEnd, end_->GetJSONNode());
907   dict.SetKey(kJsonNodeChild, std::move(child));
908   dict.SetKey(kJsonBeginToken, base::Value(begin_token_.value()));
909   return dict;
910 }
911 
912 // static
NewFromJSON(const base::Value & value)913 std::unique_ptr<ListNode> ListNode::NewFromJSON(const base::Value& value) {
914   auto ret = std::make_unique<ListNode>();
915 
916   DECLARE_CHILD_AS_LIST_OR_FAIL();
917   for (const auto& elem : child->GetList()) {
918     ret->contents_.push_back(ParseNode::BuildFromJSON(elem));
919   }
920   ret->begin_token_ =
921       Token::ClassifyAndMake(GetBeginLocationFromJSON(value),
922                              value.FindKey(kJsonBeginToken)->GetString());
923   if (value.FindKey(kJsonEnd)) {
924     ret->end_ = EndNode::NewFromJSON(*value.FindKey(kJsonEnd));
925   }
926 
927   GetCommentsFromJSON(ret.get(), value);
928   return ret;
929 }
930 
931 template <typename Comparator>
SortList(Comparator comparator)932 void ListNode::SortList(Comparator comparator) {
933   // Partitions first on BlockCommentNodes and sorts each partition separately.
934   for (auto sr : GetSortRanges()) {
935     bool skip = false;
936     for (size_t i = sr.begin; i != sr.end; ++i) {
937       // Bails out if any of the nodes are unsupported.
938       const ParseNode* node = contents_[i].get();
939       if (!node->AsLiteral() && !node->AsIdentifier() && !node->AsAccessor()) {
940         skip = true;
941         continue;
942       }
943     }
944     if (skip)
945       continue;
946     // Save the original line number so that we can re-assign ranges. We assume
947     // they're contiguous lines because GetSortRanges() does so above. We need
948     // to re-assign these line numbers primiarily because `gn format` uses them
949     // to determine whether two nodes were initially separated by a blank line
950     // or not.
951     int start_line = contents_[sr.begin]->GetRange().begin().line_number();
952     const ParseNode* original_first = contents_[sr.begin].get();
953     std::sort(contents_.begin() + sr.begin, contents_.begin() + sr.end,
954               [&comparator](const std::unique_ptr<const ParseNode>& a,
955                             const std::unique_ptr<const ParseNode>& b) {
956                 return comparator(a.get(), b.get());
957               });
958     // If the beginning of the range had before comments, and the first node
959     // moved during the sort, then move its comments to the new head of the
960     // range.
961     if (original_first->comments() &&
962         contents_[sr.begin].get() != original_first) {
963       for (const auto& hc : original_first->comments()->before()) {
964         const_cast<ParseNode*>(contents_[sr.begin].get())
965             ->comments_mutable()
966             ->append_before(hc);
967       }
968       const_cast<ParseNode*>(original_first)
969           ->comments_mutable()
970           ->clear_before();
971     }
972     const ParseNode* prev = nullptr;
973     for (size_t i = sr.begin; i != sr.end; ++i) {
974       const ParseNode* node = contents_[i].get();
975       DCHECK(node->AsLiteral() || node->AsIdentifier() || node->AsAccessor());
976       int line_number =
977           prev ? prev->GetRange().end().line_number() + 1 : start_line;
978       if (node->AsLiteral()) {
979         const_cast<LiteralNode*>(node->AsLiteral())
980             ->SetNewLocation(line_number);
981       } else if (node->AsIdentifier()) {
982         const_cast<IdentifierNode*>(node->AsIdentifier())
983             ->SetNewLocation(line_number);
984       } else if (node->AsAccessor()) {
985         const_cast<AccessorNode*>(node->AsAccessor())
986             ->SetNewLocation(line_number);
987       }
988       prev = node;
989     }
990   }
991 }
992 
SortAsStringsList()993 void ListNode::SortAsStringsList() {
994   // Sorts alphabetically.
995   SortList([](const ParseNode* a, const ParseNode* b) {
996     std::string_view astr = GetStringRepresentation(a);
997     std::string_view bstr = GetStringRepresentation(b);
998     return astr < bstr;
999   });
1000 }
1001 
SortAsTargetsList()1002 void ListNode::SortAsTargetsList() {
1003   // Sorts first relative targets, then absolute, each group is sorted
1004   // alphabetically.
1005   SortList([](const ParseNode* a, const ParseNode* b) {
1006     std::string_view astr = GetStringRepresentation(a);
1007     std::string_view bstr = GetStringRepresentation(b);
1008     return std::make_pair(GetDepsCategory(astr), SplitAtFirst(astr, ':')) <
1009            std::make_pair(GetDepsCategory(bstr), SplitAtFirst(bstr, ':'));
1010   });
1011 }
1012 
1013 // Breaks the ParseNodes of |contents| up by ranges that should be separately
1014 // sorted. In particular, we break at a block comment, or an item that has an
1015 // attached "before" comment and is separated by a blank line from the item
1016 // before it. The assumption is that both of these indicate a separate 'section'
1017 // of a sources block across which items should not be inter-sorted.
GetSortRanges() const1018 std::vector<ListNode::SortRange> ListNode::GetSortRanges() const {
1019   std::vector<SortRange> ranges;
1020   const ParseNode* prev = nullptr;
1021   size_t begin = 0;
1022   for (size_t i = begin; i < contents_.size(); prev = contents_[i++].get()) {
1023     if (IsSortRangeSeparator(contents_[i].get(), prev)) {
1024       if (i > begin) {
1025         ranges.push_back(SortRange(begin, i));
1026         // If |i| is an item with an attached comment, then we start the next
1027         // range at that point, because we want to include it in the sort.
1028         // Otherwise, it's a block comment which we skip over entirely because
1029         // we don't want to move or include it in the sort. The two cases are:
1030         //
1031         // sources = [
1032         //   "a",
1033         //   "b",
1034         //
1035         //   #
1036         //   # This is a block comment.
1037         //   #
1038         //
1039         //   "c",
1040         //   "d",
1041         // ]
1042         //
1043         // which contains 5 elements, and for which the ranges would be { [0,
1044         // 2), [3, 5) } (notably excluding 2, the block comment), and:
1045         //
1046         // sources = [
1047         //   "a",
1048         //   "b",
1049         //
1050         //   # This is a header comment.
1051         //   "c",
1052         //   "d",
1053         // ]
1054         //
1055         // which contains 4 elements, index 2 containing an attached 'before'
1056         // comments, and the ranges should be { [0, 2), [2, 4) }.
1057         if (!contents_[i]->AsBlockComment())
1058           begin = i;
1059         else
1060           begin = i + 1;
1061       } else {
1062         // If it was a one item range, just skip over it.
1063         begin = i + 1;
1064       }
1065     }
1066   }
1067   if (begin != contents_.size())
1068     ranges.push_back(SortRange(begin, contents_.size()));
1069   return ranges;
1070 }
1071 
1072 // LiteralNode -----------------------------------------------------------------
1073 
1074 LiteralNode::LiteralNode() = default;
1075 
LiteralNode(const Token & token)1076 LiteralNode::LiteralNode(const Token& token) : value_(token) {}
1077 
1078 LiteralNode::~LiteralNode() = default;
1079 
AsLiteral() const1080 const LiteralNode* LiteralNode::AsLiteral() const {
1081   return this;
1082 }
1083 
Execute(Scope * scope,Err * err) const1084 Value LiteralNode::Execute(Scope* scope, Err* err) const {
1085   switch (value_.type()) {
1086     case Token::TRUE_TOKEN:
1087       return Value(this, true);
1088     case Token::FALSE_TOKEN:
1089       return Value(this, false);
1090     case Token::INTEGER: {
1091       std::string_view s = value_.value();
1092       if ((base::starts_with(s, "0") && s.size() > 1) || base::starts_with(s, "-0")) {
1093         if (s == "-0")
1094           *err = MakeErrorDescribing("Negative zero doesn't make sense");
1095         else
1096           *err = MakeErrorDescribing("Leading zeros not allowed");
1097         return Value();
1098       }
1099       int64_t result_int;
1100       if (!base::StringToInt64(s, &result_int)) {
1101         *err = MakeErrorDescribing("This does not look like an integer");
1102         return Value();
1103       }
1104       return Value(this, result_int);
1105     }
1106     case Token::STRING: {
1107       Value v(this, Value::STRING);
1108       ExpandStringLiteral(scope, value_, &v, err);
1109       return v;
1110     }
1111     default:
1112       NOTREACHED();
1113       return Value();
1114   }
1115 }
1116 
GetRange() const1117 LocationRange LiteralNode::GetRange() const {
1118   return value_.range();
1119 }
1120 
MakeErrorDescribing(const std::string & msg,const std::string & help) const1121 Err LiteralNode::MakeErrorDescribing(const std::string& msg,
1122                                      const std::string& help) const {
1123   return Err(value_, msg, help);
1124 }
1125 
GetJSONNode() const1126 base::Value LiteralNode::GetJSONNode() const {
1127   return CreateJSONNode(kDumpNodeName, value_.value(), GetRange());
1128 }
1129 
1130 // static
NewFromJSON(const base::Value & value)1131 std::unique_ptr<LiteralNode> LiteralNode::NewFromJSON(
1132     const base::Value& value) {
1133   auto ret = std::make_unique<LiteralNode>();
1134   ret->value_ = TokenFromValue(value);
1135   GetCommentsFromJSON(ret.get(), value);
1136   return ret;
1137 }
1138 
SetNewLocation(int line_number)1139 void LiteralNode::SetNewLocation(int line_number) {
1140   Location old = value_.location();
1141   value_.set_location(Location(old.file(), line_number, old.column_number()));
1142 }
1143 
1144 // UnaryOpNode ----------------------------------------------------------------
1145 
1146 UnaryOpNode::UnaryOpNode() = default;
1147 
1148 UnaryOpNode::~UnaryOpNode() = default;
1149 
AsUnaryOp() const1150 const UnaryOpNode* UnaryOpNode::AsUnaryOp() const {
1151   return this;
1152 }
1153 
Execute(Scope * scope,Err * err) const1154 Value UnaryOpNode::Execute(Scope* scope, Err* err) const {
1155   Value operand_value = operand_->Execute(scope, err);
1156   if (err->has_error())
1157     return Value();
1158   return ExecuteUnaryOperator(scope, this, operand_value, err);
1159 }
1160 
GetRange() const1161 LocationRange UnaryOpNode::GetRange() const {
1162   return op_.range().Union(operand_->GetRange());
1163 }
1164 
MakeErrorDescribing(const std::string & msg,const std::string & help) const1165 Err UnaryOpNode::MakeErrorDescribing(const std::string& msg,
1166                                      const std::string& help) const {
1167   return Err(op_, msg, help);
1168 }
1169 
GetJSONNode() const1170 base::Value UnaryOpNode::GetJSONNode() const {
1171   base::Value dict = CreateJSONNode(kDumpNodeName, op_.value(), GetRange());
1172   base::Value child(base::Value::Type::LIST);
1173   child.GetList().push_back(operand_->GetJSONNode());
1174   dict.SetKey(kJsonNodeChild, std::move(child));
1175   return dict;
1176 }
1177 
1178 // static
NewFromJSON(const base::Value & value)1179 std::unique_ptr<UnaryOpNode> UnaryOpNode::NewFromJSON(
1180     const base::Value& value) {
1181   auto ret = std::make_unique<UnaryOpNode>();
1182   ret->op_ = TokenFromValue(value);
1183   DECLARE_CHILD_AS_LIST_OR_FAIL();
1184   ret->operand_ = ParseNode::BuildFromJSON(child->GetList()[0]);
1185   GetCommentsFromJSON(ret.get(), value);
1186   return ret;
1187 }
1188 
1189 // BlockCommentNode ------------------------------------------------------------
1190 
1191 BlockCommentNode::BlockCommentNode() = default;
1192 
1193 BlockCommentNode::~BlockCommentNode() = default;
1194 
AsBlockComment() const1195 const BlockCommentNode* BlockCommentNode::AsBlockComment() const {
1196   return this;
1197 }
1198 
Execute(Scope * scope,Err * err) const1199 Value BlockCommentNode::Execute(Scope* scope, Err* err) const {
1200   return Value();
1201 }
1202 
GetRange() const1203 LocationRange BlockCommentNode::GetRange() const {
1204   return comment_.range();
1205 }
1206 
MakeErrorDescribing(const std::string & msg,const std::string & help) const1207 Err BlockCommentNode::MakeErrorDescribing(const std::string& msg,
1208                                           const std::string& help) const {
1209   return Err(comment_, msg, help);
1210 }
1211 
GetJSONNode() const1212 base::Value BlockCommentNode::GetJSONNode() const {
1213   std::string escaped;
1214   return CreateJSONNode(kDumpNodeName, comment_.value(), GetRange());
1215 }
1216 
1217 // static
NewFromJSON(const base::Value & value)1218 std::unique_ptr<BlockCommentNode> BlockCommentNode::NewFromJSON(
1219     const base::Value& value) {
1220   auto ret = std::make_unique<BlockCommentNode>();
1221   ret->comment_ = Token(GetBeginLocationFromJSON(value), Token::BLOCK_COMMENT,
1222                         value.FindKey(kJsonNodeValue)->GetString());
1223   GetCommentsFromJSON(ret.get(), value);
1224   return ret;
1225 }
1226 
1227 // EndNode ---------------------------------------------------------------------
1228 
EndNode(const Token & token)1229 EndNode::EndNode(const Token& token) : value_(token) {}
1230 
1231 EndNode::~EndNode() = default;
1232 
AsEnd() const1233 const EndNode* EndNode::AsEnd() const {
1234   return this;
1235 }
1236 
Execute(Scope * scope,Err * err) const1237 Value EndNode::Execute(Scope* scope, Err* err) const {
1238   return Value();
1239 }
1240 
GetRange() const1241 LocationRange EndNode::GetRange() const {
1242   return value_.range();
1243 }
1244 
MakeErrorDescribing(const std::string & msg,const std::string & help) const1245 Err EndNode::MakeErrorDescribing(const std::string& msg,
1246                                  const std::string& help) const {
1247   return Err(value_, msg, help);
1248 }
1249 
GetJSONNode() const1250 base::Value EndNode::GetJSONNode() const {
1251   return CreateJSONNode(kDumpNodeName, value_.value(), GetRange());
1252 }
1253 
1254 // static
NewFromJSON(const base::Value & value)1255 std::unique_ptr<EndNode> EndNode::NewFromJSON(const base::Value& value) {
1256   auto ret = std::make_unique<EndNode>(TokenFromValue(value));
1257   GetCommentsFromJSON(ret.get(), value);
1258   return ret;
1259 }
1260