src/eric7/Plugins/CheckerPlugins/SyntaxChecker/jsCheckSyntax.py

branch
eric7
changeset 9955
aa02420279fe
parent 9954
7c5fa3eef082
child 9956
5b138f996a1e
equal deleted inserted replaced
9954:7c5fa3eef082 9955:aa02420279fe
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2014 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the syntax check for JavaScript.
8 """
9
10 import multiprocessing
11 import os
12 import queue
13 import sys
14
15
16 def initService():
17 """
18 Initialize the service and return the entry point.
19
20 @return the entry point for the background client (function)
21 """
22 path = __file__
23 for _ in range(4):
24 path = os.path.dirname(path)
25 sys.path.insert(2, os.path.join(path, "ThirdParty", "Jasy"))
26 return jsSyntaxCheck
27
28
29 def initBatchService():
30 """
31 Initialize the batch service and return the entry point.
32
33 @return the entry point for the background client (function)
34 """
35 return jsSyntaxBatchCheck
36
37
38 def jsSyntaxCheck(file, codestring):
39 """
40 Function to check a Javascript source file for syntax errors.
41
42 @param file source filename (string)
43 @param codestring string containing the code to check (string)
44 @return dictionary with the keys 'error' and 'warnings' which
45 hold a list containing details about the error/ warnings
46 (file name, line number, column, codestring (only at syntax
47 errors), the message, a list with arguments for the message)
48 """
49 return __jsSyntaxCheck(file, codestring)
50
51
52 def jsSyntaxBatchCheck(argumentsList, send, fx, cancelled, maxProcesses=0):
53 """
54 Module function to check syntax for a batch of files.
55
56 @param argumentsList list of arguments tuples as given for jsSyntaxCheck
57 @type list
58 @param send reference to send function
59 @type func
60 @param fx registered service name
61 @type str
62 @param cancelled reference to function checking for a cancellation
63 @type func
64 @param maxProcesses number of processes to be used
65 @type int
66 """
67 if maxProcesses == 0:
68 # determine based on CPU count
69 try:
70 NumberOfProcesses = multiprocessing.cpu_count()
71 if NumberOfProcesses >= 1:
72 NumberOfProcesses -= 1
73 except NotImplementedError:
74 NumberOfProcesses = 1
75 else:
76 NumberOfProcesses = maxProcesses
77
78 # Create queues
79 taskQueue = multiprocessing.Queue()
80 doneQueue = multiprocessing.Queue()
81
82 # Submit tasks (initially two times the number of processes)
83 tasks = len(argumentsList)
84 initialTasks = min(2 * NumberOfProcesses, tasks)
85 for _ in range(initialTasks):
86 taskQueue.put(argumentsList.pop(0))
87
88 # Start worker processes
89 workers = [
90 multiprocessing.Process(target=workerTask, args=(taskQueue, doneQueue))
91 for _ in range(NumberOfProcesses)
92 ]
93 for worker in workers:
94 worker.start()
95
96 # Get and send results
97 for _ in range(tasks):
98 resultSent = False
99 wasCancelled = False
100
101 while not resultSent:
102 try:
103 # get result (waiting max. 3 seconds and send it to frontend
104 filename, result = doneQueue.get()
105 send(fx, filename, result)
106 resultSent = True
107 except queue.Empty:
108 # ignore empty queue, just carry on
109 if cancelled():
110 wasCancelled = True
111 break
112
113 if wasCancelled or cancelled():
114 # just exit the loop ignoring the results of queued tasks
115 break
116
117 if argumentsList:
118 taskQueue.put(argumentsList.pop(0))
119
120 # Tell child processes to stop
121 for _ in range(NumberOfProcesses):
122 taskQueue.put("STOP")
123
124 for worker in workers:
125 worker.join()
126 worker.close()
127
128 taskQueue.close()
129 doneQueue.close()
130
131
132 def workerTask(inputQueue, outputQueue):
133 """
134 Module function acting as the parallel worker for the syntax check.
135
136 @param inputQueue input queue (multiprocessing.Queue)
137 @param outputQueue output queue (multiprocessing.Queue)
138 """
139 for filename, args in iter(inputQueue.get, "STOP"):
140 source = args[0]
141 result = __jsSyntaxCheck(filename, source)
142 outputQueue.put((filename, result))
143
144
145 def __jsSyntaxCheck(file, codestring):
146 """
147 Function to check a Javascript source file for syntax errors.
148
149 @param file source filename (string)
150 @param codestring string containing the code to check (string)
151 @return dictionary with the keys 'error' and 'warnings' which
152 hold a list containing details about the error/ warnings
153 (file name, line number, column, codestring (only at syntax
154 errors), the message, a list with arguments for the message)
155 """
156 import jasy.script.parse.Parser as jsParser # __IGNORE_WARNING_I102__
157 import jasy.script.tokenize.Tokenizer as jsTokenizer # __IGNORE_WARNING_I102__
158
159 try:
160 jsParser.parse(codestring, file)
161 except (jsParser.SyntaxError, jsTokenizer.ParseError) as exc:
162 details = exc.args[0]
163 error, details = details.splitlines()
164 fn, line = details.strip().rsplit(":", 1)
165 error = error.split(":", 1)[1].strip()
166
167 cline = min(len(codestring.splitlines()), int(line)) - 1
168 code = codestring.splitlines()[cline]
169 return [{"error": (fn, int(line), 0, code, error)}]
170 except IndexError:
171 error = "Incomplete source file"
172 splittedCode = codestring.splitlines()
173 return [
174 {
175 "error": (
176 file,
177 len(splittedCode) + 1,
178 len(splittedCode[-1]),
179 splittedCode[-1],
180 error,
181 )
182 }
183 ]
184
185 return [{}]

eric ide

mercurial