gn: Add spelling suggestions for args.gn and --args.
Demo:
ERROR at build arg file (use "gn args <out_dir>" to edit):11:13: Build argument has no effect.
use_clang = true
^---
Did you mean "is_clang"?
The variable "use_clang" was set as a build argument
but never appeared in a declare_args() block in any buildfile.
To view all possible args, run "gn args --list <builddir>"
BUG=none
Review-Url: https://codereview.chromium.org/2552593002
Cr-Original-Commit-Position: refs/heads/master@{#436572}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: e591a5fb9a0015e7dcd71e566f2914233aaea35e
diff --git a/tools/gn/args.cc b/tools/gn/args.cc
index 54703e1..f81ffbe 100644
--- a/tools/gn/args.cc
+++ b/tools/gn/args.cc
@@ -6,6 +6,7 @@
#include "base/sys_info.h"
#include "build/build_config.h"
+#include "tools/gn/string_utils.h"
#include "tools/gn/variables.h"
const char kBuildArgs_Help[] =
@@ -219,19 +220,34 @@
bool Args::VerifyAllOverridesUsed(Err* err) const {
base::AutoLock lock(lock_);
- Scope::KeyValueMap all_overrides(all_overrides_);
+ Scope::KeyValueMap unused_overrides(all_overrides_);
for (const auto& map_pair : declared_arguments_per_toolchain_)
- RemoveDeclaredOverrides(map_pair.second, &all_overrides);
+ RemoveDeclaredOverrides(map_pair.second, &unused_overrides);
- if (all_overrides.empty())
+ if (unused_overrides.empty())
return true;
- *err = Err(
- all_overrides.begin()->second.origin(), "Build argument has no effect.",
- "The variable \"" + all_overrides.begin()->first.as_string() +
- "\" was set as a build argument\nbut never appeared in a " +
- "declare_args() block in any buildfile.\n\n"
- "To view possible args, run \"gn args --list <builddir>\"");
+ // Some assignments in args.gn had no effect. Show an error for the first
+ // unused assignment.
+ base::StringPiece name = unused_overrides.begin()->first;
+ const Value& value = unused_overrides.begin()->second;
+
+ std::string err_help(
+ "The variable \"" + name + "\" was set as a build argument\n"
+ "but never appeared in a declare_args() block in any buildfile.\n\n"
+ "To view all possible args, run \"gn args --list <builddir>\"");
+
+ // Use all declare_args for a spelling suggestion.
+ std::vector<base::StringPiece> candidates;
+ for (const auto& map_pair : declared_arguments_per_toolchain_) {
+ for (const auto& declared_arg : map_pair.second)
+ candidates.push_back(declared_arg.first);
+ }
+ base::StringPiece suggestion = SpellcheckString(name, candidates);
+ if (!suggestion.empty())
+ err_help = "Did you mean \"" + suggestion + "\"?\n\n" + err_help;
+
+ *err = Err(value.origin(), "Build argument has no effect.", err_help);
return false;
}