OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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/template.h" |
| 6 |
| 7 #include "tools/gn/err.h" |
| 8 #include "tools/gn/functions.h" |
| 9 #include "tools/gn/parse_tree.h" |
| 10 #include "tools/gn/scope.h" |
| 11 #include "tools/gn/value.h" |
| 12 |
| 13 Template::Template(const Scope* scope, const FunctionCallNode* def) |
| 14 : closure_(scope->MakeClosure()), |
| 15 definition_(def) { |
| 16 } |
| 17 |
| 18 Template::Template(scoped_ptr<Scope> scope, const FunctionCallNode* def) |
| 19 : closure_(scope.Pass()), |
| 20 definition_(def) { |
| 21 } |
| 22 |
| 23 Template::~Template() { |
| 24 } |
| 25 |
| 26 scoped_ptr<Template> Template::Clone() const { |
| 27 // We can make a new closure from our closure to copy it. |
| 28 return scoped_ptr<Template>( |
| 29 new Template(closure_->MakeClosure(), definition_)); |
| 30 } |
| 31 |
| 32 Value Template::Invoke(Scope* scope, |
| 33 const FunctionCallNode* invocation, |
| 34 const std::vector<Value>& args, |
| 35 BlockNode* block, |
| 36 Err* err) const { |
| 37 // Don't allow templates to be executed from imported files. Imports are for |
| 38 // simple values only. |
| 39 if (!EnsureNotProcessingImport(invocation, scope, err)) |
| 40 return Value(); |
| 41 |
| 42 // First run the invocation's block. |
| 43 Scope invocation_scope(scope); |
| 44 if (!FillTargetBlockScope(scope, invocation, |
| 45 invocation->function().value().as_string(), |
| 46 block, args, &invocation_scope, err)) |
| 47 return Value(); |
| 48 block->ExecuteBlockInScope(&invocation_scope, err); |
| 49 if (err->has_error()) |
| 50 return Value(); |
| 51 |
| 52 // Set up the scope to run the template. This should be dependent on the |
| 53 // closure, but have the "invoker" and "target_name" values injected, and the |
| 54 // current dir matching the invoker. |
| 55 Scope template_scope(closure_.get()); |
| 56 template_scope.SetValue("invoker", Value(NULL, &invocation_scope), |
| 57 invocation); |
| 58 template_scope.set_source_dir(scope->GetSourceDir()); |
| 59 |
| 60 const base::StringPiece target_name("target_name"); |
| 61 template_scope.SetValue(target_name, |
| 62 Value(invocation, args[0].string_value()), |
| 63 invocation); |
| 64 |
| 65 // Run the template code. Don't check for unused variables since the |
| 66 // template could be executed in many different ways and it could be that |
| 67 // not all executions use all values in the closure. |
| 68 return definition_->block()->ExecuteBlockInScope(&template_scope, err); |
| 69 } |
| 70 |
| 71 LocationRange Template::GetDefinitionRange() const { |
| 72 return definition_->GetRange(); |
| 73 } |
OLD | NEW |