summaryrefslogtreecommitdiffstats
path: root/tools/gn
diff options
context:
space:
mode:
authorscottmg <scottmg@chromium.org>2014-10-03 15:52:11 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-03 22:52:24 +0000
commit56d85cbf5bddd6bb9b68104a9f30af2b215a6e27 (patch)
treef2f12d0e4c6e35703ff29c9471bdff10a3411afa /tools/gn
parent1c28072cfdcbfbb27bafe384e739877ee74b3831 (diff)
downloadchromium_src-56d85cbf5bddd6bb9b68104a9f30af2b215a6e27.zip
chromium_src-56d85cbf5bddd6bb9b68104a9f30af2b215a6e27.tar.gz
chromium_src-56d85cbf5bddd6bb9b68104a9f30af2b215a6e27.tar.bz2
gn format: accept input from stdin, add vim helper
Also add test for empty function call (which was asserting with invalid iterator). R=brettw@chromium.org BUG=348474 Review URL: https://codereview.chromium.org/626093003 Cr-Commit-Position: refs/heads/master@{#298106}
Diffstat (limited to 'tools/gn')
-rw-r--r--tools/gn/bin/gn-format.py58
-rw-r--r--tools/gn/command_format.cc109
-rw-r--r--tools/gn/command_format_unittest.cc2
-rw-r--r--tools/gn/format_test_data/024.gn1
-rw-r--r--tools/gn/format_test_data/024.golden2
5 files changed, 152 insertions, 20 deletions
diff --git a/tools/gn/bin/gn-format.py b/tools/gn/bin/gn-format.py
new file mode 100644
index 0000000..c835753
--- /dev/null
+++ b/tools/gn/bin/gn-format.py
@@ -0,0 +1,58 @@
+# Copyright 2014 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.
+#
+# Based on clang-format.py.
+#
+# This file is a minimal gn format vim-integration. To install:
+# - Change 'binary' if gn is not on the path (see below).
+# - Add to your .vimrc:
+#
+# map <F1> :pyf <path-to-this-file>/gn-format.py<CR>
+#
+# gn format currently formats only a complete file so visual ranges, etc. won't
+# be used. It operates on the current, potentially unsaved buffer and does not
+# create or save any files. To revert a formatting, just undo.
+
+import difflib
+import subprocess
+import sys
+import vim
+
+# Change this to the full path if gn is not on the path.
+binary = 'gn'
+
+def main():
+ # Get the current text.
+ buf = vim.current.buffer
+ text = '\n'.join(buf)
+
+ # Avoid flashing an ugly cmd prompt on Windows when invoking gn.
+ startupinfo = None
+ if sys.platform.startswith('win32'):
+ startupinfo = subprocess.STARTUPINFO()
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+ startupinfo.wShowWindow = subprocess.SW_HIDE
+
+ # Call formatter.
+ p = subprocess.Popen([binary, 'format', '--stdin'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ stdin=subprocess.PIPE, startupinfo=startupinfo,
+ universal_newlines=True)
+ stdout, stderr = p.communicate(input=text)
+ if p.returncode != 0:
+ print 'Formatting failed, please report to gn-dev@chromium.org.'
+ print stdout, stderr
+ else:
+ # Otherwise, replace current buffer.
+ lines = stdout.split('\n')
+ # Last line should have trailing \n, but we don't want to insert a blank
+ # line at the end of the buffer, so remove that.
+ if lines[-1] == '':
+ lines = lines[:-1]
+ sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines)
+ for op in reversed(sequence.get_opcodes()):
+ if op[0] is not 'equal':
+ vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
+
+main()
diff --git a/tools/gn/command_format.cc b/tools/gn/command_format.cc
index c7076b0..e05d0f1 100644
--- a/tools/gn/command_format.cc
+++ b/tools/gn/command_format.cc
@@ -20,6 +20,7 @@ namespace commands {
const char kSwitchDumpTree[] = "dump-tree";
const char kSwitchInPlace[] = "in-place";
+const char kSwitchStdin[] = "stdin";
const char kFormat[] = "format";
const char kFormat_HelpShort[] =
@@ -40,10 +41,15 @@ const char kFormat_Help[] =
" Instead writing the formatted file to stdout, replace the input\n"
" with the formatted output.\n"
"\n"
+ " --stdin\n"
+ " Read input from stdin (and write to stdout). Not compatible with\n"
+ " --in-place of course.\n"
+ "\n"
"Examples\n"
" gn format //some/BUILD.gn\n"
" gn format some\\BUILD.gn\n"
- " gn format /abspath/some/BUILD.gn\n";
+ " gn format /abspath/some/BUILD.gn\n"
+ " gn format --stdin\n";
namespace {
@@ -408,8 +414,10 @@ void Printer::Sequence(SequenceStyle style,
// TODO(scottmg): Need to know if there's an attached block for " {".
fits_on_current_line =
fits_on_current_line && CurrentColumn() + total_length < kMaximumWidth;
- max_item_width =
- *std::max_element(natural_lengths.begin(), natural_lengths.end());
+ if (natural_lengths.size() > 0) {
+ max_item_width =
+ *std::max_element(natural_lengths.begin(), natural_lengths.end());
+ }
}
if (list.size() == 0 && !force_multiline) {
@@ -501,6 +509,38 @@ void Printer::Sequence(SequenceStyle style,
margin_ = old_margin;
}
+void DoFormat(const ParseNode* root, bool dump_tree, std::string* output) {
+ if (dump_tree) {
+ std::ostringstream os;
+ root->Print(os, 0);
+ printf("----------------------\n");
+ printf("-- PARSE TREE --------\n");
+ printf("----------------------\n");
+ printf("%s", os.str().c_str());
+ printf("----------------------\n");
+ }
+ Printer pr;
+ pr.Block(root);
+ *output = pr.String();
+}
+
+std::string ReadStdin() {
+ static const int kBufferSize = 256;
+ char buffer[kBufferSize];
+ std::string result;
+ while (true) {
+ char* input = NULL;
+ input = fgets(buffer, kBufferSize, stdin);
+ if (input == NULL && feof(stdin))
+ return result;
+ int length = static_cast<int>(strlen(buffer));
+ if (length == 0)
+ return result;
+ else
+ result += std::string(buffer, length);
+ }
+}
+
} // namespace
bool FormatFileToString(Setup* setup,
@@ -515,35 +555,64 @@ bool FormatFileToString(Setup* setup,
err.PrintToStdout();
return false;
}
- if (dump_tree) {
- std::ostringstream os;
- parse_node->Print(os, 0);
- printf("----------------------\n");
- printf("-- PARSE TREE --------\n");
- printf("----------------------\n");
- printf("%s", os.str().c_str());
- printf("----------------------\n");
+ DoFormat(parse_node, dump_tree, output);
+ return true;
+}
+
+bool FormatStringToString(const std::string& input,
+ bool dump_tree,
+ std::string* output) {
+ SourceFile source_file;
+ InputFile file(source_file);
+ file.SetContents(input);
+ Err err;
+ // Tokenize.
+ std::vector<Token> tokens = Tokenizer::Tokenize(&file, &err);
+ if (err.has_error()) {
+ err.PrintToStdout();
+ return false;
}
- Printer pr;
- pr.Block(parse_node);
- *output = pr.String();
+
+ // Parse.
+ scoped_ptr<ParseNode> parse_node = Parser::Parse(tokens, &err);
+ if (err.has_error()) {
+ err.PrintToStdout();
+ return false;
+ }
+
+ DoFormat(parse_node.get(), dump_tree, output);
return true;
}
int RunFormat(const std::vector<std::string>& args) {
+ bool dump_tree =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchDumpTree);
+
+ bool from_stdin =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchStdin);
+
+ if (from_stdin) {
+ if (args.size() != 0) {
+ Err(Location(), "Expecting no arguments when reading from stdin.\n")
+ .PrintToStdout();
+ return 1;
+ }
+ std::string input = ReadStdin();
+ std::string output;
+ if (!FormatStringToString(input, dump_tree, &output))
+ return 1;
+ printf("%s", output.c_str());
+ return 0;
+ }
+
// TODO(scottmg): Eventually, this should be a list/spec of files, and they
- // should all be done in parallel and in-place. For now, we don't want to
- // overwrite good data with mistakenly reformatted stuff, so we just simply
- // print the formatted output to stdout.
+ // should all be done in parallel.
if (args.size() != 1) {
Err(Location(), "Expecting exactly one argument, see `gn help format`.\n")
.PrintToStdout();
return 1;
}
- bool dump_tree =
- base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchDumpTree);
-
Setup setup;
SourceDir source_dir =
SourceDirForCurrentDirectory(setup.build_settings().root_path());
diff --git a/tools/gn/command_format_unittest.cc b/tools/gn/command_format_unittest.cc
index cad69a4..4140f80 100644
--- a/tools/gn/command_format_unittest.cc
+++ b/tools/gn/command_format_unittest.cc
@@ -57,3 +57,5 @@ FORMAT_TEST(019)
FORMAT_TEST(020)
FORMAT_TEST(021)
FORMAT_TEST(022)
+// TODO(scottmg): Refactor funccall. FORMAT_TEST(023)
+FORMAT_TEST(024)
diff --git a/tools/gn/format_test_data/024.gn b/tools/gn/format_test_data/024.gn
new file mode 100644
index 0000000..5034cdc
--- /dev/null
+++ b/tools/gn/format_test_data/024.gn
@@ -0,0 +1 @@
+somefunc(){}
diff --git a/tools/gn/format_test_data/024.golden b/tools/gn/format_test_data/024.golden
new file mode 100644
index 0000000..f2c755d
--- /dev/null
+++ b/tools/gn/format_test_data/024.golden
@@ -0,0 +1,2 @@
+somefunc() {
+}