Display override values in GN args help.

Previously "gn args --list" would display the default value only. Now that we
have default_args in the .gn file, there are more places for the values to come
from and this is confusing (because the default value isn't necessarily what
you get).

This change makes --list display both the current value and the default value,
and the locations of the definitions for each. So when default_args apply, you
can see where the value is set. The same applies to args set in the args.gn
file for a build. It looks like this:

  is_debug
      Current value = false
        From //.gn:15
      Overridden from the default = true
        From //build/config/BUILDCONFIG.gn:154

The short mode --list --short has changed to list the current value rather than
the default.

Some obsolete help text was updated and some unused Args functions were removed.

BUG=684169,416139

Review-Url: https://codereview.chromium.org/2651023004
Cr-Original-Commit-Position: refs/heads/master@{#445883}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 9257ae440105ca90bd219517782cf55258fc830c
diff --git a/tools/gn/args.cc b/tools/gn/args.cc
index ceeb46b..3bb40b4 100644
--- a/tools/gn/args.cc
+++ b/tools/gn/args.cc
@@ -84,6 +84,21 @@
 
 }  // namespace
 
+Args::ValueWithOverride::ValueWithOverride()
+    : default_value(),
+      has_override(false),
+      override_value() {
+}
+
+Args::ValueWithOverride::ValueWithOverride(const Value& def_val)
+    : default_value(def_val),
+      has_override(false),
+      override_value() {
+}
+
+Args::ValueWithOverride::~ValueWithOverride() {
+}
+
 Args::Args() {
 }
 
@@ -124,11 +139,6 @@
   return &found->second;
 }
 
-Scope::KeyValueMap Args::GetAllOverrides() const {
-  base::AutoLock lock(lock_);
-  return all_overrides_;
-}
-
 void Args::SetupRootScope(Scope* dest,
                           const Scope::KeyValueMap& toolchain_overrides) const {
   base::AutoLock lock(lock_);
@@ -254,12 +264,27 @@
   return false;
 }
 
-void Args::MergeDeclaredArguments(Scope::KeyValueMap* dest) const {
+Args::ValueWithOverrideMap Args::GetAllArguments() const {
+  ValueWithOverrideMap result;
+
   base::AutoLock lock(lock_);
+
+  // Default values.
   for (const auto& map_pair : declared_arguments_per_toolchain_) {
     for (const auto& arg : map_pair.second)
-      (*dest)[arg.first] = arg.second;
+      result.insert(std::make_pair(arg.first, ValueWithOverride(arg.second)));
   }
+
+  // Merge in overrides.
+  for (const auto& over : overrides_) {
+    auto found = result.find(over.first);
+    if (found != result.end()) {
+      found->second.has_override = true;
+      found->second.override_value = over.second;
+    }
+  }
+
+  return result;
 }
 
 void Args::SetSystemVarsLocked(Scope* dest) const {
diff --git a/tools/gn/args.h b/tools/gn/args.h
index 9df5712..79fe93f 100644
--- a/tools/gn/args.h
+++ b/tools/gn/args.h
@@ -5,6 +5,8 @@
 #ifndef TOOLS_GN_ARGS_H_
 #define TOOLS_GN_ARGS_H_
 
+#include <map>
+
 #include "base/containers/hash_tables.h"
 #include "base/macros.h"
 #include "base/synchronization/lock.h"
@@ -23,6 +25,18 @@
 // the argument was unused.
 class Args {
  public:
+  struct ValueWithOverride {
+    ValueWithOverride();
+    ValueWithOverride(const Value& def_val);
+    ~ValueWithOverride();
+
+    Value default_value;  // Default value given in declare_args.
+
+    bool has_override;  // True indicates override_value is valid.
+    Value override_value;  // From .gn or the current build's "gn args".
+  };
+  using ValueWithOverrideMap = std::map<base::StringPiece, ValueWithOverride>;
+
   Args();
   Args(const Args& other);
   ~Args();
@@ -36,9 +50,6 @@
   // argument is set.
   const Value* GetArgOverride(const char* name) const;
 
-  // Gets all overrides set on the build.
-  Scope::KeyValueMap GetAllOverrides() const;
-
   // Sets up the root scope for a toolchain. This applies the default system
   // flags and saves the toolchain overrides so they can be applied to
   // declare_args blocks that appear when loading files in that toolchain.
@@ -62,10 +73,10 @@
   // arguments. If there are, this returns false and sets the error.
   bool VerifyAllOverridesUsed(Err* err) const;
 
-  // Adds all declared arguments to the given output list. If the values exist
-  // in the list already, their values will be overwriten, but other values
-  // already in the list will remain.
-  void MergeDeclaredArguments(Scope::KeyValueMap* dest) const;
+  // Returns information about all arguements, both defaults and overrides.
+  // This is used for the help system which is not performance critical. Use a
+  // map instead of a hash map so the arguements are sorted alphabetically.
+  ValueWithOverrideMap GetAllArguments() const;
 
  private:
   using ArgumentsPerToolchain =
diff --git a/tools/gn/command_args.cc b/tools/gn/command_args.cc
index 1b81135..98283f2 100644
--- a/tools/gn/command_args.cc
+++ b/tools/gn/command_args.cc
@@ -102,62 +102,91 @@
   }
 }
 
-void PrintArgHelp(const base::StringPiece& name, const Value& value) {
-  OutputString(name.as_string(), DECORATION_YELLOW);
-  OutputString("  Default = " + value.ToString(true) + "\n");
-
+// Prints the value and origin for a default value. Default values always list
+// an origin and if there is no origin, print a message about it being
+// internally set. Overrides can't be internally set so the location handling
+// is a bit different.
+//
+// The default value also contains the docstring.
+void PrintDefaultValueInfo(base::StringPiece name, const Value& value) {
+  OutputString(value.ToString(true) + "\n");
   if (value.origin()) {
     std::string location, comment;
     GetContextForValue(value, &location, &comment);
-    OutputString("    " + location + "\n" + comment);
+    OutputString("      From " + location + "\n");
+    if (!comment.empty())
+      OutputString("\n" + comment);
   } else {
-    OutputString("    (Internally set; try `gn help " + name.as_string() +
+    OutputString("      (Internally set; try `gn help " + name.as_string() +
                  "`.)\n");
   }
 }
 
+// Override value is null if there is no override.
+void PrintArgHelp(const base::StringPiece& name,
+                  const Args::ValueWithOverride& val) {
+  OutputString(name.as_string(), DECORATION_YELLOW);
+  OutputString("\n");
+
+  if (val.has_override) {
+    // Override present, print both it and the default.
+    OutputString("    Current value = " + val.override_value.ToString(true) +
+                 "\n");
+    if (val.override_value.origin()) {
+      std::string location, comment;
+      GetContextForValue(val.override_value, &location, &comment);
+      OutputString("      From " + location + "\n");
+    }
+    OutputString("    Overridden from the default = ");
+    PrintDefaultValueInfo(name, val.default_value);
+  } else {
+    // No override.
+    OutputString("    Current value (from the default) = ");
+    PrintDefaultValueInfo(name, val.default_value);
+  }
+}
+
 int ListArgs(const std::string& build_dir) {
   Setup* setup = new Setup;
   if (!setup->DoSetup(build_dir, false) || !setup->Run())
     return 1;
 
-  Scope::KeyValueMap build_args;
-  setup->build_settings().build_args().MergeDeclaredArguments(&build_args);
-
-  // Find all of the arguments we care about. Use a regular map so they're
-  // sorted nicely when we write them out.
-  std::map<base::StringPiece, Value> sorted_args;
+  Args::ValueWithOverrideMap args =
+      setup->build_settings().build_args().GetAllArguments();
   std::string list_value =
       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kSwitchList);
-  if (list_value.empty()) {
-    // List all values.
-    for (const auto& arg : build_args)
-      sorted_args.insert(arg);
-  } else {
+  if (!list_value.empty()) {
     // List just the one specified as the parameter to --list.
-    Scope::KeyValueMap::const_iterator found_arg = build_args.find(list_value);
-    if (found_arg == build_args.end()) {
+    auto found = args.find(list_value);
+    if (found == args.end()) {
       Err(Location(), "Unknown build argument.",
           "You asked for \"" + list_value + "\" which I didn't find in any "
           "build file\nassociated with this build.").PrintToStdout();
       return 1;
     }
-    sorted_args.insert(*found_arg);
+
+    // Delete everything from the map except the one requested.
+    Args::ValueWithOverrideMap::value_type preserved = *found;
+    args.clear();
+    args.insert(preserved);
   }
 
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchShort)) {
-    // Short key=value output.
-    for (const auto& arg : sorted_args) {
+    // Short <key>=<current_value> output.
+    for (const auto& arg : args) {
       OutputString(arg.first.as_string());
       OutputString(" = ");
-      OutputString(arg.second.ToString(true));
+      if (arg.second.has_override)
+        OutputString(arg.second.override_value.ToString(true));
+      else
+        OutputString(arg.second.default_value.ToString(true));
       OutputString("\n");
     }
     return 0;
   }
 
   // Long output.
-  for (const auto& arg : sorted_args) {
+  for (const auto& arg : args) {
     PrintArgHelp(arg.first, arg.second);
     OutputString("\n");
   }
@@ -199,9 +228,9 @@
 #else  // POSIX
 
 bool RunEditor(const base::FilePath& file_to_edit) {
-  const char* editor_ptr = getenv("VISUAL");
+  const char* editor_ptr = getenv("GN_EDITOR");
   if (!editor_ptr)
-    editor_ptr = getenv("GN_EDITOR");
+    editor_ptr = getenv("VISUAL");
   if (!editor_ptr)
     editor_ptr = getenv("EDITOR");
   if (!editor_ptr)
@@ -284,15 +313,19 @@
   build arguments work.
 
 Usage
+
   gn args <out_dir>
-      Open the arguments for the given build directory in an editor (as
-      specified by the EDITOR environment variable). If the given build
-      directory doesn't exist, it will be created and an empty args file will
-      be opened in the editor. You would type something like this into that
-      file:
+      Open the arguments for the given build directory in an editor. If the
+      given build directory doesn't exist, it will be created and an empty args
+      file will be opened in the editor. You would type something like this
+      into that file:
           enable_doom_melon=false
           os="android"
 
+      To find your editor on Posix, GN will search the environment variables in
+      order: GN_EDITOR, VISUAL, and EDITOR. On Windows GN will open the command
+      associated with .txt files.
+
       Note: you can edit the build args manually by editing the file "args.gn"
       in the build directory and then running "gn gen <out_dir>".
 
@@ -301,20 +334,12 @@
       an exact_arg is specified for the list flag, just that one build
       argument.
 
-      The output will list the declaration location, default value, and comment
-      preceeding the declaration. If --short is specified, only the names and
-      values will be printed.
+      The output will list the declaration location, current value for the
+      build, default value (if different than the current value), and comment
+      preceeding the declaration.
 
-      If the out_dir is specified, the build configuration will be taken from
-      that build directory. The reason this is needed is that the definition of
-      some arguments is dependent on the build configuration, so setting some
-      values might add, remove, or change the default values for other
-      arguments. Specifying your exact configuration allows the proper
-      arguments to be displayed.
-
-      Instead of specifying the out_dir, you can also use the command-line flag
-      to specify the build configuration:
-        --args=<exact list of args to use>
+      If --short is specified, only the names and current values will be
+      printed.
 
 Examples