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.
5 #include "tools/gn/template.h"
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/scope_per_file_provider.h"
12 #include "tools/gn/value.h"
14 Template::Template(const Scope
* scope
, const FunctionCallNode
* def
)
15 : closure_(scope
->MakeClosure()),
19 Template::Template(scoped_ptr
<Scope
> scope
, const FunctionCallNode
* def
)
20 : closure_(scope
.Pass()),
24 Template::~Template() {
27 Value
Template::Invoke(Scope
* scope
,
28 const FunctionCallNode
* invocation
,
29 const std::vector
<Value
>& args
,
32 // Don't allow templates to be executed from imported files. Imports are for
33 // simple values only.
34 if (!EnsureNotProcessingImport(invocation
, scope
, err
))
37 // First run the invocation's block. Need to allocate the scope on the heap
38 // so we can pass ownership to the template.
39 scoped_ptr
<Scope
> invocation_scope(new Scope(scope
));
40 if (!FillTargetBlockScope(scope
, invocation
,
41 invocation
->function().value().as_string(),
42 block
, args
, invocation_scope
.get(), err
))
44 block
->Execute(invocation_scope
.get(), err
);
48 // Set up the scope to run the template and set the current directory for the
49 // template (which ScopePerFileProvider uses to base the target-related
50 // variables target_gen_dir and target_out_dir on) to be that of the invoker.
51 // This way, files don't have to be rebased and target_*_dir works the way
52 // people expect (otherwise its to easy to be putting generated files in the
53 // gen dir corresponding to an imported file).
54 Scope
template_scope(closure_
.get());
55 template_scope
.set_source_dir(scope
->GetSourceDir());
57 ScopePerFileProvider
per_file_provider(&template_scope
, true);
59 // Targets defined in the template go in the collector for the invoking file.
60 template_scope
.set_item_collector(scope
->GetItemCollector());
62 // We jump through some hoops to avoid copying the invocation scope when
63 // setting it in the template scope (since the invocation scope may have
64 // large lists of source files in it and could be expensive to copy).
66 // Scope.SetValue will copy the value which will in turn copy the scope, but
67 // if we instead create a value and then set the scope on it, the copy can
69 const char kInvoker
[] = "invoker";
70 template_scope
.SetValue(kInvoker
, Value(nullptr, scoped_ptr
<Scope
>()),
72 Value
* invoker_value
= template_scope
.GetMutableValue(kInvoker
, false);
73 invoker_value
->SetScopeValue(invocation_scope
.Pass());
74 template_scope
.set_source_dir(scope
->GetSourceDir());
76 const base::StringPiece
target_name("target_name");
77 template_scope
.SetValue(target_name
,
78 Value(invocation
, args
[0].string_value()),
81 // Actually run the template code.
83 definition_
->block()->Execute(&template_scope
, err
);
84 if (err
->has_error()) {
85 // If there was an error, append the caller location so the error message
86 // displays a stack trace of how it got here.
87 err
->AppendSubErr(Err(invocation
, "whence it was called."));
91 // Check for unused variables in the invocation scope. This will find typos
92 // of things the caller meant to pass to the template but the template didn't
95 // This is a bit tricky because it's theoretically possible for the template
96 // to overwrite the value of "invoker" and free the Scope owned by the
97 // value. So we need to look it up again and don't do anything if it doesn't
99 invoker_value
= template_scope
.GetMutableValue(kInvoker
, false);
100 if (invoker_value
&& invoker_value
->type() == Value::SCOPE
) {
101 if (!invoker_value
->scope_value()->CheckForUnusedVars(err
))
105 // Check for unused variables in the template itself.
106 if (!template_scope
.CheckForUnusedVars(err
))
112 LocationRange
Template::GetDefinitionRange() const {
113 return definition_
->GetRange();