I need to extract method implementation from java projects. I found a code on the javalang github issues https://github.com/c2nes/javalang/issues/49 but it fails sometimes. Can anyone take a look and see whats wrong?
On a colab notebook, clone the repo with
!git clone https://github.com/google/closure-compiler
Install javalang
!pip install javalang
Run the following code (it fails on other files too, not on every function but some)
import os
import re
import javalang
import json
def get_method_start_end(tree, method_node):
startpos = None
endpos = None
startline = None
endline = None
for path, node in tree:
if startpos is not None and method_node not in path:
endpos = node.position
endline = node.position.line if node.position is not None else None
break
if startpos is None and node == method_node:
startpos = node.position
startline = node.position.line if node.position is not None else None
return startpos, endpos, startline, endline
def get_method_text(codelines, startpos, endpos, startline, endline, last_endline_index):
if startpos is None:
return "", None, None, None
else:
startline_index = startline - 1
endline_index = endline - 1 if endpos is not None else None
# 1. check for and fetch annotations
if last_endline_index is not None:
for line in codelines[(last_endline_index + 1):(startline_index)]:
if "@" in line:
startline_index = startline_index - 1
# 2. Add comments before method
comments = []
for line_index in range(startline_index - 1, -1, -1):
line = codelines[line_index].strip()
if line.startswith('//') or line.startswith('/*'):
comments.insert(0, line)
else:
break
method_lines = comments + codelines[startline_index:endline_index]
method_text = 'n'.join(method_lines)
method_text = method_text[:method_text.rfind("}") + 1]
# 3. remove trailing rbrace for last methods & any external content/comments
# if endpos is None and
if not abs(method_text.count("}") - method_text.count("{")) == 0:
# imbalanced braces
brace_diff = abs(method_text.count("}") - method_text.count("{"))
for _ in range(brace_diff):
method_text = method_text[:method_text.rfind("}")]
method_text = method_text[:method_text.rfind("}") + 1]
last_endline_index = startline_index + len(method_lines) - 1
return method_text, (startline_index + 1), (last_endline_index + 1), last_endline_index
def get_methods_info(java_content, file_path):
code_lines = java_content.split('n')
lex = None
try:
tree = javalang.parse.parse(java_content)
except:
print(f'Parsing failed for file: {file_path}')
return None
for _, method_node in tree.filter(javalang.tree.MethodDeclaration):
startpos, endpos, startline, endline = get_method_start_end(tree, method_node)
if endpos == None:
raise ValueError(f"Check file: {file_path}, {method_node.name}")
continue
method_text, startline, endline, lex = get_method_text(code_lines, startpos, endpos, startline, endline, lex)
return method_text
filename = "./closure-compiler/test/com/google/javascript/jscomp/Es6RewriteBlockScopedFunctionDeclarationTest.java"
with open(filename, 'r') as f:
java_content = f.read()
java_content = java_content.replace("@Nullable", "")
java_content = java_content.replace(r"\$", "")
java_content = re.sub(r'[^a-zA-Z](.+?)::new', lambda match: match.group(1).lower().removesuffix('[]'), java_content)
methods_info = get_methods_info(java_content, filename)