From 0af3f2a77bdb97a470206209e6ff7c92736dabd7 Mon Sep 17 00:00:00 2001 From: Terry Yin Date: Thu, 13 Feb 2025 18:53:28 +0800 Subject: [PATCH] issue: https://github.com/terryyin/lizard/issues/409 --- lizard_languages/java.py | 3 +- test/test_languages/testJava.py | 176 ++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 1 deletion(-) diff --git a/lizard_languages/java.py b/lizard_languages/java.py index c688484..1b00902 100644 --- a/lizard_languages/java.py +++ b/lizard_languages/java.py @@ -123,12 +123,13 @@ def _state_new_parameters(self, token): if token == "(": self.sub_state(JavaFunctionBodyStates(self.context), None, token) return + print(token) if token == "{": def callback(): self.next(self._state_global) self.sub_state(JavaClassBodyStates("(anonymous)", False, self.context), callback, token) return - self.next(self._state_global) + self.next(self._state_global, token) class JavaClassBodyStates(JavaStates): def __init__(self, class_name, is_record, context): diff --git a/test/test_languages/testJava.py b/test/test_languages/testJava.py index 8767304..970f8c2 100644 --- a/test/test_languages/testJava.py +++ b/test/test_languages/testJava.py @@ -229,3 +229,179 @@ class Demo { self.assertEqual(2, run_method.cyclomatic_complexity) # run method has one if, so complexity 2 testA_method = next(f for f in result if f.name.endswith("::testA")) self.assertEqual(2, testA_method.cyclomatic_complexity) # testA has one if, so complexity 2 + + def test_complex_java_class_method_count(self): + code = """ +public class GitRepository implements SCM { + private static final int MAX_SIZE_OF_A_DIFF = 100000; + private String path = null; + + public GitRepository(String path) { + this.path = path; + } + + public void setPath(String path) { + this.path = path; + } + + public void delete() { + if (path != null) { + System.out.println("Deleting: " + path); + } + } + + public void reset() { + try { + System.out.println("Resetting"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} +""" + result = get_java_function_list(code) + self.assertEqual(4, len(result)) # Should find 4 methods: constructor, setPath, delete, reset + + def test_complex_java_class_with_annotations_and_generics(self): + code = """ +public class GitRepository implements SCM { + private static final int MAX_SIZE_OF_A_DIFF = 100000; + private String path = null; + private CollectConfiguration collectConfig; + + @Override + public List getChangeSets() { + try (Git git = openRepository()) { + List allCs; + if (!firstParentOnly) allCs = getAllCommits(git); + else allCs = firstParentsOnly(git); + return allCs; + } catch (Exception e) { + throw new RuntimeException("error in getChangeSets for " + path, e); + } + } + + private List firstParentsOnly(Git git) { + RevWalk revWalk = null; + try { + List allCs = new ArrayList<>(); + return allCs; + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + revWalk.close(); + } + } + + @Override + public List getDiffBetweenCommits(String priorCommitHash, String laterCommitHash) { + try (Git git = openRepository()) { + RepositoryMining repo = git.getRepository(); + return new ArrayList<>(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private synchronized void deleteMMBranch(Git git) throws GitAPIException { + List refs = git.branchList().call(); + for (Ref r : refs) { + if (r.getName().endsWith("mm")) { + git.branchDelete().setBranchNames("mm").setForce(true).call(); + break; + } + } + } +} +""" + result = get_java_function_list(code) + print("\nFound methods:", [f.name for f in result]) # Debug output + self.assertEqual(4, len(result)) # Should find 4 methods: getChangeSets, firstParentsOnly, getDiffBetweenCommits, deleteMMBranch + + def test_very_complex_java_class_with_try_resources_and_nested_types(self): + code = """ +public class GitRepository implements SCM { + private static final int MAX_SIZE_OF_A_DIFF = 100000; + private String path = null; + + public SCMRepository info() { + try (Git git = openRepository(); RevWalk rw = new RevWalk(git.getRepository())) { + AnyObjectId headId = git.getRepository().resolve(Constants.HEAD); + RevCommit root = rw.parseCommit(headId); + rw.sort(RevSort.REVERSE); + rw.markStart(root); + RevCommit lastCommit = rw.next(); + String origin = git.getRepository().getConfig().getString("remote", "origin", "url"); + return new SCMRepository(this, origin, path, headId.getName(), lastCommit.getName()); + } catch (Exception e) { + throw new RuntimeException("error", e); + } + } + + @Override + public List getDiffBetweenCommits(String priorCommitHash, String laterCommitHash) { + try (Git git = openRepository()) { + RepositoryMining repo = git.getRepository(); + AnyObjectId priorCommit = repo.resolve(priorCommitHash); + AnyObjectId laterCommit = repo.resolve(laterCommitHash); + List diffs = this.getDiffBetweenCommits(repo, priorCommit, laterCommit); + return diffs.stream() + .map(diff -> { + class LocalClass { + void localMethod() {} + } + try { + return this.diffToModification(repo, diff); + } catch (IOException e) { + throw new RuntimeException(e); + } + }) + .collect(Collectors.toList()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private List getDiffBetweenCommits(RepositoryMining repo, AnyObjectId parentCommit, + AnyObjectId currentCommit) { + try (DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE)) { + df.setBinaryFileThreshold(2 * 1024); + df.setRepository(repo); + df.setDiffComparator(RawTextComparator.DEFAULT); + df.setDetectRenames(true); + List diffs = df.scan(parentCommit, currentCommit); + return diffs; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private Modification diffToModification(RepositoryMining repo, DiffEntry diff) throws IOException { + ModificationType change = Enum.valueOf(ModificationType.class, diff.getChangeType().toString()); + String oldPath = diff.getOldPath(); + String newPath = diff.getNewPath(); + return new Modification(oldPath, newPath, change, "", ""); + } +} +""" + result = get_java_function_list(code) + print("\nFound methods:", [f.name for f in result]) # Debug output + self.assertEqual(5, len(result)) # Should find 5 methods: info, getDiffBetweenCommits (2), diffToModification, and LocalClass::localMethod + + def test_try_with_resources(self): + code = """ +public class Test { + public void methodWithTryResources() { + try (Resource r2 = new Resource()) { + r1.use(); + r2.use(); + } + } + + public void anotherMethod() { + System.out.println("test"); + } +} +""" + result = get_java_function_list(code) + self.assertEqual(2, len(result)) # Should find both methods