From a1a984dfb70950910d537de19b1ad60f5cd94fa0 Mon Sep 17 00:00:00 2001 From: Nipuna Ranasinghe Date: Wed, 13 Nov 2024 13:39:28 +0530 Subject: [PATCH 1/4] Update debugger project loader to support bal persist sources --- .../debugadapter/utils/PackageUtils.java | 55 ++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java b/misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java index 7b127501a7f8..202abc2df198 100644 --- a/misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java +++ b/misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java @@ -34,7 +34,6 @@ import java.io.File; import java.net.URI; import java.net.URISyntaxException; -import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.util.AbstractMap; @@ -44,6 +43,8 @@ import java.util.Optional; import java.util.StringJoiner; +import static io.ballerina.projects.util.ProjectConstants.BALLERINA_TOML; +import static io.ballerina.projects.util.ProjectPaths.isBalFile; import static org.ballerinalang.debugadapter.DebugSourceType.DEPENDENCY; import static org.ballerinalang.debugadapter.DebugSourceType.PACKAGE; import static org.ballerinalang.debugadapter.evaluation.IdentifierModifier.encodeModuleName; @@ -60,6 +61,7 @@ public final class PackageUtils { public static final String GENERATED_VAR_PREFIX = "$"; static final String USER_MODULE_DIR = "modules"; static final String GEN_MODULE_DIR = "generated"; + static final String PERSIST_DIR = "persist"; static final String TEST_PKG_POSTFIX = "$test"; private static final String URI_SCHEME_FILE = "file"; private static final String URI_SCHEME_BALA = "bala"; @@ -111,15 +113,54 @@ public static Optional> getStackFrameSourcePath * @return A pair of project kind and the project root. */ public static Map.Entry computeProjectKindAndRoot(Path path) { - if (ProjectPaths.isStandaloneBalFile(path)) { + if (ProjectPaths.isStandaloneBalFile(path) && !isBalToolSpecificFile(path)) { return new AbstractMap.SimpleEntry<>(ProjectKind.SINGLE_FILE_PROJECT, path); } - // Following is a temp fix to distinguish Bala and Build projects. - Path tomlPath = ProjectPaths.packageRoot(path).resolve(ProjectConstants.BALLERINA_TOML); - if (Files.exists(tomlPath)) { - return new AbstractMap.SimpleEntry<>(ProjectKind.BUILD_PROJECT, ProjectPaths.packageRoot(path)); + // TODO: Revert 'findProjectRoot()' to `ProjectPaths.packageRoot()` API once + // https://github.com/ballerina-platform/ballerina-lang/issues/43538#issuecomment-2469488458 + // is addressed from the Ballerina platform side. + Optional packageRoot = findProjectRoot(path); + if (packageRoot.isEmpty()) { + return new AbstractMap.SimpleEntry<>(ProjectKind.SINGLE_FILE_PROJECT, path); + } else if (hasBallerinaToml(packageRoot.get())) { + return new AbstractMap.SimpleEntry<>(ProjectKind.BUILD_PROJECT, packageRoot.get()); + } else { + return new AbstractMap.SimpleEntry<>(ProjectKind.BALA_PROJECT, packageRoot.get()); } - return new AbstractMap.SimpleEntry<>(ProjectKind.BALA_PROJECT, ProjectPaths.packageRoot(path)); + } + + private static boolean isBalToolSpecificFile(Path filePath) { + // TODO: Remove after https://github.com/ballerina-platform/ballerina-lang/issues/43538#issuecomment-2469488458 + // is addressed from the Ballerina platform side. + Path parentPath = filePath.toAbsolutePath().normalize().getParent(); + return isBalFile(filePath) + && parentPath.toFile().isDirectory() + && parentPath.toFile().getName().equals(PERSIST_DIR) + && hasBallerinaToml(parentPath.getParent()); + } + + private static boolean hasBallerinaToml(Path filePath) { + Path absFilePath = filePath.toAbsolutePath().normalize(); + return absFilePath.resolve(BALLERINA_TOML).toFile().exists(); + } + + private static Optional findProjectRoot(Path filePath) { + if (filePath == null) { + return Optional.empty(); + } + + filePath = filePath.toAbsolutePath().normalize(); + if (filePath.toFile().isDirectory()) { + if (hasBallerinaToml(filePath) || hasPackageJson(filePath)) { + return Optional.of(filePath); + } + } + return findProjectRoot(filePath.getParent()); + } + + private static boolean hasPackageJson(Path filePath) { + Path absFilePath = filePath.toAbsolutePath().normalize(); + return absFilePath.resolve(ProjectConstants.PACKAGE_JSON).toFile().exists(); } /** From 87732d197bc80a1df7ee8f8795ad907dc4e54d27 Mon Sep 17 00:00:00 2001 From: Nipuna Ranasinghe Date: Wed, 13 Nov 2024 14:02:38 +0530 Subject: [PATCH 2/4] Add tests --- .../test/adapter/run/DebugEngageTest.java | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/run/DebugEngageTest.java b/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/run/DebugEngageTest.java index ed6c1d2ffc9c..7f985daf3113 100644 --- a/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/run/DebugEngageTest.java +++ b/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/run/DebugEngageTest.java @@ -40,20 +40,20 @@ public class DebugEngageTest extends BaseTestCase { DebugTestRunner debugTestRunner; + private static final String TEST_PROJECT_NAME = "basic-project"; @Override @BeforeClass public void setup() { - String testProjectName = "breakpoint-tests"; - String testModuleFileName = "Ballerina.toml"; - debugTestRunner = new DebugTestRunner(testProjectName, testModuleFileName, true); } - @Test(description = "Debug engage test for launch mode, with special ballerina project files as input(i.e. " + - "Ballerina.toml, Dependencies.toml, etc.)") - public void testNonBallerinaInputSource() throws BallerinaTestException { - Path breakpointFilePath = debugTestRunner.testProjectPath.resolve("main.bal"); - debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(breakpointFilePath, 22)); + @Test(description = "Debug engage test (launch mode), with special ballerina project files as inputs" + + "(i.e. Ballerina.toml, Dependencies.toml, etc.)") + public void testDebugLaunchWithNonBallerinaFiles() throws BallerinaTestException { + String balTomlFile = "Ballerina.toml"; + debugTestRunner = new DebugTestRunner(TEST_PROJECT_NAME, balTomlFile, true); + Path breakpointFilePath = debugTestRunner.testProjectPath.resolve("hello_world.bal"); + debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(breakpointFilePath, 19)); debugTestRunner.initDebugSession(DebugUtils.DebuggeeExecutionKind.RUN); // Test for debug engage @@ -61,6 +61,19 @@ public void testNonBallerinaInputSource() throws BallerinaTestException { Assert.assertEquals(debugHitInfo.getLeft(), debugTestRunner.testBreakpoints.get(0)); } + @Test(description = "Debug engage test (launch mode), with special Ballerina project files as inputs " + + "(i.e. persist/model.bal, etc.)") + public void testDebugLaunchWithBallerinaToolFile() throws BallerinaTestException { + String balPersistModelFile = "persist/model.bal"; + debugTestRunner = new DebugTestRunner(TEST_PROJECT_NAME, balPersistModelFile, true); + Path breakpointFilePath = debugTestRunner.testProjectPath.resolve("hello_world.bal"); + debugTestRunner.addBreakPoint(new BallerinaTestDebugPoint(breakpointFilePath, 19)); + debugTestRunner.initDebugSession(DebugUtils.DebuggeeExecutionKind.RUN); + // Test for debug engage + Pair debugHitInfo = debugTestRunner.waitForDebugHit(25000); + Assert.assertEquals(debugHitInfo.getLeft(), debugTestRunner.testBreakpoints.get(0)); + } + @Override @AfterMethod(alwaysRun = true) public void cleanUp() { From 680dd554260d683bb757e90c90bf0bfd80f245b1 Mon Sep 17 00:00:00 2001 From: Nipuna Ranasinghe Date: Wed, 13 Nov 2024 14:03:50 +0530 Subject: [PATCH 3/4] Fix test name --- .../debugger/test/adapter/run/DebugEngageTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/run/DebugEngageTest.java b/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/run/DebugEngageTest.java index 7f985daf3113..9d9e6388e76e 100644 --- a/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/run/DebugEngageTest.java +++ b/tests/jballerina-debugger-integration-test/src/test/java/org/ballerinalang/debugger/test/adapter/run/DebugEngageTest.java @@ -63,7 +63,7 @@ public void testDebugLaunchWithNonBallerinaFiles() throws BallerinaTestException @Test(description = "Debug engage test (launch mode), with special Ballerina project files as inputs " + "(i.e. persist/model.bal, etc.)") - public void testDebugLaunchWithBallerinaToolFile() throws BallerinaTestException { + public void testDebugLaunchWithBallerinaToolFiles() throws BallerinaTestException { String balPersistModelFile = "persist/model.bal"; debugTestRunner = new DebugTestRunner(TEST_PROJECT_NAME, balPersistModelFile, true); Path breakpointFilePath = debugTestRunner.testProjectPath.resolve("hello_world.bal"); From 574e7342c7c06e8c0c8aa84b853c1e5a2c23b508 Mon Sep 17 00:00:00 2001 From: Nipuna Ranasinghe Date: Wed, 13 Nov 2024 23:14:17 +0530 Subject: [PATCH 4/4] Fix spotbugs --- .../org/ballerinalang/debugadapter/utils/PackageUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java b/misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java index 202abc2df198..0ee0b4a8eba6 100644 --- a/misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java +++ b/misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java @@ -40,6 +40,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.StringJoiner; @@ -140,6 +141,9 @@ private static boolean isBalToolSpecificFile(Path filePath) { } private static boolean hasBallerinaToml(Path filePath) { + if (Objects.isNull(filePath)) { + return false; + } Path absFilePath = filePath.toAbsolutePath().normalize(); return absFilePath.resolve(BALLERINA_TOML).toFile().exists(); }