Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/compilerplugins/clang/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 6 kB image not shown  

Quelle  expandablemethods.py   Sprache: Python

 
#!/usr/bin/python

import re
import io

# --------------------------------------------------------------------------------------------
# globals
# --------------------------------------------------------------------------------------------

definitionSet = set() # set of tuple(return_type, name_and_params)
definitionToSourceLocationMap = dict()
calledFromDict = dict()
calledFromOutsideSet = set()
largeFunctionSet = set() # set of tuple(return_type, name_and_params)
addressOfSet = set() # set of tuple(return_type, name_and_params)

# clang does not always use exactly the same numbers in the type-parameter vars it generates
# so I need to substitute them to ensure we can match correctly.
normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+")
def normalizeTypeParams( line ):
    return normalizeTypeParamsRegex.sub("type-parameter-?-?", line)

# --------------------------------------------------------------------------------------------
# primary input loop
# --------------------------------------------------------------------------------------------

with io.open("workdir/loplugin.expandablemethods.log""rb", buffering=1024*1024) as txt:
    for line in txt:
        tokens = line.strip().split("\t")
        if tokens[0] == "definition:":
            access = tokens[1]
            returnType = tokens[2]
            nameAndParams = tokens[3]
            sourceLocation = tokens[4]
            funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))
            definitionSet.add(funcInfo)
            definitionToSourceLocationMap[funcInfo] = sourceLocation
        elif tokens[0] == "calledFrom:":
            calleeLocation = tokens[1]
            returnType = tokens[2]
            nameAndParams = tokens[3]
            funcInfo = (normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams))
            if funcInfo not in calledFromDict:
                calledFromDict[funcInfo] = set()
            calledFromDict[funcInfo].add(calleeLocation)
        elif tokens[0] == "outside:":
            returnType = tokens[1]
            nameAndParams = tokens[2]
            calledFromOutsideSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams)))
        elif tokens[0] == "large:":
            returnType = tokens[1]
            nameAndParams = tokens[2]
            largeFunctionSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams)))
        elif tokens[0] == "addrof:":
            returnType = tokens[1]
            nameAndParams = tokens[2]
            addressOfSet.add((normalizeTypeParams(returnType), normalizeTypeParams(nameAndParams)))
        else:
            print( "unknown line: " + line)

# Invert the definitionToSourceLocationMap.
# If we see more than one method at the same sourceLocation, it's being autogenerated as part of a template
# and we should just ignore it.
sourceLocationToDefinitionMap = {}
for k, v in definitionToSourceLocationMap.iteritems():
    sourceLocationToDefinitionMap[v] = sourceLocationToDefinitionMap.get(v, [])
    sourceLocationToDefinitionMap[v].append(k)
for k, definitions in sourceLocationToDefinitionMap.iteritems():
    if len(definitions) > 1:
        for d in definitions:
            definitionSet.remove(d)

def isOtherConstness( d, callSet ):
    method = d[0] + " " + d[1]
    # if this method is const, and there is a non-const variant of it, and the non-const variant is in use, then leave it alone
    if d[0].startswith("const "and d[1].endswith(" const"):
        if ((d[0][6:],d[1][:-6]) in callSet):
           return True
    elif method.endswith(" const"):
        method2 = method[:len(method)-6] # strip off " const"
        if ((d[0],method2) in callSet):
           return True
    if method.endswith(" const"and ("::iterator" in method):
        method2 = method[:len(method)-6] # strip off " const"
        method2 = method2.replace("::const_iterator""::iterator")
        if ((d[0],method2) in callSet):
           return True
    # if this method is non-const, and there is a const variant of it, and the const variant is in use, then leave it alone
    if (not method.endswith(" const")) and ((d[0],"const " + method + " const"in callSet):
           return True
    if (not method.endswith(" const")) and ("::iterator" in method):
        method2 = method.replace("::iterator""::const_iterator") + " const"
        if ((d[0],method2) in callSet):
           return True
    return False

# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely
def natural_sort_key(s, _nsre=re.compile('([0-9]+)')):
    return [int(text) if text.isdigit() else text.lower()
            for text in re.split(_nsre, s)]
# sort by both the source-line and the datatype, so the output file ordering is stable
# when we have multiple items on the same source line
def v_sort_key(v):
    return natural_sort_key(v[1]) + [v[0]]
def sort_set_by_natural_key(s):
    return sorted(s, key=lambda v: v_sort_key(v))


# --------------------------------------------------------------------------------------------
# Methods that are only called from inside their own class, and are only called from one spot
# --------------------------------------------------------------------------------------------

tmp4set = set()
for d in definitionSet:
    if d in calledFromOutsideSet:
        continue
    if isOtherConstness(d, calledFromOutsideSet):
        continue
    if d not in definitionToSourceLocationMap:
        print("warning, method has no location: " + d[0] + " " + d[1])
        continue
    # ignore external code
    if definitionToSourceLocationMap[d].startswith("external/"):
       continue
    # ignore constructors, calledFromOutsideSet does not provide accurate info for them
    tokens = d[1].split("(")[0].split("::")
    if len(tokens)>1 and tokens[-2] == tokens[-1]:
        continue
    # ignore large methods, which make the code clearer by being out of line
    if d in largeFunctionSet:
        continue
    # ignore methods whose address we take
    if d in addressOfSet:
        continue
    # ignore unused methods, leave them to the dedicated analysis
    if d not in calledFromDict:
        continue
    # ignore methods called from more than one site
    if len(calledFromDict[d]) > 1:
        continue

    method = d[0] + " " + d[1]
    tmp4set.add((method, definitionToSourceLocationMap[d]))

# print output, sorted by name and line number
with open("loplugin.expandablemethods.report""wt"as f:
    for t in sort_set_by_natural_key(tmp4set):
        f.write(t[1] + "\n")
        f.write(" " + t[0] + "\n")

100%


¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.