Ejemplo n.º 1
0
def main(udb_path, source_package, source_class, source_method, *args,
         **kwargs):
    db = und.open(udb_path)
    method_ent = db.lookup(f"{source_package}.{source_class}.{source_method}",
                           "Method")

    if len(method_ent) == 0:
        logger.error("Invalid inputs.")
        return
    method_ent = method_ent[0]

    if method_ent.simplename() != source_method:
        logger.error("Invalid entity.")
        return

    if not method_ent.kind().check("Public"):
        logger.error("Method is not public.")
        return

    for ent in method_ent.ents("CallBy"):
        if f"{source_package}.{source_class}" not in ent.longname():
            logger.error("Method cannot set to private.")
            return

    parent = method_ent.parent()
    while parent.parent() is not None:
        parent = parent.parent()

    main_file = parent.longname()
    parse_and_walk(file_path=main_file,
                   listener_class=DecreaseMethodVisibilityListener,
                   has_write=True,
                   source_class=source_class,
                   source_method=source_method)
    db.close()
Ejemplo n.º 2
0
    def do_refactor(self):
        if not self.check_preconditions():
            logger.error("Pre conditions failed.")
            return False
        # Update usages
        for file_path in self.usages:
            parse_and_walk(file_path=file_path,
                           listener_class=UpdateImportsListener,
                           has_write=True,
                           source_package=self.source_package,
                           target_package=self.target_package,
                           class_name=self.class_name)

        # Delete source class
        os.remove(self.class_dir)

        # Write the new class
        with open(self.new_class_path, 'w') as f:
            package = ""
            if self.target_package != ROOT_PACKAGE:
                package = f"package {self.target_package};\n\n"
            imports = ""
            if self.source_package != ROOT_PACKAGE:
                imports = f"import {self.source_package}.*;\n\n"

            f.write(package + imports + self.class_content)

        return True
Ejemplo n.º 3
0
def main(udb_path, source_package, source_class, source_field, *args,
         **kwargs):
    db = und.open(udb_path)
    field_ent = db.lookup(f"{source_package}.{source_class}.{source_field}",
                          "Variable")

    if len(field_ent) == 0:
        logger.error("Invalid inputs.")
        return
    field_ent = field_ent[0]

    if field_ent.simplename() != source_field:
        logger.error("Invalid entity.")
        return

    if not field_ent.kind().check("Private"):
        logger.error("Field is not private.")
        return

    parent = field_ent.parent()
    while parent.parent() is not None:
        parent = parent.parent()

    main_file = parent.longname()
    parse_and_walk(file_path=main_file,
                   listener_class=IncreaseFieldVisibilityListener,
                   has_write=True,
                   source_class=source_class,
                   source_field=source_field)
    db.close()
Ejemplo n.º 4
0
def main(udb_path, source_package, source_class, method_name,
         target_classes: list, *args, **kwargs):
    db = und.open(udb_path)
    source_class_ents = db.lookup(f"{source_package}.{source_class}", "Class")
    target_class_ents = []
    source_class_ent = None

    if len(source_class_ents) == 0:
        logger.error(f"Cannot find source class: {source_class}")
        return
    else:
        for ent in source_class_ents:
            if ent.simplename() == source_class:
                source_class_ent = ent
                break
    if source_class_ent is None:
        logger.error(f"Cannot find source class: {source_class}")
        return

    method_ent = db.lookup(f"{source_package}.{source_class}.{method_name}",
                           "Method")
    if len(method_ent) == 0:
        logger.error(f"Cannot find method to pushdown: {method_name}")
        return
    else:
        method_ent = method_ent[0]

    for ref in source_class_ent.refs("extendBy"):
        if ref.ent().simplename() not in target_classes:
            logger.error("Target classes are not children classes")
            return
        target_class_ents.append(ref.ent())

    for ref in method_ent.refs("callBy"):
        if ref.file().simplename().split(".")[0] in target_classes:
            continue
        else:
            logger.error("Method has dependencies.")
            return

    # Remove field from source class
    listener = parse_and_walk(file_path=source_class_ent.parent().longname(),
                              listener_class=CutMethodListener,
                              has_write=True,
                              source_class=source_class,
                              method_name=method_name,
                              debug=False)
    # Insert field in children classes
    for target_class in target_class_ents:
        parse_and_walk(file_path=target_class.parent().longname(),
                       listener_class=PasteMethodListener,
                       has_write=True,
                       source_class=target_class.simplename(),
                       method_content=listener.method_content,
                       import_statements=listener.import_statements,
                       debug=False)
    db.close()
Ejemplo n.º 5
0
def main(udb_path, source_package, source_class, source_field, *args,
         **kwargs):
    db = und.open(udb_path)
    field_ent = db.lookup(f"{source_package}.{source_class}.{source_field}",
                          "Variable")

    if len(field_ent) == 0:
        logger.error("Invalid inputs.")
        return
    field_ent = field_ent[0]

    if field_ent.simplename() != source_field:
        logger.error("Invalid entity.")
        return

    if not field_ent.kind().check("Public"):
        logger.error("Field is not public.")
        return

    for ref in field_ent.refs("UseBy,SetBy"):
        ent = ref.ent()
        if f"{source_package}.{source_class}" not in ent.longname():
            logger.debug(
                f"{source_package}.{source_class} not in {ent.longname()}")
            logger.error("Field cannot set to private.")
            return

    parent = field_ent.parent()
    while parent.parent() is not None:
        parent = parent.parent()

    main_file = parent.longname()
    parse_and_walk(file_path=main_file,
                   listener_class=DecreaseFieldVisibilityListener,
                   has_write=True,
                   source_class=source_class,
                   source_field=source_field)
    db.close()
Ejemplo n.º 6
0
def main(udb_path, source_package, target_class, class_names: list, *args,
         **kwargs):
    if len(class_names) < 2:
        logger.error("class_names is empty.")
        return None
    db = und.open(udb_path)
    parent_cons = []

    # Check children
    parent = db.lookup(f"{target_class}", "Public Class")
    if len(parent) != 1:
        logger.error("Count of target class is not 1.")
        db.close()
        return
    parent = parent[0]
    parent_file = db.lookup(f"{target_class}.java", "File")[0].longname()

    for i in parent.ents("Define", "Constructor"):
        parent_cons.append(i.parameters())

    # Find constructor entities group by signature
    constructors = {}

    for child in class_names:
        cons = db.lookup(f"{child}.{child}", "Constructor")
        for con in cons:
            if source_package not in con.parent().longname():
                logger.error("Source package does not match.")
                db.close()
                return
            parameters = con.parameters()
            if parameters in constructors:
                constructors[parameters].append(con)
            else:
                constructors[parameters] = [con]

    # Find common statements
    for k in constructors:
        meta_data = {
            parent_file: {
                'is_father': True,
                'has_father_con': k in parent_cons,
                'class_name': parent.simplename()
            },
        }
        con = constructors[k][0]
        ents = []

        for ref in con.refs("Set"):
            data = {
                'is_father': False,
                'has_father_con': k in parent_cons,
                'class_name': con.parent().simplename()
            }
            if ref.file().longname() not in meta_data.keys():
                meta_data[ref.file().longname()] = data
            if target_class in ref.ent().longname():
                ents.append(ref.ent().simplename())

        for i in range(1, len(constructors[k])):
            con2 = constructors[k][i]
            for ref in con2.refs("Set"):
                data = {
                    'is_father': False,
                    'has_father_con': k in parent_cons,
                    'class_name': con2.parent().simplename()
                }
                if ref.file().longname() not in meta_data.keys():
                    meta_data[ref.file().longname()] = data
                if target_class in ref.ent().longname():
                    ents.append(ref.ent().simplename())

        ents = [
            item for item, count in collections.Counter(ents).items()
            if count > 1
        ]
        if len(meta_data.keys()) > 1:
            for file_name in meta_data:
                data = meta_data[file_name]
                parse_and_walk(file_name,
                               PullUpConstructorListener,
                               has_write=True,
                               is_father=data['is_father'],
                               has_father_con=data['has_father_con'],
                               common_sets=ents,
                               class_name=data['class_name'],
                               params=k)
    db.close()
Ejemplo n.º 7
0
def main(source_class: str, source_package: str, target_class: str,
         target_package: str, field_name: str, udb_path: str, *args, **kwargs):
    import_statement = None
    if source_package != target_package:
        import_statement = f"\nimport {target_package}.{target_class};"
    instance_name = target_class.lower() + "ByCodArt"
    db = und.open(udb_path)

    # Check if field is static
    field_ent = db.lookup(f"{source_package}.{source_class}.{field_name}",
                          "Variable")
    if len(field_ent) == 0:
        logger.error(
            f"Entity not found with query: {source_package}.{source_class}.{field_name}."
        )
        db.close()
        return None

    if source_package == target_package and source_class == target_class:
        logger.error("Can not move to self.")
        db.close()
        return None
    field_ent = field_ent[0]
    is_static = field_ent.kindname() == STATIC

    if is_static:
        logger.warning("Field is static!")

    # Find usages
    usages = {}

    for ref in field_ent.refs("setby,useby"):
        file = ref.file().longname()
        if file in usages:
            usages[file].append(ref.line())
        else:
            usages[file] = [
                ref.line(),
            ]
    try:
        src_class_file = db.lookup(
            f"{source_package}.{source_class}.java")[0].longname()
        target_class_file = db.lookup(
            f"{target_package}.{target_class}.java")[0].longname()
    except IndexError:
        logger.error("This is a nested class.")
        logger.info(f"{source_package}.{source_class}.java")
        logger.info(f"{target_package}.{target_class}.java")
        db.close()
        return None

    # Check if there is an cycle
    listener = parse_and_walk(
        file_path=target_class_file,
        listener_class=CheckCycleListener,
        class_name=source_class,
    )

    if not listener.is_valid:
        logger.error(
            f"Can not move field because there is a cycle between {source_class}, {target_class}"
        )
        db.close()
        return

    # Propagate Changes
    for file in usages.keys():
        parse_and_walk(
            file_path=file,
            listener_class=PropagateListener,
            has_write=True,
            field_name=field_name,
            new_name=f"{instance_name}.{field_name}",
            lines=usages[file],
        )

    # Do the cut and paste!
    # Cut

    listener = parse_and_walk(file_path=src_class_file,
                              listener_class=CutFieldListener,
                              has_write=True,
                              class_name=target_class,
                              instance_name=instance_name,
                              field_name=field_name,
                              is_static=is_static,
                              import_statement=import_statement)

    field_text = listener.field_text

    # Paste
    parse_and_walk(
        file_path=target_class_file,
        listener_class=PasteFieldListener,
        has_write=True,
        field_text=field_text,
    )

    db.close()
Ejemplo n.º 8
0
def main(source_class: str, source_package: str, target_class: str,
         target_package: str, method_name: str, udb_path: str, *args,
         **kwargs):
    import_statement = None
    if source_package != target_package:
        import_statement = f"\nimport {target_package}.{target_class};"
    instance_name = target_class.lower() + "ByCodArt"
    db = und.open(udb_path)
    method_map, class_ent = get_source_class_map(db, source_class)

    if class_ent.refs("Extend ~Implicit, ExtendBy, Implement"):
        logger.error("Class is in inheritance or implements an interface.")
        db.close()
        return None

    # Check if method is static
    method_ent = db.lookup(f"{source_package}.{source_class}.{method_name}",
                           "Method")
    if len(method_ent) >= 1:
        method_ent = method_ent[0]
    else:
        logger.error("Entity not found.")
        db.close()
        return None

    if method_ent.simplename() != method_name:
        logger.error("Can not move method duo to duplicated entities.")
        logger.info(f"{method_ent}, {method_ent.kindname()}")
        db.close()
        return None

    if source_package == target_package and source_class == target_class:
        logger.error("Can not move to self.")
        db.close()
        return None
    is_static = STATIC in method_ent.kindname()
    # Find usages
    usages = {}

    for ref in method_ent.refs("callby"):
        file = ref.file().longname()
        if file in usages:
            usages[file].append(ref.line())
        else:
            usages[file] = [
                ref.line(),
            ]

    try:
        src_class_file = db.lookup(f"{source_package}.{source_class}.java",
                                   "File")[0].longname()
        target_class_file = db.lookup(f"{target_package}.{target_class}.java",
                                      "File")[0].longname()
    except IndexError:
        logger.error("This is a nested method.")
        logger.info(f"{source_package}.{source_class}.java")
        logger.info(f"{target_package}.{target_class}.java")
        db.close()
        return None

    # Check if there is an cycle
    listener = parse_and_walk(file_path=target_class_file,
                              listener_class=CheckCycleListener,
                              class_name=source_class)

    if not listener.is_valid:
        logger.error(
            f"Can not move method because there is a cycle between {source_class}, {target_class}"
        )
        db.close()
        return None
    # Propagate Changes
    for file in usages.keys():
        public_class_name = os.path.basename(file).split(".")[0]
        is_in_target_class = public_class_name == target_class
        parse_and_walk(
            file_path=file,
            listener_class=PropagateListener,
            has_write=True,
            method_name=method_name,
            new_name=f"{instance_name}.{method_name}",
            lines=usages[file],
            is_in_target_class=is_in_target_class,
            method_map=method_map,
        )
    # exit(-1)
    # Do the cut and paste!
    # Cut
    listener = parse_and_walk(
        file_path=src_class_file,
        listener_class=CutMethodListener,
        has_write=True,
        class_name=target_class,
        instance_name=instance_name,
        method_name=method_name,
        is_static=is_static,
        import_statement=import_statement,
    )

    method_text = listener.method_text

    # Paste
    listener = parse_and_walk(
        file_path=target_class_file,
        listener_class=PasteMethodListener,
        has_write=True,
        method_text=method_text,
        source_class=source_class,
        method_map=method_map,
        imports=listener.imports,
    )

    # Post-Paste: Reference Injection
    parse_and_walk(
        file_path=target_class_file,
        listener_class=ReferenceInjectorAndConstructorListener,
        has_write=True,
        method_text=method_text,
        source_class=source_class,
        method_map=method_map,
        imports=None,
        has_empty_cons=listener.has_empty_cons,
    )
    db.close()