Ejemplo n.º 1
0
def check(uast):
    findings = []

    for cl in [
            utils.JClass(i)
            for i in bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]")
    ]:
        instance_creations = bblfsh.filter(
            cl.node, "//ClassInstanceCreation/SimpleType/Identifier")
        all_creations = {i.properties["Name"] for i in instance_creations}

        for cls in [
                utils.JClass(i) for i in bblfsh.filter(
                    cl.node, "//TypeDeclaration//TypeDeclaration")
        ]:
            for child in cls.node.children:
                if child.internal_type == "Modifier" and child.token == "private" and\
                    cls.name not in all_creations:
                    findings.append({
                        "msg":
                        "Private class {} defined but not used, remove it".
                        format(cls.name),
                        "pos":
                        cls.node.start_position
                    })

    return findings
Ejemplo n.º 2
0
def check(uast):
    findings = []

    jclasses = [
        utils.JClass(i)
        for i in bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]")
    ]

    for cl in jclasses:
        hash2methods = {}

        for m in cl.methods:
            body_hash = utils.hash_node(m.body).hexdigest()

            if body_hash in hash2methods:
                findings.append({
                    "msg":
                    "Method {m1_name} has the same implementation as method {m2_name}"
                    .format(m1_name=hash2methods[body_hash].name,
                            m2_name=m.name),
                    "pos":
                    hash2methods[body_hash].node.start_position
                })
            else:
                hash2methods[body_hash] = m

    return findings
Ejemplo n.º 3
0
def check(uast):
    findings = []
    name2class = {}

    cl_nodes = bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]")

    for cl in cl_nodes:
        jc = utils.JClass(cl)
        name2class[jc.name] = jc

    for clname, cl in name2class.items():
        if not cl.parent:
            continue

        methods = cl.methods
        for method in methods:
            par_class = name2class.get(cl.parent)
            if not par_class:
                continue

            for parmethod in par_class.methods:
                if parmethod.name != method.name and \
                   parmethod.name.lower() == method.name.lower():

                    findings.append({
                        "msg":
                        "Methods with same name but different casing in subclass: "
                        "{}.{} and {}.{}".format(clname, method.name,
                                                 cl.parent, parmethod.name)
                    })

    return findings
Ejemplo n.º 4
0
def check(uast):
    findings = []

    classes = []
    name2class = {}

    cl_nodes = bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]")

    for cl in cl_nodes:
        jc = utils.JClass(cl)
        name2class[jc.name] = jc

    for clname, cl in name2class.items():
        if not cl.parent:
            continue

        parent = name2class.get(cl.parent)
        if not parent:
            continue

        common = set([i.name for i in cl.fields]) & set(
            [i.name for i in parent.fields])
        if len(common):
            findings.append({
                "msg":
                'Class {} uses field(s) with same name as parent {}: {}'.
                format(cl.name, parent.name, common)
            })

    return findings
Ejemplo n.º 5
0
def check(uast):
    findings = []

    cl_nodes = bblfsh.filter(
        uast, "//TypeDeclaration[@roleDeclaration and @roleType]//SimpleType"
        "[@internalRole='superInterfaceTypes']//Identifier[@Name='Serializable']/"
        "parent::*/parent::TypeDeclaration")

    for cl in cl_nodes:
        jc = utils.JClass(cl)

        for method in jc.methods:
            if method.name == 'readResolve' and 'private' in method.modifiers and\
                    method.return_ and method.return_.type_name == 'Object' and\
                    not method.arguments:
                findings.append({
                    "msg":
                    "Class {} implementing Serializable should have a public or protested "
                    "readResolve() method".format(jc.name),
                    "pos":
                    cl.start_position
                })
            break
        else:
            findings.append({
                "msg":
                "Class {} implementing Serializable should have a readResolve() method"
                .format(jc.name),
                "pos":
                cl.start_position
            })

    return findings
Ejemplo n.º 6
0
def check(uast):
    findings = []

    cl_nodes = bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]")

    for cl in cl_nodes:
        jc = utils.JClass(cl)
        if jc.parent.split('.')[-1] == jc.name:
            findings.append({"msg": 'Class has same name as parent'})

        for impl in jc.implements:
            if impl.split('.')[-1] == jc.name:
                findings.append({"msg": 'Class has same name as interface'})

    return findings
Ejemplo n.º 7
0
def check(uast):
    findings = []


    cl_nodes = bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]")
    classes = []
    lowered_field_names = set()

    for cl in cl_nodes:
        jc = utils.JClass(cl)

        for field in [i.name for i in jc.fields]:
            lowered_field_names.add(field.lower())

        for method in jc.methods:
            # Avoid complex getters/setters
            if len(list(method.body.children)) > 1:
                continue

            m_name = method.name.lower()

            if m_name.startswith("get"):
                should_return = m_name[3:]
                returns = bblfsh.filter(method.body, "//*[@roleReturn]//Identifier")
                for r in returns:
                    returned_var = r.properties["Name"]

                    if returned_var and returned_var.lower() != should_return.lower():
                        findings.append({"msg": "Getter '{}' probably should return '{}' instead of '{}'"
                                          .format(method.name, should_return, returned_var),
                                          "pos": r.start_position})


            elif m_name.startswith("set"):
                should_assign = m_name[3:]
                assgns = bblfsh.filter(method.body, "//Assignment//Identifier[@roleLeft]|"
                                                    "//Assignment//*[@roleLeft]//Identifier")

                for a in assgns:
                    assigned_var = a.properties["Name"]

                    if assigned_var and assigned_var.lower() != should_assign.lower():
                        findings.append({"msg": "Setter '{}' probably should assign to '{}' instead of '{}'"
                                  .format(method.name, should_assign, assigned_var),
                                  "pos": a.start_position})

    return findings
Ejemplo n.º 8
0
def check(uast):
    findings = []

    cl_nodes = bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]")
    jclasses = [utils.JClass(i) for i in cl_nodes]

    for jc in jclasses:
        if jc.parent == 'HttpServlet':
            mains = bblfsh.filter(
                uast, "//FunctionGroup//Alias/Identifier[@Name='main']")
            for m in mains:
                findings.append({
                    "msg":
                    "Don't use a main() function on HttpServlet derived classes",
                    "pos": m.start_position
                })

    return findings
Ejemplo n.º 9
0
def check(uast):
    findings = []

    classes = []
    parent2children = {}
    name2class = {}

    cl_nodes = bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]")

    for cl in cl_nodes:
        jc = utils.JClass(cl)
        name2class[jc.name] = jc

        if jc.parent in parent2children:
            parent2children[jc.parent].append(jc.name)
        else:
            parent2children[jc.name] = [jc.parent]

        classes.append(jc)
        name2class[jc.name] = cl

    for cl in parent2children:
        for child in parent2children[cl]:
            # Alternative: generate a string with all the child names in the Identifier selector
            child_cl = name2class.get(cl)
            if not child_cl:
                continue

            calls = bblfsh.filter(
                child_cl,
                "(//MethodInvocation//Identifier[@roleCall and @roleReceiver and @Name='%s']|"
                "//QualifiedIdentifier//Identifier[@Name='%s'])" %
                (child, child))

            for call in calls:
                findings.append({
                    "msg":
                    "Call in class {} to subclass {} member".format(cl, child),
                    "pos":
                    call.start_position.line
                })

    return findings
Ejemplo n.º 10
0
def check(uast):
    findings = []

    cl_nodes = bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]")

    getters = {}
    setters = {}
    classes = []

    def add_dict(dict_, key, value):
        if key in dict_:
            dict_[key].append(value)
        else:
            dict_[key] = [value]

    for cl in cl_nodes:
        jc = utils.JClass(cl)

        for method in jc.methods:
            if 'public' in method.modifiers:
                if len(method.name) > 0:
                    if method.name.startswith("get"):
                        getters[method.name[3:]] = method
                    elif method.name.startswith("set"):
                        setters[method.name[3:]] = method

        for property_, getter in getters.items():
            try:
                setter = setters[property_]
            except KeyError:
                continue

            sync = 'synchronized'
            if sync in getter.modifiers and sync not in setter.modifiers or\
                    sync in setter.modifiers and sync not in getter.modifiers:
                findings.append({
                    "msg":
                    "Getter and setter for '%s' should both or none be synchronized"
                    % property_
                })

    return findings
Ejemplo n.º 11
0
def check(uast):
    findings = []

    cl_nodes = bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]//SimpleType"
            "[@internalRole='superInterfaceTypes']//Identifier[@Name='Cloneable']/"
            "parent::*/parent::TypeDeclaration")

    for cl in cl_nodes:
        jc = utils.JClass(cl)

        for method in jc.methods:
            if method.name == 'clone' and 'public' in method.modifiers and\
                    method.return_ and method.return_.type_name == 'Object' and\
                    not method.arguments:
                break
        else:
            findings.append({"msg": "Class {} implementing Cloneable should have a clone() method",
                             "pos": cl.start_position})

    return findings
Ejemplo n.º 12
0
def check(uast):
    findings = []

    classes = []
    parent2children = {}
    name2class = {}

    cl_nodes = bblfsh.filter(uast, "//*[@roleDeclaration and @roleType]")

    for cl in cl_nodes:
        jc = utils.JClass(cl)

        if jc.parent == 'HttpServlet':
            for f in jc.fields:
                if "static" not in f.modifiers and "final" not in f.modifiers:
                    findings.append({
                        "msg": "Servlet fields should be static or final",
                        "pos": f.node.start_position
                    })

    return findings