Index: tools/gn/functions.cc |
diff --git a/tools/gn/functions.cc b/tools/gn/functions.cc |
index 1d17d42988d9bfe4f8989e34cdb1bfb4d2787a91..23319e4b59a9cd50a4da595a853031babb1e3c14 100644 |
--- a/tools/gn/functions.cc |
+++ b/tools/gn/functions.cc |
@@ -638,6 +638,122 @@ Value RunImport(Scope* scope, |
return Value(); |
} |
+// not_needed ----------------------------------------------------------------- |
+ |
+const char kNotNeeded[] = "not_needed"; |
+const char kNotNeeded_HelpShort[] = |
+ "not_needed: Mark variables from scope as not needed."; |
+const char kNotNeeded_Help[] = |
+ R"(not_needed: Mark variables from scope as not needed. |
+ |
+ not_needed(variable_list_or_star, variable_to_ignore_list = []) |
+ not_needed(from_scope, variable_list_or_star, |
+ variable_to_ignore_list = []) |
+ |
+ Mark the variables in the current or given scope as not needed, which means |
+ you will not get an error about unused variables for these. The |
+ variable_to_ignore_list allows excluding variables from "all matches" if |
+ variable_list_or_star is "*". |
+ |
+Example |
+ |
+ not_needed("*", [ "config" ]) |
+ not_needed([ "data_deps", "deps" ]) |
+ not_needed(invoker, "*", [ "config" ]) |
+ not_needed(invoker, [ "data_deps", "deps" ]) |
+)"; |
+ |
+Value RunNotNeeded(Scope* scope, |
+ const FunctionCallNode* function, |
+ const ListNode* args_list, |
+ Err* err) { |
+ const auto& args_vector = args_list->contents(); |
+ if (args_vector.size() < 1 && args_vector.size() > 3) { |
+ *err = Err(function, "Wrong number of arguments.", |
+ "Expecting one, two or three arguments."); |
+ return Value(); |
+ } |
+ auto args_cur = args_vector.begin(); |
+ |
+ Value* value = nullptr; // Value to use, may point to result_value. |
+ Value result_value; // Storage for the "evaluate" case. |
+ const IdentifierNode* identifier = (*args_cur)->AsIdentifier(); |
+ if (identifier) { |
+ // Optimize the common case where the input scope is an identifier. This |
+ // prevents a copy of a potentially large Scope object. |
+ value = scope->GetMutableValue(identifier->value().value(), |
+ Scope::SEARCH_NESTED, true); |
+ if (!value) { |
+ *err = Err(identifier, "Undefined identifier."); |
+ return Value(); |
+ } |
+ } else { |
+ // Non-optimized case, just evaluate the argument. |
+ result_value = (*args_cur)->Execute(scope, err); |
+ if (err->has_error()) |
+ return Value(); |
+ value = &result_value; |
+ } |
+ args_cur++; |
+ |
+ // Extract the source scope if different from current one. |
+ Scope* source = scope; |
+ if (value->type() == Value::SCOPE) { |
+ source = value->scope_value(); |
+ result_value = (*args_cur)->Execute(scope, err); |
+ if (err->has_error()) |
+ return Value(); |
+ value = &result_value; |
+ args_cur++; |
+ } |
+ |
+ // Extract the exclusion list if defined. |
+ Value exclusion_value; |
+ std::set<std::string> exclusion_set; |
+ if (args_cur != args_vector.end()) { |
+ exclusion_value = (*args_cur)->Execute(source, err); |
+ if (err->has_error()) |
+ return Value(); |
+ |
+ if (exclusion_value.type() != Value::LIST) { |
+ *err = Err(exclusion_value, "Not a valid list of variables to exclude.", |
+ "Expecting a list of strings."); |
+ return Value(); |
+ } |
+ |
+ for (const Value& cur : exclusion_value.list_value()) { |
+ if (!cur.VerifyTypeIs(Value::STRING, err)) |
+ return Value(); |
+ |
+ exclusion_set.insert(cur.string_value()); |
+ } |
+ } |
+ |
+ if (value->type() == Value::STRING) { |
+ if (value->string_value() == "*") { |
+ source->MarkAllUsed(exclusion_set); |
+ return Value(); |
+ } |
+ } else if (value->type() == Value::LIST) { |
+ if (exclusion_value.type() != Value::NONE) { |
+ *err = Err(exclusion_value, "Not supported with a variable list.", |
+ "Exclusion list can only be used with the string \"*\"."); |
+ return Value(); |
+ } |
+ for (const Value& cur : value->list_value()) { |
+ if (!cur.VerifyTypeIs(Value::STRING, err)) |
+ return Value(); |
+ source->MarkUsed(cur.string_value()); |
+ } |
+ return Value(); |
+ } |
+ |
+ // Not the right type of argument. |
+ *err = Err(*value, "Not a valid list of variables.", |
+ "Expecting either the string \"*\" or a list of strings."); |
+ return Value(); |
+} |
+ |
// set_sources_assignment_filter ----------------------------------------------- |
const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter"; |
@@ -1040,6 +1156,7 @@ struct FunctionInfoInitializer { |
INSERT_FUNCTION(GetPathInfo, false) |
INSERT_FUNCTION(GetTargetOutputs, false) |
INSERT_FUNCTION(Import, false) |
+ INSERT_FUNCTION(NotNeeded, false) |
INSERT_FUNCTION(Pool, false) |
INSERT_FUNCTION(Print, false) |
INSERT_FUNCTION(ProcessFileTemplate, false) |