From 16810b083ae6589a26ee0d0b60563447a92fc588 Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Wed, 11 Jan 2017 00:48:06 +0100 Subject: Add support for running checkstyle after compilation --- README | 28 +++++++++++++ bin/flycheck-android-java.py | 85 ++++++++++++++++++++++++++++------------ flycheck-android-experimental.el | 33 +++++++++++++++- 3 files changed, 119 insertions(+), 27 deletions(-) diff --git a/README b/README index b01226f..2071e72 100644 --- a/README +++ b/README @@ -32,6 +32,34 @@ allprojects { That should be it. +If you use checkstyle, you can expand the java-mode-hook: +(add-to-list + 'java-mode-hook + '(lambda () + (progn + (require 'flycheck-android-experimental) + (setq flycheck-android-java-checkstyle-jar + "tools/checkstyle/checkstyle-6.5-all.jar" + flycheck-android-java-checkstyle-path + "tools/checkstyle" + flycheck-android-java-checkstyle-config + "checkstyle-config-android.xml" + flycheck-android-java-checkstyle-properties + "checkstyle.properties")))) + +These are standard flycheck options so there are other ways to set them. + +If flycheck-android-java-checkstyle-jar is set checkstyle will be used, if it +isn't set then the other options are ignored. +flycheck-android-java-checkstyle-jar and flycheck-android-java-checkstyle-path +are both relative the project directory. +flycheck-android-java-checkstyle-config and +flycheck-android-java-checkstyle-properties are both relative +flycheck-android-java-checkstyle-path or if it's not set, the project directory. +All options can be absolute paths. +If flycheck-android-java-checkstyle-path is set it will be used as working +directory otherwise the project directory is. + ============================================================================= For the developer ============================================================================= diff --git a/bin/flycheck-android-java.py b/bin/flycheck-android-java.py index 4c9c82f..badf1e5 100644 --- a/bin/flycheck-android-java.py +++ b/bin/flycheck-android-java.py @@ -1,6 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +import argparse import errno import os import subprocess @@ -41,10 +42,12 @@ While iterating the paths, also check mtime on build.gradle files""" if gradlew: cmd = [gradlew, '-p', topdir] elif build_gradle: - cmd = ['gradle', '-p', os.path.dirname(build_gradle)] + topdir = os.path.dirname(build_gradle) + cmd = ['gradle', '-p', topdir] else: + topdir = '' cmd = ['gradle'] - return (cmd, mtime) + return (cmd, mtime, topdir) def filter_source_files(files): """Remove any item not looking like a Java source file.""" @@ -97,9 +100,9 @@ Otherwise return None.""" return files[0:i] + files[i + 1:] return None -def figure_out_java_compilation(sessiondir, sourcefile, tempfile): +def figure_out_java_compilation(sessiondir, sourcefile, tempfile, checkstyle): """Get options for Java compilation from gradle project and run javac.""" - (cmd, mtime) = get_gradle_command_and_project_mtime( + (cmd, mtime, projectdir) = get_gradle_command_and_project_mtime( os.path.dirname(sourcefile)) output = None if sessiondir != None: @@ -132,15 +135,18 @@ def figure_out_java_compilation(sessiondir, sourcefile, tempfile): output = output.split('\n') data = None + ret = 0 for line in output: if line == '***': if data: files = file_in_list(sourcefile, data['files']) if files: - return run_javac(data['encoding'], data['source'], - data['target'], data['bootcp'], - data['cp'], files, data['output'], - data['args'], tempfile, outdir) + ret = run_javac(data['encoding'], data['source'], + data['target'], data['bootcp'], + data['cp'], files, data['output'], + data['args'], tempfile, outdir) + data = None + break data = {} elif data != None: if line.startswith('args='): @@ -159,31 +165,58 @@ def figure_out_java_compilation(sessiondir, sourcefile, tempfile): data['files'] = line[6:].split(':') elif line.startswith('output='): data['output'] = line[7:] + if data: files = file_in_list(sourcefile, data['files']) if files: - return run_javac(data['encoding'], data['source'], data['target'], - data['bootcp'], data['cp'], files, data['output'], - data['args'], tempfile, outdir) + ret = run_javac(data['encoding'], data['source'], data['target'], + data['bootcp'], data['cp'], files, data['output'], + data['args'], tempfile, outdir) + + if not ret and checkstyle: + cmd = ['java', '-jar', + os.path.abspath(os.path.join(projectdir, checkstyle['jar']))] + + if 'config' in checkstyle: + cmd.extend(['-c', checkstyle['config']]) + + if 'properties' in checkstyle: + cmd.extend(['-p', checkstyle['properties']]) + + cmd.append(tempfile) + if checkstyle['path']: + cwd = os.path.join(projectdir, checkstyle['path']) + elif len(projectdir): + cwd = projectdir + else: + cwd = None + return subprocess.call(cmd, cwd=cwd) + return 0 def main(argv): - sessiondir = None - - if len(sys.argv) == 4: - sessiondir = sys.argv[1] - sourcefile = sys.argv[2] - tempfile = sys.argv[3] - elif len(sys.argv) == 3: - sourcefile = sys.argv[1] - tempfile = sys.argv[2] - elif len(sys.argv) == 2: - sourcefile = sys.argv[1] - tempfile = sourcefile - else: - return -1 + parser = argparse.ArgumentParser() + parser.add_argument('--checkstyle-jar') + parser.add_argument('--checkstyle-path') + parser.add_argument('--checkstyle-config') + parser.add_argument('--checkstyle-properties') + parser.add_argument('sessiondir', nargs='?') + parser.add_argument('sourcefile') + parser.add_argument('tempfile', nargs='?') + args = parser.parse_args(argv[1:]) + + sourcefile = args.sourcefile + tempfile = args.tempfile or sourcefile + + checkstyle = None + if args.checkstyle_jar: + checkstyle = {'jar': args.checkstyle_jar, + 'path': args.checkstyle_path, + 'config': args.checkstyle_config, + 'properties': args.checkstyle_properties} sourcefile = os.path.abspath(sourcefile) - return figure_out_java_compilation(sessiondir, sourcefile, tempfile) + return figure_out_java_compilation(args.sessiondir, sourcefile, tempfile, + checkstyle) sys.exit(main(sys.argv)) diff --git a/flycheck-android-experimental.el b/flycheck-android-experimental.el index 181b056..e041e76 100644 --- a/flycheck-android-experimental.el +++ b/flycheck-android-experimental.el @@ -14,10 +14,38 @@ (defvar flycheck-android-sessiondir nil "Session directory used for caching.") +(flycheck-def-option-var flycheck-android-java-checkstyle-jar nil android-java + "Path to checkstyle-VERSION-all.jar." + :safe #'stringp) +(make-variable-buffer-local 'flycheck-android-java-checkstyle-jar) + +(flycheck-def-option-var flycheck-android-java-checkstyle-path nil android-java + "Path to use as workdir and base for config and properties." + :safe #'stringp) +(make-variable-buffer-local 'flycheck-android-java-checkstyle-path) + +(flycheck-def-option-var flycheck-android-java-checkstyle-config nil android-java + "Path to checkstyle-config.xml if one should be used." + :safe #'stringp) +(make-variable-buffer-local 'flycheck-android-java-checkstyle-config) + +(flycheck-def-option-var flycheck-android-java-checkstyle-properties nil android-java + "Path to checkstyle.properties if one should be used." + :safe #'stringp) +(make-variable-buffer-local 'flycheck-android-java-checkstyle-properties) + (flycheck-define-checker android-java "Java syntax checker using javac." :command ("python" (eval (flycheck-android-find-tool "java")) + (option "--checkstyle-jar=" + flycheck-android-java-checkstyle-jar concat) + (option "--checkstyle-path=" + flycheck-android-java-checkstyle-path concat) + (option "--checkstyle-config=" + flycheck-android-java-checkstyle-config concat) + (option "--checkstyle-properties=" + flycheck-android-java-checkstyle-properties concat) (eval (flycheck-android-get-sessiondir)) (eval buffer-file-name) source) @@ -29,7 +57,10 @@ (error line-start (file-name) ":" line ": error:" (message (one-or-more (not (any "^"))) (any "^")) - line-end)) + line-end) + ;; checkstyle messages + (warning line-start (file-name) ":" line ": warning: " (message) line-end) + (error line-start (file-name) ":" line ": " (message) line-end)) :modes java-mode) (defun flycheck-android-find-tool (tool) -- cgit v1.2.3-70-g09d2