android/mobile-config.py | 2 compilerplugins/clang/constantparam.py | 63 +++++++++++++++++-------- compilerplugins/clang/finalclasses.py | 48 ++++++++++++------- compilerplugins/clang/finalmethods.py | 42 +++++++++++------ compilerplugins/clang/methodcycles.py | 3 - compilerplugins/clang/pahole-all-classes.py | 15 ++++-- compilerplugins/clang/unnecessaryvirtual.py | 69 ++++++++++++++++++---------- compilerplugins/clang/unusedmethods.py | 60 ++++++++++++++++-------- compilerplugins/clang/virtualdead.py | 60 ++++++++++++++++-------- compilerplugins/clang/virtualdown.py | 3 - 10 files changed, 243 insertions(+), 122 deletions(-)
New commits: commit c5823a2e276a26194aec82297bade6648626b690 Author: Ilmari Lauhakangas <ilmari.lauhakan...@libreoffice.org> AuthorDate: Thu Jul 25 20:56:05 2024 +0300 Commit: Ilmari Lauhakangas <ilmari.lauhakan...@libreoffice.org> CommitDate: Fri Jul 26 18:45:56 2024 +0200 android, compilerplugins: fix issues found by Ruff linter Change-Id: Idab013bf2ff1f274a07911ec8b545cd26142139c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171050 Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakan...@libreoffice.org> Tested-by: Ilmari Lauhakangas <ilmari.lauhakan...@libreoffice.org> diff --git a/android/mobile-config.py b/android/mobile-config.py index 5998e5d1f9b7..89bb7e773666 100755 --- a/android/mobile-config.py +++ b/android/mobile-config.py @@ -62,7 +62,7 @@ if __name__ == '__main__': for child in root: section = child.attrib['{http://openoffice.org/2001/registry}name'] package = child.attrib['{http://openoffice.org/2001/registry}package'] - size = len(ET.tostring(child)); + size = len(ET.tostring(child)) key = '%s/%s' % (package, section) if key in main_xcd_discard: print('removed %s - saving %d' % (key, size)) diff --git a/compilerplugins/clang/constantparam.py b/compilerplugins/clang/constantparam.py index d2d33087a4c9..24c4d257e1e0 100755 --- a/compilerplugins/clang/constantparam.py +++ b/compilerplugins/clang/constantparam.py @@ -21,7 +21,8 @@ with io.open("workdir/loplugin.constantparam.log", "r") as txt: nameAndParams = normalizeTypeParams(tokens[1]) sourceLocation = tokens[2] # the cxx should actually ignore these - if sourceLocation.startswith("workdir/"): continue + if sourceLocation.startswith("workdir/"): + continue paramName = tokens[3] paramType = normalizeTypeParams(tokens[4]) callValue = tokens[5] @@ -61,19 +62,27 @@ for callInfo, callValues in iter(callDict.items()): if ("," not in nameAndParams) and (("::set" in nameAndParams) or ("::Set" in nameAndParams)): continue # ignore code that follows a common pattern - if sourceLoc.startswith("sw/inc/swatrset.hxx"): continue - if sourceLoc.startswith("sw/inc/format.hxx"): continue + if sourceLoc.startswith("sw/inc/swatrset.hxx"): + continue + if sourceLoc.startswith("sw/inc/format.hxx"): + continue # template generated code - if sourceLoc.startswith("include/sax/fshelper.hxx"): continue + if sourceLoc.startswith("include/sax/fshelper.hxx"): + continue # debug code - if sourceLoc.startswith("include/oox/dump"): continue + if sourceLoc.startswith("include/oox/dump"): + continue # part of our binary API - if sourceLoc.startswith("include/LibreOfficeKit"): continue + if sourceLoc.startswith("include/LibreOfficeKit"): + continue # ignore methods generated by SFX macros - if "RegisterInterface(class SfxModule *)" in nameAndParams: continue - if "RegisterChildWindow(_Bool,class SfxModule *,enum SfxChildWindowFlags)" in nameAndParams: continue - if "RegisterControl(unsigned short,class SfxModule *)" in nameAndParams: continue + if "RegisterInterface(class SfxModule *)" in nameAndParams: + continue + if "RegisterChildWindow(_Bool,class SfxModule *,enum SfxChildWindowFlags)" in nameAndParams: + continue + if "RegisterControl(unsigned short,class SfxModule *)" in nameAndParams: + continue if RepresentsInt(callValue): if callValue == "0" or callValue == "1": @@ -82,13 +91,20 @@ for callInfo, callValues in iter(callDict.items()): tmp2list.append((sourceLoc, functionSig, callInfo[3] + " " + callInfo[2], callValue)) # look for places where the callsite is always a constructor invocation elif constructor_regex.match(callValue) or callValue == "\"\"": - if callValue.startswith("Get"): continue - if callValue.startswith("get"): continue - if "operator=" in functionSig: continue - if "&&" in functionSig: continue - if callInfo[2] == "###0" and callValue == "InitData()": continue - if callInfo[2] == "###0" and callValue == "InitAggregate()": continue - if callValue == "shared_from_this()": continue + if callValue.startswith("Get"): + continue + if callValue.startswith("get"): + continue + if "operator=" in functionSig: + continue + if "&&" in functionSig: + continue + if callInfo[2] == "###0" and callValue == "InitData()": + continue + if callInfo[2] == "###0" and callValue == "InitAggregate()": + continue + if callValue == "shared_from_this()": + continue tmp3list.append((sourceLoc, functionSig, callInfo[3] + " " + callInfo[2], callValue)) else: tmp4list.append((sourceLoc, functionSig, callInfo[3] + " " + callInfo[2], callValue)) @@ -151,8 +167,10 @@ for callInfo, callValues in iter(callDict.items()): if len(callValues) < 2: continue # we are only interested in enum parameters - if "enum" not in callInfo[3]: continue - if "Flag" not in callInfo[3] and "flag" not in callInfo[3] and "Bit" not in callInfo[3] and "State" not in callInfo[3]: continue + if "enum" not in callInfo[3]: + continue + if "Flag" not in callInfo[3] and "flag" not in callInfo[3] and "Bit" not in callInfo[3] and "State" not in callInfo[3]: + continue # try to ignore setter methods if ("," not in nameAndParams) and (("::set" in nameAndParams) or ("::Set" in nameAndParams)): continue @@ -177,14 +195,17 @@ for callInfo, callValues in iter(callDict.items()): # TODO dump more precise information about the allBits values of enums allBits = (1 << setBits.bit_length()) - 1 clearBits = clearBits & allBits - if continue_flag or (setBits == 0 and clearBits == 0): continue + if continue_flag or (setBits == 0 and clearBits == 0): + continue sourceLoc = callInfo[4] functionSig = callInfo[0] + " " + callInfo[1] v2 = callInfo[3] + " " + callInfo[2] - if setBits != 0: v2 += " setBits=" + hex(setBits) - if clearBits != 0: v2 += " clearBits=" + hex(clearBits) + if setBits != 0: + v2 += " setBits=" + hex(setBits) + if clearBits != 0: + v2 += " clearBits=" + hex(clearBits) tmp2list.append((sourceLoc, functionSig, v2)) diff --git a/compilerplugins/clang/finalclasses.py b/compilerplugins/clang/finalclasses.py index 55b3d1c5acb1..aa223f6703b5 100755 --- a/compilerplugins/clang/finalclasses.py +++ b/compilerplugins/clang/finalclasses.py @@ -37,28 +37,44 @@ tmpset = set() for clazz in sorted(definitionSet - inheritFromSet): file = definitionToFileDict[clazz] # ignore classes defined inside compilation units, the compiler knows they are final already - if (".cxx" in file): continue + if (".cxx" in file): + continue # ignore test and external code - if ("/qa/" in file): continue - if (file.startswith("workdir/")): continue + if ("/qa/" in file): + continue + if (file.startswith("workdir/")): + continue # We are only really interested in classes that are shared between linkage units, where the compiler # is not able to figure out for itself that classes are final. - if not(file.startswith("include/") or match_module_inc1.match(file) or match_module_inc2.match(file)): continue - #if not(file.endswith(".hxx")): continue + if not(file.startswith("include/") or match_module_inc1.match(file) or match_module_inc2.match(file)): + continue + #if not(file.endswith(".hxx")): + continue # Exclude URE - if file.startswith("include/com/"): continue - if file.startswith("include/cppu/"): continue - if file.startswith("include/cppuhelper/"): continue - if file.startswith("include/osl/"): continue - if file.startswith("include/rtl/"): continue - if file.startswith("include/sal/"): continue - if file.startswith("include/salhelper/"): continue - if file.startswith("include/typelib/"): continue - if file.startswith("include/uno/"): continue + if file.startswith("include/com/"): + continue + if file.startswith("include/cppu/"): + continue + if file.startswith("include/cppuhelper/"): + continue + if file.startswith("include/osl/"): + continue + if file.startswith("include/rtl/"): + continue + if file.startswith("include/sal/"): + continue + if file.startswith("include/salhelper/"): + continue + if file.startswith("include/typelib/"): + continue + if file.startswith("include/uno/"): + continue # some kind of template noise - if file.startswith("include/unotest/"): continue + if file.startswith("include/unotest/"): + continue # no point optimising test code - if file.startswith("include/test/"): continue + if file.startswith("include/test/"): + continue tmpset.add((clazz, file)) # sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely diff --git a/compilerplugins/clang/finalmethods.py b/compilerplugins/clang/finalmethods.py index 21414c1acbef..756e1cdc44de 100755 --- a/compilerplugins/clang/finalmethods.py +++ b/compilerplugins/clang/finalmethods.py @@ -32,24 +32,38 @@ tmpset = set() for method in sorted(definitionSet - overriddenSet): file = definitionToFileDict[method] # ignore classes defined inside compilation units, the compiler knows they are final already - if (".cxx" in file): continue + if (".cxx" in file): + continue # ignore test and external code - if ("/qa/" in file): continue - if (file.startswith("workdir/")): continue + if ("/qa/" in file): + continue + if (file.startswith("workdir/")): + continue # We are only really interested in classes that are shared between linkage units, where the compiler # is not able to figure out for itself that classes are final. - if not(file.startswith("include/") or match_module_inc1.match(file) or match_module_inc2.match(file)): continue - #if not(file.endswith(".hxx")): continue + if not(file.startswith("include/") or match_module_inc1.match(file) or match_module_inc2.match(file)): + continue + #if not(file.endswith(".hxx")): + continue # Exclude URE - if file.startswith("include/com/"): continue - if file.startswith("include/cppu/"): continue - if file.startswith("include/cppuhelper/"): continue - if file.startswith("include/osl/"): continue - if file.startswith("include/rtl/"): continue - if file.startswith("include/sal/"): continue - if file.startswith("include/salhelper/"): continue - if file.startswith("include/typelib/"): continue - if file.startswith("include/uno/"): continue + if file.startswith("include/com/"): + continue + if file.startswith("include/cppu/"): + continue + if file.startswith("include/cppuhelper/"): + continue + if file.startswith("include/osl/"): + continue + if file.startswith("include/rtl/"): + continue + if file.startswith("include/sal/"): + continue + if file.startswith("include/salhelper/"): + continue + if file.startswith("include/typelib/"): + continue + if file.startswith("include/uno/"): + continue tmpset.add((method, file)) # sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely diff --git a/compilerplugins/clang/methodcycles.py b/compilerplugins/clang/methodcycles.py index ddb72ec50db2..8cb023ffb290 100755 --- a/compilerplugins/clang/methodcycles.py +++ b/compilerplugins/clang/methodcycles.py @@ -260,6 +260,7 @@ def print_partitions(): for c in print_tree_recurse_set: callDict2.pop(c, None) count = count + 1 - if count>1000: break + if count>1000: + break print_partitions() diff --git a/compilerplugins/clang/pahole-all-classes.py b/compilerplugins/clang/pahole-all-classes.py index 4990a01f2c79..e6a72c4a219d 100755 --- a/compilerplugins/clang/pahole-all-classes.py +++ b/compilerplugins/clang/pahole-all-classes.py @@ -31,9 +31,11 @@ with a.stdout as txt: className = tokens[2].strip() srcLoc = tokens[5].strip() # ignore things like unions - if "anonymous" in className: continue + if "anonymous" in className: + continue # ignore duplicates - if className in classSet: continue + if className in classSet: + continue classSet.add(className) classSourceLocDict[className] = srcLoc locToClassDict[srcLoc] = className @@ -57,13 +59,16 @@ def write_pahole_commands(classes): def read_generator(gdbOutput): while True: line = gdbOutput.readline() - if line == "": return # end of file + if line == "": + return # end of file line = line.decode('utf8').strip() print("gdb: " + line) for split in line.split("(gdb)"): split = split.strip() - if len(split) == 0: continue - if "all-done" in split: return + if len(split) == 0: + continue + if "all-done" in split: + return yield split # build list of classes sorted by source location to increase the chances of diff --git a/compilerplugins/clang/unnecessaryvirtual.py b/compilerplugins/clang/unnecessaryvirtual.py index 12d8b00af470..063fcba3c068 100755 --- a/compilerplugins/clang/unnecessaryvirtual.py +++ b/compilerplugins/clang/unnecessaryvirtual.py @@ -30,35 +30,54 @@ unnecessaryVirtualSet = set() for clazz in (definitionSet - overridingSet): # windows-specific stuff - if clazz.startswith("canvas::"): continue - if clazz.startswith("psp::PrinterInfoManager"): continue - if clazz.startswith("DdeTopic::"): continue - if clazz == "basegfx::unotools::UnoPolyPolygon::void-modifying()const": continue - if clazz == "SalLayout::_Bool-IsKashidaPosValid(int,)const": continue - if clazz == "SalLayout::void-DisableGlyphInjection(_Bool,)": continue + if clazz.startswith("canvas::"): + continue + if clazz.startswith("psp::PrinterInfoManager"): + continue + if clazz.startswith("DdeTopic::"): + continue + if clazz == "basegfx::unotools::UnoPolyPolygon::void-modifying()const": + continue + if clazz == "SalLayout::_Bool-IsKashidaPosValid(int,)const": + continue + if clazz == "SalLayout::void-DisableGlyphInjection(_Bool,)": + continue # Linux-TDF specific - if clazz == "X11SalFrame::void-updateGraphics(_Bool,)": continue + if clazz == "X11SalFrame::void-updateGraphics(_Bool,)": + continue # OSX specific - if clazz == "SalFrame::void-SetRepresentedURL(const class rtl::OUString &,)": continue - if clazz == "SalMenu::_Bool-AddMenuBarButton(const struct SalMenuButtonItem &,)": continue - if clazz == "SalMenu::class Rectangle-GetMenuBarButtonRectPixel(sal_uInt16,class SalFrame *,)": continue - if clazz == "SalMenu::void-RemoveMenuBarButton(sal_uInt16,)": continue - if clazz == "SalLayout::_Bool-DrawTextSpecial(class SalGraphics &,sal_uInt32,)const": continue + if clazz == "SalFrame::void-SetRepresentedURL(const class rtl::OUString &,)": + continue + if clazz == "SalMenu::_Bool-AddMenuBarButton(const struct SalMenuButtonItem &,)": + continue + if clazz == "SalMenu::class Rectangle-GetMenuBarButtonRectPixel(sal_uInt16,class SalFrame *,)": + continue + if clazz == "SalMenu::void-RemoveMenuBarButton(sal_uInt16,)": + continue + if clazz == "SalLayout::_Bool-DrawTextSpecial(class SalGraphics &,sal_uInt32,)const": + continue # GTK < 3 - if clazz == "GtkSalDisplay::int-CaptureMouse(class SalFrame *,)": continue + if clazz == "GtkSalDisplay::int-CaptureMouse(class SalFrame *,)": + continue # some test magic - if clazz.startswith("apitest::"): continue + if clazz.startswith("apitest::"): + continue loc = definitionToSourceLocationMap[clazz] # ignore external code - if loc.startswith("external/"): continue - if loc.startswith("workdir/"): continue - if loc.startswith("64-linux-gnu/"): continue + if loc.startswith("external/"): + continue + if loc.startswith("workdir/"): + continue + if loc.startswith("64-linux-gnu/"): + continue # there is a bunch of Windows specific code that we don't see - if loc.startswith("include/canvas/"): continue + if loc.startswith("include/canvas/"): + continue # not sure what the problem is here - if loc.startswith("include/test/"): continue + if loc.startswith("include/test/"): + continue unnecessaryVirtualSet.add( (clazz,loc) ) @@ -68,14 +87,18 @@ deadSet = set() for clazz in (definitionSet - nonEmptySet): # ignore destructors - if "::~" in clazz: continue + if "::~" in clazz: + continue loc = definitionToSourceLocationMap[clazz] # ignore external code - if loc.startswith("external/"): continue - if loc.startswith("workdir/"): continue - if loc.startswith("64-linux-gnu/"): continue + if loc.startswith("external/"): + continue + if loc.startswith("workdir/"): + continue + if loc.startswith("64-linux-gnu/"): + continue deadSet.add( (clazz,loc) ) diff --git a/compilerplugins/clang/unusedmethods.py b/compilerplugins/clang/unusedmethods.py index 485647450c24..a69ea6529d4a 100755 --- a/compilerplugins/clang/unusedmethods.py +++ b/compilerplugins/clang/unusedmethods.py @@ -46,7 +46,8 @@ with io.open("workdir/loplugin.unusedmethods.log", "r", buffering=16*1024*1024) nameAndParams = tokens[3] sourceLocation = tokens[4] virtual = "" - if len(tokens)>=6: virtual = tokens[5] + if len(tokens)>=6: + virtual = tokens[5] funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams)) definitionSet.add(funcInfo) if access == "public": @@ -162,28 +163,40 @@ for d in definitionSet: if d[0] == "basic_ostream<type-parameter-?-?, type-parameter-?-?> &" and d[1].startswith("operator<<(basic_ostream<type-parameter-?-?"): continue # ignore lambdas - if (" ::operator " in method) or (" ::__invoke(" in method) or (" ::operator())" in method): continue - if ("(lambda at " in method): continue + if (" ::operator " in method) or (" ::__invoke(" in method) or (" ::operator())" in method): + continue + if ("(lambda at " in method): + continue # ignore stuff generated by std::function parameters - if ("(anonymous)::operator " in method) and ("(*)" in method): continue + if ("(anonymous)::operator " in method) and ("(*)" in method): + continue # stuff generated by Qt - if "::tr(" in method or "::trUtf8(" in method: continue + if "::tr(" in method or "::trUtf8(" in method: + continue location = definitionToSourceLocationMap[d] # whacky template stuff - if location.startswith("sc/source/ui/vba/vbaformat.hxx"): continue + if location.startswith("sc/source/ui/vba/vbaformat.hxx"): + continue # not sure how this stuff is called - if location.startswith("include/test"): continue + if location.startswith("include/test"): + continue # leave the debug/dump alone - if location.startswith("include/oox/dump"): continue + if location.startswith("include/oox/dump"): + continue # plugin testing stuff - if location.startswith("compilerplugins/clang/test"): continue + if location.startswith("compilerplugins/clang/test"): + continue # leave this alone for now - if location.startswith("include/LibreOfficeKit"): continue + if location.startswith("include/LibreOfficeKit"): + continue # template stuff - if location.startswith("include/vcl/vclptr.hxx"): continue - if location.startswith("include/oox/helper/refvector.hxx"): continue - if location.startswith("include/oox/drawingml/chart/modelbase.hxx"): continue + if location.startswith("include/vcl/vclptr.hxx"): + continue + if location.startswith("include/oox/helper/refvector.hxx"): + continue + if location.startswith("include/oox/drawingml/chart/modelbase.hxx"): + continue unusedSet.add(d) # used by the "unused return types" analysis tmp1set.add((method, location)) @@ -241,15 +254,21 @@ for d in definitionSet: continue location = definitionToSourceLocationMap[d] # windows only - if location.startswith("include/svl/svdde.hxx"): continue + if location.startswith("include/svl/svdde.hxx"): + continue # fluent API (return ref to self) - if location.startswith("include/tools/stream.hxx"): continue - if location.startswith("include/oox/helper/refvector.hxx"): continue - if location.startswith("include/oox/drawingml/chart/modelbase.hxx"): continue + if location.startswith("include/tools/stream.hxx"): + continue + if location.startswith("include/oox/helper/refvector.hxx"): + continue + if location.startswith("include/oox/drawingml/chart/modelbase.hxx"): + continue # templates - if location.startswith("include/vcl/vclptr.hxx"): continue + if location.startswith("include/vcl/vclptr.hxx"): + continue # external API - if location.startswith("include/LibreOfficeKit/LibreOfficeKit.hxx"): continue + if location.startswith("include/LibreOfficeKit/LibreOfficeKit.hxx"): + continue tmp2set.add((method, location)) #Disable this for now, not really using it @@ -296,7 +315,8 @@ potentialClassesSourceLocationMap = dict() matchClassName = re.compile(r"(\w+)::") for d in protectedDefinitionSet: m = matchClassName.match(d[1]) - if not m: continue + if not m: + continue clazz = m.group(1) if d in calledFromOutsideSet: excludedClasses.add(clazz) diff --git a/compilerplugins/clang/virtualdead.py b/compilerplugins/clang/virtualdead.py index e32de264ed68..79c1022ed75e 100755 --- a/compilerplugins/clang/virtualdead.py +++ b/compilerplugins/clang/virtualdead.py @@ -55,19 +55,27 @@ for callInfo, callValues in iter(callDict.items()): if "pure" in callValue: continue srcloc = callInfo[1] - if srcloc.startswith("workdir/"): continue + if srcloc.startswith("workdir/"): + continue # ignore Qt stuff - if srcloc.startswith("Gui/"): continue - if srcloc.startswith("Widgets/"): continue - if srcloc.startswith("Core/"): continue - if srcloc.startswith("/Qt"): continue - if srcloc.startswith("Qt"): continue - if srcloc.startswith("64-"): continue + if srcloc.startswith("Gui/"): + continue + if srcloc.startswith("Widgets/"): + continue + if srcloc.startswith("Core/"): + continue + if srcloc.startswith("/Qt"): + continue + if srcloc.startswith("Qt"): + continue + if srcloc.startswith("64-"): + continue functionSig = callInfo[0] tmp1list.append((srcloc, functionSig, callValue)) def merge_bitfield(a, b): - if len(a) == 0: return b + if len(a) == 0: + return b ret = "" for i, c in enumerate(b): if c == "1" or a[i] == "1": @@ -80,10 +88,14 @@ tmp2list = list() for paramInfo in paramSet: name = paramInfo[0] bitfield = paramInfo[1] - if re.match( r"\w+ com::", name): continue - if re.match( r"\w+ ooo::vba::", name): continue - if re.match( r"\w+ orcus::", name): continue - if re.match( r"\w+ std::", name): continue + if re.match( r"\w+ com::", name): + continue + if re.match( r"\w+ ooo::vba::", name): + continue + if re.match( r"\w+ orcus::", name): + continue + if re.match( r"\w+ std::", name): + continue if name not in tmp2dict: tmp2dict[name] = bitfield else: @@ -91,16 +103,24 @@ for paramInfo in paramSet: for name, bitfield in iter(tmp2dict.items()): srcloc = definitionToSourceLocationMap[name] # ignore Qt stuff - if srcloc.startswith("Gui/"): continue - if srcloc.startswith("Widgets/"): continue - if srcloc.startswith("Core/"): continue - if srcloc.startswith("/Qt"): continue - if srcloc.startswith("Qt"): continue - if srcloc.startswith("64-"): continue + if srcloc.startswith("Gui/"): + continue + if srcloc.startswith("Widgets/"): + continue + if srcloc.startswith("Core/"): + continue + if srcloc.startswith("/Qt"): + continue + if srcloc.startswith("Qt"): + continue + if srcloc.startswith("64-"): + continue # ignore external stuff - if srcloc.startswith("workdir/"): continue + if srcloc.startswith("workdir/"): + continue # referenced by generated code in workdir/ - if srcloc.startswith("sw/source/writerfilter/ooxml/OOXMLFactory.hxx"): continue + if srcloc.startswith("sw/source/writerfilter/ooxml/OOXMLFactory.hxx"): + continue if "0" in bitfield: tmp2list.append((srcloc, name, bitfield)) diff --git a/compilerplugins/clang/virtualdown.py b/compilerplugins/clang/virtualdown.py index f71ec576adb4..29a8f24037b9 100755 --- a/compilerplugins/clang/virtualdown.py +++ b/compilerplugins/clang/virtualdown.py @@ -28,7 +28,8 @@ for clazz in (definitionSet - callSet): # if clazz.startswith("canvas::"): continue # if clazz == "basegfx::unotools::UnoPolyPolygon::void-modifying()const": continue # ignore external code - if definitionToSourceLocationMap[clazz].startswith("external/"): continue + if definitionToSourceLocationMap[clazz].startswith("external/"): + continue unnecessaryVirtualSet.add((clazz,definitionToSourceLocationMap[clazz] ))