eric6/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckService.py

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

eric ide

mercurial