Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Debugger] Update debugger project loader to support bal persist sources #43578

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,18 @@
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;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
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;
Expand All @@ -60,6 +62,7 @@
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";
Expand Down Expand Up @@ -111,15 +114,57 @@
* @return A pair of project kind and the project root.
*/
public static Map.Entry<ProjectKind, Path> 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<Path> packageRoot = findProjectRoot(path);
if (packageRoot.isEmpty()) {
return new AbstractMap.SimpleEntry<>(ProjectKind.SINGLE_FILE_PROJECT, path);

Check warning on line 125 in misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java

View check run for this annotation

Codecov / codecov/patch

misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java#L125

Added line #L125 was not covered by tests
} 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) {
if (Objects.isNull(filePath)) {
return false;

Check warning on line 145 in misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java

View check run for this annotation

Codecov / codecov/patch

misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java#L145

Added line #L145 was not covered by tests
}
Path absFilePath = filePath.toAbsolutePath().normalize();
return absFilePath.resolve(BALLERINA_TOML).toFile().exists();
}

private static Optional<Path> findProjectRoot(Path filePath) {
if (filePath == null) {
return Optional.empty();

Check warning on line 153 in misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java

View check run for this annotation

Codecov / codecov/patch

misc/debug-adapter/modules/debug-adapter-core/src/main/java/org/ballerinalang/debugadapter/utils/PackageUtils.java#L153

Added line #L153 was not covered by tests
}

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();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,40 @@
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
Pair<BallerinaTestDebugPoint, StoppedEventArguments> debugHitInfo = debugTestRunner.waitForDebugHit(25000);
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 testDebugLaunchWithBallerinaToolFiles() 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<BallerinaTestDebugPoint, StoppedEventArguments> debugHitInfo = debugTestRunner.waitForDebugHit(25000);
Assert.assertEquals(debugHitInfo.getLeft(), debugTestRunner.testBreakpoints.get(0));
}

@Override
@AfterMethod(alwaysRun = true)
public void cleanUp() {
Expand Down