eric7/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckService.py

branch
eric7
changeset 8312
800c432b34c8
parent 8218
7c09585bd960
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2013 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5 # pylint: disable=C0103
6
7 """
8 Module implementing an interface to add different languages to do a syntax
9 check.
10 """
11
12 from PyQt5.QtCore import QObject, pyqtSignal
13
14 from E5Gui.E5Application import e5App
15 from Utilities import determinePythonVersion
16
17
18 class SyntaxCheckService(QObject):
19 """
20 Implement the syntax check service.
21
22 Plugins can add other languages to the syntax check by calling addLanguage
23 and support of an extra checker module on the client side which has to
24 connect directly to the background service.
25
26 @signal syntaxChecked(str, dict) emitted when the syntax check was done for
27 one file
28 @signal batchFinished() emitted when a syntax check batch is done
29 @signal error(str, str) emitted in case of an error
30 """
31 syntaxChecked = pyqtSignal(str, dict)
32 batchFinished = pyqtSignal()
33 error = pyqtSignal(str, str)
34
35 def __init__(self):
36 """
37 Constructor
38 """
39 super().__init__()
40 self.backgroundService = e5App().getObject("BackgroundService")
41 self.__supportedLanguages = {}
42
43 self.queuedBatches = []
44 self.batchesFinished = True
45
46 def __determineLanguage(self, filename, source):
47 """
48 Private methode to determine the language of the file.
49
50 @param filename of the sourcefile (str)
51 @param source code of the file (str)
52 @return language of the file or None if not found (str or None)
53 """
54 pyVer = determinePythonVersion(filename, source)
55 if pyVer:
56 return 'Python{0}'.format(pyVer)
57
58 for lang, (_env, _getArgs, getExt) in (
59 self.__supportedLanguages.items()
60 ):
61 if filename.endswith(tuple(getExt())):
62 return lang
63
64 return None
65
66 def addLanguage(
67 self, lang, env, path, module, getArgs, getExt, callback, onError):
68 """
69 Public method to register a new language to the supported languages.
70
71 @param lang new language to check syntax (str)
72 @param env the environment in which the checker is implemented (str)
73 @param path full path to the module (str)
74 @param module name to import (str)
75 @param getArgs function to collect the required arguments to call the
76 syntax checker on client side (function)
77 @param getExt function that returns the supported file extensions of
78 the syntax checker (function)
79 @param callback function on service response (function)
80 @param onError callback function if client or service isn't available
81 (function)
82 """
83 self.__supportedLanguages[lang] = env, getArgs, getExt
84 # Connect to the background service
85 self.backgroundService.serviceConnect(
86 '{0}Syntax'.format(lang), env, path, module, callback, onError,
87 onBatchDone=self.batchJobDone)
88
89 def getLanguages(self):
90 """
91 Public method to return the supported language names.
92
93 @return list of languanges supported (list of str)
94 """
95 return list(self.__supportedLanguages.keys()) + ["MicroPython"]
96
97 def removeLanguage(self, lang):
98 """
99 Public method to remove the language from syntax check.
100
101 @param lang language to remove (str)
102 """
103 self.__supportedLanguages.pop(lang, None)
104 self.backgroundService.serviceDisconnect(
105 '{0}Syntax'.format(lang), lang)
106
107 def getExtensions(self):
108 """
109 Public method to return all supported file extensions for the
110 syntax checker dialog.
111
112 @return set of all supported file extensions (set of str)
113 """
114 extensions = set()
115 for _env, _getArgs, getExt in self.__supportedLanguages.values():
116 for ext in getExt():
117 extensions.add(ext)
118 return extensions
119
120 def syntaxCheck(self, lang, filename, source):
121 """
122 Public method to prepare a syntax check of one source file.
123
124 @param lang language of the file or None to determine by internal
125 algorithm (str or None)
126 @param filename source filename (string)
127 @param source string containing the code to check (string)
128 """
129 if not lang:
130 lang = self.__determineLanguage(filename, source)
131 if lang not in self.getLanguages():
132 return
133 if lang == "MicroPython":
134 lang = "Python3"
135
136 data = [source]
137 # Call the getArgs function to get the required arguments
138 env, args, getExt = self.__supportedLanguages[lang]
139 data.extend(args())
140 self.backgroundService.enqueueRequest(
141 '{0}Syntax'.format(lang), env, filename, data)
142
143 def syntaxBatchCheck(self, argumentsList):
144 """
145 Public method to prepare a syntax check on multiple source files.
146
147 @param argumentsList list of arguments tuples with each tuple
148 containing filename and source (string, string)
149 """
150 data = {
151 }
152 for lang in self.getLanguages():
153 data[lang] = []
154
155 for filename, source in argumentsList:
156 lang = self.__determineLanguage(filename, source)
157 if lang not in self.getLanguages():
158 continue
159 else:
160 jobData = [source]
161 # Call the getArgs function to get the required arguments
162 args = self.__supportedLanguages[lang][1]
163 jobData.extend(args())
164 data[lang].append((filename, jobData))
165
166 self.queuedBatches = []
167 for lang in self.getLanguages():
168 if data[lang]:
169 self.queuedBatches.append(lang)
170 env = self.__supportedLanguages[lang][0]
171 self.backgroundService.enqueueRequest(
172 'batch_{0}Syntax'.format(lang), env, "", data[lang])
173 self.batchesFinished = False
174
175 def cancelSyntaxBatchCheck(self):
176 """
177 Public method to cancel all batch jobs.
178 """
179 for lang in self.getLanguages():
180 try:
181 env = self.__supportedLanguages[lang][0]
182 self.backgroundService.requestCancel(
183 'batch_{0}Syntax'.format(lang), env)
184 except KeyError:
185 continue
186
187 def __serviceError(self, fn, msg):
188 """
189 Private slot handling service errors.
190
191 @param fn file name (string)
192 @param msg message text (string)
193 """
194 self.error.emit(fn, msg)
195
196 def serviceErrorPy3(self, fx, lang, fn, msg):
197 """
198 Public method handling service errors for Python 3.
199
200 @param fx service name (string)
201 @param lang language (string)
202 @param fn file name (string)
203 @param msg message text (string)
204 """
205 if fx in ['Python3Syntax', 'batch_Python3Syntax']:
206 if fx == 'Python3Syntax':
207 self.__serviceError(fn, msg)
208 else:
209 self.__serviceError(self.tr("Python 3 batch check"), msg)
210 self.batchJobDone(fx, lang)
211
212 def serviceErrorJavaScript(self, fx, lang, fn, msg):
213 """
214 Public method handling service errors for JavaScript.
215
216 @param fx service name (string)
217 @param lang language (string)
218 @param fn file name (string)
219 @param msg message text (string)
220 """
221 if fx in ['JavaScriptSyntax', 'batch_JavaScriptSyntax']:
222 if fx == 'JavaScriptSyntax':
223 self.__serviceError(fn, msg)
224 else:
225 self.__serviceError(self.tr("JavaScript batch check"), msg)
226 self.batchJobDone(fx, lang)
227
228 def serviceErrorYAML(self, fx, lang, fn, msg):
229 """
230 Public method handling service errors for YAML.
231
232 @param fx service name (string)
233 @param lang language (string)
234 @param fn file name (string)
235 @param msg message text (string)
236 """
237 if fx in ['YAMLSyntax', 'batch_YAMLSyntax']:
238 if fx == 'YAMLSyntax':
239 self.__serviceError(fn, msg)
240 else:
241 self.__serviceError(self.tr("YAML batch check"), msg)
242 self.batchJobDone(fx, lang)
243
244 def serviceErrorJSON(self, fx, lang, fn, msg):
245 """
246 Public method handling service errors for JSON.
247
248 @param fx service name (string)
249 @param lang language (string)
250 @param fn file name (string)
251 @param msg message text (string)
252 """
253 if fx in ['JSONSyntax', 'batch_JSONSyntax']:
254 if fx == 'JSONSyntax':
255 self.__serviceError(fn, msg)
256 else:
257 self.__serviceError(self.tr("JSON batch check"), msg)
258 self.batchJobDone(fx, lang)
259
260 def serviceErrorTOML(self, fx, lang, fn, msg):
261 """
262 Public method handling service errors for TOML.
263
264 @param fx service name (string)
265 @param lang language (string)
266 @param fn file name (string)
267 @param msg message text (string)
268 """
269 if fx in ['TOMLSyntax', 'batch_TOMLSyntax']:
270 if fx == 'TOMLSyntax':
271 self.__serviceError(fn, msg)
272 else:
273 self.__serviceError(self.tr("TOML batch check"), msg)
274 self.batchJobDone(fx, lang)
275
276 def batchJobDone(self, fx, lang):
277 """
278 Public slot handling the completion of a batch job.
279
280 @param fx service name (string)
281 @param lang language (string)
282 """
283 if fx in [
284 'Python3Syntax', 'batch_Python3Syntax',
285 'JavaScriptSyntax', 'batch_JavaScriptSyntax',
286 'YAMLSyntax', 'batch_YAMLSyntax',
287 'JSONSyntax', 'batch_JSONSyntax',
288 'TOMLSyntax', 'batch_TOMLSyntax',
289 ]:
290 if lang in self.queuedBatches:
291 self.queuedBatches.remove(lang)
292 # prevent sending the signal multiple times
293 if len(self.queuedBatches) == 0 and not self.batchesFinished:
294 self.batchFinished.emit()
295 self.batchesFinished = True

eric ide

mercurial