Decrease method visibility
Introduction
Decrease method visibility refactoring
Decrease the visibility of a method from public to protected, protected to package or package to private.
DecreaseMethodVisibilityListener (JavaParserLabeledListener)
To implement ِDecrease Method Visibility refactoring based on its actors.
Detects the required method and decreases/changes its visibility status.
Source code in codart\refactorings\decrease_method_visibility.py
class DecreaseMethodVisibilityListener(JavaParserLabeledListener):
"""
To implement ِDecrease Method Visibility refactoring based on its actors.
Detects the required method and decreases/changes its visibility status.
"""
def __init__(self, source_class, source_method, rewriter: TokenStreamRewriter):
"""
Args:
source_class (str): Name of the class in which the refactoring has to be done
source_method (str): Name of the field whose visibility status has to be changed
rewriter (CommonTokenStream): An instance of TokenStreamRewriter
Returns:
object (DecreaseMethodVisibilityListener): An instance of DecreaseMethodVisibilityListener
"""
self.source_class = source_class
self.source_method = source_method
self.in_class = False
self.detected_method = False
self.rewriter = rewriter
def enterClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
if ctx.IDENTIFIER().getText() == self.source_class:
self.in_class = True
def exitClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
if ctx.IDENTIFIER().getText() == self.source_class:
self.in_class = False
def enterMethodDeclaration(self, ctx: JavaParserLabeled.MethodDeclarationContext):
if ctx.IDENTIFIER().getText() == self.source_method:
self.detected_method = True
def exitClassBodyDeclaration2(self, ctx: JavaParserLabeled.ClassBodyDeclaration2Context):
if self.detected_method:
if ctx.modifier(0) is not None:
if "@" in ctx.modifier(0).getText():
if ctx.modifier(1) is not None:
self.rewriter.replaceSingleToken(
token=ctx.modifier(1).start,
text="private "
)
else:
self.rewriter.replaceSingleToken(
ctx.memberDeclaration().getChild(0).getChild(0).start,
text="private " + ctx.memberDeclaration().getChild(0).getChild(0).getText()
)
else:
if ctx.modifier(0).getText() == 'public' or ctx.modifier(0).getText() == 'protected':
self.rewriter.replaceSingleToken(
token=ctx.modifier(0).start,
text="private "
)
else:
self.rewriter.insertBeforeToken(
token=ctx.modifier(0).start,
text="private "
)
else:
if ctx.memberDeclaration().getChild(0).getChild(0) is not None:
self.rewriter.insertBeforeToken(
ctx.memberDeclaration().getChild(0).getChild(0).start,
text="private "
)
self.detected_method = False
__init__(self, source_class, source_method, rewriter)
special
Parameters:
Name | Type | Description | Default |
---|---|---|---|
source_class |
str |
Name of the class in which the refactoring has to be done |
required |
source_method |
str |
Name of the field whose visibility status has to be changed |
required |
rewriter |
CommonTokenStream |
An instance of TokenStreamRewriter |
required |
Returns:
Type | Description |
---|---|
object (DecreaseMethodVisibilityListener) |
An instance of DecreaseMethodVisibilityListener |
Source code in codart\refactorings\decrease_method_visibility.py
def __init__(self, source_class, source_method, rewriter: TokenStreamRewriter):
"""
Args:
source_class (str): Name of the class in which the refactoring has to be done
source_method (str): Name of the field whose visibility status has to be changed
rewriter (CommonTokenStream): An instance of TokenStreamRewriter
Returns:
object (DecreaseMethodVisibilityListener): An instance of DecreaseMethodVisibilityListener
"""
self.source_class = source_class
self.source_method = source_method
self.in_class = False
self.detected_method = False
self.rewriter = rewriter
main(udb_path, source_package, source_class, source_method, *args, **kwargs)
Source code in codart\refactorings\decrease_method_visibility.py
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.")
db.close()
return False
method_ent = method_ent[0]
if method_ent.simplename() != source_method:
logger.error("Invalid entity.")
db.close()
return False
# Strong overlay precondition
# if not method_ent.kind().check("Public"):
# logger.error("Method is not public.")
# db.close()
# return False
for ent in method_ent.ents("CallBy"):
if f"{source_package}.{source_class}" not in ent.longname():
logger.error("Method cannot set to private.")
db.close()
return False
parent = method_ent.parent()
while parent.parent() is not None:
parent = parent.parent()
main_file = parent.longname()
db.close()
parse_and_walk(
file_path=main_file,
listener_class=DecreaseMethodVisibilityListener,
has_write=True,
source_class=source_class,
source_method=source_method
)
return True