javalang
javalang copied to clipboard
How to associate methods to a class in a java file
A java file can contain multiple classes as well as inner classes. I want to associate methods to the class it belongs to. How can I do this>
I had the same issue and ended up with the following code:
import javalang
def traverse_for_methods(node, fn, klass='', level=0):
# print(' ' * level, type(node), node.name if hasattr(node, 'name') else "")
if isinstance(node, javalang.tree.ConstructorDeclaration) or isinstance(node, javalang.tree.MethodDeclaration):
fn(node, klass)
elif isinstance(node, javalang.tree.ClassDeclaration):
klass = node.name
elif isinstance(node, javalang.tree.ClassCreator):
# Anonymous classes
klass = node.type.name
if hasattr(node, 'children'):
for child in node.children:
if isinstance(child, list) and (len(child) > 0):
for item in child:
traverse_for_methods(item, fn, klass, level+1)
else:
traverse_for_methods(child, fn, klass, level+1)
with open('src/Foo.java', mode='r') as f:
source = f.read()
tree = javalang.parse.parse(source)
def do_with_node(node, klass):
# Do whatever you like for each method node (e.g. pushing them to a list outside)
print(klass, node.name, node.position.line)
traverse_for_methods(tree, do_with_node)
(I borrowed the traverse logic from https://github.com/c2nes/javalang/issues/68#issuecomment-654793446. Thanks.)
Actually, you cannot know the source class name. Because you can only iterate to the end of the tree:
class->method->member ref. Here, when you have reached member ref
leaf, you do not know where you are exactly in the tree. You can't also iterate over parents nodes.
But you can do the following trick:
import javalang
ast = javalang.parse.parse(open(r'D:\target\0001\ReconfigurableBase.java').read())
# Get main class among all classes, declared in a file
main_class = list(ast.filter(javalang.tree.ClassDeclaration))[0][1]
for _, inner_class_ast in main_class.filter(javalang.tree.ClassDeclaration):
if main_class.name != inner_class_ast.name:
for method_inner in inner_class_ast.methods:
print(f'class {inner_class_ast.name}, method name {method_inner.name}')
So, the method is to iterate over the other class declarations and remember class name from the outer loop. The original filname is ReconfigurableBase.txt The output will be the following:
class ReconfigurationThread, method name run