Initial import master
authorAntonio Ospite <ao2@ao2.it>
Fri, 28 Apr 2017 07:35:51 +0000 (09:35 +0200)
committerAntonio Ospite <ao2@ao2.it>
Fri, 28 Apr 2017 07:35:51 +0000 (09:35 +0200)
addOption-null-shortname-php-parse.php [new file with mode: 0644]
addOption-null-shortname.sh [new file with mode: 0755]

diff --git a/addOption-null-shortname-php-parse.php b/addOption-null-shortname-php-parse.php
new file mode 100644 (file)
index 0000000..49dbf73
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * Change the second argument of "addOption" to null.
+ *
+ * Copyright (C) 2017  Antonio Ospite <ao2@ao2.it>
+ */
+
+/*
+ * php-parse is installed with:
+ *  composer global require nikic/php-parser
+ */
+include getenv('HOME') . '/.config/composer/vendor/autoload.php';
+
+use PhpParser\Node;
+use PhpParser\NodeTraverser;
+use PhpParser\NodeVisitorAbstract;
+use PhpParser\ParserFactory;
+use PhpParser\PrettyPrinter;
+
+class AddOptionSecondArgumentVisitor extends NodeVisitorAbstract {
+
+  public function leaveNode(Node $node) {
+    if ($node instanceof Node\Expr\MethodCall && $node->name === "addOption") {
+
+      $shortname_arg = $node->args[1];
+
+      // If it's a constant expression (e.g. false or null) make it null.
+      if ($shortname_arg->value instanceof Node\Expr\ConstFetch) {
+        $shortname_arg->value->name = new Node\Name("null");
+      }
+      elseif ($shortname_arg->value instanceof Node\Scalar\String_) {
+        // If it's an empty string, make it null keeping the attributes.
+        if (empty($shortname_arg->value->value)) {
+          $old_attributes = $shortname_arg->value->getAttributes();
+          $shortname_arg->value = new Node\Expr\ConstFetch(new Node\Name("null"), $old_attributes);
+        }
+      }
+      else {
+        echo "UNEXPECTED argument type\n";
+      }
+    }
+  }
+
+}
+
+$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
+$traverser = new NodeTraverser();
+$prettyPrinter = new PrettyPrinter\Standard();
+
+$traverser->addVisitor(new AddOptionSecondArgumentVisitor());
+
+try {
+  $code = file_get_contents($argv[1]);
+  $stmts = $parser->parse($code);
+  $stmts = $traverser->traverse($stmts);
+
+  // $stmts is an array of statement nodes.
+  $code = $prettyPrinter->prettyPrintFile($stmts);
+  echo $code;
+
+}
+catch (Error $e) {
+  echo 'Parse Error: ', $e->getMessage();
+}
diff --git a/addOption-null-shortname.sh b/addOption-null-shortname.sh
new file mode 100755 (executable)
index 0000000..c677e99
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+# Change the second argument of "addOption" to null.
+#
+# Copyright (C) 2017  Antonio Ospite <ao2@ao2.it>
+
+set -e
+set -x
+
+[ "x$1" = "x" ] && { echo "usage: $(basename $0) <drupal-console-dir>" 2>&1; exit 1; }
+
+DRUPAL_CONSOLE_DIR="$1"
+PHP_PARSER_RESULTS_DIR=__php_parser_results
+LOG_FILE=null_shortname.log
+
+echo "This will loose all unstaged changes, Continue?"
+read response
+case $response in
+  y|Y|yes|YES) ;;
+  *)           echo "Aborting" 2>&1; exit 1; ;;
+esac
+
+rm -rf "$PHP_PARSER_RESULTS_DIR"
+mkdir "$PHP_PARSER_RESULTS_DIR"
+
+rm -f "$LOG_FILE"
+
+git -C "$DRUPAL_CONSOLE_DIR" checkout .
+
+git -C "$DRUPAL_CONSOLE_DIR" grep -l addOption |
+while read file;
+do
+  PARSED_FILE="$(echo "$file" | sed -e 's/\//_/g')"
+  SRC_FILE="${DRUPAL_CONSOLE_DIR}/${file}"
+
+  # Do a first conversion with php-parser, this looses the original
+  # formatting, but it's robust because it uses an actual parser, so the
+  # result can be used to validate the sed solution below.
+  php addOption-null-shortname-php-parse.php "$SRC_FILE" > "${PHP_PARSER_RESULTS_DIR}/${PARSED_FILE}"
+
+  # The sed expression does this:
+  # - look for addOption;
+  # - append the next two lines to the pattern space (N;N;), to cover the case
+  #   when the arguments on different lines;
+  # - separate the arguments, but also consider what the characters after the
+  #   first comma are, sometimes there is a space and sometimes there is
+  #   a newline with the indentation following, and we want to keep those as
+  #   they were.
+  # - if it's false or an empty string, replace the second argument which
+  #   would be in \3, with null
+  # - keep everything else as it was.
+  #
+  # The sed commands after the substitution tell to go on (N;N;) if there is
+  # no substitution (t) and to print and delete the pattern (P;D;) when
+  # a substitution succeed.
+  #
+  # This covers the case when another pattern is in the three lines which are
+  # being analyzed, e.g:
+  #
+  #   ->addOption('quick', '', InputOption::VALUE_NONE, $this->trans('commands.database.query.options.quick'))
+  #   ->addOption('debug', '', InputOption::VALUE_NONE, $this->trans('commands.database.query.options.debug'))
+  #   ->addOption('html', '', InputOption::VALUE_NONE, $this->trans('commands.database.query.options.html'))
+  #   ->addOption('xml', '', InputOption::VALUE_NONE, $this->trans('commands.database.query.options.xml'))
+  #   ->addOption('raw', '', InputOption::VALUE_NONE, $this->trans('commands.database.query.options.raw'))
+  #   ->addOption('vertical', '', InputOption::VALUE_NONE, $this->trans('commands.database.query.options.vertical'))
+  #   ->addOption('batch', '', InputOption::VALUE_NONE, $this->trans('commands.database.query.options.batch'))
+  #
+  # See also https://unix.stackexchange.com/questions/26284
+  sed -e "/addOption/{N;N;s/addOption(\([^,]*\),\([ \n]*\)\(''\|false\),\(.*\)/addOption(\1,\2null,\4/;ty;N;N;:y;P;D}" -i "$SRC_FILE"
+
+  # Pretty print with php-parse the files converted with sed, so that they can be compared
+  # with the ones converted with addOption-null-shortname-php-parse.php from above.
+  php-parse  -p "$SRC_FILE" | grep -v "^==" > "${PHP_PARSER_RESULTS_DIR}/${PARSED_FILE}.sed"
+
+  # And print a report of the difference between the two conversion, if the
+  # sed command is correct there should be no difference at all.
+  echo "$file" >> "$LOG_FILE"
+  wdiff -3 "${PHP_PARSER_RESULTS_DIR}/${PARSED_FILE}" "${PHP_PARSER_RESULTS_DIR}/${PARSED_FILE}.sed" >> "$LOG_FILE" || true
+  echo >> "$LOG_FILE"
+  echo >> "$LOG_FILE"
+done