summaryrefslogtreecommitdiff
path: root/bin/flycheck-android-java.py
blob: 3f0f4bf8d093b9fd3c0dd2ee756112e4286f5394 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import subprocess
import sys
import tempfile
import time

def find_dominating_file(dir, file):
    """Find directory containing file."""
    if os.path.exists(os.path.join(dir, file)):
        return dir
    return find_dominating_file(os.path.dirname(dir), file)

def get_gradle_command(dir):
    """Find top-project gradlew or fallback to using gradle on sub-project dir."""
    topdir = find_dominating_file(dir, 'gradlew')
    if topdir:
        return [os.path.join(topdir, 'gradlew'), '-p', topdir]
    topdir = find_dominating_file(dir, 'build.gradle')
    if topdir:
        return ['gradle', '-p', topdir]
    return ['gradle']

def filter_source_files(files):
    """Remove any item not looking like a Java source file."""
    return [f for f in files if f.endswith('.java')]

def run_javac(encoding, source, target, bootcp, cp, files, output, args,
              sourcefile):
    """Execute javac with the given options."""
    command = ['javac']
    if encoding:
        command.extend(['-encoding', encoding])
    if source:
        command.extend(['-source', source])
    if target:
        command.extend(['-target', target])
    if bootcp:
        command.extend(['-bootclasspath', bootcp])
    if cp:
        command.extend(['-cp', ':'.join(cp)])
    if output:
        command.extend(['-d', output])
    command.extend(args)
    command.append(sourcefile)
    with tempfile.NamedTemporaryFile(mode='w') as f:
        command.append('@' + f.name)
        for source in filter_source_files(files):
            f.write(source)
            f.write('\n')
        f.flush()
        return subprocess.call(command)

def file_in_list(needle, files):
    """Find needle in files and if so, return the list without needle.
Otherwise return None."""
    for i in range(0, len(files) - 1):
        if os.path.samefile(needle, files[i]):
            return files[0:i] + files[i + 1:]
    return None

def figure_out_java_compilation(sourcefile, tempfile):
    """Get options for Java compilation from gradle project and run javac."""
    cmd = get_gradle_command(os.path.dirname(sourcefile))
    cmd.extend(['-q', 'flycheckAndroidJava'])
    output = subprocess.check_output(cmd, universal_newlines=True).split('\n')
    data = None
    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)
            data = {}
        elif data != None:
            if line.startswith('args='):
                data['args'] = line[6:-1].split(', ')
            elif line.startswith('encoding='):
                data['encoding'] = line[9:]
            elif line.startswith('bootcp='):
                data['bootcp'] = line[7:]
            elif line.startswith('cp='):
                data['cp'] = line[3:].split(':')
            elif line.startswith('source='):
                data['source'] = line[7:]
            elif line.startswith('target='):
                data['target'] = line[7:]
            elif line.startswith('files='):
                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)
    return 0

if len(sys.argv) == 3:
    sys.exit(figure_out_java_compilation(os.path.abspath(sys.argv[1]),
                                         sys.argv[2]))
elif len(sys.argv) == 2:
    sys.exit(figure_out_java_compilation(os.path.abspath(sys.argv[1]),
                                         sys.argv[1]))
else:
    sys.exit(-1)