File indexing completed on 2024-12-01 07:28:02
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 def MergeSipScope(sipsym,primaryScope,updateScope): 0020 """ 0021 Updates the given primary scope using the content of the update scope. 0022 The primary scope typically contains extra annotations and edits which 0023 have been added by hand. This function updates the primary scope with 0024 function, class and method etc contents of the update scope while 0025 trying to preserve any manually added annoations etc. 0026 0027 Keyword arguments: 0028 primaryScope -- A `sipsymboldata.SymbolData.Scope` 0029 updateScope -- A `sipsymboldata.SymbolData.Scope` object. Update information is taken from here and merged into the primary scope. 0030 """ 0031 newScope = primaryScope 0032 oldScope = updateScope 0033 primaryFunctionMap = {} 0034 primaryClassMap = {} 0035 primaryNamespaceMap = {} 0036 primaryEnumMap = {} 0037 primaryTypedefMap = {} 0038 0039 handledFunctions = set() 0040 0041 # Index the primary scope 0042 for item in primaryScope: 0043 if isinstance(item,sipsym.Function) or isinstance(item,sipsym.Constructor) or isinstance(item,sipsym.Destructor): 0044 primaryFunctionMap[_MangleFunctionName(sipsym,item)] = item 0045 elif isinstance(item,sipsym.SipClass): 0046 primaryClassMap[item.fqName()] = item 0047 elif isinstance(item,sipsym.Namespace): 0048 primaryNamespaceMap[item.fqName()] = item 0049 elif isinstance(item,sipsym.Enum): 0050 primaryEnumMap[item.fqName()] = item 0051 elif isinstance(item,sipsym.Typedef): 0052 primaryTypedefMap[item.fqName()] = item 0053 0054 # Update 0055 for item in updateScope[:]: 0056 # Loop over a copy of the item because we might change the list on the fly. 0057 0058 if isinstance(item,sipsym.Function) or isinstance(item,sipsym.Constructor) or isinstance(item,sipsym.Destructor): 0059 mangledName = _MangleFunctionName(sipsym,item) 0060 if mangledName in primaryFunctionMap: 0061 _MergeSipFunction(sipsym,primaryFunctionMap[mangledName],item) 0062 del primaryFunctionMap[mangledName] 0063 handledFunctions.add(mangledName) 0064 else: 0065 # New function. 0066 if mangledName not in handledFunctions: 0067 primaryScope.append(item) 0068 0069 elif isinstance(item,sipsym.SipClass): 0070 if item.fqName() in primaryClassMap: 0071 _MergeSipClass(sipsym,primaryClassMap[item.fqName()],item) 0072 else: 0073 # New class 0074 primaryScope.append(item) 0075 0076 elif isinstance(item,sipsym.Namespace): 0077 if item.fqName() in primaryNamespaceMap: 0078 primaryNamespace = primaryNamespaceMap[item.fqName()] 0079 if not primaryNamespace.ignore(): 0080 MergeSipScope(sipsym,primaryNamespace,item) 0081 else: 0082 # New namespace 0083 primaryScope.append(item) 0084 0085 elif isinstance(item,sipsym.Enum): 0086 if item.fqName() in primaryEnumMap: 0087 _MergeEnum(sipsym,primaryEnumMap[item.fqName()],item) 0088 del primaryEnumMap[item.fqName()] 0089 else: 0090 # New enum 0091 primaryScope.append(item) 0092 0093 elif isinstance(item,sipsym.Typedef): 0094 # FIXME Try to be independant from Qt not hard code QFlags in. 0095 if item.argumentType() is not None and "QFlags" in item.argumentType(): 0096 if item.fqName() not in primaryTypedefMap: 0097 primaryScope.append(item) 0098 else: 0099 print("Warning: Skipping typdef " +str(item)) 0100 else: 0101 if not isinstance(item,sipsym.SipDirective) and not isinstance(item,sipsym.Comment): 0102 print("Warning: Unknown object " +str(item)) 0103 0104 # Handle any left over functions which are forced. 0105 for primaryFunctionName,function in primaryFunctionMap.items(): 0106 if not function.force(): 0107 del primaryScope[primaryScope.index(function)] 0108 0109 for primaryEnumName,enum in primaryEnumMap.items(): 0110 if not enum.force(): 0111 del primaryScope[primaryScope.index(enum)] 0112 0113 primaryScope._fixScope() 0114 0115 def _MergeSipFunction(sipsym,primaryFunction,updateFunction): 0116 if updateFunction.annotations() is not None: 0117 annotations = set(updateFunction.annotations()) 0118 if primaryFunction.annotations() is not None: 0119 annotations.update(primaryFunction.annotations()) 0120 primaryFunction.setAnnotations(annotations) 0121 0122 # Update the arguments by name. 0123 0124 def name(item): 0125 if item.name() is not None and name!="": 0126 return item.name() 0127 else: 0128 return "$a" + str(i) 0129 0130 primaryArguments = {} 0131 i = 0 0132 for arg in primaryFunction.arguments(): 0133 primaryArguments[name(arg)] = arg 0134 i += 1 0135 0136 newArguments = [] 0137 i = 0 0138 for updateArg in updateFunction.arguments(): 0139 if name(updateArg) in primaryArguments: 0140 newArguments.append(_MergeArgument(sipsym,primaryArguments[name(updateArg)],updateArg)) 0141 else: 0142 newArguments.append(_MergeArgument(sipsym,updateArg,updateArg)) 0143 i += 1 0144 0145 primaryFunction.setArguments(newArguments) 0146 0147 def _MangleFunctionName(sipsym,function): 0148 name = function.name() 0149 if isinstance(function,sipsym.Destructor): 0150 name = "~" + name 0151 0152 name = name + '(' + \ 0153 ','.join([arg.argumentType() for arg in function.arguments() if arg.defaultValue() is None]) + ')' 0154 0155 if 'const' in function._qualifier: 0156 name = name + " const" 0157 0158 return name 0159 0160 def _MergeArgument(sipsym,primaryArgument,updateArgument): 0161 resultArg = sipsym.Argument(primaryArgument.argumentType(), 0162 primaryArgument.name(), 0163 primaryArgument.defaultValue(), 0164 primaryArgument.template(), 0165 primaryArgument.defaultTypes()) 0166 0167 annotations = list(primaryArgument.annotations()) 0168 for anno in updateArgument.annotations(): 0169 if anno not in annotations: 0170 annotations.append(anno) 0171 0172 resultArg.setAnnotations(annotations) 0173 return resultArg 0174 0175 def _MergeSipClass(sipsym,primaryClass,updateClass): 0176 annotations = list(updateClass.annotations()) 0177 for anno in primaryClass.annotations(): 0178 if anno not in annotations: 0179 annotations.append(anno) 0180 primaryClass.setAnnotations(annotations) 0181 0182 MergeSipScope(sipsym,primaryClass,updateClass) 0183 0184 def _MergeEnum(sipsym,primaryEnum,updateEnum): 0185 annotations = list(updateEnum.annotations()) 0186 for anno in primaryEnum.annotations(): 0187 if anno not in annotations: 0188 annotations.append(anno) 0189 primaryEnum.setAnnotations(annotations) 0190 0191 primaryEnum[:] = [sipsym.Enumerator(e.name(),e.value()) for e in updateEnum]