src/eric7/Utilities/ClassBrowsers/idlclbr.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
19 import Utilities 19 import Utilities
20 import Utilities.ClassBrowsers as ClassBrowsers 20 import Utilities.ClassBrowsers as ClassBrowsers
21 from . import ClbrBaseClasses 21 from . import ClbrBaseClasses
22 22
23 SUPPORTED_TYPES = [ClassBrowsers.IDL_SOURCE] 23 SUPPORTED_TYPES = [ClassBrowsers.IDL_SOURCE]
24 24
25 _getnext = re.compile( 25 _getnext = re.compile(
26 r""" 26 r"""
27 (?P<String> 27 (?P<String>
28 " [^"\\\n]* (?: \\. [^"\\\n]*)* " 28 " [^"\\\n]* (?: \\. [^"\\\n]*)* "
29 ) 29 )
81 ) 81 )
82 82
83 | (?P<End> 83 | (?P<End>
84 [ \t]* } [ \t]* ; 84 [ \t]* } [ \t]* ;
85 )""", 85 )""",
86 re.VERBOSE | re.DOTALL | re.MULTILINE).search 86 re.VERBOSE | re.DOTALL | re.MULTILINE,
87 ).search
87 88
88 # function to replace comments 89 # function to replace comments
89 _commentsub = re.compile(r"""//[^\n]*\n|//[^\n]*$""").sub 90 _commentsub = re.compile(r"""//[^\n]*\n|//[^\n]*$""").sub
90 # function to normalize whitespace 91 # function to normalize whitespace
91 _normalize = re.compile(r"""[ \t]{2,}""").sub 92 _normalize = re.compile(r"""[ \t]{2,}""").sub
92 93
93 _modules = {} # cache of modules we've seen 94 _modules = {} # cache of modules we've seen
94 95
95 96
96 class VisibilityMixin(ClbrBaseClasses.ClbrVisibilityMixinBase): 97 class VisibilityMixin(ClbrBaseClasses.ClbrVisibilityMixinBase):
97 """ 98 """
98 Mixin class implementing the notion of visibility. 99 Mixin class implementing the notion of visibility.
99 """ 100 """
101
100 def __init__(self): 102 def __init__(self):
101 """ 103 """
102 Constructor 104 Constructor
103 """ 105 """
104 self.setPublic() 106 self.setPublic()
106 108
107 class Module(ClbrBaseClasses.Module, VisibilityMixin): 109 class Module(ClbrBaseClasses.Module, VisibilityMixin):
108 """ 110 """
109 Class to represent a CORBA IDL module. 111 Class to represent a CORBA IDL module.
110 """ 112 """
113
111 def __init__(self, module, name, file, lineno): 114 def __init__(self, module, name, file, lineno):
112 """ 115 """
113 Constructor 116 Constructor
114 117
115 @param module name of the module containing this module 118 @param module name of the module containing this module
116 @type str 119 @type str
117 @param name name of this module 120 @param name name of this module
118 @type str 121 @type str
119 @param file filename containing this module 122 @param file filename containing this module
127 130
128 class Interface(ClbrBaseClasses.Class, VisibilityMixin): 131 class Interface(ClbrBaseClasses.Class, VisibilityMixin):
129 """ 132 """
130 Class to represent a CORBA IDL interface. 133 Class to represent a CORBA IDL interface.
131 """ 134 """
135
132 def __init__(self, module, name, superClasses, file, lineno): 136 def __init__(self, module, name, superClasses, file, lineno):
133 """ 137 """
134 Constructor 138 Constructor
135 139
136 @param module name of the module containing this interface 140 @param module name of the module containing this interface
137 @type str 141 @type str
138 @param name name of this interface 142 @param name name of this interface
139 @type str 143 @type str
140 @param superClasses list of interface names this interface is 144 @param superClasses list of interface names this interface is
143 @param file filename containing this interface 147 @param file filename containing this interface
144 @type str 148 @type str
145 @param lineno line number of the interface definition 149 @param lineno line number of the interface definition
146 @type int 150 @type int
147 """ 151 """
148 ClbrBaseClasses.Class.__init__(self, module, name, superClasses, file, 152 ClbrBaseClasses.Class.__init__(self, module, name, superClasses, file, lineno)
149 lineno)
150 VisibilityMixin.__init__(self) 153 VisibilityMixin.__init__(self)
151 154
152 155
153 class Function(ClbrBaseClasses.Function, VisibilityMixin): 156 class Function(ClbrBaseClasses.Function, VisibilityMixin):
154 """ 157 """
155 Class to represent a CORBA IDL function. 158 Class to represent a CORBA IDL function.
156 """ 159 """
157 def __init__(self, module, name, file, lineno, signature='', 160
158 separator=','): 161 def __init__(self, module, name, file, lineno, signature="", separator=","):
159 """ 162 """
160 Constructor 163 Constructor
161 164
162 @param module name of the module containing this function 165 @param module name of the module containing this function
163 @type str 166 @type str
164 @param name name of this function 167 @param name name of this function
165 @type str 168 @type str
166 @param file filename containing this function 169 @param file filename containing this function
170 @param signature parameter list of the function 173 @param signature parameter list of the function
171 @type str 174 @type str
172 @param separator string separating the parameters 175 @param separator string separating the parameters
173 @type str 176 @type str
174 """ 177 """
175 ClbrBaseClasses.Function.__init__(self, module, name, file, lineno, 178 ClbrBaseClasses.Function.__init__(
176 signature, separator) 179 self, module, name, file, lineno, signature, separator
180 )
177 VisibilityMixin.__init__(self) 181 VisibilityMixin.__init__(self)
178 182
179 183
180 class Attribute(ClbrBaseClasses.Attribute, VisibilityMixin): 184 class Attribute(ClbrBaseClasses.Attribute, VisibilityMixin):
181 """ 185 """
182 Class to represent a CORBA IDL attribute. 186 Class to represent a CORBA IDL attribute.
183 """ 187 """
188
184 def __init__(self, module, name, file, lineno): 189 def __init__(self, module, name, file, lineno):
185 """ 190 """
186 Constructor 191 Constructor
187 192
188 @param module name of the module containing this attribute 193 @param module name of the module containing this attribute
189 @type str 194 @type str
190 @param name name of this attribute 195 @param name name of this attribute
191 @type str 196 @type str
192 @param file filename containing this attribute 197 @param file filename containing this attribute
209 @type list of str 214 @type list of str
210 @return the resulting dictionary 215 @return the resulting dictionary
211 @rtype dict 216 @rtype dict
212 """ 217 """
213 global _modules 218 global _modules
214 219
215 if module in _modules: 220 if module in _modules:
216 # we've seen this file before... 221 # we've seen this file before...
217 return _modules[module] 222 return _modules[module]
218 223
219 # search the path for the file 224 # search the path for the file
231 src = Utilities.readEncodedFile(file)[0] 236 src = Utilities.readEncodedFile(file)[0]
232 except (UnicodeError, OSError): 237 except (UnicodeError, OSError):
233 # can't do anything with this module 238 # can't do anything with this module
234 _modules[module] = {} 239 _modules[module] = {}
235 return {} 240 return {}
236 241
237 _modules[module] = scan(src, file, module) 242 _modules[module] = scan(src, file, module)
238 return _modules[module] 243 return _modules[module]
239 244
240 245
241 def scan(src, file, module): 246 def scan(src, file, module):
242 """ 247 """
243 Public method to scan the given source text. 248 Public method to scan the given source text.
244 249
245 @param src source text to be scanned 250 @param src source text to be scanned
246 @type str 251 @type str
247 @param file file name associated with the source text 252 @param file file name associated with the source text
248 @type str 253 @type str
249 @param module module name associated with the source text 254 @param module module name associated with the source text
250 @type str 255 @type str
251 @return dictionary containing the extracted data 256 @return dictionary containing the extracted data
252 @rtype dict 257 @rtype dict
253 """ 258 """
259
254 def calculateEndline(lineno, lines): 260 def calculateEndline(lineno, lines):
255 """ 261 """
256 Function to calculate the end line. 262 Function to calculate the end line.
257 263
258 @param lineno line number to start at (one based) 264 @param lineno line number to start at (one based)
259 @type int 265 @type int
260 @param lines list of source lines 266 @param lines list of source lines
261 @type list of str 267 @type list of str
262 @return end line (one based) 268 @return end line (one based)
276 # found a matching brace 282 # found a matching brace
277 return lineno + 1 283 return lineno + 1
278 else: 284 else:
279 # nothing found 285 # nothing found
280 return -1 286 return -1
281 287
282 def calculateMethodEndline(lineno, lines): 288 def calculateMethodEndline(lineno, lines):
283 """ 289 """
284 Function to calculate the end line. 290 Function to calculate the end line.
285 291
286 @param lineno line number to start at (one based) 292 @param lineno line number to start at (one based)
287 @type int 293 @type int
288 @param lines list of source lines 294 @param lines list of source lines
289 @type list of str 295 @type list of str
290 @return end line (one based) 296 @return end line (one based)
297 if ";" in lines[lineno]: 303 if ";" in lines[lineno]:
298 # found an end indicator, i.e. ';' 304 # found an end indicator, i.e. ';'
299 return lineno + 1 305 return lineno + 1
300 else: 306 else:
301 return -1 307 return -1
302 308
303 # convert eol markers the Python style 309 # convert eol markers the Python style
304 src = src.replace("\r\n", "\n").replace("\r", "\n") 310 src = src.replace("\r\n", "\n").replace("\r", "\n")
305 srcLines = src.splitlines() 311 srcLines = src.splitlines()
306 312
307 dictionary = {} 313 dictionary = {}
308 dict_counts = {} 314 dict_counts = {}
309 315
310 classstack = [] # stack of (class, indent) pairs 316 classstack = [] # stack of (class, indent) pairs
311 indent = 0 317 indent = 0
312 318
313 lineno, last_lineno_pos = 1, 0 319 lineno, last_lineno_pos = 1, 0
314 i = 0 320 i = 0
315 while True: 321 while True:
316 m = _getnext(src, i) 322 m = _getnext(src, i)
317 if not m: 323 if not m:
321 if m.start("Method") >= 0: 327 if m.start("Method") >= 0:
322 # found a method definition or function 328 # found a method definition or function
323 thisindent = indent 329 thisindent = indent
324 meth_name = m.group("MethodName") 330 meth_name = m.group("MethodName")
325 meth_sig = m.group("MethodSignature") 331 meth_sig = m.group("MethodSignature")
326 meth_sig = meth_sig and meth_sig.replace('\\\n', '') or '' 332 meth_sig = meth_sig and meth_sig.replace("\\\n", "") or ""
327 meth_sig = _commentsub('', meth_sig) 333 meth_sig = _commentsub("", meth_sig)
328 meth_sig = _normalize(' ', meth_sig) 334 meth_sig = _normalize(" ", meth_sig)
329 lineno += src.count('\n', last_lineno_pos, start) 335 lineno += src.count("\n", last_lineno_pos, start)
330 last_lineno_pos = start 336 last_lineno_pos = start
331 # close all interfaces/modules indented at least as much 337 # close all interfaces/modules indented at least as much
332 while classstack and classstack[-1][1] >= thisindent: 338 while classstack and classstack[-1][1] >= thisindent:
333 del classstack[-1] 339 del classstack[-1]
334 if classstack: 340 if classstack:
335 # it's an interface/module method 341 # it's an interface/module method
336 cur_class = classstack[-1][0] 342 cur_class = classstack[-1][0]
337 if isinstance(cur_class, (Interface, Module)): 343 if isinstance(cur_class, (Interface, Module)):
338 # it's a method 344 # it's a method
339 f = Function(None, meth_name, 345 f = Function(None, meth_name, file, lineno, meth_sig)
340 file, lineno, meth_sig)
341 cur_class._addmethod(meth_name, f) 346 cur_class._addmethod(meth_name, f)
342 # else it's a nested def 347 # else it's a nested def
343 else: 348 else:
344 f = None 349 f = None
345 else: 350 else:
346 # it's a function 351 # it's a function
347 f = Function(module, meth_name, 352 f = Function(module, meth_name, file, lineno, meth_sig)
348 file, lineno, meth_sig)
349 if meth_name in dict_counts: 353 if meth_name in dict_counts:
350 dict_counts[meth_name] += 1 354 dict_counts[meth_name] += 1
351 meth_name = "{0}_{1:d}".format( 355 meth_name = "{0}_{1:d}".format(meth_name, dict_counts[meth_name])
352 meth_name, dict_counts[meth_name])
353 else: 356 else:
354 dict_counts[meth_name] = 0 357 dict_counts[meth_name] = 0
355 dictionary[meth_name] = f 358 dictionary[meth_name] = f
356 if f: 359 if f:
357 endline = calculateMethodEndline(lineno, srcLines) 360 endline = calculateMethodEndline(lineno, srcLines)
366 thisindent = indent 369 thisindent = indent
367 indent += 1 370 indent += 1
368 # close all interfaces/modules indented at least as much 371 # close all interfaces/modules indented at least as much
369 while classstack and classstack[-1][1] >= thisindent: 372 while classstack and classstack[-1][1] >= thisindent:
370 del classstack[-1] 373 del classstack[-1]
371 lineno += src.count('\n', last_lineno_pos, start) 374 lineno += src.count("\n", last_lineno_pos, start)
372 last_lineno_pos = start 375 last_lineno_pos = start
373 class_name = m.group("InterfaceName") 376 class_name = m.group("InterfaceName")
374 inherit = m.group("InterfaceSupers") 377 inherit = m.group("InterfaceSupers")
375 if inherit: 378 if inherit:
376 # the interface inherits from other interfaces 379 # the interface inherits from other interfaces
377 inherit = inherit[1:].strip() 380 inherit = inherit[1:].strip()
378 inherit = [_commentsub('', inherit)] 381 inherit = [_commentsub("", inherit)]
379 # remember this interface 382 # remember this interface
380 cur_class = Interface(module, class_name, inherit, 383 cur_class = Interface(module, class_name, inherit, file, lineno)
381 file, lineno)
382 endline = calculateEndline(lineno, srcLines) 384 endline = calculateEndline(lineno, srcLines)
383 cur_class.setEndLine(endline) 385 cur_class.setEndLine(endline)
384 if not classstack: 386 if not classstack:
385 dictionary[class_name] = cur_class 387 dictionary[class_name] = cur_class
386 else: 388 else:
393 thisindent = indent 395 thisindent = indent
394 indent += 1 396 indent += 1
395 # close all interfaces/modules indented at least as much 397 # close all interfaces/modules indented at least as much
396 while classstack and classstack[-1][1] >= thisindent: 398 while classstack and classstack[-1][1] >= thisindent:
397 del classstack[-1] 399 del classstack[-1]
398 lineno += src.count('\n', last_lineno_pos, start) 400 lineno += src.count("\n", last_lineno_pos, start)
399 last_lineno_pos = start 401 last_lineno_pos = start
400 module_name = m.group("ModuleName") 402 module_name = m.group("ModuleName")
401 # remember this module 403 # remember this module
402 cur_class = Module(module, module_name, file, lineno) 404 cur_class = Module(module, module_name, file, lineno)
403 endline = calculateEndline(lineno, srcLines) 405 endline = calculateEndline(lineno, srcLines)
405 if not classstack: 407 if not classstack:
406 dictionary[module_name] = cur_class 408 dictionary[module_name] = cur_class
407 classstack.append((cur_class, thisindent)) 409 classstack.append((cur_class, thisindent))
408 410
409 elif m.start("Attribute") >= 0: 411 elif m.start("Attribute") >= 0:
410 lineno += src.count('\n', last_lineno_pos, start) 412 lineno += src.count("\n", last_lineno_pos, start)
411 last_lineno_pos = start 413 last_lineno_pos = start
412 index = -1 414 index = -1
413 while index >= -len(classstack): 415 while index >= -len(classstack):
414 if ( 416 if (
415 classstack[index][0] is not None and 417 classstack[index][0] is not None
416 not isinstance(classstack[index][0], Function) and 418 and not isinstance(classstack[index][0], Function)
417 classstack[index][1] < indent 419 and classstack[index][1] < indent
418 ): 420 ):
419 attributes = m.group("AttributeNames").split(',') 421 attributes = m.group("AttributeNames").split(",")
420 ro = m.group("AttributeReadonly") 422 ro = m.group("AttributeReadonly")
421 for attribute in attributes: 423 for attribute in attributes:
422 attr = Attribute(module, attribute, file, lineno) 424 attr = Attribute(module, attribute, file, lineno)
423 if ro: 425 if ro:
424 attr.setPrivate() 426 attr.setPrivate()

eric ide

mercurial