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
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
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
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
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
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
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
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
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
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
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
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