1 |
|
2 |
|
3 | import sys
|
4 | import os
|
5 | import argparse
|
6 | import subprocess
|
7 | import re
|
8 | import tempfile
|
9 |
|
10 | scriptPath = os.path.realpath(__file__)
|
11 | toolsPath = os.path.dirname(scriptPath)
|
12 | basePath = os.path.dirname(toolsPath)
|
13 |
|
14 | advancedDisable = False
|
15 | allIncludedFiles = []
|
16 |
|
17 | TYPE_EXTERN = '--externs'
|
18 | TYPE_SOURCE = '--js'
|
19 |
|
20 | def upsertIncludedFile(path, type):
|
21 | for incFile in allIncludedFiles:
|
22 | if incFile.path == path:
|
23 | return incFile
|
24 |
|
25 | newfile = IncludedFile(path, type)
|
26 | allIncludedFiles.append(newfile)
|
27 | return newfile
|
28 |
|
29 | class IncludedFile:
|
30 | def __init__(self, path, type):
|
31 | self.path = path
|
32 | self.type = type
|
33 | self.dependencies = set()
|
34 | self.visited = False
|
35 | self.added = False
|
36 |
|
37 | def addDependency(self, incfile):
|
38 | self.dependencies.add(incfile)
|
39 |
|
40 | def addDependencies(self, deps):
|
41 | self.dependencies.update(deps)
|
42 |
|
43 | def parsePaths(line, type):
|
44 | return [upsertIncludedFile(os.path.join(basePath, path.strip()), type) for path in line.split(',') if len(path.strip()) > 0]
|
45 |
|
46 | def visitFile(thisFile):
|
47 | global advancedDisable
|
48 |
|
49 | if thisFile.visited:
|
50 | return
|
51 |
|
52 | thisFile.visted = True
|
53 |
|
54 | with open(thisFile.path, 'r') as file:
|
55 | for line in file:
|
56 | if line.startswith("/*extern"):
|
57 | thisFile.addDependencies(parsePaths(line.replace("/*extern", "").replace("*/", ""), TYPE_EXTERN))
|
58 | if line.startswith("/*source"):
|
59 | thisFile.addDependencies(parsePaths(line.replace("/*source", "").replace("*/", ""), TYPE_SOURCE))
|
60 | if line.startswith("/*advanced-disable"):
|
61 | advancedDisable = True
|
62 |
|
63 | for incfile in thisFile.dependencies:
|
64 | visitFile(incfile)
|
65 |
|
66 | def getCommandLineFileArgs(thisFile, argsList):
|
67 | for incfile in thisFile.dependencies:
|
68 | getCommandLineFileArgs(incfile, argsList)
|
69 |
|
70 | if thisFile.added:
|
71 | return
|
72 |
|
73 | thisFile.added = True
|
74 | argsList.extend([thisFile.type, thisFile.path])
|
75 |
|
76 | if __name__ == "__main__":
|
77 | parser = argparse.ArgumentParser(description='Compile one or many scripts using Google Closure Compiler to be uploaded to NetSuite')
|
78 | parser.add_argument('--debug', type=str, nargs='?')
|
79 | parser.add_argument('infile', type=argparse.FileType('rU'))
|
80 | parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'), default=sys.stdout)
|
81 | args = parser.parse_args()
|
82 |
|
83 | inFilePath = os.path.realpath(args.infile.name)
|
84 | basePath = os.path.dirname(inFilePath)
|
85 | rootFile = upsertIncludedFile(inFilePath, TYPE_SOURCE)
|
86 |
|
87 | try:
|
88 | visitFile(rootFile)
|
89 | except Exception as e:
|
90 | args.outfile.write(str(e))
|
91 | sys.exit(-1)
|
92 |
|
93 | doAdvanced = False
|
94 | doAdvancedDebug = False
|
95 |
|
96 | if not advancedDisable:
|
97 | args.infile.seek(0)
|
98 | for line in args.infile:
|
99 | if line.strip() == '/*advanced*/':
|
100 | doAdvanced = True
|
101 | break
|
102 |
|
103 | args.infile.seek(0)
|
104 | for line in args.infile:
|
105 | if line.strip() == '/*advanced-debug*/':
|
106 | doAdvancedDebug = True
|
107 | break
|
108 |
|
109 | compilerPath = os.path.join(toolsPath, "compiler.jar")
|
110 | command = ["java", "-jar", compilerPath]
|
111 | fileArgs = []
|
112 | getCommandLineFileArgs(rootFile, fileArgs)
|
113 | command.extend(fileArgs)
|
114 | for errName in ['accessControls', 'ambiguousFunctionDecl', 'checkRegExp', 'checkVars', 'constantProperty', 'deprecated', 'duplicateMessage', 'es5Strict', 'externsValidation', 'fileoverviewTags', 'globalThis', 'internetExplorerChecks', 'invalidCasts', 'missingProperties', 'nonStandardJsDocs', 'strictModuleDepCheck', 'typeInvalidation', 'undefinedNames', 'undefinedVars', 'unknownDefines', 'uselessCode', 'visibility', 'checkTypes']:
|
115 | command.extend(["--jscomp_error", errName])
|
116 | command.extend(["--compilation_level", "WHITESPACE_ONLY", "--formatting", "pretty_print"])
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 | commandline = ' '.join(command)
|
127 |
|
128 | tempoutput = tempfile.TemporaryFile()
|
129 |
|
130 | try:
|
131 | output = subprocess.check_output(command, stderr=tempoutput)
|
132 | except subprocess.CalledProcessError:
|
133 | tempoutput.seek(0)
|
134 | for outline in tempoutput:
|
135 | args.outfile.write(outline)
|
136 | args.outfile.write('\n\nCommand:\n' + commandline)
|
137 | raise
|
138 |
|
139 | tempoutput.seek(0)
|
140 | for line in tempoutput:
|
141 | if re.search("\d+ error\(s\), \d+ warning\(s\)", line):
|
142 | tempoutput.seek(0)
|
143 | for outline in tempoutput:
|
144 | args.outfile.write(outline)
|
145 | args.outfile.write('\n\nCommand:\n' + commandline + '\n\n')
|
146 | args.outfile.flush()
|
147 | raise Exception("Compiling failed")
|
148 |
|
149 | args.outfile.write(output)
|
150 |
|
151 | args.infile.close()
|
152 | args.outfile.close() |
\ | No newline at end of file |