File indexing completed on 2024-12-08 04:20:21
0001 # -*- coding: utf-8 -*- 0002 # Copyright 2009 Simon Edwards <simon@simonzone.com> 0003 # 0004 # This program is free software; you can redistribute it and/or modify 0005 # it under the terms of the GNU General Public License as published by 0006 # the Free Software Foundation; either version 2 of the License, or 0007 # (at your option) any later version. 0008 # 0009 # This program is distributed in the hope that it will be useful, 0010 # but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 # GNU General Public License for more details. 0013 # 0014 # You should have received a copy of the GNU General Public License 0015 # along with this program; if not, write to the 0016 # Free Software Foundation, Inc., 0017 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0018 0019 import os.path 0020 import re 0021 from .sealed import sealed 0022 import kbindinggenerator.sipsymboldata as sipsymboldata 0023 import kbindinggenerator.cppsymboldata as cppsymboldata 0024 0025 class CppToSipTransformer(object): 0026 @sealed 0027 def __init__(self): 0028 self._sipsym = None 0029 self._exportMacros = None 0030 self._ignoredBaseClasses = [] 0031 self._copyrightNotice = None 0032 self._cppScope = None 0033 0034 def setExportMacros(self, macroList): 0035 self._exportMacros = set(macroList) if macroList is not None else None 0036 0037 def setIgnoreBaseClasses(self, baseClassList): 0038 self._ignoredBaseClasses = baseClassList if baseClassList is not None else [] 0039 0040 def setCopyrightNotice(self,noticeText): 0041 self._copyrightNotice = noticeText 0042 0043 def convert(self, cppScope, sipsymboldata): 0044 self._cppScope = cppScope 0045 self._sipsym = sipsymboldata 0046 sipScope = self._sipsym.newScope() 0047 sipScope.setHeaderFilename(cppScope.headerFilename()) 0048 0049 if self._copyrightNotice is not None: 0050 for line in self._copyrightNotice.split('\n'): 0051 comment = self._sipsym.Comment(sipScope) 0052 comment.setValue(line+'\n') 0053 0054 self._convertScope(cppScope,sipScope) 0055 return sipScope 0056 0057 def _convertScope(self,cppScope,destScope): 0058 for item in cppScope: 0059 #print("==================================") 0060 #print(item.format()) 0061 if isinstance(item,cppsymboldata.SymbolData.CppClass): 0062 self._convertClass(item,destScope) 0063 0064 elif isinstance(item,cppsymboldata.SymbolData.Function): 0065 self._convertFunction(item,destScope) 0066 0067 elif isinstance(item,cppsymboldata.SymbolData.Variable): 0068 self._convertVariable(item,destScope) 0069 0070 elif isinstance(item,cppsymboldata.SymbolData.Namespace): 0071 self._convertNamespace(item,destScope) 0072 0073 elif isinstance(item,cppsymboldata.SymbolData.Enum): 0074 self._convertEnum(item,destScope) 0075 0076 elif isinstance(item,cppsymboldata.SymbolData.EnumTypedef): 0077 self._convertEnumTypedef(item,destScope) 0078 0079 elif isinstance(item,cppsymboldata.SymbolData.Typedef): 0080 self._convertTypedef(item,destScope) 0081 0082 def _convertFunction(self,cppFunction,destScope): 0083 isCtor = isinstance(cppFunction,cppsymboldata.SymbolData.Constructor) 0084 isDtor = isinstance(cppFunction,cppsymboldata.SymbolData.Destructor) 0085 0086 if len(cppFunction.template())!=0: 0087 # Ignore templated functions. 0088 return 0089 0090 # Private funcions/methods are not copied. 0091 if cppFunction.access()==cppsymboldata.SymbolData.ACCESS_PRIVATE and not isCtor and not isDtor: 0092 return 0093 0094 # Ignore these operators. 0095 if cppFunction.name() in ['operator =', 'operator ++', 'operator --']: 0096 return 0097 0098 if isCtor: 0099 sipFunction = self._sipsym.Constructor(destScope,cppFunction.name(),filename=cppFunction._filename,lineno=cppFunction._lineno) 0100 elif isDtor: 0101 sipFunction = self._sipsym.Destructor(destScope,cppFunction.name(),filename=cppFunction._filename,lineno=cppFunction._lineno) 0102 else: 0103 sipFunction = self._sipsym.Function(destScope,cppFunction.name(),filename=cppFunction._filename,lineno=cppFunction._lineno) 0104 sipFunction.setReturn(self._convertArgument(cppFunction.return_())) 0105 sipFunction.setAccess(cppFunction.access()) 0106 sipFunction.setArguments( [self._convertArgument(x) for x in cppFunction.arguments() if x.argumentType()!="void"] ) 0107 if cppFunction.storage()=='static': 0108 sipFunction.setStorage('static') 0109 0110 for qual in cppFunction.qualifier(): 0111 sipFunction.addQualifier(qual) 0112 0113 def _convertClass(self,cppClass,parentScope): 0114 if not self._isClassExported(cppClass) or cppClass.opaque(): 0115 return None 0116 0117 sipClass = self._sipsym.SipClass(parentScope, cppClass.name(),filename=cppClass._filename,lineno=cppClass._lineno) 0118 sipClass.setBases( [base for base in cppClass.bases() if base not in self._ignoredBaseClasses] ) 0119 0120 if self._cppScope.headerFilename() is not None: 0121 includeDirective = self._sipsym.SipDirective(sipClass,"%TypeHeaderCode") 0122 includeDirective.setBody( 0123 """%%TypeHeaderCode 0124 #include <%s> 0125 %%End 0126 """ % (self._cppScope.headerFilename(),)) 0127 0128 self._convertScope(cppClass,sipClass) 0129 0130 def _isClassExported(self,cppClass): 0131 if self._exportMacros is not None: 0132 if self._exportMacros.isdisjoint( set( (x.name() for x in cppClass.macros()))): 0133 return False 0134 return True 0135 0136 def _convertArgument(self,cppArgument): 0137 argumentType = cppArgument.argumentType() 0138 argumentType = { 0139 'short int': 'short', 0140 'unsigned short int': 'unsigned short', 0141 'long unsigned int': 'unsigned long' 0142 }.get(argumentType,argumentType) 0143 0144 defaultValue = cppArgument.defaultValue() 0145 if defaultValue=='true': 0146 defaultValue = '1' 0147 if defaultValue=='false': 0148 defaultValue = '0' 0149 0150 return self._sipsym.Argument(argumentType, cppArgument.name(), defaultValue) 0151 0152 def _convertVariable(self,cppVariable,parentScope): 0153 if cppVariable.access()!=cppsymboldata.SymbolData.ACCESS_PUBLIC: 0154 return 0155 0156 sipVariable = self._sipsym.Variable(parentScope, cppVariable.name()) 0157 sipVariable.setArgument(self._convertArgument(cppVariable.argument())) 0158 if cppVariable.storage()=='static': 0159 sipVariable.setStorage('static') 0160 sipVariable.setAccess(cppVariable.access()) 0161 return sipVariable 0162 0163 def _convertNamespace(self,cppNamespace,parentScope): 0164 sipNamespace = self._sipsym.Namespace(parentScope, cppNamespace.name()) 0165 self._convertScope(cppNamespace,sipNamespace) 0166 if len(sipNamespace)==0: 0167 del parentScope[parentScope.index(sipNamespace)] 0168 0169 def _convertEnum(self,cppEnum,parentScope): 0170 if cppEnum.access()==cppsymboldata.SymbolData.ACCESS_PRIVATE: 0171 return 0172 0173 sipEnum = self._sipsym.Enum(parentScope, cppEnum.name()) 0174 sipEnum.setAccess(cppEnum.access()) 0175 for item in cppEnum: 0176 sipEnum.append(self._sipsym.Enumerator(item.name(),item.value())) 0177 0178 def _convertTypedef(self,cppTypedef,parentScope): 0179 sipTypedef = self._sipsym.Typedef(parentScope, cppTypedef.name(), 0180 filename=cppTypedef._filename,lineno=cppTypedef._lineno) 0181 sipTypedef.setAccess(cppTypedef.access()) 0182 sipTypedef.setArgumentType(cppTypedef.argumentType()) 0183 return sipTypedef 0184 0185 def _convertEnumTypedef(self,cppEnumTypedef,parentScope): 0186 sipEnum = self._sipsym.Enum(parentScope, cppEnumTypedef.name()) 0187 sipEnum.setAccess(cppEnumTypedef.enum().access()) 0188 for item in cppEnumTypedef.enum(): 0189 sipEnum.append(item) 0190 return sipEnum 0191 0192 ########################################################################### 0193 def ExpandClassNames(sipsym,scope): 0194 for item in scope: 0195 if isinstance(item,sipsym.SipClass): 0196 _ExpandClassNamesForClass(sipsym,item) 0197 0198 elif isinstance(item,sipsym.Namespace): 0199 ExpandClassNames(sipsym,item) 0200 0201 elif isinstance(item,sipsym.Constructor): 0202 _ExpandClassNamesForArguments(sipsym,scope,item) 0203 0204 elif isinstance(item,sipsym.Function): 0205 _ExpandClassNamesForFunction(sipsym,scope,item) 0206 0207 elif isinstance(item,sipsym.Variable): 0208 _ExpandClassNamesForVariable(sipsym,scope,item) 0209 0210 def _ExpandClassNamesForClass(sipsym,sipClass): 0211 # Use FQNs when talking about base classes, otherwise SIP fails. 0212 fqnBaseList = [] 0213 for base in sipClass.bases(): 0214 try: 0215 baseObject = sipsym.lookupType(base,sipClass.parentScope()) 0216 fqnBaseList.append(baseObject.fqName()) 0217 except KeyError: 0218 fqnBaseList.append(base) 0219 sipClass.setBases(fqnBaseList) 0220 0221 ExpandClassNames(sipsym,sipClass) 0222 0223 def _ExpandClassNamesForFunction(sipsym,context,sipFunction): 0224 sipFunction.setReturn(_ExpandArgument(sipsym,context,sipFunction.return_())) 0225 0226 _ExpandClassNamesForArguments(sipsym,context,sipFunction) 0227 0228 def _ExpandClassNamesForVariable(sipsym,context,sipVariable): 0229 sipVariable.setArgument(_ExpandArgument(sipsym,context,sipVariable.argument())) 0230 0231 def _ExpandClassNamesForArguments(sipsym,context,sipFunction): 0232 sipFunction.setArguments( [_ExpandArgument(sipsym,context,argument) for argument in sipFunction.arguments()] ) 0233 0234 _PrimitiveTypes = ["char","signed char","unsigned char","wchar_t","int","unsigned", 0235 "unsigned int","short","unsigned short","long","unsigned long","long long", 0236 "unsigned long long","float","double","bool","void"] 0237 0238 _templateArgRegex = re.compile(r'^([^<]*)<(.*)>$') 0239 0240 def _ExpandArgument(sipsym,context,argument): 0241 className = _ExpandArgumentType(sipsym,context,argument.argumentType()) 0242 0243 defaultValue = argument.defaultValue() 0244 if defaultValue is not None: 0245 if defaultValue.endswith("()"): 0246 try: 0247 valueObject = sipsym.lookupType(defaultValue[:-2],context) 0248 defaultValue = valueObject.fqName() + "()" 0249 except KeyError: 0250 pass 0251 else: 0252 enum = sipsym.lookupEnum(defaultValue,context) 0253 if enum is not None and enum.name() is not None: 0254 defaultValue = enum.fqName() + "::" + defaultValue 0255 else: 0256 try: 0257 valueObject = sipsym.lookupType(defaultValue,context) 0258 defaultValue = valueObject.fqName() 0259 except KeyError: 0260 pass 0261 0262 newArgument = sipsym.Argument(className, argument.name(), defaultValue, 0263 argument.template(), argument.defaultTypes()) 0264 newArgument.setAnnotations(argument.annotations()) 0265 return newArgument 0266 0267 def _ExpandArgumentType(sipsym,context,origClassName): 0268 className = origClassName 0269 0270 suffix = "" 0271 if className.endswith('*'): 0272 className = className[:-1] 0273 suffix = '*' 0274 if className.endswith('&'): 0275 className = className[:-1] 0276 suffix = '&' 0277 0278 prefix = "" 0279 if className.startswith("const "): 0280 className = className[6:] 0281 prefix = "const " 0282 0283 match = re.match(_templateArgRegex,className) 0284 if match is not None: 0285 # Got a templated thingy. 0286 firstPart = _ExpandArgumentType(sipsym,context,match.group(1)) 0287 containedPart = _ExpandArgumentType(sipsym,context,match.group(2)) 0288 return "%s%s<%s>%s" % (prefix,firstPart,containedPart,suffix) 0289 0290 else: 0291 if className not in _PrimitiveTypes: 0292 # return argument 0293 try: 0294 classObject = sipsym.lookupType(className,context) 0295 if classObject.fqName()==className: 0296 return origClassName # Nothing to do. 0297 className = classObject.fqName() 0298 except KeyError: 0299 print("Warning: %s Unrecognized type '%s' was found when expanding argument type names." % (context.sourceLocation(),className)) 0300 return origClassName 0301 0302 return prefix + className + suffix 0303 0304 ########################################################################### 0305 class MethodAnnotationRule(object): 0306 @sealed 0307 def __init__(self,methodTypeMatch,parameterTypeMatch,parameterNameMatch,annotations): 0308 self._methodTypeMatch = methodTypeMatch 0309 0310 if parameterTypeMatch=='*': 0311 self._parameterTypeMatch = None 0312 else: 0313 self._parameterTypeMatch = set([parameterTypeMatch]) if isinstance(parameterTypeMatch,str) else set(parameterTypeMatch) 0314 0315 self._parameterNameMatch = set([parameterNameMatch]) if isinstance(parameterNameMatch,str) else set(parameterNameMatch) 0316 self._annotations = [annotations] if isinstance(annotations,str) else annotations 0317 0318 def apply(self,symbolData,sipFunction,sipClass): 0319 matchCtor = self._methodTypeMatch in ('ctor','all') 0320 matchDtor = self._methodTypeMatch in ('dtor','all') 0321 matchFunc = self._methodTypeMatch in ('function','all') 0322 0323 isCtor = isinstance(sipFunction,symbolData.Constructor) 0324 isDtor = isinstance(sipFunction,symbolData.Destructor) 0325 isFunc = isinstance(sipFunction,symbolData.Function) 0326 if (matchCtor and isCtor) or (matchDtor and isDtor) or \ 0327 (matchFunc and isFunc and not isCtor and not isDtor): 0328 for argument in sipFunction.arguments(): 0329 if self._parameterTypeMatch is None or argument.argumentType() in self._parameterTypeMatch: 0330 if argument.name() in self._parameterNameMatch: 0331 newAnnotations = list(argument.annotations()) 0332 for anno in self._annotations: 0333 if anno not in newAnnotations: 0334 newAnnotations.append(anno) 0335 argument.setAnnotations(newAnnotations) 0336 0337 def __str__(self): 0338 return "ClassMatch: " + repr(self._classMatch) + " MethodTypeMatch: " + methodTypeMatch + \ 0339 " MethodNameMatch: " + repr(methodNameMatch) + " Annotations: " + repr(self._annotations) 0340 0341 class PySlotRule(object): 0342 @sealed 0343 def __init__(self,className=None,namespaceName=None,arg1Name=None,arg2Name=None): 0344 self._className = className 0345 self._namespaceName = namespaceName 0346 self._arg1Name = arg1Name 0347 self._arg2Name = arg2Name 0348 0349 def apply(self,symbolData,sipFunction,sipClassOrNamespace): 0350 if self._className is not None and not isinstance(sipClassOrNamespace,symbolData.SipClass): 0351 return 0352 if self._namespaceName is not None and not isinstance(sipClassOrNamespace,symbolData.Namespace): 0353 return 0354 0355 if isinstance(sipFunction,symbolData.Function): 0356 args = sipFunction.arguments() 0357 if len(args) >= 2: 0358 for i in range(len(args)-1): 0359 arg1 = args[i] 0360 arg2 = args[i+1] 0361 if arg1.name()==self._arg1Name and arg2.name()==self._arg2Name: 0362 args = list(args) 0363 newArg1 = symbolData.Argument("SIP_RXOBJ_CON", None, None, None, None) 0364 args[i] = newArg1 0365 0366 newArg2 = symbolData.Argument("SIP_SLOT_CON ()", None, None, None, None) 0367 args[i+1] = newArg2 0368 sipFunction.setArguments(args) 0369 break 0370 0371 def __str__(self): 0372 return "PySlotRule ClassName: " + self._className + " Arg1: " + self._arg1 + " Arg2: " + self._arg2 0373 0374 class SipAnnotator(object): 0375 @sealed 0376 def __init__(self): 0377 self._methodAnnotationRules = None 0378 self._sipsym = sipsymboldata.SymbolData() 0379 0380 def setMethodAnnotationRules(self,rules): 0381 self._methodAnnotationRules = rules 0382 0383 def applyRules(self,sipTree): 0384 for item in sipTree: 0385 if isinstance(item,self._sipsym.SipClass) or isinstance(item,self._sipsym.Namespace): 0386 self._applyRulesToClassOrNamespace(item) 0387 0388 def _applyRulesToClassOrNamespace(self,sipClass): 0389 for item in sipClass: 0390 if isinstance(item,self._sipsym.Function): 0391 self._applyRulesToFunction(self._methodAnnotationRules,item,sipClass) 0392 elif isinstance(item,self._sipsym.Constructor): 0393 self._applyRulesToFunction(self._methodAnnotationRules,item,sipClass) 0394 elif isinstance(item,self._sipsym.Destructor): 0395 self._applyRulesToFunction(self._methodAnnotationRules,item,sipClass) 0396 0397 self.applyRules(sipClass) 0398 0399 def _applyRulesToFunction(self,rules,sipFunction,sipClass=None): 0400 for rule in rules: 0401 rule.apply(self._sipsym, sipFunction, sipClass) 0402 0403 ########################################################################### 0404 0405 def UpdateConvertToSubClassCodeDirectives(symbolData,scopeList,ignoreClassList=[]): 0406 """Insert of update CTSCC directives 0407 0408 Insert or update the Sip ConvertToSubClassCode directives in the given list of scopes. 0409 0410 Keyword arguments: 0411 symbolData -- 0412 scopeList -- List of scopes containing the classes which need to be updated. 0413 ignoreClassList -- List of class names which should be ignored. 0414 """ 0415 _UpdateConvertToSubClassCodeDirectives(symbolData,scopeList,ignoreClassList).run() 0416 0417 class _UpdateConvertToSubClassCodeDirectives(object): 0418 def __init__(self,symbolData,scopeList,ignoreClassList): 0419 self._symbolData = symbolData 0420 self._scopeList = scopeList 0421 self._ignoreClassList = ignoreClassList 0422 self._subclassList = None 0423 self.INDENT = " " 0424 0425 def run(self): 0426 if len(self._scopeList)==0: 0427 return 0428 0429 # Collect all of the classes that we need to consider. 0430 self._classList = self._findClasses(self._scopeList) 0431 0432 # Filter out uninteresting classes from the _classList. 0433 # FIXME compare the fqn instead of name(). 0434 self._subclassList = [class_ for class_ in self._classList 0435 if len(class_.bases())!=0 and class_.name() not in self._ignoreClassList] 0436 0437 # Build a mapping from class objects to their subclasses. 0438 classToSubclassMapping = {} 0439 topSuperClasses = set() 0440 for class_ in self._subclassList: 0441 topSuperClass = self._updateSubclassBaseMapping(classToSubclassMapping,class_) 0442 if topSuperClass is None: 0443 topSuperClass = class_ 0444 topSuperClasses.add(topSuperClass) 0445 0446 for class_ in topSuperClasses: 0447 self._insertCTSCC(classToSubclassMapping,class_) 0448 0449 def _updateSubclassBaseMapping(self,mapping,class_): 0450 lastBase = None 0451 0452 for baseName in class_.bases(): 0453 try: 0454 base = self._symbolData.lookupType(baseName,class_.parentScope()) 0455 if isinstance(base, self._symbolData.Typedef): 0456 print("Warning: %s Skipping typedef base '%s' while updating CTSCC." % (class_.sourceLocation(),baseName)) 0457 continue 0458 0459 if lastBase is None: 0460 lastBase = base 0461 subClassList = mapping.setdefault(base,set()) 0462 subClassList.add(class_) 0463 top = self._updateSubclassBaseMapping(mapping,base) 0464 if top is not None: 0465 lastBase = top 0466 except KeyError: 0467 print("Warning: %s Unrecognized type '%s' was found when updating CTSCC." % (class_.sourceLocation(),baseName)) 0468 return lastBase 0469 0470 def _generateCTSCC(self,classToSubclassMapping,class_): 0471 return "%%ConvertToSubClassCode\n // CTSCC for subclasses of '%s'\n sipType = NULL;\n\n%s%%End" % (class_.name(),self._generateCTSCCPart(classToSubclassMapping,class_,self.INDENT)) 0472 0473 def _generateCTSCCPart(self,classToSubclassMapping,class_,indent="",joiner=""): 0474 accu = [] 0475 0476 subclasses = list(classToSubclassMapping.get(class_,set())) 0477 def namekey(class_): return class_.fqName() 0478 subclasses.sort(key=namekey) 0479 0480 if class_ in self._subclassList: 0481 accu.append(indent) 0482 accu.append(joiner) 0483 joiner = "" 0484 accu.append("if (dynamic_cast<") 0485 accu.append(class_.fqName()) 0486 accu.append("*>(sipCpp))\n") 0487 if len(subclasses)!=0: 0488 accu.append(indent); 0489 accu.append(self.INDENT) 0490 accu.append("{\n") 0491 0492 if class_ in self._subclassList: 0493 accu.append(indent) 0494 accu.append(self.INDENT) 0495 accu.append("sipType = sipType_") 0496 accu.append(class_.fqName().replace("::","_")) 0497 accu.append(";\n") 0498 extraIndent = self.INDENT 0499 else: 0500 extraIndent = "" 0501 0502 for subclass in subclasses: 0503 accu.append(self._generateCTSCCPart(classToSubclassMapping,subclass,indent+extraIndent,joiner)) 0504 joiner = "else " 0505 0506 if class_ in self._subclassList and len(subclasses)!=0: 0507 accu.append(indent) 0508 accu.append(self.INDENT) 0509 accu.append("}\n") 0510 0511 return "".join(accu) 0512 0513 def _insertCTSCC(self,classToSubclassMapping,class_): 0514 subclasses = self._findAllSubclasses(classToSubclassMapping,class_) 0515 subclasses.append(class_) 0516 0517 # Find an existing %ConvertToSubClassCode block. 0518 directiveClass = None 0519 for subclass in subclasses: 0520 directive = self._findDirective(subclass,"%ConvertToSubClassCode") 0521 if directive is not None: 0522 directiveClass = subclass 0523 break 0524 else: 0525 # Create a new %ConvertToSubClassCode block. 0526 # Try the root first. 0527 if class_ in self._classList: 0528 directiveClass = class_ 0529 else: 0530 # Choose a subclass, use the first one by name. 0531 def namekey(class_): return class_.name() 0532 subclasses.sort(key=namekey) 0533 directiveClass = subclasses[0] 0534 directive = self._symbolData.SipDirective(directiveClass,"%ConvertToSubClassCode") 0535 directive.setBody(self._generateCTSCC(classToSubclassMapping,class_)) 0536 0537 # Update the %TypeHeaderCode #include list. 0538 headerCode = self._findDirective(directiveClass.topScope(),"%ModuleHeaderCode") 0539 if headerCode is None: 0540 headerCode = self._symbolData.SipDirective(directiveClass.topScope(),"%ModuleHeaderCode") 0541 0542 fileScopes = list(set( (subclass.topScope().headerFilename() for subclass in subclasses) )) 0543 def key(x): return os.path.basename(x) 0544 fileScopes.sort(key=key) 0545 0546 headerCode.setBody("%ModuleHeaderCode\n//ctscc\n" + 0547 "".join(["#include <"+str(x)+">\n" for x in fileScopes]) + 0548 "%End") 0549 0550 def _findDirective(self,class_,directiveName): 0551 for item in class_: 0552 if isinstance(item,self._symbolData.SipDirective): 0553 if item.name()==directiveName: 0554 return item 0555 return None 0556 0557 def _findAllSubclasses(self,classToSubclassMapping,class_): 0558 result = [] 0559 if class_ in self._subclassList: 0560 result.append(class_) 0561 for subclass in classToSubclassMapping.get(class_,[]): 0562 result.extend(self._findAllSubclasses(classToSubclassMapping,subclass)) 0563 return result 0564 0565 def _findClasses(self,scope): 0566 classList = [] 0567 for item in scope: 0568 if isinstance(item,self._symbolData.SipClass): 0569 classList.append(item) 0570 if isinstance(item,self._symbolData.Entity): 0571 classList.extend(self._findClasses(item)) 0572 return classList 0573 0574 ########################################################################### 0575 def SanityCheckSip(symbolData,scopeList): 0576 _SanityCheckSip(symbolData,scopeList).run() 0577 0578 class _SanityCheckSip(object): 0579 def __init__(self,symbolData,scopeList): 0580 self._symbolData = symbolData 0581 self._scopeList = scopeList 0582 0583 def run(self): 0584 for scope in self._scopeList: 0585 self._checkScope(scope) 0586 0587 def _checkScope(self,scope): 0588 for item in scope: 0589 if isinstance(item,self._symbolData.SipClass): 0590 self._checkClass(item) 0591 elif isinstance(item,self._symbolData.Function): 0592 self._checkFunction(item) 0593 0594 def _checkClass(self,sipClass): 0595 # Check the base classes. 0596 for baseName in sipClass.bases(): 0597 try: 0598 self._symbolData.lookupType(baseName,sipClass.parentScope()) 0599 except KeyError: 0600 print("Error: %s Unknown base class '%s'" % (sipClass.sourceLocation(),baseName)) 0601 0602 for item in sipClass: 0603 if isinstance(item,self._symbolData.Constructor) or isinstance(item,self._symbolData.Destructor) or \ 0604 isinstance(item,self._symbolData.Function): 0605 self._checkFunction(item) 0606 0607 def _checkFunction(self,function): 0608 if function.ignore(): 0609 return 0610 0611 for arg in function.arguments(): 0612 if arg.argumentType().endswith('&') and 'In' not in arg.annotations() and 'Out' not in arg.annotations(): 0613 print("Error: %s Parameter '%s' requires a /In/ or /Out/ annotation." % (function.sourceLocation(),arg.name()))