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

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

Issue 1632573002: Support for excluding variable from forwarding via forward_variables_form. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@web_shell
Patch Set: Created 4 years, 10 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
« no previous file with comments | « tools/gn/docs/reference.md ('k') | tools/gn/function_forward_variables_from_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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/err.h" 5 #include "tools/gn/err.h"
6 #include "tools/gn/functions.h" 6 #include "tools/gn/functions.h"
7 #include "tools/gn/parse_tree.h" 7 #include "tools/gn/parse_tree.h"
8 #include "tools/gn/scope.h" 8 #include "tools/gn/scope.h"
9 9
10 namespace functions { 10 namespace functions {
11 11
12 namespace { 12 namespace {
13 13
14 void ForwardAllValues(const FunctionCallNode* function, 14 void ForwardAllValues(const FunctionCallNode* function,
15 Scope* source, 15 Scope* source,
16 Scope* dest, 16 Scope* dest,
17 const std::set<std::string>& exclusion_set,
17 Err* err) { 18 Err* err) {
18 Scope::MergeOptions options; 19 Scope::MergeOptions options;
19 // This function needs to clobber existing for it to be useful. It will be 20 // This function needs to clobber existing for it to be useful. It will be
20 // called in a template to forward all values, but there will be some 21 // called in a template to forward all values, but there will be some
21 // default stuff like configs set up in both scopes, so it would always 22 // default stuff like configs set up in both scopes, so it would always
22 // fail if it didn't clobber. 23 // fail if it didn't clobber.
23 options.clobber_existing = true; 24 options.clobber_existing = true;
24 options.skip_private_vars = true; 25 options.skip_private_vars = true;
25 options.mark_dest_used = false; 26 options.mark_dest_used = false;
27 options.excluded_values = exclusion_set;
26 source->NonRecursiveMergeTo(dest, options, function, 28 source->NonRecursiveMergeTo(dest, options, function,
27 "source scope", err); 29 "source scope", err);
28 source->MarkAllUsed(); 30 source->MarkAllUsed();
29 } 31 }
30 32
31 void ForwardValuesFromList(Scope* source, 33 void ForwardValuesFromList(Scope* source,
32 Scope* dest, 34 Scope* dest,
33 const std::vector<Value>& list, 35 const std::vector<Value>& list,
36 const std::set<std::string>& exclusion_set,
34 Err* err) { 37 Err* err) {
35 for (const Value& cur : list) { 38 for (const Value& cur : list) {
36 if (!cur.VerifyTypeIs(Value::STRING, err)) 39 if (!cur.VerifyTypeIs(Value::STRING, err))
37 return; 40 return;
41 if (exclusion_set.find(cur.string_value()) != exclusion_set.end())
42 continue;
38 const Value* value = source->GetValue(cur.string_value(), true); 43 const Value* value = source->GetValue(cur.string_value(), true);
39 if (value) { 44 if (value) {
40 // Use the storage key for the original value rather than the string in 45 // Use the storage key for the original value rather than the string in
41 // "cur" because "cur" is a temporary that will be deleted, and Scopes 46 // "cur" because "cur" is a temporary that will be deleted, and Scopes
42 // expect a persistent StringPiece (it won't copy). Not doing this will 47 // expect a persistent StringPiece (it won't copy). Not doing this will
43 // lead the scope's key to point to invalid memory after this returns. 48 // lead the scope's key to point to invalid memory after this returns.
44 base::StringPiece storage_key = source->GetStorageKey(cur.string_value()); 49 base::StringPiece storage_key = source->GetStorageKey(cur.string_value());
45 if (storage_key.empty()) { 50 if (storage_key.empty()) {
46 // Programmatic value, don't allow copying. 51 // Programmatic value, don't allow copying.
47 *err = Err(cur, "This value can't be forwarded.", 52 *err = Err(cur, "This value can't be forwarded.",
(...skipping 13 matching lines...) Expand all
61 } // namespace 66 } // namespace
62 67
63 const char kForwardVariablesFrom[] = "forward_variables_from"; 68 const char kForwardVariablesFrom[] = "forward_variables_from";
64 const char kForwardVariablesFrom_HelpShort[] = 69 const char kForwardVariablesFrom_HelpShort[] =
65 "forward_variables_from: Copies variables from a different scope."; 70 "forward_variables_from: Copies variables from a different scope.";
66 const char kForwardVariablesFrom_Help[] = 71 const char kForwardVariablesFrom_Help[] =
67 "forward_variables_from: Copies variables from a different scope.\n" 72 "forward_variables_from: Copies variables from a different scope.\n"
68 "\n" 73 "\n"
69 " forward_variables_from(from_scope, variable_list_or_star)\n" 74 " forward_variables_from(from_scope, variable_list_or_star)\n"
70 "\n" 75 "\n"
76 " forward_variables_from(from_scope, variable_list_or_star,\n"
77 " variable_to_not_forward_list)\n"
78 "\n"
71 " Copies the given variables from the given scope to the local scope\n" 79 " Copies the given variables from the given scope to the local scope\n"
72 " if they exist. This is normally used in the context of templates to\n" 80 " if they exist. This is normally used in the context of templates to\n"
73 " use the values of variables defined in the template invocation to\n" 81 " use the values of variables defined in the template invocation to\n"
74 " a template-defined target.\n" 82 " a template-defined target.\n"
75 "\n" 83 "\n"
76 " The variables in the given variable_list will be copied if they exist\n" 84 " The variables in the given variable_list will be copied if they exist\n"
77 " in the given scope or any enclosing scope. If they do not exist,\n" 85 " in the given scope or any enclosing scope. If they do not exist,\n"
78 " nothing will happen and they be left undefined in the current scope.\n" 86 " nothing will happen and they be left undefined in the current scope.\n"
79 "\n" 87 "\n"
80 " As a special case, if the variable_list is a string with the value of\n" 88 " As a special case, if the variable_list is a string with the value of\n"
81 " \"*\", all variables from the given scope will be copied. \"*\" only\n" 89 " \"*\", all variables from the given scope will be copied. \"*\" only\n"
82 " copies variables set directly on the from_scope, not enclosing ones.\n" 90 " copies variables set directly on the from_scope, not enclosing ones.\n"
83 " Otherwise it would duplicate all global variables.\n" 91 " Otherwise it would duplicate all global variables.\n"
84 "\n" 92 "\n"
85 " When an explicit list of variables is supplied, if the variable exists\n" 93 " When an explicit list of variables is supplied, if the variable exists\n"
86 " in the current (destination) scope already, an error will be thrown.\n" 94 " in the current (destination) scope already, an error will be thrown.\n"
87 " If \"*\" is specified, variables in the current scope will be\n" 95 " If \"*\" is specified, variables in the current scope will be\n"
88 " clobbered (the latter is important because most targets have an\n" 96 " clobbered (the latter is important because most targets have an\n"
89 " implicit configs list, which means it wouldn't work at all if it\n" 97 " implicit configs list, which means it wouldn't work at all if it\n"
90 " didn't clobber).\n" 98 " didn't clobber).\n"
91 "\n" 99 "\n"
92 " The sources assignment filter (see \"gn help " 100 " The sources assignment filter (see \"gn help "
93 "set_sources_assignment_filter\")\n" 101 "set_sources_assignment_filter\")\n"
94 " is never applied by this function. It's assumed than any desired\n" 102 " is never applied by this function. It's assumed than any desired\n"
95 " filtering was already done when sources was set on the from_scope.\n" 103 " filtering was already done when sources was set on the from_scope.\n"
96 "\n" 104 "\n"
105 " The second form of the function allows to give a list of variables not\n"
106 " to forward. This is mostly useful when used in combination with \"*\".\n"
107 "\n"
97 "Examples\n" 108 "Examples\n"
98 "\n" 109 "\n"
99 " # This is a common action template. It would invoke a script with\n" 110 " # This is a common action template. It would invoke a script with\n"
100 " # some given parameters, and wants to use the various types of deps\n" 111 " # some given parameters, and wants to use the various types of deps\n"
101 " # and the visibility from the invoker if it's defined. It also injects\n" 112 " # and the visibility from the invoker if it's defined. It also injects\n"
102 " # an additional dependency to all targets.\n" 113 " # an additional dependency to all targets.\n"
103 " template(\"my_test\") {\n" 114 " template(\"my_test\") {\n"
104 " action(target_name) {\n" 115 " action(target_name) {\n"
105 " forward_variables_from(invoker, [ \"data_deps\", \"deps\",\n" 116 " forward_variables_from(invoker, [ \"data_deps\", \"deps\",\n"
106 " \"public_deps\", \"visibility\" " 117 " \"public_deps\", \"visibility\" "
107 "])\n" 118 "])\n"
108 " # Add our test code to the dependencies.\n" 119 " # Add our test code to the dependencies.\n"
109 " # \"deps\" may or may not be defined at this point.\n" 120 " # \"deps\" may or may not be defined at this point.\n"
110 " if (defined(deps)) {\n" 121 " if (defined(deps)) {\n"
111 " deps += [ \"//tools/doom_melon\" ]\n" 122 " deps += [ \"//tools/doom_melon\" ]\n"
112 " } else {\n" 123 " } else {\n"
113 " deps = [ \"//tools/doom_melon\" ]\n" 124 " deps = [ \"//tools/doom_melon\" ]\n"
114 " }\n" 125 " }\n"
115 " }\n" 126 " }\n"
116 " }\n" 127 " }\n"
117 "\n" 128 "\n"
118 " # This is a template around either a target whose type depends on a\n" 129 " # This is a template around either a target whose type depends on a\n"
119 " # global variable. It forwards all values from the invoker.\n" 130 " # global variable. It forwards all values from the invoker.\n"
120 " template(\"my_wrapper\") {\n" 131 " template(\"my_wrapper\") {\n"
121 " target(my_wrapper_target_type, target_name) {\n" 132 " target(my_wrapper_target_type, target_name) {\n"
122 " forward_variables_from(invoker, \"*\")\n" 133 " forward_variables_from(invoker, \"*\")\n"
123 " }\n" 134 " }\n"
124 " }\n"; 135 " }\n"
136 "\n"
137 " # This is a template around another template that uses a variable to\n"
138 " # initialize another variable and is only interested in that one.\n"
139 " template(\"my_ios_test_app\") {\n"
140 " ios_test_app(target_name) {\n"
141 " forward_variables_from(invoker, \"*\", [\"test_bundle_name\"])\n"
142 " if (!defined(extra_substitutions)) {\n"
143 " extra_substitutions = []\n"
144 " }\n"
145 " extra_substitutions += [ \"BUNDLE_ID_TEST_NAME=$test_bundle_name\" "
146 "]\n"
147 " }\n"
148 " }\n";
125 149
126 // This function takes a ListNode rather than a resolved vector of values 150 // This function takes a ListNode rather than a resolved vector of values
127 // both avoid copying the potentially-large source scope, and so the variables 151 // both avoid copying the potentially-large source scope, and so the variables
128 // in the source scope can be marked as used. 152 // in the source scope can be marked as used.
129 Value RunForwardVariablesFrom(Scope* scope, 153 Value RunForwardVariablesFrom(Scope* scope,
130 const FunctionCallNode* function, 154 const FunctionCallNode* function,
131 const ListNode* args_list, 155 const ListNode* args_list,
132 Err* err) { 156 Err* err) {
133 const std::vector<const ParseNode*>& args_vector = args_list->contents(); 157 const std::vector<const ParseNode*>& args_vector = args_list->contents();
134 if (args_vector.size() != 2) { 158 if (args_vector.size() != 2 && args_vector.size() != 3) {
tfarina 2016/01/25 12:15:25 just args_vector.size() != 3 right?
sdefresne 2016/01/25 15:28:30 No, the last argument is optional, so "forward_var
135 *err = Err(function, "Wrong number of arguments.", 159 *err = Err(function, "Wrong number of arguments.",
136 "Expecting exactly two."); 160 "Expecting exactly two.");
tfarina 2016/01/25 12:15:25 update this error message?
sdefresne 2016/01/25 15:28:30 Done, thank you.
137 return Value(); 161 return Value();
138 } 162 }
139 163
140 // Extract the scope identifier. This assumes the first parameter is an 164 // Extract the scope identifier. This assumes the first parameter is an
141 // identifier. It is difficult to write code where this is not the case, and 165 // identifier. It is difficult to write code where this is not the case, and
142 // this saves an expensive scope copy. If necessary, this could be expanded 166 // this saves an expensive scope copy. If necessary, this could be expanded
143 // to execute the ParseNode and get the value out if it's not an identifer. 167 // to execute the ParseNode and get the value out if it's not an identifer.
144 const IdentifierNode* identifier = args_vector[0]->AsIdentifier(); 168 const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
145 if (!identifier) { 169 if (!identifier) {
146 *err = Err(args_vector[0], "Expected an identifier for the scope."); 170 *err = Err(args_vector[0], "Expected an identifier for the scope.");
147 return Value(); 171 return Value();
148 } 172 }
149 173
150 // Extract the source scope. 174 // Extract the source scope.
151 Value* value = scope->GetMutableValue(identifier->value().value(), true); 175 Value* value = scope->GetMutableValue(identifier->value().value(), true);
152 if (!value) { 176 if (!value) {
153 *err = Err(identifier, "Undefined identifier."); 177 *err = Err(identifier, "Undefined identifier.");
154 return Value(); 178 return Value();
155 } 179 }
156 if (!value->VerifyTypeIs(Value::SCOPE, err)) 180 if (!value->VerifyTypeIs(Value::SCOPE, err))
157 return Value(); 181 return Value();
158 Scope* source = value->scope_value(); 182 Scope* source = value->scope_value();
159 183
184 // Extract the exclusion list if defined.
185 std::set<std::string> exclusion_set;
186 if (args_vector.size() == 3) {
187 Value exclusion_value = args_vector[2]->Execute(scope, err);
188 if (err->has_error())
189 return Value();
190
191 if (exclusion_value.type() != Value::LIST) {
192 *err = Err(exclusion_value, "Not a valid list of variables to exclude.",
193 "Expecting a list of strings.");
194 return Value();
195 }
196
197 for (const Value& cur : exclusion_value.list_value()) {
198 if (!cur.VerifyTypeIs(Value::STRING, err))
199 return Value();
200
201 exclusion_set.insert(exclusion_set.end(), cur.string_value());
202 }
203 }
204
160 // Extract the list. If all_values is not set, the what_value will be a list. 205 // Extract the list. If all_values is not set, the what_value will be a list.
161 Value what_value = args_vector[1]->Execute(scope, err); 206 Value what_value = args_vector[1]->Execute(scope, err);
162 if (err->has_error()) 207 if (err->has_error())
163 return Value(); 208 return Value();
164 if (what_value.type() == Value::STRING) { 209 if (what_value.type() == Value::STRING) {
165 if (what_value.string_value() == "*") { 210 if (what_value.string_value() == "*") {
166 ForwardAllValues(function, source, scope, err); 211 ForwardAllValues(function, source, scope, exclusion_set, err);
167 return Value(); 212 return Value();
168 } 213 }
169 } else { 214 } else {
170 if (what_value.type() == Value::LIST) { 215 if (what_value.type() == Value::LIST) {
171 ForwardValuesFromList(source, scope, what_value.list_value(), err); 216 ForwardValuesFromList(source, scope, what_value.list_value(),
217 exclusion_set, err);
172 return Value(); 218 return Value();
173 } 219 }
174 } 220 }
175 221
176 // Not the right type of argument. 222 // Not the right type of argument.
177 *err = Err(what_value, "Not a valid list of variables to copy.", 223 *err = Err(what_value, "Not a valid list of variables to copy.",
178 "Expecting either the string \"*\" or a list of strings."); 224 "Expecting either the string \"*\" or a list of strings.");
179 return Value(); 225 return Value();
180 } 226 }
181 227
182 } // namespace functions 228 } // namespace functions
OLDNEW
« no previous file with comments | « tools/gn/docs/reference.md ('k') | tools/gn/function_forward_variables_from_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698