Revert of [GN] Add JSON project writer (patchset #11 id:200001 of https://codereview.chromium.org/2064533002/ )

Reason for revert:
Broke Win8 GYP (dbg) builder:
[822/12249] LINK_EMBED gn.exe
FAILED: gn.exe gn.exe.pdb
E:\b\depot_tools\python276_bin\python.exe gyp-win-tool link-with-manifests environment.x86 True gn.exe "E:\b\depot_tools\python276_bin\python.exe gyp-win-tool link-wrapper environment.x86 False link.exe /nologo /OUT:gn.exe @gn.exe.rsp" 1 mt.exe rc.exe "obj\tools\gn\gn.gn.exe.intermediate.manifest" obj\tools\gn\gn.gn.exe.generated.manifest ..\..\build\win\compatibility.manifest
gn_lib.lib(gn_lib.command_desc.obj) : error LNK2019: unresolved external symbol "public: static class std::unique_ptr<class base::DictionaryValue,struct std::default_delete<class base::DictionaryValue> > __cdecl DescBuilder::DescriptionForTarget(class Target const *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,bool,bool,bool)" (?DescriptionForTarget@DescBuilder@@SA?AV?$unique_ptr@VDictionaryValue@base@@U?$default_delete@VDictionaryValue@base@@@std@@@std@@PBVTarget@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@_N22@Z) referenced in function "bool __cdecl commands::`anonymous namespace'::PrintTarget(class Target const *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,bool,bool,bool,bool)" (?PrintTarget@?A0x51180473@commands@@YA_NPBVTarget@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_N222@Z)

gn_lib.lib(gn_lib.command_desc.obj) : error LNK2019: unresolved external symbol "public: static class std::unique_ptr<class base::DictionaryValue,struct std::default_delete<class base::DictionaryValue> > __cdecl DescBuilder::DescriptionForConfig(class Config const *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?DescriptionForConfig@DescBuilder@@SA?AV?$unique_ptr@VDictionaryValue@base@@U?$default_delete@VDictionaryValue@base@@@std@@@std@@PBVConfig@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@@Z) referenced in function "bool __cdecl commands::`anonymous namespace'::PrintConfig(class Config const *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,bool)" (?PrintConfig@?A0x51180473@commands@@YA_NPBVConfig@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_N@Z)

gn_lib.lib(gn_lib.command_gen.obj) : error LNK2019: unresolved external symbol "public: static bool __cdecl JSONProjectWriter::RunAndWriteFiles(class BuildSettings const *,class Builder const *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,bool,class Err *)" (?RunAndWriteFiles@JSONProjectWriter@@SA_NPBVBuildSettings@@PBVBuilder@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@222_NPAVErr@@@Z) referenced in function "bool __cdecl commands::`anonymous namespace'::RunIdeWriter(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class BuildSettings const *,class Builder *,class Err *)" (?RunIdeWriter@?A0x1eff038c@commands@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PBVBuildSettings@@PAVBuilder@@PAVErr@@@Z)

gn.exe : fatal error LNK1120: 3 unresolved externals

Traceback (most recent call last):

  File "gyp-win-tool", line 323, in <module>

    sys.exit(main(sys.argv[1:]))

  File "gyp-win-tool", line 29, in main

    exit_code = executor.Dispatch(args)

  File "gyp-win-tool", line 71, in Dispatch

    return getattr(self, method)(*args[1:])

  File "gyp-win-tool", line 179, in ExecLinkWithManifests

    subprocess.check_call(ldcmd + add_to_ld)

  File "E:\b\depot_tools\python276_bin\lib\subprocess.py", line 540, in check_call

    raise CalledProcessError(retcode, cmd)

subprocess.CalledProcessError: Command 'E:\b\depot_tools\python276_bin\python.exe gyp-win-tool link-wrapper environment.x86 False link.exe /nologo /OUT:gn.exe @gn.exe.rsp gn.exe.manifest.res' returned non-zero exit status 1120

Original issue's description:
> [GN] Add JSON project writer
>
> Output is a JSON file containing information about targets. The generator
> can also optionally invoke a python script on generated file.
>
> Example:
> gn gen --ide=json ./out-json --json-ide-script=//scripts/custom-ide-generator.py \
>     --ison-ide-script-args="additional script arguments"
>
> Also implements --format=json for gn desc as described in https://bugs.chromium.org/p/chromium/issues/detail?id=620132
>
> BUG=
>
> Committed: https://crrev.com/d2edeb9a743ad5a2046e655997277d3bb630db03
> Cr-Commit-Position: refs/heads/master@{#406064}

TBR=brettw@chromium.org,matej.knopp@gmail.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=

Review-Url: https://codereview.chromium.org/2160533004
Cr-Original-Commit-Position: refs/heads/master@{#406074}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 5a1b4b1725ec0685c99741620752e9f65db17d90
diff --git a/tools/gn/BUILD.gn b/tools/gn/BUILD.gn
index b77d2af..510c178 100644
--- a/tools/gn/BUILD.gn
+++ b/tools/gn/BUILD.gn
@@ -58,8 +58,6 @@
     "create_bundle_target_generator.h",
     "deps_iterator.cc",
     "deps_iterator.h",
-    "desc_builder.cc",
-    "desc_builder.h",
     "eclipse_writer.cc",
     "eclipse_writer.h",
     "err.cc",
@@ -103,8 +101,6 @@
     "input_file_manager.h",
     "item.cc",
     "item.h",
-    "json_project_writer.cc",
-    "json_project_writer.h",
     "label.cc",
     "label.h",
     "label_pattern.cc",
diff --git a/tools/gn/command_desc.cc b/tools/gn/command_desc.cc
index 72525e9..ea1bab3 100644
--- a/tools/gn/command_desc.cc
+++ b/tools/gn/command_desc.cc
@@ -9,14 +9,18 @@
 #include <sstream>
 
 #include "base/command_line.h"
-#include "base/json/json_writer.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_util.h"
+#include "build/build_config.h"
 #include "tools/gn/commands.h"
 #include "tools/gn/config.h"
-#include "tools/gn/desc_builder.h"
+#include "tools/gn/config_values_extractors.h"
+#include "tools/gn/deps_iterator.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/item.h"
+#include "tools/gn/label.h"
+#include "tools/gn/runtime_deps.h"
 #include "tools/gn/setup.h"
 #include "tools/gn/standard_out.h"
+#include "tools/gn/substitution_writer.h"
 #include "tools/gn/switches.h"
 #include "tools/gn/target.h"
 #include "tools/gn/variables.h"
@@ -28,258 +32,725 @@
 // Desc-specific command line switches.
 const char kBlame[] = "blame";
 const char kTree[] = "tree";
-const char kAll[] = "all";
 
-// Prints value with specified indentation level
-void PrintValue(const base::Value* value, int indentLevel) {
-  std::string indent(indentLevel * 2, ' ');
-  const base::ListValue* list_value = nullptr;
-  const base::DictionaryValue* dict_value = nullptr;
-  std::string string_value;
-  bool bool_value = false;
-  if (value->GetAsList(&list_value)) {
-    for (const auto& v : *list_value) {
-      PrintValue(v.get(), indentLevel);
+// Prints the given directory in a nice way for the user to view.
+std::string FormatSourceDir(const SourceDir& dir) {
+#if defined(OS_WIN)
+  // On Windows we fix up system absolute paths to look like native ones.
+  // Internally, they'll look like "/C:\foo\bar/"
+  if (dir.is_system_absolute()) {
+    std::string buf = dir.value();
+    if (buf.size() > 3 && buf[2] == ':') {
+      buf.erase(buf.begin());  // Erase beginning slash.
+      return buf;
     }
-  } else if (value->GetAsString(&string_value)) {
-    OutputString(indent);
-    OutputString(string_value);
-    OutputString("\n");
-  } else if (value->GetAsBoolean(&bool_value)) {
-    OutputString(indent);
-    OutputString(bool_value ? "true" : "false");
-    OutputString("\n");
-  } else if (value->GetAsDictionary(&dict_value)) {
-    base::DictionaryValue::Iterator iter(*dict_value);
-    while (!iter.IsAtEnd()) {
-      OutputString(indent + iter.key() + "\n");
-      PrintValue(&iter.value(), indentLevel + 1);
-      iter.Advance();
+  }
+#endif
+  return dir.value();
+}
+
+void RecursiveCollectChildDeps(const Target* target,
+                               std::set<const Target*>* result);
+
+void RecursiveCollectDeps(const Target* target,
+                          std::set<const Target*>* result) {
+  if (result->find(target) != result->end())
+    return;  // Already did this target.
+  result->insert(target);
+
+  RecursiveCollectChildDeps(target, result);
+}
+
+void RecursiveCollectChildDeps(const Target* target,
+                               std::set<const Target*>* result) {
+  for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
+    RecursiveCollectDeps(pair.ptr, result);
+}
+
+// Prints dependencies of the given target (not the target itself). If the
+// set is non-null, new targets encountered will be added to the set, and if
+// a dependency is in the set already, it will not be recused into. When the
+// set is null, all dependencies will be printed.
+void RecursivePrintDeps(const Target* target,
+                        const Label& default_toolchain,
+                        std::set<const Target*>* seen_targets,
+                        int indent_level) {
+  // Combine all deps into one sorted list.
+  std::vector<LabelTargetPair> sorted_deps;
+  for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
+    sorted_deps.push_back(pair);
+  std::sort(sorted_deps.begin(), sorted_deps.end(),
+            LabelPtrLabelLess<Target>());
+
+  std::string indent(indent_level * 2, ' ');
+  for (const auto& pair : sorted_deps) {
+    const Target* cur_dep = pair.ptr;
+
+    OutputString(indent +
+        cur_dep->label().GetUserVisibleName(default_toolchain));
+    bool print_children = true;
+    if (seen_targets) {
+      if (seen_targets->find(cur_dep) == seen_targets->end()) {
+        // New target, mark it visited.
+        seen_targets->insert(cur_dep);
+      } else {
+        // Already seen.
+        print_children = false;
+        // Only print "..." if something is actually elided, which means that
+        // the current target has children.
+        if (!cur_dep->public_deps().empty() ||
+            !cur_dep->private_deps().empty() ||
+            !cur_dep->data_deps().empty())
+          OutputString("...");
+      }
     }
-  } else if (value->IsType(base::Value::TYPE_NULL)) {
-    OutputString(indent + "<null>\n");
+
+    OutputString("\n");
+    if (print_children) {
+      RecursivePrintDeps(cur_dep, default_toolchain, seen_targets,
+                         indent_level + 1);
+    }
   }
 }
 
-// Default handler for property
-void DefaultHandler(const std::string& name, const base::Value* value) {
-  OutputString("\n");
-  OutputString(name);
-  OutputString("\n");
-  PrintValue(value, 1);
-}
+void PrintDeps(const Target* target, bool display_header) {
+  const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
+  Label toolchain_label = target->label().GetToolchainLabel();
 
-// Specific handler for properties that need different treatment
+  // Tree mode is separate.
+  if (cmdline->HasSwitch(kTree)) {
+    if (display_header)
+      OutputString("\nDependency tree\n");
 
-// Prints label and property value on one line, capitalizing the label.
-void LabelHandler(std::string name, const base::Value* value) {
-  name[0] = base::ToUpperASCII(name[0]);
-  std::string string_value;
-  if (value->GetAsString(&string_value)) {
-    OutputString(name + ": ", DECORATION_YELLOW);
-    OutputString(string_value + "\n");
-  }
-}
-
-void VisibilityHandler(const std::string& name, const base::Value* value) {
-  const base::ListValue* list;
-  if (value->GetAsList(&list)) {
-    if (list->empty()) {
-      base::StringValue str("(no visibility)");
-      DefaultHandler(name, &str);
+    if (cmdline->HasSwitch("all")) {
+      // Show all tree deps with no eliding.
+      RecursivePrintDeps(target, toolchain_label, nullptr, 1);
     } else {
-      DefaultHandler(name, value);
+      // Don't recurse into duplicates.
+      std::set<const Target*> seen_targets;
+      RecursivePrintDeps(target, toolchain_label, &seen_targets, 1);
     }
+    return;
   }
-}
 
-void PublicHandler(const std::string& name, const base::Value* value) {
-  std::string p;
-  if (value->GetAsString(&p)) {
-    if (p == "*") {
-      base::StringValue str("[All headers listed in the sources are public.]");
-      DefaultHandler(name, &str);
-      return;
-    }
-  }
-  DefaultHandler(name, value);
-}
+  // Collect the deps to display.
+  if (cmdline->HasSwitch("all")) {
+    // Show all dependencies.
+    if (display_header)
+      OutputString("\nAll recursive dependencies\n");
 
-void ConfigsHandler(const std::string& name, const base::Value* value) {
-  bool tree = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree);
-  if (tree)
-    DefaultHandler(name + " tree (in order applying)", value);
-  else
-    DefaultHandler(name + " (in order applying, try also --tree)", value);
-}
-
-void DepsHandler(const std::string& name, const base::Value* value) {
-  bool tree = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree);
-  bool all = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree);
-  if (tree) {
-    DefaultHandler("Dependency tree", value);
+    std::set<const Target*> all_deps;
+    RecursiveCollectChildDeps(target, &all_deps);
+    FilterAndPrintTargetSet(display_header, all_deps);
   } else {
-    if (!all) {
-      DefaultHandler(
-          "Direct dependencies "
-          "(try also \"--all\", \"--tree\", or even \"--all --tree\")",
-          value);
-    } else {
-      DefaultHandler("All recursive dependencies", value);
+    std::vector<const Target*> deps;
+    // Show direct dependencies only.
+    if (display_header) {
+      OutputString(
+          "\nDirect dependencies "
+          "(try also \"--all\", \"--tree\", or even \"--all --tree\")\n");
     }
+    for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
+      deps.push_back(pair.ptr);
+    std::sort(deps.begin(), deps.end());
+    FilterAndPrintTargets(display_header, &deps);
   }
 }
 
-// Outputs need special processing when output patterns are present.
-void ProcessOutputs(base::DictionaryValue* target) {
-  base::ListValue* patterns = nullptr;
-  base::ListValue* outputs = nullptr;
-  target->GetList("output_patterns", &patterns);
-  target->GetList(variables::kOutputs, &outputs);
+// libs and lib_dirs are special in that they're inherited. We don't currently
+// implement a blame feature for this since the bottom-up inheritance makes
+// this difficult.
+void PrintLibDirs(const Target* target, bool display_header) {
+  const OrderedSet<SourceDir>& lib_dirs = target->all_lib_dirs();
+  if (lib_dirs.empty())
+    return;
 
-  if (outputs || patterns) {
+  if (display_header)
+    OutputString("\nlib_dirs\n");
+
+  for (size_t i = 0; i < lib_dirs.size(); i++)
+    OutputString("    " + FormatSourceDir(lib_dirs[i]) + "\n");
+}
+
+void PrintLibs(const Target* target, bool display_header) {
+  const OrderedSet<LibFile>& libs = target->all_libs();
+  if (libs.empty())
+    return;
+
+  if (display_header)
+    OutputString("\nlibs\n");
+
+  for (size_t i = 0; i < libs.size(); i++)
+    OutputString("    " + libs[i].value() + "\n");
+}
+
+void PrintPublic(const Target* target, bool display_header) {
+  if (display_header)
+    OutputString("\npublic\n");
+
+  if (target->all_headers_public()) {
+    OutputString("  [All headers listed in the sources are public.]\n");
+    return;
+  }
+
+  Target::FileList public_headers = target->public_headers();
+  std::sort(public_headers.begin(), public_headers.end());
+  for (const auto& hdr : public_headers)
+    OutputString("  " + hdr.value() + "\n");
+}
+
+void PrintCheckIncludes(const Target* target, bool display_header) {
+  if (display_header)
+    OutputString("\ncheck_includes\n");
+
+  if (target->check_includes())
+    OutputString("  true\n");
+  else
+    OutputString("  false\n");
+}
+
+void PrintAllowCircularIncludesFrom(const Target* target, bool display_header) {
+  if (display_header)
+    OutputString("\nallow_circular_includes_from\n");
+
+  Label toolchain_label = target->label().GetToolchainLabel();
+  for (const auto& cur : target->allow_circular_includes_from())
+    OutputString("  " + cur.GetUserVisibleName(toolchain_label) + "\n");
+}
+
+void PrintVisibility(const Target* target, bool display_header) {
+  if (display_header)
+    OutputString("\nvisibility\n");
+
+  OutputString(target->visibility().Describe(2, false));
+}
+
+void PrintTestonly(const Target* target, bool display_header) {
+  if (display_header)
+    OutputString("\ntestonly\n");
+
+  if (target->testonly())
+    OutputString("  true\n");
+  else
+    OutputString("  false\n");
+}
+
+// Recursively prints subconfigs of a config.
+void PrintSubConfigs(const Config* config, int indent_level) {
+  if (config->configs().empty())
+    return;
+
+  std::string indent(indent_level * 2, ' ');
+  Label toolchain_label = config->label().GetToolchainLabel();
+  for (const auto& pair : config->configs()) {
+    OutputString(
+        indent + pair.label.GetUserVisibleName(toolchain_label) + "\n");
+    PrintSubConfigs(pair.ptr, indent_level + 1);
+  }
+}
+
+// This allows configs stored as either std::vector<LabelConfigPair> or
+// UniqueVector<LabelConfigPair> to be printed.
+template <class VectorType>
+void PrintConfigsVector(const Item* item,
+                        const VectorType& configs,
+                        const std::string& heading,
+                        bool display_header) {
+  if (configs.empty())
+    return;
+
+  bool tree = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree);
+
+  // Don't sort since the order determines how things are processed.
+  if (display_header) {
+    if (tree)
+      OutputString("\n" + heading + " tree (in order applying)\n");
+    else
+      OutputString("\n" + heading + " (in order applying, try also --tree)\n");
+  }
+
+  Label toolchain_label = item->label().GetToolchainLabel();
+  for (const auto& config : configs) {
+    OutputString("  " + config.label.GetUserVisibleName(toolchain_label) +
+                 "\n");
+    if (tree)
+      PrintSubConfigs(config.ptr, 2);  // 2 = start with double-indent.
+  }
+}
+
+void PrintConfigs(const Target* target, bool display_header) {
+  PrintConfigsVector(target, target->configs().vector(), "configs",
+                     display_header);
+}
+
+void PrintConfigs(const Config* config, bool display_header) {
+  PrintConfigsVector(config, config->configs().vector(), "configs",
+                     display_header);
+}
+
+void PrintPublicConfigs(const Target* target, bool display_header) {
+  PrintConfigsVector(target, target->public_configs(),
+                     "public_configs", display_header);
+}
+
+void PrintAllDependentConfigs(const Target* target, bool display_header) {
+  PrintConfigsVector(target, target->all_dependent_configs(),
+                     "all_dependent_configs", display_header);
+}
+
+void PrintFileList(const Target::FileList& files,
+                   const std::string& header,
+                   bool indent_extra,
+                   bool display_header) {
+  if (files.empty())
+    return;
+
+  if (display_header)
+    OutputString("\n" + header + "\n");
+
+  std::string indent = indent_extra ? "    " : "  ";
+
+  Target::FileList sorted = files;
+  std::sort(sorted.begin(), sorted.end());
+  for (const auto& elem : sorted)
+    OutputString(indent + elem.value() + "\n");
+}
+
+void PrintSources(const Target* target, bool display_header) {
+  PrintFileList(target->sources(), "sources", false, display_header);
+}
+
+void PrintInputs(const Target* target, bool display_header) {
+  PrintFileList(target->inputs(), "inputs", false, display_header);
+}
+
+void PrintOutputs(const Target* target, bool display_header) {
+  if (display_header)
     OutputString("\noutputs\n");
-    int indent = 1;
-    if (patterns) {
-      OutputString("  Output patterns\n");
-      indent = 2;
-      PrintValue(patterns, indent);
+
+  if (target->output_type() == Target::ACTION) {
+    // Action, print out outputs, don't apply sources to it.
+    for (const auto& elem : target->action_values().outputs().list()) {
+      OutputString("  " + elem.AsString() + "\n");
+    }
+  } else if (target->output_type() == Target::CREATE_BUNDLE) {
+    std::vector<SourceFile> output_files;
+    target->bundle_data().GetOutputsAsSourceFiles(target->settings(),
+                                                  &output_files);
+    PrintFileList(output_files, std::string(), true, false);
+  } else if (target->output_type() == Target::ACTION_FOREACH) {
+    const SubstitutionList& outputs = target->action_values().outputs();
+    if (!outputs.required_types().empty()) {
+      // Display the pattern and resolved pattern separately, since there are
+      // subtitutions used.
+      OutputString("  Output pattern\n");
+      for (const auto& elem : outputs.list())
+        OutputString("    " + elem.AsString() + "\n");
+
+      // Now display what that resolves to given the sources.
       OutputString("\n  Resolved output file list\n");
     }
-    if (outputs)
-      PrintValue(outputs, indent);
 
-    target->Remove("output_patterns", nullptr);
-    target->Remove(variables::kOutputs, nullptr);
+    // Resolved output list.
+    std::vector<SourceFile> output_files;
+    SubstitutionWriter::ApplyListToSources(target->settings(), outputs,
+                                           target->sources(), &output_files);
+    PrintFileList(output_files, std::string(), true, false);
+  } else {
+    DCHECK(target->IsBinary());
+    const Tool* tool = target->toolchain()->GetToolForTargetFinalOutput(target);
+
+    std::vector<OutputFile> output_files;
+    SubstitutionWriter::ApplyListToLinkerAsOutputFile(
+        target, tool, tool->outputs(), &output_files);
+
+    std::vector<SourceFile> output_files_as_source_file;
+    for (const OutputFile& output_file : output_files) {
+      output_files_as_source_file.push_back(
+          output_file.AsSourceFile(target->settings()->build_settings()));
+    }
+
+    PrintFileList(output_files_as_source_file, std::string(), true, false);
   }
 }
 
+void PrintScript(const Target* target, bool display_header) {
+  if (display_header)
+    OutputString("\nscript\n");
+  OutputString("  " + target->action_values().script().value() + "\n");
+}
+
+void PrintArgs(const Target* target, bool display_header) {
+  if (display_header)
+    OutputString("\nargs\n");
+  for (const auto& elem : target->action_values().args().list()) {
+    OutputString("  " + elem.AsString() + "\n");
+  }
+}
+
+void PrintDepfile(const Target* target, bool display_header) {
+  if (target->action_values().depfile().empty())
+    return;
+  if (display_header)
+    OutputString("\ndepfile\n");
+  OutputString("  " + target->action_values().depfile().AsString() + "\n");
+}
+
+// Attribute the origin for attributing from where a target came from. Does
+// nothing if the input is null or it does not have a location.
+void OutputSourceOfDep(const ParseNode* origin, std::ostream& out) {
+  if (!origin)
+    return;
+  Location location = origin->GetRange().begin();
+  out << "       (Added by " + location.file()->name().value() << ":"
+      << location.line_number() << ")\n";
+}
+
+// Templatized writer for writing out different config value types.
+template<typename T> struct DescValueWriter {};
+template<> struct DescValueWriter<std::string> {
+  void operator()(const std::string& str, std::ostream& out) const {
+    out << "    " << str << "\n";
+  }
+};
+
+template<> struct DescValueWriter<SourceDir> {
+  void operator()(const SourceDir& dir, std::ostream& out) const {
+    out << "    " << FormatSourceDir(dir) << "\n";
+  }
+};
+
+template<> struct DescValueWriter<LibFile> {
+  void operator()(const LibFile& lib, std::ostream& out) const {
+    if (lib.is_source_file())
+      out << "    " << lib.source_file().value() << "\n";
+    else
+      out << "    " << lib.value() << "\n";
+  }
+};
+
+// Writes a given config value type to the string, optionally with attribution.
+// This should match RecursiveTargetConfigToStream in the order it traverses.
+template<typename T> void OutputRecursiveTargetConfig(
+    const Target* target,
+    const char* header_name,
+    const std::vector<T>& (ConfigValues::* getter)() const) {
+  bool display_blame =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(kBlame);
+
+  DescValueWriter<T> writer;
+  std::ostringstream out;
+
+  for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
+    if ((iter.cur().*getter)().empty())
+      continue;
+
+    // Optional blame sub-head.
+    if (display_blame) {
+      const Config* config = iter.GetCurrentConfig();
+      if (config) {
+        // Source of this value is a config.
+        out << "  From " << config->label().GetUserVisibleName(false) << "\n";
+        OutputSourceOfDep(iter.origin(), out);
+      } else {
+        // Source of this value is the target itself.
+        out << "  From " << target->label().GetUserVisibleName(false) << "\n";
+      }
+    }
+
+    // Actual values.
+    ConfigValuesToStream(iter.cur(), getter, writer, out);
+  }
+
+  std::string out_str = out.str();
+  if (!out_str.empty()) {
+    if (header_name)
+      OutputString("\n" + std::string(header_name) + "\n");
+    OutputString(out_str);
+  }
+}
+
+template<typename T> void OutputConfigValueArray(
+    const ConfigValues& values,
+    const char* header_name,
+    const std::vector<T>& (ConfigValues::* getter)() const) {
+  std::ostringstream out;
+
+  DescValueWriter<T> writer;
+  for (const T& cur : (values.*getter)())
+    writer(cur, out);
+
+  std::string out_str = out.str();
+  if (!out_str.empty()) {
+    if (header_name)
+      OutputString("\n" + std::string(header_name) + "\n");
+    OutputString(out_str);
+  }
+}
+
+void PrintRuntimeDeps(const Target* target) {
+  bool display_blame =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(kBlame);
+  Label toolchain = target->label().GetToolchainLabel();
+
+  const Target* previous_from = NULL;
+  for (const auto& pair : ComputeRuntimeDeps(target)) {
+    if (display_blame) {
+      // Generally a target's runtime deps will be listed sequentially, so
+      // group them and don't duplicate the "from" label for two in a row.
+      if (previous_from == pair.second) {
+        OutputString("  ");  // Just indent.
+      } else {
+        previous_from = pair.second;
+        OutputString("From ");
+        OutputString(pair.second->label().GetUserVisibleName(toolchain));
+        OutputString("\n  ");  // Make the file name indented.
+      }
+    }
+    OutputString(pair.first.value());
+    OutputString("\n");
+  }
+}
+
+// If "what" is empty, prints all PCH info. If "what" is nonempty, prints only
+// the things that match (if any). Returns true if anything was printed.
+bool PrintPrecompiledHeaderInfo(const ConfigValues& values,
+                                const std::string& what,
+                                bool display_headers) {
+  bool found_match = false;
+  if (what == variables::kPrecompiledHeader || what.empty()) {
+    if (!values.precompiled_header().empty()) {
+      if (display_headers)
+        OutputString("\nprecompiled_header\n");
+      OutputString(values.precompiled_header() + "\n");
+    }
+    found_match = true;
+  }
+  if (what == variables::kPrecompiledSource || what.empty()) {
+    if (!values.precompiled_source().is_null()) {
+      if (display_headers)
+        OutputString("\nprecompiled_source\n");
+      OutputString(values.precompiled_source().value() + "\n");
+    }
+    found_match = true;
+  }
+  return found_match;
+}
+
 bool PrintTarget(const Target* target,
                  const std::string& what,
-                 bool single_target,
-                 bool all,
-                 bool tree,
-                 bool blame) {
-  std::unique_ptr<base::DictionaryValue> dict =
-      DescBuilder::DescriptionForTarget(target, what, all, tree, blame);
-  if (!what.empty() && dict->empty()) {
+                 bool display_target_header) {
+  if (display_target_header) {
+    OutputString("Target: ", DECORATION_YELLOW);
+    OutputString(target->label().GetUserVisibleName(false) + "\n");
+    OutputString("Type: ", DECORATION_YELLOW);
+    OutputString(std::string(
+        Target::GetStringForOutputType(target->output_type())) + "\n");
+    OutputString("Toolchain: ", DECORATION_YELLOW);
+    OutputString(
+        target->label().GetToolchainLabel().GetUserVisibleName(false) + "\n");
+  }
+
+  // Display headers when outputting everything.
+  bool display_headers = what.empty();
+  bool is_binary_output = target->IsBinary();
+
+  bool found_match = false;
+
+  // General target meta variables.
+  if (what.empty() || what == variables::kVisibility) {
+    PrintVisibility(target, display_headers);
+    found_match = true;
+  }
+  if (what.empty() || what == variables::kTestonly) {
+    PrintTestonly(target, display_headers);
+    found_match  = true;
+  }
+
+  // Binary target meta variables.
+  if (is_binary_output) {
+    if (what.empty() || what == variables::kCheckIncludes) {
+      PrintCheckIncludes(target, display_headers);
+      found_match = true;
+    }
+    if (what.empty() || what == variables::kAllowCircularIncludesFrom) {
+      PrintAllowCircularIncludesFrom(target, display_headers);
+      found_match = true;
+    }
+  }
+
+  // Sources and inputs.
+  if (what.empty() || what == variables::kSources) {
+    PrintSources(target, display_headers);
+    found_match = true;
+  }
+  if (what.empty() || what == variables::kPublic) {
+    PrintPublic(target, display_headers);
+    found_match = true;
+  }
+  if (what.empty() || what == variables::kInputs) {
+    PrintInputs(target, display_headers);
+    found_match = true;
+  }
+
+  // Configs. Configs set directly on a target are only relevant for binary
+  // targets
+  if (is_binary_output && (what.empty() || what == variables::kConfigs)) {
+    PrintConfigs(target, display_headers);
+    found_match = true;
+  }
+
+  // Dependent/public configs can be applied to anything.
+  if (what.empty() || what == variables::kPublicConfigs) {
+    PrintPublicConfigs(target, display_headers);
+    found_match = true;
+  }
+  if (what.empty() || what == variables::kAllDependentConfigs) {
+    PrintAllDependentConfigs(target, display_headers);
+    found_match = true;
+  }
+
+  // Action values.
+  if (target->output_type() == Target::ACTION ||
+      target->output_type() == Target::ACTION_FOREACH) {
+    if (what.empty() || what == variables::kScript) {
+      PrintScript(target, display_headers);
+      found_match = true;
+    }
+    if (what.empty() || what == variables::kArgs) {
+      PrintArgs(target, display_headers);
+      found_match = true;
+    }
+    if (what.empty() || what == variables::kDepfile) {
+      PrintDepfile(target, display_headers);
+      found_match = true;
+    }
+  }
+
+  // Outputs.
+  if (target->output_type() != Target::SOURCE_SET &&
+      target->output_type() != Target::GROUP) {
+    if (what.empty() || what == variables::kOutputs) {
+      PrintOutputs(target, display_headers);
+      found_match = true;
+    }
+  }
+
+  // Values from configs only apply to binary targets.
+  if (is_binary_output) {
+    #define CONFIG_VALUE_ARRAY_HANDLER(name, type) \
+      if (what.empty() || what == #name) { \
+        OutputRecursiveTargetConfig<type>( \
+            target, display_headers ? #name : nullptr, &ConfigValues::name); \
+        found_match = true; \
+      }
+
+    CONFIG_VALUE_ARRAY_HANDLER(arflags, std::string)
+    CONFIG_VALUE_ARRAY_HANDLER(asmflags, std::string)
+    CONFIG_VALUE_ARRAY_HANDLER(cflags, std::string)
+    CONFIG_VALUE_ARRAY_HANDLER(cflags_c, std::string)
+    CONFIG_VALUE_ARRAY_HANDLER(cflags_cc, std::string)
+    CONFIG_VALUE_ARRAY_HANDLER(cflags_objc, std::string)
+    CONFIG_VALUE_ARRAY_HANDLER(cflags_objcc, std::string)
+    CONFIG_VALUE_ARRAY_HANDLER(defines, std::string)
+    CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir)
+    CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string)
+    // Libs and lib_dirs are handled specially below.
+
+    #undef CONFIG_VALUE_ARRAY_HANDLER
+
+    found_match |= PrintPrecompiledHeaderInfo(target->config_values(),
+                                              what, display_headers);
+  }
+
+  // Deps
+  if (what.empty() || what == "deps") {
+    PrintDeps(target, display_headers);
+    found_match = true;
+  }
+
+  // Runtime deps are special, print only when explicitly asked for and not in
+  // overview mode.
+  if (what == "runtime_deps") {
+    PrintRuntimeDeps(target);
+    found_match = true;
+  }
+
+  // Libs can be part of any target and get recursively pushed up the chain,
+  // so display them regardless of target type.
+  if (what.empty() || what == variables::kLibs) {
+    PrintLibs(target, display_headers);
+    found_match = true;
+  }
+  if (what.empty() || what == variables::kLibDirs) {
+    PrintLibDirs(target, display_headers);
+    found_match = true;
+  }
+
+  if (!found_match) {
     OutputString("Don't know how to display \"" + what + "\" for \"" +
-                 Target::GetStringForOutputType(target->output_type()) +
-                 "\".\n");
+        Target::GetStringForOutputType(target->output_type()) + "\".\n");
     return false;
   }
-  // Print single value, without any headers
-  if (!what.empty() && dict->size() == 1 && single_target) {
-    base::DictionaryValue::Iterator iter(*dict);
-    PrintValue(&iter.value(), 0);
-    return true;
-  }
-
-  OutputString("Target ", DECORATION_YELLOW);
-  OutputString(target->label().GetUserVisibleName(false));
-  OutputString("\n");
-
-  std::unique_ptr<base::Value> v;
-#define HANDLER(property, handler_name) \
-  if (dict->Remove(property, &v)) {     \
-    handler_name(property, v.get());    \
-  }
-
-  // Entries with DefaultHandler are present to enforce order
-  HANDLER("type", LabelHandler);
-  HANDLER("toolchain", LabelHandler);
-  HANDLER(variables::kVisibility, VisibilityHandler);
-  HANDLER(variables::kTestonly, DefaultHandler);
-  HANDLER(variables::kCheckIncludes, DefaultHandler);
-  HANDLER(variables::kAllowCircularIncludesFrom, DefaultHandler);
-  HANDLER(variables::kSources, DefaultHandler);
-  HANDLER(variables::kPublic, PublicHandler);
-  HANDLER(variables::kInputs, DefaultHandler);
-  HANDLER(variables::kConfigs, ConfigsHandler);
-  HANDLER(variables::kPublicConfigs, ConfigsHandler);
-  HANDLER(variables::kAllDependentConfigs, ConfigsHandler);
-  HANDLER(variables::kScript, DefaultHandler);
-  HANDLER(variables::kArgs, DefaultHandler);
-  HANDLER(variables::kDepfile, DefaultHandler);
-  ProcessOutputs(dict.get());
-  HANDLER("bundle_data", DefaultHandler);
-  HANDLER(variables::kArflags, DefaultHandler);
-  HANDLER(variables::kAsmflags, DefaultHandler);
-  HANDLER(variables::kCflags, DefaultHandler);
-  HANDLER(variables::kCflagsC, DefaultHandler);
-  HANDLER(variables::kCflagsCC, DefaultHandler);
-  HANDLER(variables::kCflagsObjC, DefaultHandler);
-  HANDLER(variables::kCflagsObjCC, DefaultHandler);
-  HANDLER(variables::kDefines, DefaultHandler);
-  HANDLER(variables::kIncludeDirs, DefaultHandler);
-  HANDLER(variables::kLdflags, DefaultHandler);
-  HANDLER(variables::kPrecompiledHeader, DefaultHandler);
-  HANDLER(variables::kPrecompiledSource, DefaultHandler);
-  HANDLER(variables::kDeps, DepsHandler);
-  HANDLER(variables::kLibs, DefaultHandler);
-  HANDLER(variables::kLibDirs, DefaultHandler);
-
-#undef HANDLER
-
-  // Process the rest (if any)
-  base::DictionaryValue::Iterator iter(*dict);
-  while (!iter.IsAtEnd()) {
-    DefaultHandler(iter.key(), &iter.value());
-    iter.Advance();
-  }
-
   return true;
 }
 
 bool PrintConfig(const Config* config,
                  const std::string& what,
-                 bool single_config) {
-  std::unique_ptr<base::DictionaryValue> dict =
-      DescBuilder::DescriptionForConfig(config, what);
-  if (!what.empty() && dict->empty()) {
+                 bool display_config_header) {
+  const ConfigValues& values = config->resolved_values();
+
+  if (display_config_header) {
+    OutputString("Config: ", DECORATION_YELLOW);
+    OutputString(config->label().GetUserVisibleName(false) + "\n");
+    OutputString("Toolchain: ", DECORATION_YELLOW);
+    OutputString(
+        config->label().GetToolchainLabel().GetUserVisibleName(false) + "\n");
+    if (what.empty() && !config->configs().empty()) {
+      OutputString(
+          "(This is a composite config, the values below are after the\n"
+          "expansion of the child configs.)\n");
+    }
+  }
+
+  // Display headers when outputting everything.
+  bool display_headers = what.empty();
+
+  if (what.empty() || what == variables::kConfigs)
+    PrintConfigs(config, display_headers);
+
+#define CONFIG_VALUE_ARRAY_HANDLER(name, type) \
+  if (what.empty() || what == #name) { \
+    OutputConfigValueArray<type>(values, display_headers ? #name : nullptr, \
+                                 &ConfigValues::name); \
+    found_match = true; \
+  }
+
+  bool found_match = false;
+
+  CONFIG_VALUE_ARRAY_HANDLER(arflags, std::string)
+  CONFIG_VALUE_ARRAY_HANDLER(asmflags, std::string)
+  CONFIG_VALUE_ARRAY_HANDLER(cflags, std::string)
+  CONFIG_VALUE_ARRAY_HANDLER(cflags_c, std::string)
+  CONFIG_VALUE_ARRAY_HANDLER(cflags_cc, std::string)
+  CONFIG_VALUE_ARRAY_HANDLER(cflags_objc, std::string)
+  CONFIG_VALUE_ARRAY_HANDLER(cflags_objcc, std::string)
+  CONFIG_VALUE_ARRAY_HANDLER(defines, std::string)
+  CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir)
+  CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string)
+  CONFIG_VALUE_ARRAY_HANDLER(lib_dirs, SourceDir)
+  CONFIG_VALUE_ARRAY_HANDLER(libs, LibFile)
+
+#undef CONFIG_VALUE_ARRAY_HANDLER
+
+  // Handles all PCH-related variables.
+  found_match |= PrintPrecompiledHeaderInfo(config->resolved_values(),
+                                            what, display_headers);
+
+  if (!found_match) {
     OutputString("Don't know how to display \"" + what + "\" for a config.\n");
     return false;
   }
-  // Print single value, without any headers
-  if (!what.empty() && dict->size() == 1 && single_config) {
-    base::DictionaryValue::Iterator iter(*dict);
-    PrintValue(&iter.value(), 0);
-    return true;
-  }
-
-  OutputString("Config: ", DECORATION_YELLOW);
-  OutputString(config->label().GetUserVisibleName(false));
-  OutputString("\n");
-
-  std::unique_ptr<base::Value> v;
-#define HANDLER(property, handler_name) \
-  if (dict->Remove(property, &v)) {     \
-    handler_name(property, v.get());    \
-  }
-
-  HANDLER("toolchain", LabelHandler);
-  if (!config->configs().empty()) {
-    OutputString(
-        "(This is a composite config, the values below are after the\n"
-        "expansion of the child configs.)\n");
-  }
-  HANDLER(variables::kArflags, DefaultHandler);
-  HANDLER(variables::kAsmflags, DefaultHandler);
-  HANDLER(variables::kCflags, DefaultHandler);
-  HANDLER(variables::kCflagsC, DefaultHandler);
-  HANDLER(variables::kCflagsCC, DefaultHandler);
-  HANDLER(variables::kCflagsObjC, DefaultHandler);
-  HANDLER(variables::kCflagsObjCC, DefaultHandler);
-  HANDLER(variables::kDefines, DefaultHandler);
-  HANDLER(variables::kIncludeDirs, DefaultHandler);
-  HANDLER(variables::kLdflags, DefaultHandler);
-  HANDLER(variables::kLibs, DefaultHandler);
-  HANDLER(variables::kLibDirs, DefaultHandler);
-  HANDLER(variables::kPrecompiledHeader, DefaultHandler);
-  HANDLER(variables::kPrecompiledSource, DefaultHandler);
-
-#undef HANDLER
-
   return true;
 }
 
@@ -291,8 +762,7 @@
 const char kDesc_HelpShort[] =
     "desc: Show lots of insightful information about a target or config.";
 const char kDesc_Help[] =
-    "gn desc <out_dir> <label or pattern> [<what to show>] [--blame] "
-    "[--format=json]\n"
+    "gn desc <out_dir> <label or pattern> [<what to show>] [--blame]\n"
     "\n"
     "  Displays information about a given target or config. The build\n"
     "  build parameters will be taken for the build in the given <out_dir>.\n"
@@ -344,9 +814,6 @@
     "\n"
     ALL_TOOLCHAINS_SWITCH_HELP
     "\n"
-    "  --format=json\n"
-    "      Format the output as JSON instead of text.\n"
-    "\n"
     "Target flags\n"
     "\n"
     "  --blame\n"
@@ -455,52 +922,28 @@
   if (args.size() == 3)
     what_to_print = args[2];
 
-  bool json = cmdline->GetSwitchValueASCII("format") == "json";
+  bool multiple_outputs = (target_matches.size() + config_matches.size()) > 1;
 
-  if (json) {
-    // Convert all targets/configs to JSON, serialize and print them
-    auto res = base::WrapUnique(new base::DictionaryValue());
-    if (!target_matches.empty()) {
-      for (const auto* target : target_matches) {
-        res->Set(target->label().GetUserVisibleName(
-                     target->settings()->default_toolchain_label()),
-                 DescBuilder::DescriptionForTarget(
-                     target, what_to_print, cmdline->HasSwitch(kAll),
-                     cmdline->HasSwitch(kTree), cmdline->HasSwitch(kBlame)));
-      }
-    } else if (!config_matches.empty()) {
-      for (const auto* config : config_matches) {
-        res->Set(config->label().GetUserVisibleName(false),
-                 DescBuilder::DescriptionForConfig(config, what_to_print));
-      }
-    }
-    std::string s;
-    base::JSONWriter::WriteWithOptions(
-        *res.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &s);
-    OutputString(s);
-  } else {
-    // Regular (non-json) formatted output
-    bool multiple_outputs = (target_matches.size() + config_matches.size()) > 1;
+  // Display headers for each target when printing all values, or when printing
+  // multiple targets or configs.
+  bool display_item_header = multiple_outputs || what_to_print.empty();
 
-    bool printed_output = false;
-    for (const Target* target : target_matches) {
-      if (printed_output)
-        OutputString("\n\n");
-      printed_output = true;
+  bool printed_output = false;
+  for (const Target* target : target_matches) {
+    if (printed_output)
+      OutputString("\n\n");
+    printed_output = true;
 
-      if (!PrintTarget(target, what_to_print, !multiple_outputs,
-                       cmdline->HasSwitch(kAll), cmdline->HasSwitch(kTree),
-                       cmdline->HasSwitch(kBlame)))
-        return 1;
-    }
-    for (const Config* config : config_matches) {
-      if (printed_output)
-        OutputString("\n\n");
-      printed_output = true;
+    if (!PrintTarget(target, what_to_print, display_item_header))
+      return 1;
+  }
+  for (const Config* config : config_matches) {
+    if (printed_output)
+      OutputString("\n\n");
+    printed_output = true;
 
-      if (!PrintConfig(config, what_to_print, !multiple_outputs))
-        return 1;
-    }
+    if (!PrintConfig(config, what_to_print, display_item_header))
+      return 1;
   }
 
   return 0;
diff --git a/tools/gn/command_gen.cc b/tools/gn/command_gen.cc
index 06b99ca..3d44274 100644
--- a/tools/gn/command_gen.cc
+++ b/tools/gn/command_gen.cc
@@ -11,7 +11,6 @@
 #include "tools/gn/build_settings.h"
 #include "tools/gn/commands.h"
 #include "tools/gn/eclipse_writer.h"
-#include "tools/gn/json_project_writer.h"
 #include "tools/gn/ninja_target_writer.h"
 #include "tools/gn/ninja_writer.h"
 #include "tools/gn/qt_creator_writer.h"
@@ -37,14 +36,10 @@
 const char kSwitchIdeValueVs2013[] = "vs2013";
 const char kSwitchIdeValueVs2015[] = "vs2015";
 const char kSwitchIdeValueXcode[] = "xcode";
-const char kSwitchIdeValueJson[] = "json";
 const char kSwitchNinjaExtraArgs[] = "ninja-extra-args";
 const char kSwitchRootTarget[] = "root-target";
 const char kSwitchSln[] = "sln";
 const char kSwitchWorkspace[] = "workspace";
-const char kSwitchJsonFileName[] = "json-file-name";
-const char kSwitchJsonIdeScript[] = "json-ide-script";
-const char kSwitchJsonIdeScriptArgs[] = "json-ide-script-args";
 
 // Called on worker thread to write the ninja file.
 void BackgroundDoWrite(const Target* target) {
@@ -118,7 +113,7 @@
 
   if (generator) {
     err += "but this file was not generated by any dependencies of the " +
-           target_str + ". The target\nthat generates the file is:\n  ";
+        target_str + ". The target\nthat generates the file is:\n  ";
     err += generator->label().GetUserVisibleName(show_toolchains);
   } else {
     err += "but no targets in the build generate that file.";
@@ -171,12 +166,11 @@
                   Err* err) {
   const base::CommandLine* command_line =
       base::CommandLine::ForCurrentProcess();
-  bool quiet = command_line->HasSwitch(switches::kQuiet);
   base::ElapsedTimer timer;
 
   if (ide == kSwitchIdeValueEclipse) {
     bool res = EclipseWriter::RunAndWriteFile(build_settings, builder, err);
-    if (res && !quiet) {
+    if (res && !command_line->HasSwitch(switches::kQuiet)) {
       OutputString("Generating Eclipse settings took " +
                    base::Int64ToString(timer.Elapsed().InMilliseconds()) +
                    "ms\n");
@@ -195,7 +189,7 @@
       filters = command_line->GetSwitchValueASCII(kSwitchFilters);
     bool res = VisualStudioWriter::RunAndWriteFiles(
         build_settings, builder, version, sln_name, filters, err);
-    if (res && !quiet) {
+    if (res && !command_line->HasSwitch(switches::kQuiet)) {
       OutputString("Generating Visual Studio projects took " +
                    base::Int64ToString(timer.Elapsed().InMilliseconds()) +
                    "ms\n");
@@ -208,7 +202,7 @@
         command_line->GetSwitchValueASCII(kSwitchNinjaExtraArgs),
         command_line->GetSwitchValueASCII(kSwitchFilters), build_settings,
         builder, err);
-    if (res && !quiet) {
+    if (res && !command_line->HasSwitch(switches::kQuiet)) {
       OutputString("Generating Xcode projects took " +
                    base::Int64ToString(timer.Elapsed().InMilliseconds()) +
                    "ms\n");
@@ -220,32 +214,12 @@
       root_target = command_line->GetSwitchValueASCII(kSwitchRootTarget);
     bool res = QtCreatorWriter::RunAndWriteFile(build_settings, builder, err,
                                                 root_target);
-    if (res && !quiet) {
+    if (res && !command_line->HasSwitch(switches::kQuiet)) {
       OutputString("Generating QtCreator projects took " +
                    base::Int64ToString(timer.Elapsed().InMilliseconds()) +
                    "ms\n");
     }
     return res;
-  } else if (ide == kSwitchIdeValueJson) {
-    std::string file_name =
-        command_line->GetSwitchValueASCII(kSwitchJsonFileName);
-    if (file_name.empty())
-      file_name = "project.json";
-    std::string exec_script =
-        command_line->GetSwitchValueASCII(kSwitchJsonIdeScript);
-    std::string exec_script_extra_args =
-        command_line->GetSwitchValueASCII(kSwitchJsonIdeScriptArgs);
-    std::string filters = command_line->GetSwitchValueASCII(kSwitchFilters);
-
-    bool res = JSONProjectWriter::RunAndWriteFiles(
-        build_settings, builder, file_name, exec_script, exec_script_extra_args,
-        filters, quiet, err);
-    if (res && !quiet) {
-      OutputString("Generating JSON projects took " +
-                   base::Int64ToString(timer.Elapsed().InMilliseconds()) +
-                   "ms\n");
-    }
-    return res;
   }
 
   *err = Err(Location(), "Unknown IDE: " + ide);
@@ -255,7 +229,8 @@
 }  // namespace
 
 const char kGen[] = "gen";
-const char kGen_HelpShort[] = "gen: Generate ninja files.";
+const char kGen_HelpShort[] =
+    "gen: Generate ninja files.";
 const char kGen_Help[] =
     "gn gen: Generate ninja files.\n"
     "\n"
@@ -284,13 +259,12 @@
     "      \"vs2015\" - Visual Studio 2015 project/solution files.\n"
     "      \"xcode\" - Xcode workspace/solution files.\n"
     "      \"qtcreator\" - QtCreator project files.\n"
-    "      \"json\" - JSON file containing target information\n"
     "\n"
     "  --filters=<path_prefixes>\n"
     "      Semicolon-separated list of label patterns used to limit the set\n"
     "      of generated projects (see \"gn help label_pattern\"). Only\n"
     "      matching targets and their dependencies will be included in the\n"
-    "      solution. Only used for Visual Studio, Xcode and JSON.\n"
+    "      solution. Only used for Visual Studio and Xcode.\n"
     "\n"
     "Visual Studio Flags\n"
     "\n"
@@ -331,27 +305,7 @@
     "  properly define includes/defines for each file individually.\n"
     "  Instead, one set of includes/defines is generated for the entire\n"
     "  project. This works fairly well but may still result in a few indexer\n"
-    "  issues here and there.\n"
-    "\n"
-    "Generic JSON Output\n"
-    "\n"
-    "  Dumps target information to JSON file and optionally invokes python\n"
-    "  script on generated file. \n"
-    "  See comments at the beginning of json_project_writer.cc and\n"
-    "  desc_builder.cc for overview of JSON file format.\n"
-    "\n"
-    "  --json-file-name=<json_file_name>\n"
-    "      Overrides default file name (project.json) of generated JSON file.\n"
-    "\n"
-    "  --json-ide-script=<path_to_python_script>\n"
-    "      Executes python script after the JSON file is generated.\n"
-    "      Path can be project absolute (//), system absolute (/) or\n"
-    "      relative, in which case the output directory will be base.\n"
-    "      Path to generated JSON file will be first argument when invoking\n"
-    "      script.\n"
-    "\n"
-    "  --json-ide-script-args=<argument>\n"
-    "      Optional second argument that will passed to executed script.\n";
+    "  issues here and there.\n";
 
 int RunGen(const std::vector<std::string>& args) {
   base::ElapsedTimer timer;
diff --git a/tools/gn/commands.cc b/tools/gn/commands.cc
index 492b74f..a646679 100644
--- a/tools/gn/commands.cc
+++ b/tools/gn/commands.cc
@@ -6,7 +6,6 @@
 
 #include "base/command_line.h"
 #include "base/strings/string_split.h"
-#include "base/values.h"
 #include "tools/gn/builder.h"
 #include "tools/gn/filesystem_utils.h"
 #include "tools/gn/item.h"
@@ -281,20 +280,22 @@
   return item->defined_from()->GetRange().begin().file()->physical_name();
 }
 
-void PrintTargetsAsBuildfiles(const std::vector<const Target*>& targets,
-                              base::ListValue* out) {
+void PrintTargetsAsBuildfiles(bool indent,
+                              const std::vector<const Target*>& targets) {
   // Output the set of unique source files.
   std::set<std::string> unique_files;
   for (const Target* target : targets)
     unique_files.insert(FilePathToUTF8(BuildFileForItem(target)));
 
   for (const std::string& file : unique_files) {
-    out->AppendString(file);
+    if (indent)
+      OutputString("  ");
+    OutputString(file + "\n");
   }
 }
 
-void PrintTargetsAsLabels(const std::vector<const Target*>& targets,
-                          base::ListValue* out) {
+void PrintTargetsAsLabels(bool indent,
+                          const std::vector<const Target*>& targets) {
   // Putting the labels into a set automatically sorts them for us.
   std::set<Label> unique_labels;
   for (auto* target : targets)
@@ -306,13 +307,16 @@
 
   for (const Label& label : unique_labels) {
     // Print toolchain only for ones not in the default toolchain.
-    out->AppendString(label.GetUserVisibleName(label.GetToolchainLabel() !=
-                                               default_tc_label));
+    if (indent)
+      OutputString("  ");
+    OutputString(label.GetUserVisibleName(
+        label.GetToolchainLabel() != default_tc_label));
+    OutputString("\n");
   }
 }
 
-void PrintTargetsAsOutputs(const std::vector<const Target*>& targets,
-                           base::ListValue* out) {
+void PrintTargetsAsOutputs(bool indent,
+                           const std::vector<const Target*>& targets) {
   if (targets.empty())
     return;
 
@@ -332,7 +336,10 @@
     std::string result = RebasePath(output_as_source.value(),
                                     build_settings->build_dir(),
                                     build_settings->root_path_utf8());
-    out->AppendString(result);
+    if (indent)
+      OutputString("  ");
+    OutputString(result);
+    OutputString("\n");
   }
 }
 
@@ -483,8 +490,7 @@
   return true;
 }
 
-void FilterAndPrintTargets(std::vector<const Target*>* targets,
-                           base::ListValue* out) {
+void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets) {
   if (targets->empty())
     return;
 
@@ -498,40 +504,21 @@
     return;
   switch (printing_mode) {
     case TARGET_PRINT_BUILDFILE:
-      PrintTargetsAsBuildfiles(*targets, out);
+      PrintTargetsAsBuildfiles(indent, *targets);
       break;
     case TARGET_PRINT_LABEL:
-      PrintTargetsAsLabels(*targets, out);
+      PrintTargetsAsLabels(indent, *targets);
       break;
     case TARGET_PRINT_OUTPUT:
-      PrintTargetsAsOutputs(*targets, out);
+      PrintTargetsAsOutputs(indent, *targets);
       break;
   }
 }
 
-void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets) {
-  base::ListValue tmp;
-  FilterAndPrintTargets(targets, &tmp);
-  for (const auto& value : tmp) {
-    std::string string;
-    value->GetAsString(&string);
-    if (indent)
-      OutputString("  ");
-    OutputString(string);
-    OutputString("\n");
-  }
-}
-
 void FilterAndPrintTargetSet(bool indent,
                              const std::set<const Target*>& targets) {
   std::vector<const Target*> target_vector(targets.begin(), targets.end());
   FilterAndPrintTargets(indent, &target_vector);
 }
 
-void FilterAndPrintTargetSet(const std::set<const Target*>& targets,
-                             base::ListValue* out) {
-  std::vector<const Target*> target_vector(targets.begin(), targets.end());
-  FilterAndPrintTargets(&target_vector, out);
-}
-
 }  // namespace commands
diff --git a/tools/gn/commands.h b/tools/gn/commands.h
index 01bf0ee..fdd10fc 100644
--- a/tools/gn/commands.h
+++ b/tools/gn/commands.h
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/strings/string_piece.h"
-#include "base/values.h"
 #include "tools/gn/target.h"
 #include "tools/gn/unique_vector.h"
 
@@ -180,13 +179,8 @@
 //
 // The vector will be modified so that only the printed targets will remain.
 void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets);
-void FilterAndPrintTargets(std::vector<const Target*>* targets,
-                           base::ListValue* out);
-
 void FilterAndPrintTargetSet(bool indent,
                              const std::set<const Target*>& targets);
-void FilterAndPrintTargetSet(const std::set<const Target*>& targets,
-                             base::ListValue* out);
 
 // Extra help from command_check.cc
 extern const char kNoGnCheck_Help[];
diff --git a/tools/gn/desc_builder.cc b/tools/gn/desc_builder.cc
deleted file mode 100644
index bc8f02a..0000000
--- a/tools/gn/desc_builder.cc
+++ /dev/null
@@ -1,694 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <set>
-
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/config.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/desc_builder.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/runtime_deps.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/variables.h"
-
-// Example structure of Value for single target
-// (not applicable or empty fields will be ommitted depending on target type)
-//
-// target_properties = {
-//   "type" : "output_type", // matching Target::GetStringForOutputType
-//   "toolchain" : "toolchain_name",
-//   "visibility" : [ list of visibility pattern descriptions ],
-//   "test_only" : true or false,
-//   "check_includes": true or false,
-//   "allow_circular_includes_from": [ list of target names ],
-//   "sources" : [ list of source files ],
-//   "public" : either "*" or [ list of public headers],
-//   "inputs" : [ list of inputs for target ],
-//   "configs" : [ list of configs for this target ],
-//   "public_configs" : [ list of public configs for this taget],
-//   "all_dependent_configs", [ list of all dependent configs for this target],
-//   "script" : "script for action targets",
-//   "args" : [ argument list for action targets ],
-//   "depfile : "file name for action input dependencies",
-//   "outputs" : [ list of target outputs ],
-//   "arflags", "asmflags", "cflags", "cflags_c",
-//   "clfags_cc", "cflags_objc", "clfags_objcc" : [ list of flags],
-//   "defines" : [ list of preprocessor definitions ],
-//   "include_dirs" : [ list of include directories ],
-//   "precompiled_header" : "name of precompiled header file",
-//   "precompiled_source" : "path to precompiled source",
-//   "deps : [ list of target dependencies ],
-//   "libs" : [ list of libraries ],
-//   "lib_dirs" : [ list of library directories ]
-// }
-//
-// Optionally, if "what" is specified while generating description, two other
-// properties can be requested that are not included by default
-//
-// "runtime_deps" : [list of computed runtime dependencies]
-// "source_outputs" : {
-//    "source_file x" : [ list of outputs for source file x ]
-//    "source_file y" : [ list of outputs for source file y ]
-//    ...
-// }
-
-namespace {
-
-std::string FormatSourceDir(const SourceDir& dir) {
-#if defined(OS_WIN)
-  // On Windows we fix up system absolute paths to look like native ones.
-  // Internally, they'll look like "/C:\foo\bar/"
-  if (dir.is_system_absolute()) {
-    std::string buf = dir.value();
-    if (buf.size() > 3 && buf[2] == ':') {
-      buf.erase(buf.begin());  // Erase beginning slash.
-      return buf;
-    }
-  }
-#endif
-  return dir.value();
-}
-
-void RecursiveCollectChildDeps(const Target* target,
-                               std::set<const Target*>* result);
-
-void RecursiveCollectDeps(const Target* target,
-                          std::set<const Target*>* result) {
-  if (result->find(target) != result->end())
-    return;  // Already did this target.
-  result->insert(target);
-
-  RecursiveCollectChildDeps(target, result);
-}
-
-void RecursiveCollectChildDeps(const Target* target,
-                               std::set<const Target*>* result) {
-  for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
-    RecursiveCollectDeps(pair.ptr, result);
-}
-
-// Common functionality for target and config description builder
-class BaseDescBuilder {
- public:
-  typedef std::unique_ptr<base::Value> ValuePtr;
-
-  BaseDescBuilder(const std::set<std::string>& what,
-                  bool all,
-                  bool tree,
-                  bool blame)
-      : what_(what), all_(all), tree_(tree), blame_(blame) {}
-
- protected:
-  virtual Label GetToolchainLabel() const = 0;
-
-  bool what(const std::string& w) const {
-    return what_.empty() || what_.find(w) != what_.end();
-  }
-
-  template <typename T>
-  ValuePtr RenderValue(const std::vector<T>& vector) {
-    auto res = base::WrapUnique(new base::ListValue());
-    for (const auto& v : vector)
-      res->Append(RenderValue(v));
-
-    return std::move(res);
-  }
-
-  ValuePtr RenderValue(const std::string& s, bool optional = false) {
-    return (s.empty() && optional) ? base::Value::CreateNullValue()
-                                   : ValuePtr(new base::StringValue(s));
-  }
-
-  ValuePtr RenderValue(const SourceDir& d) {
-    return d.is_null() ? base::Value::CreateNullValue()
-                       : ValuePtr(new base::StringValue(FormatSourceDir(d)));
-  }
-
-  ValuePtr RenderValue(const SourceFile& f) {
-    return f.is_null() ? base::Value::CreateNullValue()
-                       : ValuePtr(new base::StringValue(f.value()));
-  }
-
-  ValuePtr RenderValue(const LibFile& lib) {
-    if (lib.is_source_file())
-      return RenderValue(lib.source_file());
-    return RenderValue(lib.value());
-  }
-
-  template <class VectorType>
-  void FillInConfigVector(base::ListValue* out,
-                          const VectorType& configs,
-                          int indent = 0) {
-    for (const auto& config : configs) {
-      std::string name(indent * 2, ' ');
-      name.append(config.label.GetUserVisibleName(GetToolchainLabel()));
-      out->AppendString(name);
-      if (tree_)
-        FillInConfigVector(out, config.ptr->configs(), indent + 1);
-    }
-  }
-
-  void FillInPrecompiledHeader(base::DictionaryValue* out,
-                               const ConfigValues& values) {
-    if (what(variables::kPrecompiledHeader) &&
-        !values.precompiled_header().empty()) {
-      out->Set(variables::kPrecompiledHeader,
-               RenderValue(values.precompiled_header(), true));
-    }
-    if (what(variables::kPrecompiledSource) &&
-        !values.precompiled_source().is_null()) {
-      out->Set(variables::kPrecompiledSource,
-               RenderValue(values.precompiled_source()));
-    }
-  }
-
-  std::set<std::string> what_;
-  bool all_;
-  bool tree_;
-  bool blame_;
-};
-
-class ConfigDescBuilder : public BaseDescBuilder {
- public:
-  ConfigDescBuilder(const Config* config, const std::set<std::string>& what)
-      : BaseDescBuilder(what, false, false, false), config_(config) {}
-
-  std::unique_ptr<base::DictionaryValue> BuildDescription() {
-    auto res = base::WrapUnique(new base::DictionaryValue());
-    const ConfigValues& values = config_->resolved_values();
-
-    if (what_.empty())
-      res->SetString(
-          "toolchain",
-          config_->label().GetToolchainLabel().GetUserVisibleName(false));
-
-    if (what(variables::kConfigs) && !config_->configs().empty()) {
-      auto configs = base::WrapUnique(new base::ListValue());
-      FillInConfigVector(configs.get(), config_->configs().vector());
-      res->Set(variables::kConfigs, std::move(configs));
-    }
-
-#define CONFIG_VALUE_ARRAY_HANDLER(name, type)                        \
-  if (what(#name)) {                                                  \
-    ValuePtr ptr =                                                    \
-        render_config_value_array<type>(values, &ConfigValues::name); \
-    if (ptr) {                                                        \
-      res->Set(#name, std::move(ptr));                                \
-    }                                                                 \
-  }
-    CONFIG_VALUE_ARRAY_HANDLER(arflags, std::string)
-    CONFIG_VALUE_ARRAY_HANDLER(asmflags, std::string)
-    CONFIG_VALUE_ARRAY_HANDLER(cflags, std::string)
-    CONFIG_VALUE_ARRAY_HANDLER(cflags_c, std::string)
-    CONFIG_VALUE_ARRAY_HANDLER(cflags_cc, std::string)
-    CONFIG_VALUE_ARRAY_HANDLER(cflags_objc, std::string)
-    CONFIG_VALUE_ARRAY_HANDLER(cflags_objcc, std::string)
-    CONFIG_VALUE_ARRAY_HANDLER(defines, std::string)
-    CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir)
-    CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string)
-    CONFIG_VALUE_ARRAY_HANDLER(lib_dirs, SourceDir)
-    CONFIG_VALUE_ARRAY_HANDLER(libs, LibFile)
-
-#undef CONFIG_VALUE_ARRAY_HANDLER
-
-    FillInPrecompiledHeader(res.get(), values);
-
-    return res;
-  }
-
- protected:
-  Label GetToolchainLabel() const override {
-    return config_->label().GetToolchainLabel();
-  }
-
- private:
-  template <typename T>
-  ValuePtr render_config_value_array(
-      const ConfigValues& values,
-      const std::vector<T>& (ConfigValues::*getter)() const) {
-    auto res = base::WrapUnique(new base::ListValue());
-
-    for (const T& cur : (values.*getter)())
-      res->Append(RenderValue(cur));
-
-    return res->empty() ? nullptr : std::move(res);
-  }
-
-  const Config* config_;
-};
-
-class TargetDescBuilder : public BaseDescBuilder {
- public:
-  TargetDescBuilder(const Target* target,
-                    const std::set<std::string>& what,
-                    bool all,
-                    bool tree,
-                    bool blame)
-      : BaseDescBuilder(what, all, tree, blame), target_(target) {}
-
-  std::unique_ptr<base::DictionaryValue> BuildDescription() {
-    auto res = base::WrapUnique(new base::DictionaryValue());
-    bool is_binary_output = target_->IsBinary();
-
-    if (what_.empty()) {
-      res->SetString("type",
-                     Target::GetStringForOutputType(target_->output_type()));
-      res->SetString(
-          "toolchain",
-          target_->label().GetToolchainLabel().GetUserVisibleName(false));
-    }
-
-    // General target meta variables.
-    if (what(variables::kVisibility))
-      res->Set(variables::kVisibility, target_->visibility().AsValue());
-
-    if (what(variables::kTestonly))
-      res->SetBoolean(variables::kTestonly, target_->testonly());
-
-    if (is_binary_output) {
-      if (what(variables::kCheckIncludes))
-        res->SetBoolean(variables::kCheckIncludes, target_->check_includes());
-
-      if (what(variables::kAllowCircularIncludesFrom)) {
-        auto labels = base::WrapUnique(new base::ListValue());
-        for (const auto& cur : target_->allow_circular_includes_from())
-          labels->AppendString(cur.GetUserVisibleName(GetToolchainLabel()));
-
-        res->Set(variables::kAllowCircularIncludesFrom, std::move(labels));
-      }
-    }
-
-    if (what(variables::kSources) && !target_->sources().empty())
-      res->Set(variables::kSources, RenderValue(target_->sources()));
-
-    if (what(variables::kOutputName) && !target_->output_name().empty())
-      res->SetString(variables::kOutputName, target_->output_name());
-
-    if (what(variables::kOutputDir) && !target_->output_dir().is_null())
-      res->Set(variables::kOutputDir, RenderValue(target_->output_dir()));
-
-    if (what(variables::kOutputExtension) && target_->output_extension_set())
-      res->SetString(variables::kOutputExtension, target_->output_extension());
-
-    if (what(variables::kPublic)) {
-      if (target_->all_headers_public())
-        res->SetString(variables::kPublic, "*");
-      else
-        res->Set(variables::kPublic, RenderValue(target_->public_headers()));
-    }
-
-    if (what(variables::kInputs) && !target_->inputs().empty())
-      res->Set(variables::kInputs, RenderValue(target_->inputs()));
-
-    if (is_binary_output && what(variables::kConfigs) &&
-        !target_->configs().empty()) {
-      auto configs = base::WrapUnique(new base::ListValue());
-      FillInConfigVector(configs.get(), target_->configs().vector());
-      res->Set(variables::kConfigs, std::move(configs));
-    }
-
-    if (what(variables::kPublicConfigs) && !target_->public_configs().empty()) {
-      auto configs = base::WrapUnique(new base::ListValue());
-      FillInConfigVector(configs.get(), target_->public_configs());
-      res->Set(variables::kPublicConfigs, std::move(configs));
-    }
-
-    if (what(variables::kAllDependentConfigs) &&
-        !target_->all_dependent_configs().empty()) {
-      auto configs = base::WrapUnique(new base::ListValue());
-      FillInConfigVector(configs.get(), target_->all_dependent_configs());
-      res->Set(variables::kAllDependentConfigs, std::move(configs));
-    }
-
-    // Action
-    if (target_->output_type() == Target::ACTION ||
-        target_->output_type() == Target::ACTION_FOREACH) {
-      if (what(variables::kScript))
-        res->SetString(variables::kScript,
-                       target_->action_values().script().value());
-
-      if (what(variables::kArgs)) {
-        auto args = base::WrapUnique(new base::ListValue());
-        for (const auto& elem : target_->action_values().args().list())
-          args->AppendString(elem.AsString());
-
-        res->Set(variables::kArgs, std::move(args));
-      }
-      if (what(variables::kDepfile) &&
-          !target_->action_values().depfile().empty()) {
-        res->SetString(variables::kDepfile,
-                       target_->action_values().depfile().AsString());
-      }
-    }
-
-    if (target_->output_type() != Target::SOURCE_SET &&
-        target_->output_type() != Target::GROUP &&
-        target_->output_type() != Target::BUNDLE_DATA) {
-      if (what(variables::kOutputs))
-        FillInOutputs(res.get());
-    }
-
-    // Source outputs are only included when specifically asked for it
-    if (what_.find("source_outputs") != what_.end())
-      FillInSourceOutputs(res.get());
-
-    if (target_->output_type() == Target::CREATE_BUNDLE && what("bundle_data"))
-      FillInBundle(res.get());
-
-    if (is_binary_output) {
-#define CONFIG_VALUE_ARRAY_HANDLER(name, type)                    \
-  if (what(#name)) {                                              \
-    ValuePtr ptr = RenderConfigValues<type>(&ConfigValues::name); \
-    if (ptr) {                                                    \
-      res->Set(#name, std::move(ptr));                            \
-    }                                                             \
-  }
-      CONFIG_VALUE_ARRAY_HANDLER(arflags, std::string)
-      CONFIG_VALUE_ARRAY_HANDLER(asmflags, std::string)
-      CONFIG_VALUE_ARRAY_HANDLER(cflags, std::string)
-      CONFIG_VALUE_ARRAY_HANDLER(cflags_c, std::string)
-      CONFIG_VALUE_ARRAY_HANDLER(cflags_cc, std::string)
-      CONFIG_VALUE_ARRAY_HANDLER(cflags_objc, std::string)
-      CONFIG_VALUE_ARRAY_HANDLER(cflags_objcc, std::string)
-      CONFIG_VALUE_ARRAY_HANDLER(defines, std::string)
-      CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir)
-      CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string)
-#undef CONFIG_VALUE_ARRAY_HANDLER
-
-      // Libs and lib_dirs are handled specially below.
-
-      FillInPrecompiledHeader(res.get(), target_->config_values());
-    }
-
-    if (what(variables::kDeps))
-      res->Set(variables::kDeps, RenderDeps());
-
-    // Runtime deps are special, print only when explicitly asked for and not in
-    // overview mode.
-    if (what_.find("runtime_deps") != what_.end())
-      res->Set("runtime_deps", RenderRuntimeDeps());
-
-    // libs and lib_dirs are special in that they're inherited. We don't
-    // currently
-    // implement a blame feature for this since the bottom-up inheritance makes
-    // this difficult.
-
-    // Libs can be part of any target and get recursively pushed up the chain,
-    // so display them regardless of target type.
-    if (what(variables::kLibs)) {
-      const OrderedSet<LibFile>& all_libs = target_->all_libs();
-      if (!all_libs.empty()) {
-        auto libs = base::WrapUnique(new base::ListValue());
-        for (size_t i = 0; i < all_libs.size(); i++)
-          libs->AppendString(all_libs[i].value());
-        res->Set(variables::kLibs, std::move(libs));
-      }
-    }
-
-    if (what(variables::kLibDirs)) {
-      const OrderedSet<SourceDir>& all_lib_dirs = target_->all_lib_dirs();
-      if (!all_lib_dirs.empty()) {
-        auto lib_dirs = base::WrapUnique(new base::ListValue());
-        for (size_t i = 0; i < all_lib_dirs.size(); i++)
-          lib_dirs->AppendString(FormatSourceDir(all_lib_dirs[i]));
-        res->Set(variables::kLibDirs, std::move(lib_dirs));
-      }
-    }
-
-    return res;
-  }
-
- private:
-  // Prints dependencies of the given target (not the target itself). If the
-  // set is non-null, new targets encountered will be added to the set, and if
-  // a dependency is in the set already, it will not be recused into. When the
-  // set is null, all dependencies will be printed.
-  void RecursivePrintDeps(base::ListValue* out,
-                          const Target* target,
-                          std::set<const Target*>* seen_targets,
-                          int indent_level) {
-    // Combine all deps into one sorted list.
-    std::vector<LabelTargetPair> sorted_deps;
-    for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
-      sorted_deps.push_back(pair);
-    std::sort(sorted_deps.begin(), sorted_deps.end(),
-              LabelPtrLabelLess<Target>());
-
-    std::string indent(indent_level * 2, ' ');
-
-    for (const auto& pair : sorted_deps) {
-      const Target* cur_dep = pair.ptr;
-      std::string str =
-          indent + cur_dep->label().GetUserVisibleName(GetToolchainLabel());
-
-      bool print_children = true;
-      if (seen_targets) {
-        if (seen_targets->find(cur_dep) == seen_targets->end()) {
-          // New target, mark it visited.
-          seen_targets->insert(cur_dep);
-        } else {
-          // Already seen.
-          print_children = false;
-          // Only print "..." if something is actually elided, which means that
-          // the current target has children.
-          if (!cur_dep->public_deps().empty() ||
-              !cur_dep->private_deps().empty() || !cur_dep->data_deps().empty())
-            str += "...";
-        }
-      }
-
-      out->AppendString(str);
-
-      if (print_children)
-        RecursivePrintDeps(out, cur_dep, seen_targets, indent_level + 1);
-    }
-  }
-
-  ValuePtr RenderDeps() {
-    auto res = base::WrapUnique(new base::ListValue());
-
-    // Tree mode is separate.
-    if (tree_) {
-      if (all_) {
-        // Show all tree deps with no eliding.
-        RecursivePrintDeps(res.get(), target_, nullptr, 0);
-      } else {
-        // Don't recurse into duplicates.
-        std::set<const Target*> seen_targets;
-        RecursivePrintDeps(res.get(), target_, &seen_targets, 0);
-      }
-    } else {  // not tree
-
-      // Collect the deps to display.
-      if (all_) {
-        // Show all dependencies.
-        std::set<const Target*> all_deps;
-        RecursiveCollectChildDeps(target_, &all_deps);
-        commands::FilterAndPrintTargetSet(all_deps, res.get());
-      } else {
-        // Show direct dependencies only.
-        std::vector<const Target*> deps;
-        for (const auto& pair : target_->GetDeps(Target::DEPS_ALL))
-          deps.push_back(pair.ptr);
-        std::sort(deps.begin(), deps.end());
-        commands::FilterAndPrintTargets(&deps, res.get());
-      }
-    }
-
-    return std::move(res);
-  }
-
-  ValuePtr RenderRuntimeDeps() {
-    auto res = base::WrapUnique(new base::ListValue());
-
-    const Target* previous_from = NULL;
-    for (const auto& pair : ComputeRuntimeDeps(target_)) {
-      std::string str;
-      if (blame_) {
-        // Generally a target's runtime deps will be listed sequentially, so
-        // group them and don't duplicate the "from" label for two in a row.
-        if (previous_from == pair.second) {
-          str = "  ";
-        } else {
-          previous_from = pair.second;
-          res->AppendString(
-              str + "From " +
-              pair.second->label().GetUserVisibleName(GetToolchainLabel()));
-          str = "  ";
-        }
-      }
-
-      res->AppendString(str + pair.first.value());
-    }
-
-    return std::move(res);
-  }
-
-  void FillInSourceOutputs(base::DictionaryValue* res) {
-    auto dict = base::WrapUnique(new base::DictionaryValue());
-    for (const auto& source : target_->sources()) {
-      std::vector<OutputFile> outputs;
-      Toolchain::ToolType tool_type = Toolchain::TYPE_NONE;
-      if (target_->GetOutputFilesForSource(source, &tool_type, &outputs)) {
-        auto list = base::WrapUnique(new base::ListValue());
-        for (const auto& output : outputs)
-          list->AppendString(output.value());
-
-        dict->SetWithoutPathExpansion(source.value(), std::move(list));
-      }
-    }
-    res->Set("source_outputs", std::move(dict));
-  }
-
-  void FillInBundle(base::DictionaryValue* res) {
-    auto data = base::WrapUnique(new base::DictionaryValue());
-    const BundleData& bundle_data = target_->bundle_data();
-    const Settings* settings = target_->settings();
-    BundleData::SourceFiles sources;
-    bundle_data.GetSourceFiles(&sources);
-    data->Set("source_files", RenderValue(sources));
-    data->SetString("root_dir_output",
-                    bundle_data.GetBundleRootDirOutput(settings).value());
-    data->Set("root_dir", RenderValue(bundle_data.root_dir()));
-    data->Set("resources_dir", RenderValue(bundle_data.resources_dir()));
-    data->Set("executable_dir", RenderValue(bundle_data.executable_dir()));
-    data->Set("plugins_dir", RenderValue(bundle_data.plugins_dir()));
-    data->SetString("product_type", bundle_data.product_type());
-
-    auto deps = base::WrapUnique(new base::ListValue());
-    for (const auto* dep : bundle_data.bundle_deps())
-      deps->AppendString(dep->label().GetUserVisibleName(GetToolchainLabel()));
-
-    data->Set("deps", std::move(deps));
-    res->Set("bundle_data", std::move(data));
-  }
-
-  void FillInOutputs(base::DictionaryValue* res) {
-    if (target_->output_type() == Target::ACTION) {
-      auto list = base::WrapUnique(new base::ListValue());
-      for (const auto& elem : target_->action_values().outputs().list())
-        list->AppendString(elem.AsString());
-
-      res->Set(variables::kOutputs, std::move(list));
-    } else if (target_->output_type() == Target::CREATE_BUNDLE) {
-      std::vector<SourceFile> output_files;
-      target_->bundle_data().GetOutputsAsSourceFiles(target_->settings(),
-                                                     &output_files);
-      res->Set(variables::kOutputs, RenderValue(output_files));
-    } else if (target_->output_type() == Target::ACTION_FOREACH ||
-               target_->output_type() == Target::COPY_FILES) {
-      const SubstitutionList& outputs = target_->action_values().outputs();
-      if (!outputs.required_types().empty()) {
-        auto patterns = base::WrapUnique(new base::ListValue());
-        for (const auto& elem : outputs.list())
-          patterns->AppendString(elem.AsString());
-
-        res->Set("output_patterns", std::move(patterns));
-      }
-      std::vector<SourceFile> output_files;
-      SubstitutionWriter::ApplyListToSources(target_->settings(), outputs,
-                                             target_->sources(), &output_files);
-      res->Set(variables::kOutputs, RenderValue(output_files));
-    } else {
-      DCHECK(target_->IsBinary());
-      const Tool* tool =
-          target_->toolchain()->GetToolForTargetFinalOutput(target_);
-
-      std::vector<OutputFile> output_files;
-      SubstitutionWriter::ApplyListToLinkerAsOutputFile(
-          target_, tool, tool->outputs(), &output_files);
-      std::vector<SourceFile> output_files_as_source_file;
-      for (const OutputFile& output_file : output_files)
-        output_files_as_source_file.push_back(
-            output_file.AsSourceFile(target_->settings()->build_settings()));
-
-      res->Set(variables::kOutputs, RenderValue(output_files_as_source_file));
-    }
-  }
-
-  // Writes a given config value type to the string, optionally with
-  // attribution.
-  // This should match RecursiveTargetConfigToStream in the order it traverses.
-  template <class T>
-  ValuePtr RenderConfigValues(const std::vector<T>& (ConfigValues::*getter)()
-                                  const) {
-    auto res = base::WrapUnique(new base::ListValue());
-    for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
-      const std::vector<T>& vec = (iter.cur().*getter)();
-
-      if (vec.empty())
-        continue;
-
-      if (blame_) {
-        const Config* config = iter.GetCurrentConfig();
-        if (config) {
-          // Source of this value is a config.
-          std::string from =
-              "From " + config->label().GetUserVisibleName(false);
-          res->AppendString(from);
-          if (iter.origin()) {
-            Location location = iter.origin()->GetRange().begin();
-            from = "     (Added by " + location.file()->name().value() + ":" +
-                   base::IntToString(location.line_number()) + ")";
-            res->AppendString(from);
-          }
-        } else {
-          // Source of this value is the target itself.
-          std::string from =
-              "From " + target_->label().GetUserVisibleName(false);
-          res->AppendString(from);
-        }
-      }
-
-      for (const T& val : vec) {
-        ValuePtr rendered = RenderValue(val);
-        std::string str;
-        // Indent string values in blame mode
-        if (blame_ && rendered->GetAsString(&str)) {
-          str = "  " + str;
-          rendered = base::WrapUnique(new base::StringValue(str));
-        }
-        res->Append(std::move(rendered));
-      }
-    }
-    return res->empty() ? nullptr : std::move(res);
-  }
-
-  Label GetToolchainLabel() const override {
-    return target_->label().GetToolchainLabel();
-  }
-
-  const Target* target_;
-};
-
-}  // namespace
-
-std::unique_ptr<base::DictionaryValue> DescBuilder::DescriptionForTarget(
-    const Target* target,
-    const std::string& what,
-    bool all,
-    bool tree,
-    bool blame) {
-  std::set<std::string> w;
-  if (!what.empty())
-    w.insert(what);
-  TargetDescBuilder b(target, w, all, tree, blame);
-  return b.BuildDescription();
-}
-
-std::unique_ptr<base::DictionaryValue> DescBuilder::DescriptionForConfig(
-    const Config* config,
-    const std::string& what) {
-  std::set<std::string> w;
-  if (!what.empty())
-    w.insert(what);
-  ConfigDescBuilder b(config, w);
-  return b.BuildDescription();
-}
diff --git a/tools/gn/desc_builder.h b/tools/gn/desc_builder.h
deleted file mode 100644
index 1f0c395..0000000
--- a/tools/gn/desc_builder.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_DESC_BUILDER_H_
-#define TOOLS_GN_DESC_BUILDER_H_
-
-#include "base/values.h"
-#include "tools/gn/target.h"
-
-class DescBuilder {
- public:
-  // Creates Dictionary representation for given target
-  static std::unique_ptr<base::DictionaryValue> DescriptionForTarget(
-      const Target* target,
-      const std::string& what,
-      bool all,
-      bool tree,
-      bool blame);
-
-  // Creates Dictionary representation for given config
-  static std::unique_ptr<base::DictionaryValue> DescriptionForConfig(
-      const Config* config,
-      const std::string& what);
-};
-
-#endif
diff --git a/tools/gn/json_project_writer.cc b/tools/gn/json_project_writer.cc
deleted file mode 100644
index 272a288..0000000
--- a/tools/gn/json_project_writer.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/json_project_writer.h"
-
-#include <iostream>
-
-#include "base/command_line.h"
-#include "base/json/json_writer.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/desc_builder.h"
-#include "tools/gn/exec_process.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/settings.h"
-
-// Structure of JSON output file
-// {
-//   "build_settings" = {
-//     "root_path" : "absolute path of project root",
-//     "build_dir" : "build directory (project relative)",
-//     "default_toolchain" : "name of default toolchain"
-//   }
-//   "targets" = {
-//      "target x name" : { target x properties },
-//      "target y name" : { target y properties },
-//      ...
-//    }
-// }
-// See desc_builder.cc for overview of target properties
-
-namespace {
-
-void AddTargetDependencies(const Target* target,
-                           std::set<const Target*>* deps) {
-  for (const auto& pair : target->GetDeps(Target::DEPS_LINKED)) {
-    if (deps->find(pair.ptr) == deps->end()) {
-      deps->insert(pair.ptr);
-      AddTargetDependencies(pair.ptr, deps);
-    }
-  }
-}
-
-// Filters targets according to filter string; Will also recursively
-// add dependent targets.
-bool FilterTargets(const BuildSettings* build_settings,
-                   std::vector<const Target*>& all_targets,
-                   std::vector<const Target*>* targets,
-                   const std::string& dir_filter_string,
-                   Err* err) {
-  if (dir_filter_string.empty()) {
-    *targets = all_targets;
-  } else {
-    targets->reserve(all_targets.size());
-    std::vector<LabelPattern> filters;
-    if (!commands::FilterPatternsFromString(build_settings, dir_filter_string,
-                                            &filters, err)) {
-      return false;
-    }
-    commands::FilterTargetsByPatterns(all_targets, filters, targets);
-
-    std::set<const Target*> target_set(targets->begin(), targets->end());
-    for (const auto* target : *targets)
-      AddTargetDependencies(target, &target_set);
-
-    targets->clear();
-    targets->insert(targets->end(), target_set.begin(), target_set.end());
-  }
-
-  // Sort the list of targets per-label to get a consistent ordering of them
-  // in the generated project (and thus stability of the file generated).
-  std::sort(targets->begin(), targets->end(),
-            [](const Target* a, const Target* b) {
-              return a->label().name() < b->label().name();
-            });
-
-  return true;
-}
-
-std::string RenderJSON(const BuildSettings* build_settings,
-                       const Builder* builder,
-                       std::vector<const Target*>& all_targets) {
-  Label default_toolchain_label;
-
-  auto targets = base::WrapUnique(new base::DictionaryValue());
-  for (const auto* target : all_targets) {
-    if (default_toolchain_label.is_null())
-      default_toolchain_label = target->settings()->default_toolchain_label();
-    auto description =
-        DescBuilder::DescriptionForTarget(target, "", false, false, false);
-    // Outputs need to be asked for separately.
-    auto outputs = DescBuilder::DescriptionForTarget(target, "source_outputs",
-                                                     false, false, false);
-    base::DictionaryValue* outputs_value = nullptr;
-    if (outputs->GetDictionary("source_outputs", &outputs_value) &&
-        !outputs_value->empty()) {
-      description->MergeDictionary(outputs.get());
-    }
-    targets->Set(target->label().GetUserVisibleName(default_toolchain_label),
-                 std::move(description));
-  }
-
-  auto settings = base::WrapUnique(new base::DictionaryValue());
-  settings->SetString("root_path", build_settings->root_path_utf8());
-  settings->SetString("build_dir", build_settings->build_dir().value());
-  settings->SetString("default_toolchain",
-                      default_toolchain_label.GetUserVisibleName(false));
-
-  auto output = base::WrapUnique(new base::DictionaryValue());
-  output->Set("targets", std::move(targets));
-  output->Set("build_settings", std::move(settings));
-
-  std::string s;
-  base::JSONWriter::WriteWithOptions(
-      *output.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &s);
-  return s;
-}
-
-bool InvokePython(const BuildSettings* build_settings,
-                  const base::FilePath& python_script_path,
-                  const std::string& python_script_extra_args,
-                  const base::FilePath& output_path,
-                  bool quiet,
-                  Err* err) {
-  const base::FilePath& python_path = build_settings->python_path();
-  base::CommandLine cmdline(python_path);
-  cmdline.AppendArg("--");
-  cmdline.AppendArgPath(python_script_path);
-  cmdline.AppendArgPath(output_path);
-  if (!python_script_extra_args.empty()) {
-    cmdline.AppendArg(python_script_extra_args);
-  }
-  base::FilePath startup_dir =
-      build_settings->GetFullPath(build_settings->build_dir());
-
-  std::string output;
-  std::string stderr_output;
-
-  int exit_code = 0;
-  if (!internal::ExecProcess(cmdline, startup_dir, &output, &stderr_output,
-                             &exit_code)) {
-    *err =
-        Err(Location(), "Could not execute python.",
-            "I was trying to execute \"" + FilePathToUTF8(python_path) + "\".");
-    return false;
-  }
-
-  if (!quiet) {
-    std::cout << output;
-    std::cerr << stderr_output;
-  }
-
-  if (exit_code != 0) {
-    *err = Err(Location(), "Python has quit with exit code " +
-                               base::IntToString(exit_code) + ".");
-    return false;
-  }
-
-  return true;
-}
-
-}  // namespace
-
-bool JSONProjectWriter::RunAndWriteFiles(
-    const BuildSettings* build_settings,
-    const Builder* builder,
-    const std::string& file_name,
-    const std::string& exec_script,
-    const std::string& exec_script_extra_args,
-    const std::string& dir_filter_string,
-    bool quiet,
-    Err* err) {
-  SourceFile output_file = build_settings->build_dir().ResolveRelativeFile(
-      Value(nullptr, file_name), err);
-  if (output_file.is_null()) {
-    return false;
-  }
-
-  base::FilePath output_path = build_settings->GetFullPath(output_file);
-
-  std::vector<const Target*> all_targets = builder->GetAllResolvedTargets();
-  std::vector<const Target*> targets;
-  if (!FilterTargets(build_settings, all_targets, &targets, dir_filter_string,
-                     err)) {
-    return false;
-  }
-
-  std::string json = RenderJSON(build_settings, builder, targets);
-  if (!ContentsEqual(output_path, json)) {
-    if (!WriteFileIfChanged(output_path, json, err)) {
-      return false;
-    }
-
-    if (!exec_script.empty()) {
-      SourceFile script_file;
-      if (exec_script[0] != '/') {
-        // Relative path, assume the base is in build_dir.
-        script_file = build_settings->build_dir().ResolveRelativeFile(
-            Value(nullptr, exec_script), err);
-        if (script_file.is_null()) {
-          return false;
-        }
-      } else {
-        script_file = SourceFile(exec_script);
-      }
-      base::FilePath script_path = build_settings->GetFullPath(script_file);
-      return InvokePython(build_settings, script_path, exec_script_extra_args,
-                          output_path, quiet, err);
-    }
-  }
-
-  return true;
-}
diff --git a/tools/gn/json_project_writer.h b/tools/gn/json_project_writer.h
deleted file mode 100644
index e69dc3a..0000000
--- a/tools/gn/json_project_writer.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_JSON_WRITER_H_
-#define TOOLS_GN_JSON_WRITER_H_
-
-#include "tools/gn/err.h"
-#include "tools/gn/target.h"
-
-class Builder;
-class BuildSettings;
-
-class JSONProjectWriter {
- public:
-  static bool RunAndWriteFiles(const BuildSettings* build_setting,
-                               const Builder* builder,
-                               const std::string& file_name,
-                               const std::string& exec_script,
-                               const std::string& exec_script_extra_args,
-                               const std::string& dir_filter_string,
-                               bool quiet,
-                               Err* err);
-};
-
-#endif
diff --git a/tools/gn/target.cc b/tools/gn/target.cc
index 9851035..aa1fcf6 100644
--- a/tools/gn/target.cc
+++ b/tools/gn/target.cc
@@ -14,7 +14,6 @@
 #include "tools/gn/config_values_extractors.h"
 #include "tools/gn/deps_iterator.h"
 #include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
 #include "tools/gn/scheduler.h"
 #include "tools/gn/source_file_type.h"
 #include "tools/gn/substitution_writer.h"
@@ -216,29 +215,29 @@
 const char* Target::GetStringForOutputType(OutputType type) {
   switch (type) {
     case UNKNOWN:
-      return "unknown";
+      return "Unknown";
     case GROUP:
-      return functions::kGroup;
+      return "Group";
     case EXECUTABLE:
-      return functions::kExecutable;
+      return "Executable";
     case LOADABLE_MODULE:
-      return functions::kLoadableModule;
+      return "Loadable module";
     case SHARED_LIBRARY:
-      return functions::kSharedLibrary;
+      return "Shared library";
     case STATIC_LIBRARY:
-      return functions::kStaticLibrary;
+      return "Static library";
     case SOURCE_SET:
-      return functions::kSourceSet;
+      return "Source set";
     case COPY_FILES:
-      return functions::kCopy;
+      return "Copy";
     case ACTION:
-      return functions::kAction;
+      return "Action";
     case ACTION_FOREACH:
-      return functions::kActionForEach;
+      return "ActionForEach";
     case BUNDLE_DATA:
-      return functions::kBundleData;
+      return "Bundle data";
     case CREATE_BUNDLE:
-      return functions::kCreateBundle;
+      return "Create bundle";
     default:
       return "";
   }
diff --git a/tools/gn/visibility.cc b/tools/gn/visibility.cc
index b32586c..a61a5cd 100644
--- a/tools/gn/visibility.cc
+++ b/tools/gn/visibility.cc
@@ -4,10 +4,8 @@
 
 #include "tools/gn/visibility.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
-#include "base/values.h"
 #include "tools/gn/err.h"
 #include "tools/gn/filesystem_utils.h"
 #include "tools/gn/item.h"
@@ -85,14 +83,6 @@
   return result;
 }
 
-std::unique_ptr<base::Value> Visibility::AsValue() const {
-  auto* res = new base::ListValue();
-  for (const auto& pattern : patterns_)
-    res->AppendString(pattern.Describe());
-
-  return WrapUnique(res);
-}
-
 // static
 bool Visibility::CheckItemVisibility(const Item* from,
                                      const Item* to,
@@ -103,7 +93,7 @@
         "The item " + from->label().GetUserVisibleName(false) + "\n"
         "can not depend on " + to_label + "\n"
         "because it is not in " + to_label + "'s visibility list: " +
-                   to->visibility().Describe(0, true));
+        to->visibility().Describe(0, true));
     return false;
   }
   return true;
diff --git a/tools/gn/visibility.h b/tools/gn/visibility.h
index 4228f9d..d6d7f1f 100644
--- a/tools/gn/visibility.h
+++ b/tools/gn/visibility.h
@@ -5,17 +5,12 @@
 #ifndef TOOLS_GN_VISIBILITY_H_
 #define TOOLS_GN_VISIBILITY_H_
 
-#include <memory>
 #include <vector>
 
 #include "base/macros.h"
 #include "tools/gn/label_pattern.h"
 #include "tools/gn/source_dir.h"
 
-namespace base {
-class Value;
-}
-
 class Err;
 class Item;
 class Label;
@@ -48,9 +43,6 @@
   // result will end in a newline.
   std::string Describe(int indent, bool include_brackets) const;
 
-  // Returns value representation of this visibility
-  std::unique_ptr<base::Value> AsValue() const;
-
   // Helper function to check visibility between the given two items. If
   // to is invisible to from, returns false and sets the error.
   static bool CheckItemVisibility(const Item* from, const Item* to, Err* err);