From 18f275a5447afad4a5d48607b5423b9981937fc5 Mon Sep 17 00:00:00 2001 From: Saurabh Misra Date: Mon, 2 Feb 2026 23:23:14 +0000 Subject: [PATCH] feat: include package in Java function qualified names Java function qualified names now include the package prefix for proper identification in markdown output and PR descriptions. Before: "Calculator.fibonacci" After: "com.example.Calculator.fibonacci" This ensures consistent fully-qualified naming for Java functions similar to how Python functions include their module path. The parents tuple now includes: 1. Package (type="package") - e.g., "com.example" 2. Class (type="ClassDef") - e.g., "Calculator" Functions without a package declaration maintain the previous behavior (just class.method). Co-Authored-By: Claude Opus 4.5 --- codeflash/languages/java/discovery.py | 7 +- .../test_java/test_discovery.py | 85 +++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/codeflash/languages/java/discovery.py b/codeflash/languages/java/discovery.py index 7d27fea65..d7e4941c3 100644 --- a/codeflash/languages/java/discovery.py +++ b/codeflash/languages/java/discovery.py @@ -82,6 +82,9 @@ def discover_functions_from_source( include_static=True, ) + # Extract package name for qualified names + package_name = analyzer.get_package_name(source) + functions: list[FunctionInfo] = [] for method in methods: @@ -89,8 +92,10 @@ def discover_functions_from_source( if not _should_include_method(method, criteria, source, analyzer): continue - # Build parents list + # Build parents list - include package for fully qualified names parents: list[ParentInfo] = [] + if package_name: + parents.append(ParentInfo(name=package_name, type="package")) if method.class_name: parents.append(ParentInfo(name=method.class_name, type="ClassDef")) diff --git a/tests/test_languages/test_java/test_discovery.py b/tests/test_languages/test_java/test_discovery.py index a1199b4a7..e622336d9 100644 --- a/tests/test_languages/test_java/test_discovery.py +++ b/tests/test_languages/test_java/test_discovery.py @@ -333,3 +333,88 @@ def test_discover_tests_from_fixture(self, java_fixture_path: Path): tests = discover_test_methods(test_file) assert len(tests) > 0 + + +class TestQualifiedNameWithPackage: + """Tests for qualified name including package in Java functions.""" + + def test_qualified_name_includes_package(self): + """Test that qualified name includes the package for Java functions. + + This fixes the issue where Java functions showed up as "Calculator.add" + instead of "com.example.Calculator.add" in markdown output. + """ + source = """ +package com.example; + +public class Calculator { + public int add(int a, int b) { + return a + b; + } +} +""" + functions = discover_functions_from_source(source) + assert len(functions) == 1 + + func = functions[0] + assert func.name == "add" + assert func.class_name == "Calculator" + # qualified_name should include package + assert func.qualified_name == "com.example.Calculator.add" + + def test_qualified_name_with_nested_package(self): + """Test qualified name with deeply nested package.""" + source = """ +package com.aerospike.client.command; + +public class Buffer { + public static String bytesToHexString(byte[] buf) { + return ""; + } +} +""" + functions = discover_functions_from_source(source) + assert len(functions) == 1 + + func = functions[0] + assert func.name == "bytesToHexString" + assert func.qualified_name == "com.aerospike.client.command.Buffer.bytesToHexString" + + def test_qualified_name_without_package(self): + """Test qualified name when no package is declared (default package).""" + source = """ +public class Utils { + public static String format(String s) { + return s.toUpperCase(); + } +} +""" + functions = discover_functions_from_source(source) + assert len(functions) == 1 + + func = functions[0] + assert func.name == "format" + # Without package, should just be class.method + assert func.qualified_name == "Utils.format" + + def test_parents_include_package_and_class(self): + """Test that parents tuple includes both package and class info.""" + source = """ +package com.example.utils; + +public class StringHelper { + public String reverse(String s) { + return new StringBuilder(s).reverse().toString(); + } +} +""" + functions = discover_functions_from_source(source) + assert len(functions) == 1 + + func = functions[0] + # Should have 2 parents: package and class + assert len(func.parents) == 2 + assert func.parents[0].name == "com.example.utils" + assert func.parents[0].type == "package" + assert func.parents[1].name == "StringHelper" + assert func.parents[1].type == "ClassDef"