diff --git a/CHANGELOG.md b/CHANGELOG.md index 250d99b3f..444dc9d65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ ### Fixes 🛠️ +- Parsing of project view file fails if the file doesn't exist. + | [#215](https://github.com/JetBrains/bazel-bsp/pull/215) - Project view path is mapped to the absolute path in the installer. | [#213](https://github.com/JetBrains/bazel-bsp/pull/213) - Kotlin targets don't break import. diff --git a/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/BUILD b/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/BUILD index be056e885..9342d4bda 100644 --- a/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/BUILD +++ b/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/BUILD @@ -1,4 +1,5 @@ load("@rules_java//java:defs.bzl", "java_library") +load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") java_library( name = "parser", @@ -9,11 +10,13 @@ java_library( ], exports = [ "//executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/model", + "//executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser:parser_kotlin", "//executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/sections", ], deps = [ "//commons", "//executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/model", + "//executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser:parser_kotlin", "//executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/sections", "@maven//:com_google_guava_guava", "@maven//:io_vavr_vavr", @@ -21,3 +24,15 @@ java_library( "@maven//:org_apache_logging_log4j_log4j_core", ], ) + +kt_jvm_library( + name = "parser_kotlin", + srcs = glob(["*.kt"]), + deps = [ + "//executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/model", + "//executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/sections", + "@maven//:io_vavr_vavr", + "@maven//:org_apache_logging_log4j_log4j_api", + "@maven//:org_apache_logging_log4j_log4j_core", + ], +) diff --git a/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParser.java b/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParser.java deleted file mode 100644 index 553d36e15..000000000 --- a/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParser.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.jetbrains.bsp.bazel.projectview.parser; - -import io.vavr.control.Try; -import java.nio.file.Path; -import org.jetbrains.bsp.bazel.projectview.model.ProjectView; - -/** - * Project view file parser. Its purpose is to parse *.bazelproject file and create an instance of - * ProjectView. - * - * @see org.jetbrains.bsp.bazel.projectview.model.ProjectView - */ -public interface ProjectViewParser { - - /** - * Parses file under projectViewFilePath using file under - * defaultProjectViewFilePath as a default. - * - * @param projectViewFilePath path to file with project view - * @param defaultProjectViewFilePath path to file with default project view - * @return - *

Try.success with ProjectView if parsing has finished with - * success, it means: - *

1) files under projectViewFilePath and defaultProjectViewFilePath - * were successfully parsed (not all values have to be provided -- some fields in - * ProjectView might be Optional.empty).
- * File under projectViewFilePath can contain all values, then - * defaultProjectViewFilePath won't be used, or file under projectViewFilePath - * can be empty, then all values from file under defaultProjectViewFilePath - * will be used, any other configuration is possible as well. - *

2) file under projectViewFilePath doesn't exist, then all values from - * defaultProjectViewFilePath will be used.
- *
- *

Try.failure with if: - *

1) file under defaultProjectViewFilePath doesn't exist - *

2) any other fail happen - */ - Try parse(Path projectViewFilePath, Path defaultProjectViewFilePath); - - /** - * Parses projectViewFileContent using defaultProjectViewFileContent as - * a default. - * - * @param projectViewFileContent string with project view - * @param defaultProjectViewFileContent string with default project view - * @return - *

Try.success with ProjectView if parsing has finished with - * success, it means: - *

1) projectViewFileContent and defaultProjectViewFileContent - * were successfully parsed (not all values have to be provided -- some fields in - * ProjectView might be Optional.empty).
- * projectViewFileContent can contain all values, then - * defaultProjectViewFileContent won't be used, projectViewFileContent - * can be empty, then all values from defaultProjectViewFileContent will - * be used, any other configuration is possible as well.
- *
- *

Try.failure with if: - *

1) any fail happen - */ - Try parse(String projectViewFileContent, String defaultProjectViewFileContent); - - /** - * Parses file under projectViewFilePath. - * - * @param projectViewFilePath path to file with project view - * @return - *

Try.success with ProjectView if parsing has finished with - * success, it means: - *

1) file under projectViewFilePath was successfully parsed (not all values - * have to be provided -- some fields in ProjectView might be - * Optional.empty).
- *

Try.failure with if: - *

1) file under projectViewFilePath doesn't exist - *

2) any other fail happen - */ - Try parse(Path projectViewFilePath); - - /** - * Parses projectViewFileContent. - * - * @param projectViewFileContent string with project view - * @return - *

Try.success with ProjectView if parsing has finished with - * success, it means: - *

1) projectViewFileContent was successfully parsed (not all values have to - * be provided -- some fields in ProjectView might be Optional.empty - * ).
- *

Try.failure with if: - *

1) any fail happen - */ - Try parse(String projectViewFileContent); -} diff --git a/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParser.kt b/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParser.kt new file mode 100644 index 000000000..8bb37a911 --- /dev/null +++ b/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParser.kt @@ -0,0 +1,110 @@ +package org.jetbrains.bsp.bazel.projectview.parser + +import io.vavr.control.Try +import org.jetbrains.bsp.bazel.projectview.model.ProjectView +import java.nio.file.Path + +/** + * Project view file parser. Its purpose is to parse *.bazelproject file and create an instance of + * ProjectView. + * + * @see org.jetbrains.bsp.bazel.projectview.model.ProjectView + */ +interface ProjectViewParser { + /** + * Parses file under `projectViewFilePath` using file under ` + * defaultProjectViewFilePath` as a default. + * + * @param projectViewFilePath path to file with project view + * @param defaultProjectViewFilePath path to file with default project view + * @return + * + * `Try.success` with `ProjectView` if parsing has finished with + * success, it means: + * + * 1) files under `projectViewFilePath` and `defaultProjectViewFilePath + ` * were successfully parsed (not all values have to be provided -- some fields in + * `ProjectView` might be `Optional.empty`).

+ * File under `projectViewFilePath` can contain all values, then ` + * defaultProjectViewFilePath` won't be used, or file under `projectViewFilePath + ` * can be empty, then all values from file under `defaultProjectViewFilePath + ` * will be used, any other configuration is possible as well. + * + * 2) file under `projectViewFilePath` doesn't exist, then all values from + * `defaultProjectViewFilePath` will be used.

+ *

+ * + * `Try.failure` with if: + * + * 1) file under `defaultProjectViewFilePath` doesn't exist + * + * 2) any other fail happen + */ + fun parse(projectViewFilePath: Path, defaultProjectViewFilePath: Path): Try + + /** + * Parses `projectViewFileContent` using `defaultProjectViewFileContent` as + * a default. + * + * @param projectViewFileContent string with project view + * @param defaultProjectViewFileContent string with default project view + * @return + * + * `Try.success` with `ProjectView` if parsing has finished with + * success, it means: + * + * 1) `projectViewFileContent` and `defaultProjectViewFileContent + ` * were successfully parsed (not all values have to be provided -- some fields in + * `ProjectView` might be `Optional.empty`).

+ * `projectViewFileContent` can contain all values, then ` + * defaultProjectViewFileContent` won't be used, `projectViewFileContent + ` * can be empty, then all values from `defaultProjectViewFileContent` will + * be used, any other configuration is possible as well.

+ *

+ * + * `Try.failure` with if: + * + * 1) any fail happen + */ + fun parse(projectViewFileContent: String, defaultProjectViewFileContent: String): Try + + /** + * Parses file under `projectViewFilePath`. + * + * @param projectViewFilePath path to file with project view + * @return + * + * `Try.success` with `ProjectView` if parsing has finished with + * success, it means: + * + * 1) file under `projectViewFilePath` was successfully parsed (not all values + * have to be provided -- some fields in `ProjectView` might be ` + * Optional.empty`).

+ * + * `Try.failure` with if: + * + * 1) file under `projectViewFilePath` doesn't exist + * + * 2) any other fail happen + */ + fun parse(projectViewFilePath: Path): Try + + /** + * Parses `projectViewFileContent`. + * + * @param projectViewFileContent string with project view + * @return + * + * `Try.success` with `ProjectView` if parsing has finished with + * success, it means: + * + * 1) `projectViewFileContent` was successfully parsed (not all values have to + * be provided -- some fields in `ProjectView` might be `Optional.empty + ` * ).

+ * + * `Try.failure` with if: + * + * 1) any fail happen + */ + fun parse(projectViewFileContent: String): Try +} diff --git a/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImpl.java b/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImpl.java deleted file mode 100644 index fc7cc1793..000000000 --- a/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImpl.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.jetbrains.bsp.bazel.projectview.parser; - -import io.vavr.collection.List; -import io.vavr.control.Try; -import java.nio.file.Path; -import java.nio.file.Paths; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.bsp.bazel.commons.BetterFiles; -import org.jetbrains.bsp.bazel.projectview.model.ProjectView; -import org.jetbrains.bsp.bazel.projectview.parser.sections.ProjectViewBazelPathSectionParser; -import org.jetbrains.bsp.bazel.projectview.parser.sections.ProjectViewDebuggerAddressSectionParser; -import org.jetbrains.bsp.bazel.projectview.parser.sections.ProjectViewJavaPathSectionParser; -import org.jetbrains.bsp.bazel.projectview.parser.sections.ProjectViewTargetsSectionParser; -import org.jetbrains.bsp.bazel.projectview.parser.splitter.ProjectViewRawSection; -import org.jetbrains.bsp.bazel.projectview.parser.splitter.ProjectViewRawSections; -import org.jetbrains.bsp.bazel.projectview.parser.splitter.ProjectViewSectionSplitter; - -/** - * Default implementation of ProjectViewParser. - * - * @see org.jetbrains.bsp.bazel.projectview.parser.ProjectViewParser - * @see org.jetbrains.bsp.bazel.projectview.parser.splitter.ProjectViewSectionSplitter - */ -public class ProjectViewParserImpl implements ProjectViewParser { - - private static final Logger log = LogManager.getLogger(ProjectViewParserImpl.class); - - private static final String IMPORT_STATEMENT = "import"; - - private static final ProjectViewTargetsSectionParser targetsParser = - new ProjectViewTargetsSectionParser(); - - private static final ProjectViewBazelPathSectionParser bazelPathParser = - new ProjectViewBazelPathSectionParser(); - - private static final ProjectViewDebuggerAddressSectionParser debuggerAddressParser = - new ProjectViewDebuggerAddressSectionParser(); - - private static final ProjectViewJavaPathSectionParser javaPathParser = - new ProjectViewJavaPathSectionParser(); - - @Override - public Try parse(Path projectViewFilePath, Path defaultProjectViewFilePath) { - log.info( - "Parsing project view from {} with default from {}.", - projectViewFilePath, - defaultProjectViewFilePath); - - return BetterFiles.tryReadFileContent(defaultProjectViewFilePath) - .onFailure( - exception -> - log.error( - "Failed to read default file {}. Parsing failed!", - defaultProjectViewFilePath, - exception)) - .flatMap( - defaultProjectViewFileContent -> - parseWithDefault(projectViewFilePath, defaultProjectViewFileContent)) - .onSuccess( - projectView -> - log.info( - "Project view from {} with default from {} parsed!\n{}", - projectViewFilePath, - defaultProjectViewFilePath, - projectView)) - .onFailure( - exception -> - log.error( - "Failed to parse default file {}. Parsing failed!", - defaultProjectViewFilePath, - exception)); - } - - private Try parseWithDefault( - Path projectViewFilePath, String defaultProjectViewFileContent) { - return BetterFiles.tryReadFileContent(projectViewFilePath) - .onFailure( - exception -> - log.info("Failed to read file {}. Parsing default file.", projectViewFilePath)) - .flatMap( - projectViewFilePathContent -> - parse(projectViewFilePathContent, defaultProjectViewFileContent)) - .onFailure( - exception -> - log.info("Failed to parse file {}. Parsing default file.", projectViewFilePath)) - .orElse(() -> parse(defaultProjectViewFileContent)) - .onFailure( - exception -> log.error("Failed to parse default file. Parsing failed!", exception)); - } - - @Override - public Try parse( - String projectViewFileContent, String defaultProjectViewFileContent) { - log.debug( - "Parsing project view for the content:\n'{}'\n\nand the default content:\n'{}'.", - projectViewFileContent, - defaultProjectViewFileContent); - - return parse(defaultProjectViewFileContent) - .onFailure( - exception -> log.error("Failed to parse default content. Parsing failed!", exception)) - .flatMap(defaultProjectView -> parseWithDefault(projectViewFileContent, defaultProjectView)) - .onFailure(exception -> log.error("Failed to parse content. Parsing failed!", exception)); - } - - private Try parseWithDefault( - String projectViewFileContent, ProjectView defaultProjectView) { - ProjectViewRawSections rawSections = - ProjectViewSectionSplitter.getRawSectionsForFileContent(projectViewFileContent); - - log.debug("Parsing project view with default project view {}.", defaultProjectView); - - return ProjectView.builder() - .imports(findImportedProjectViews(rawSections)) - .targets(targetsParser.parseOrDefault(rawSections, defaultProjectView.getTargets())) - .bazelPath(bazelPathParser.parseOrDefault(rawSections, defaultProjectView.getBazelPath())) - .debuggerAddress( - debuggerAddressParser.parseOrDefault( - rawSections, defaultProjectView.getDebuggerAddress())) - .javaPath(javaPathParser.parseOrDefault(rawSections, defaultProjectView.getJavaPath())) - .build(); - } - - @Override - public Try parse(Path projectViewFilePath) { - log.info("Parsing project view from {}.", projectViewFilePath); - - return BetterFiles.tryReadFileContent(projectViewFilePath) - .onFailure( - exception -> - log.error( - "Failed to read file {}. Parsing failed!", projectViewFilePath, exception)) - .flatMap(this::parse) - .onSuccess( - projectView -> - log.info("Project view from {} parsed!\n{}", projectViewFilePath, projectView)) - .onFailure( - exception -> - log.error( - "Failed to parse file {}. Parsing failed!", projectViewFilePath, exception)); - } - - @Override - public Try parse(String projectViewFileContent) { - log.debug("Parsing project view for the content:\n'{}'.", projectViewFileContent); - - ProjectViewRawSections rawSections = - ProjectViewSectionSplitter.getRawSectionsForFileContent(projectViewFileContent); - - return ProjectView.builder() - .imports(findImportedProjectViews(rawSections)) - .targets(targetsParser.parse(rawSections)) - .bazelPath(bazelPathParser.parse(rawSections)) - .debuggerAddress(debuggerAddressParser.parse(rawSections)) - .javaPath(javaPathParser.parse(rawSections)) - .build(); - } - - private List> findImportedProjectViews(ProjectViewRawSections rawSections) { - return rawSections - .getAllWithName(IMPORT_STATEMENT) - .map(ProjectViewRawSection::getSectionBody) - .map(String::trim) - .map(Paths::get) - .peek(path -> log.debug("Parsing imported file {}.", path)) - .map(this::parse); - } -} diff --git a/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImpl.kt b/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImpl.kt new file mode 100644 index 000000000..bd60228d7 --- /dev/null +++ b/executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImpl.kt @@ -0,0 +1,115 @@ +package org.jetbrains.bsp.bazel.projectview.parser; + +import io.vavr.collection.List +import io.vavr.control.Try +import org.apache.logging.log4j.LogManager +import org.jetbrains.bsp.bazel.commons.BetterFiles +import org.jetbrains.bsp.bazel.projectview.model.ProjectView +import org.jetbrains.bsp.bazel.projectview.parser.sections.ProjectViewBazelPathSectionParser +import org.jetbrains.bsp.bazel.projectview.parser.sections.ProjectViewDebuggerAddressSectionParser +import org.jetbrains.bsp.bazel.projectview.parser.sections.ProjectViewJavaPathSectionParser +import org.jetbrains.bsp.bazel.projectview.parser.sections.ProjectViewTargetsSectionParser +import org.jetbrains.bsp.bazel.projectview.parser.splitter.ProjectViewRawSection +import org.jetbrains.bsp.bazel.projectview.parser.splitter.ProjectViewRawSections +import org.jetbrains.bsp.bazel.projectview.parser.splitter.ProjectViewSectionSplitter +import java.nio.file.Path +import java.nio.file.Paths + +/** + * Default implementation of ProjectViewParser. + * + * @see ProjectViewParser + * @see ProjectViewSectionSplitter + */ +open class ProjectViewParserImpl : ProjectViewParser { + + override fun parse(projectViewFilePath: Path, defaultProjectViewFilePath: Path): Try { + log.info("Parsing project view from {} with default from {}.", projectViewFilePath, defaultProjectViewFilePath) + + return BetterFiles.tryReadFileContent(projectViewFilePath) + .onFailure { log.error("Failed to read file {}. Parsing failed!", projectViewFilePath, it) } + .flatMap { parse(it, defaultProjectViewFilePath) } + .onSuccess { + log.info( + "Project view from {} with default from {} parsed!\n{}", + projectViewFilePath, + defaultProjectViewFilePath, + it + ) + } + .onFailure { log.error("Failed to parse project view!", it) } + } + + private fun parse(projectViewFileContent: String, defaultProjectViewFilePath: Path): Try = + BetterFiles.tryReadFileContent(defaultProjectViewFilePath) + .flatMap { parse(projectViewFileContent, it) } + + + override fun parse(projectViewFileContent: String, defaultProjectViewFileContent: String): Try { + log.debug( + "Parsing project view for the content:\n'{}'\n\nand the default content:\n'{}'.", + projectViewFileContent, + defaultProjectViewFileContent + ) + + return parse(defaultProjectViewFileContent) + .onFailure { log.error("Failed to parse default content. Parsing failed!", it) } + .flatMap { parseWithDefault(projectViewFileContent, it) } + .onFailure { log.error("Failed to parse content. Parsing failed!", it) } + } + + private fun parseWithDefault(projectViewFileContent: String, defaultProjectView: ProjectView): Try { + val rawSections = ProjectViewSectionSplitter.getRawSectionsForFileContent(projectViewFileContent) + + log.debug("Parsing project view with default project view {}.", defaultProjectView) + + return ProjectView.builder() + .imports(findImportedProjectViews(rawSections)) + .targets(targetsParser.parseOrDefault(rawSections, defaultProjectView.targets)) + .bazelPath(bazelPathParser.parseOrDefault(rawSections, defaultProjectView.bazelPath)) + .debuggerAddress(debuggerAddressParser.parseOrDefault(rawSections, defaultProjectView.debuggerAddress)) + .javaPath(javaPathParser.parseOrDefault(rawSections, defaultProjectView.javaPath)) + .build() + } + + override fun parse(projectViewFilePath: Path): Try { + log.info("Parsing project view from {}.", projectViewFilePath) + + return BetterFiles.tryReadFileContent(projectViewFilePath) + .onFailure { log.error("Failed to read file {}. Parsing failed!", projectViewFilePath, it) } + .flatMap(this::parse) + .onSuccess { log.info("Project view from {} parsed!\n{}", projectViewFilePath, it) } + .onFailure { log.error("Failed to parse file {}. Parsing failed!", projectViewFilePath, it) } + } + + override fun parse(projectViewFileContent: String): Try { + log.debug("Parsing project view for the content:\n'{}'.", projectViewFileContent) + + val rawSections = ProjectViewSectionSplitter.getRawSectionsForFileContent(projectViewFileContent) + + return ProjectView.builder().imports(findImportedProjectViews(rawSections)) + .targets(targetsParser.parse(rawSections)).bazelPath(bazelPathParser.parse(rawSections)) + .debuggerAddress(debuggerAddressParser.parse(rawSections)).javaPath(javaPathParser.parse(rawSections)) + .build(); + } + + private fun findImportedProjectViews(rawSections: ProjectViewRawSections): List> = + rawSections + .getAllWithName(IMPORT_STATEMENT) + .map(ProjectViewRawSection::getSectionBody) + .map(String::trim) + .map(Paths::get) + .peek { log.debug("Parsing imported file {}.", it) } + .map(this::parse) + + private companion object { + private val log = LogManager.getLogger(ProjectViewParserImpl::class.java) + + private const val IMPORT_STATEMENT = "import" + + private val targetsParser = ProjectViewTargetsSectionParser() + private val bazelPathParser = ProjectViewBazelPathSectionParser() + private val debuggerAddressParser = ProjectViewDebuggerAddressSectionParser() + private val javaPathParser = ProjectViewJavaPathSectionParser() + } +} diff --git a/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/BUILD b/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/BUILD index 16ea60469..e9b384598 100644 --- a/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/BUILD +++ b/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/BUILD @@ -1,10 +1,10 @@ -load("@rules_java//java:defs.bzl", "java_library") -load("//:junit5.bzl", "java_junit5_test") +load("//:junit5.bzl", "kt_junit5_test") +load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") -java_junit5_test( +kt_junit5_test( name = "ProjectViewParserImplTest", size = "small", - srcs = ["ProjectViewParserImplTest.java"], + srcs = ["ProjectViewParserImplTest.kt"], resources = ["//executioncontext/projectview/src/test/resources:projectview"], test_package = "org.jetbrains.bsp.bazel.projectview.parser", deps = [ @@ -13,10 +13,10 @@ java_junit5_test( ], ) -java_library( +kt_jvm_library( name = "parser_mock_test_impl", testonly = 1, - srcs = ["ProjectViewParserMockTestImpl.java"], + srcs = ["ProjectViewParserMockTestImpl.kt"], deps = [ "//executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser", "@maven//:com_google_guava_guava", diff --git a/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImplTest.java b/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImplTest.java deleted file mode 100644 index 19b385a8e..000000000 --- a/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImplTest.java +++ /dev/null @@ -1,580 +0,0 @@ -package org.jetbrains.bsp.bazel.projectview.parser; - -import static org.assertj.core.api.Assertions.assertThat; - -import ch.epfl.scala.bsp4j.BuildTargetIdentifier; -import com.google.common.net.HostAndPort; -import io.vavr.collection.List; -import io.vavr.control.Option; -import java.io.IOException; -import java.nio.file.Paths; -import org.jetbrains.bsp.bazel.projectview.model.ProjectView; -import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewBazelPathSection; -import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewDebuggerAddressSection; -import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewJavaPathSection; -import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewTargetsSection; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -public class ProjectViewParserImplTest { - - private ProjectViewParser parser; - - @BeforeEach - public void before() { - // given - this.parser = new ProjectViewParserMockTestImpl(); - } - - @Nested - @DisplayName("ProjectView parse(projectViewFilePath) tests") - class ParseProjectViewFilePathTest { - - @Test - public void shouldReturnFailureForNotExistingFile() { - // given - var projectViewFilePath = Paths.get("/does/not/exist.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - assertThat(projectViewTry.isFailure()).isTrue(); - assertThat(projectViewTry.getCause().getClass()).isEqualTo(IOException.class); - assertThat(projectViewTry.getCause().getMessage()) - .isEqualTo("/does/not/exist.bazelproject file does not exist!"); - } - - @Test - public void shouldReturnFailureForNotExistingImportedFile() { - // given - var projectViewFilePath = Paths.get("/projectview/file9ImportsNotExisting.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - assertThat(projectViewTry.isFailure()).isTrue(); - assertThat(projectViewTry.getCause().getClass()).isEqualTo(IOException.class); - assertThat(projectViewTry.getCause().getMessage()) - .isEqualTo("/projectview/does/not/exist.bazelproject file does not exist!"); - } - - @Test - public void shouldReturnEmptyTargetsSectionForFileWithoutTargetsSection() { - // given - var projectViewFilePath = Paths.get("/projectview/without/targets.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - assertThat(projectViewTry.isSuccess()).isTrue(); - var projectView = projectViewTry.get(); - - assertThat(projectView.getTargets()).isEmpty(); - } - - @Test - public void shouldReturnEmptyBazelPathForFileWithoutBazelPathSection() { - // given - var projectViewFilePath = Paths.get("/projectview/without/bazelpath.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - assertThat(projectViewTry.isSuccess()).isTrue(); - var projectView = projectViewTry.get(); - - assertThat(projectView.getBazelPath()).isEmpty(); - } - - @Test - public void shouldReturnEmptyDebuggerAddressForFileWithoutDebuggerAddressSection() { - // given - var projectViewFilePath = Paths.get("/projectview/without/debuggeraddress.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - assertThat(projectViewTry.isSuccess()).isTrue(); - var projectView = projectViewTry.get(); - - assertThat(projectView.getDebuggerAddress()).isEmpty(); - } - - @Test - public void shouldReturnEmptyJavaPathSectionForFileWithoutJavaPathSection() { - // given - var projectViewFilePath = Paths.get("/projectview/without/javapath.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - assertThat(projectViewTry.isSuccess()).isTrue(); - var projectView = projectViewTry.get(); - - assertThat(projectView.getJavaPath()).isEmpty(); - } - - @Test - public void shouldParseEmptyFile() { - // given - var projectViewFilePath = Paths.get("/projectview/empty.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets(Option.none()) - .bazelPath(Option.none()) - .debuggerAddress(Option.none()) - .javaPath(Option.none()) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - - @Test - public void shouldParseFileWithAllSections() { - // given - var projectViewFilePath = Paths.get("/projectview/file1.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of( - new BuildTargetIdentifier("//included_target1.1"), - new BuildTargetIdentifier("//included_target1.2")), - List.of(new BuildTargetIdentifier("//excluded_target1.1"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.1:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path1/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - - @Test - public void shouldParseFileWithSingleImportedFileWithoutSingletonValues() { - // given - var projectViewFilePath = Paths.get("/projectview/file4ImportsFile1.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of( - new BuildTargetIdentifier("//included_target1.1"), - new BuildTargetIdentifier("//included_target1.2"), - new BuildTargetIdentifier("//included_target4.1")), - List.of( - new BuildTargetIdentifier("//excluded_target1.1"), - new BuildTargetIdentifier("//excluded_target4.1"), - new BuildTargetIdentifier("//excluded_target4.2"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.1:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path1/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - - @Test - public void shouldParseFileWithSingleImportedFileWithSingletonValues() { - // given - var projectViewFilePath = Paths.get("/projectview/file7ImportsFile1.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of( - new BuildTargetIdentifier("//included_target1.1"), - new BuildTargetIdentifier("//included_target1.2"), - new BuildTargetIdentifier("//included_target7.1")), - List.of( - new BuildTargetIdentifier("//excluded_target1.1"), - new BuildTargetIdentifier("//excluded_target7.1"), - new BuildTargetIdentifier("//excluded_target7.2"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path7/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.7:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path7/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - - @Test - public void shouldParseFileWithEmptyImportedFile() { - // given - var projectViewFilePath = Paths.get("/projectview/file8ImportsEmpty.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of(new BuildTargetIdentifier("//included_target8.1")), - List.of( - new BuildTargetIdentifier("//excluded_target8.1"), - new BuildTargetIdentifier("//excluded_target8.2"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path8/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.8:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path8/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - - @Test - public void shouldParseFileWithThreeImportedFiles() { - // given - var projectViewFilePath = Paths.get("/projectview/file5ImportsFile1File2File3.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of( - new BuildTargetIdentifier("//included_target1.1"), - new BuildTargetIdentifier("//included_target1.2"), - new BuildTargetIdentifier("//included_target2.1"), - new BuildTargetIdentifier("//included_target3.1")), - List.of( - new BuildTargetIdentifier("//excluded_target1.1"), - new BuildTargetIdentifier("//excluded_target2.1"), - new BuildTargetIdentifier("//excluded_target5.1"), - new BuildTargetIdentifier("//excluded_target5.2"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path3/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.3:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path3/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - - @Test - public void shouldParseFileWithNestedImportedFiles() { - // given - var projectViewFilePath = Paths.get("/projectview/file6ImportsFile2File3File4.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of( - new BuildTargetIdentifier("//included_target1.1"), - new BuildTargetIdentifier("//included_target1.2"), - new BuildTargetIdentifier("//included_target2.1"), - new BuildTargetIdentifier("//included_target3.1"), - new BuildTargetIdentifier("//included_target4.1")), - List.of( - new BuildTargetIdentifier("//excluded_target1.1"), - new BuildTargetIdentifier("//excluded_target2.1"), - new BuildTargetIdentifier("//excluded_target4.1"), - new BuildTargetIdentifier("//excluded_target4.2"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.1:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path1/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - } - - @Nested - @DisplayName("ProjectView parse(projectViewFilePath, defaultProjectViewFilePath) tests") - class ParseProjectViewFilePathDefaultProjectViewFilePathTest { - - @Test - public void shouldReturnFailureForNotExistingDefaultFile() { - // given - var projectViewFilePath = Paths.get("/projectview/file1.bazelproject"); - var defaultProjectViewFilePath = Paths.get("/does/not/exist.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - assertThat(projectViewTry.isFailure()).isTrue(); - assertThat(projectViewTry.getCause().getClass()).isEqualTo(IOException.class); - assertThat(projectViewTry.getCause().getMessage()) - .isEqualTo("/does/not/exist.bazelproject file does not exist!"); - } - - @Test - public void shouldReturnFailureForNotExistingDefaultFileAndNotExistingFile() { - // given - var projectViewFilePath = Paths.get("/does/not/exist.bazelproject"); - var defaultProjectViewFilePath = Paths.get("/does/not/exist.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - assertThat(projectViewTry.isFailure()).isTrue(); - assertThat(projectViewTry.getCause().getClass()).isEqualTo(IOException.class); - assertThat(projectViewTry.getCause().getMessage()) - .isEqualTo("/does/not/exist.bazelproject file does not exist!"); - } - - @Test - public void shouldReturnFile1ForEmptyDefaultFile() { - // given - var projectViewFilePath = Paths.get("/projectview/file1.bazelproject"); - var defaultProjectViewFilePath = Paths.get("/projectview/empty.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of( - new BuildTargetIdentifier("//included_target1.1"), - new BuildTargetIdentifier("//included_target1.2")), - List.of(new BuildTargetIdentifier("//excluded_target1.1"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.1:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path1/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - - @Test - public void shouldReturnEmptyTargetsForDefaultFileWithoutTargetsSection() { - // given - var projectViewFilePath = Paths.get("/projectview/empty.bazelproject"); - var defaultProjectViewFilePath = Paths.get("/projectview/without/targets.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - assertThat(projectViewTry.isSuccess()).isTrue(); - var projectView = projectViewTry.get(); - - assertThat(projectView.getTargets()).isEmpty(); - } - - @Test - public void shouldReturnEmptyForDefaultFileWithoutBazelPathSection() { - // given - var projectViewFilePath = Paths.get("/projectview/empty.bazelproject"); - var defaultProjectViewFilePath = Paths.get("/projectview/without/bazelpath.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - assertThat(projectViewTry.isSuccess()).isTrue(); - var projectView = projectViewTry.get(); - - assertThat(projectView.getBazelPath()).isEmpty(); - } - - @Test - public void shouldReturnEmptyForDefaultFileWithoutDebuggerAddressSection() { - // given - var projectViewFilePath = Paths.get("/projectview/empty.bazelproject"); - var defaultProjectViewFilePath = - Paths.get("/projectview/without/debuggeraddress.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - assertThat(projectViewTry.isSuccess()).isTrue(); - var projectView = projectViewTry.get(); - - assertThat(projectView.getDebuggerAddress()).isEmpty(); - } - - @Test - public void shouldReturnEmptyForDefaultFileWithoutJavaPathSection() { - // given - var projectViewFilePath = Paths.get("/projectview/empty.bazelproject"); - var defaultProjectViewFilePath = Paths.get("/projectview/without/javapath.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - assertThat(projectViewTry.isSuccess()).isTrue(); - var projectView = projectViewTry.get(); - - assertThat(projectView.getJavaPath()).isEmpty(); - } - - @Test - public void shouldParseFileAndSkipDefaults() { - // given - var projectViewFilePath = Paths.get("/projectview/file1.bazelproject"); - var defaultProjectViewFilePath = Paths.get("/projectview/file2.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of( - new BuildTargetIdentifier("//included_target1.1"), - new BuildTargetIdentifier("//included_target1.2")), - List.of(new BuildTargetIdentifier("//excluded_target1.1"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.1:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path1/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - - @Test - public void shouldParseDefaultsForNotExistingFile() { - // given - var projectViewFilePath = Paths.get("/doesnt/exist.bazelproject"); - var defaultProjectViewFilePath = Paths.get("/projectview/file1.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of( - new BuildTargetIdentifier("//included_target1.1"), - new BuildTargetIdentifier("//included_target1.2")), - List.of(new BuildTargetIdentifier("//excluded_target1.1"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.1:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path1/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - - @Test - public void shouldParseFileAndUseDefaults() { - // given - var projectViewFilePath = Paths.get("/projectview/empty.bazelproject"); - var defaultProjectViewFilePath = Paths.get("/projectview/file1.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of( - new BuildTargetIdentifier("//included_target1.1"), - new BuildTargetIdentifier("//included_target1.2")), - List.of(new BuildTargetIdentifier("//excluded_target1.1"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.1:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path1/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - - @Test - public void shouldParseFileAndUseDefaultsWithEmptyImportedFile() { - // given - var projectViewFilePath = Paths.get("/projectview/empty.bazelproject"); - var defaultProjectViewFilePath = Paths.get("/projectview/file8ImportsEmpty.bazelproject"); - - // when - var projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath); - - // then - var expectedProjectViewTry = - ProjectView.builder() - .targets( - Option.of( - new ProjectViewTargetsSection( - List.of(new BuildTargetIdentifier("//included_target8.1")), - List.of( - new BuildTargetIdentifier("//excluded_target8.1"), - new BuildTargetIdentifier("//excluded_target8.2"))))) - .bazelPath(Option.of(new ProjectViewBazelPathSection(Paths.get("path8/to/bazel")))) - .debuggerAddress( - Option.of( - new ProjectViewDebuggerAddressSection( - HostAndPort.fromString("0.0.0.8:8000")))) - .javaPath(Option.of(new ProjectViewJavaPathSection(Paths.get("path8/to/java")))) - .build(); - assertThat(projectViewTry).isEqualTo(expectedProjectViewTry); - } - } -} diff --git a/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImplTest.kt b/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImplTest.kt new file mode 100644 index 000000000..e35831cf8 --- /dev/null +++ b/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserImplTest.kt @@ -0,0 +1,627 @@ +package org.jetbrains.bsp.bazel.projectview.parser + +import ch.epfl.scala.bsp4j.BuildTargetIdentifier +import com.google.common.net.HostAndPort +import io.vavr.collection.List +import io.vavr.control.Option +import org.assertj.core.api.Assertions.assertThat +import org.jetbrains.bsp.bazel.projectview.model.ProjectView +import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewBazelPathSection +import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewDebuggerAddressSection +import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewJavaPathSection +import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewTargetsSection +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import java.io.FileNotFoundException +import java.nio.file.Paths + +class ProjectViewParserImplTest { + + private lateinit var parser: ProjectViewParser + + @BeforeEach + fun before() { + // given + parser = ProjectViewParserMockTestImpl() + } + + @Nested + @DisplayName("fun parse(projectViewFilePath): ProjectView tests") + internal inner class ParseProjectViewFilePathTest { + + @Test + fun `should return failure for not existing file`() { + // given + val projectViewFilePath = Paths.get("/does/not/exist.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + assertThat(projectViewTry.isFailure).isTrue + assertThat(projectViewTry.cause.javaClass).isEqualTo(FileNotFoundException::class.java) + assertThat(projectViewTry.cause.message) + .isEqualTo("/does/not/exist.bazelproject (No such file or directory)") + } + + @Test + fun `should return failure for not existing imported file`() { + // given + val projectViewFilePath = Paths.get("/projectview/file9ImportsNotExisting.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + assertThat(projectViewTry.isFailure).isTrue + assertThat(projectViewTry.cause.javaClass).isEqualTo( + FileNotFoundException::class.java + ) + assertThat(projectViewTry.cause.message) + .isEqualTo("/projectview/does/not/exist.bazelproject (No such file or directory)") + } + + @Test + fun `should return empty targets section for file without targets section`() { + // given + val projectViewFilePath = Paths.get("/projectview/without/targets.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + assertThat(projectViewTry.isSuccess).isTrue + val projectView = projectViewTry.get() + assertThat(projectView.targets).isEmpty() + } + + @Test + fun `should return empty bazel path for file without bazel path section`() { + // given + val projectViewFilePath = Paths.get("/projectview/without/bazelpath.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + assertThat(projectViewTry.isSuccess).isTrue + val projectView = projectViewTry.get() + assertThat(projectView.bazelPath).isEmpty() + } + + @Test + fun `should return empty debugger address for file without debugger address section`() { + // given + val projectViewFilePath = Paths.get("/projectview/without/debuggeraddress.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + assertThat(projectViewTry.isSuccess).isTrue + val projectView = projectViewTry.get() + assertThat(projectView.debuggerAddress).isEmpty() + } + + @Test + fun `should return empty java path section for file without java path section`() { + // given + val projectViewFilePath = Paths.get("/projectview/without/javapath.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + assertThat(projectViewTry.isSuccess).isTrue + val projectView = projectViewTry.get() + assertThat(projectView.javaPath).isEmpty() + } + + @Test + fun `should parse empty file`() { + // given + val projectViewFilePath = Paths.get("/projectview/empty.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets(Option.none()) + .bazelPath(Option.none()) + .debuggerAddress(Option.none()) + .javaPath(Option.none()) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + + @Test + fun `should parse file with all sections`() { + // given + val projectViewFilePath = Paths.get("/projectview/file1.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets( + Option.of( + ProjectViewTargetsSection( + List.of( + BuildTargetIdentifier("//included_target1.1"), + BuildTargetIdentifier("//included_target1.2") + ), + List.of(BuildTargetIdentifier("//excluded_target1.1")) + ) + ) + ) + .bazelPath(Option.of(ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) + .debuggerAddress( + Option.of( + ProjectViewDebuggerAddressSection( + HostAndPort.fromString("0.0.0.1:8000") + ) + ) + ) + .javaPath(Option.of(ProjectViewJavaPathSection(Paths.get("path1/to/java")))) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + + @Test + fun `should parse file with single imported file without singleton values`() { + // given + val projectViewFilePath = Paths.get("/projectview/file4ImportsFile1.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets( + Option.of( + ProjectViewTargetsSection( + List.of( + BuildTargetIdentifier("//included_target1.1"), + BuildTargetIdentifier("//included_target1.2"), + BuildTargetIdentifier("//included_target4.1") + ), + List.of( + BuildTargetIdentifier("//excluded_target1.1"), + BuildTargetIdentifier("//excluded_target4.1"), + BuildTargetIdentifier("//excluded_target4.2") + ) + ) + ) + ) + .bazelPath(Option.of(ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) + .debuggerAddress( + Option.of( + ProjectViewDebuggerAddressSection( + HostAndPort.fromString("0.0.0.1:8000") + ) + ) + ) + .javaPath(Option.of(ProjectViewJavaPathSection(Paths.get("path1/to/java")))) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + + @Test + fun `should parse file with single imported file with singleton values`() { + // given + val projectViewFilePath = Paths.get("/projectview/file7ImportsFile1.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets( + Option.of( + ProjectViewTargetsSection( + List.of( + BuildTargetIdentifier("//included_target1.1"), + BuildTargetIdentifier("//included_target1.2"), + BuildTargetIdentifier("//included_target7.1") + ), + List.of( + BuildTargetIdentifier("//excluded_target1.1"), + BuildTargetIdentifier("//excluded_target7.1"), + BuildTargetIdentifier("//excluded_target7.2") + ) + ) + ) + ) + .bazelPath(Option.of(ProjectViewBazelPathSection(Paths.get("path7/to/bazel")))) + .debuggerAddress( + Option.of( + ProjectViewDebuggerAddressSection( + HostAndPort.fromString("0.0.0.7:8000") + ) + ) + ) + .javaPath(Option.of(ProjectViewJavaPathSection(Paths.get("path7/to/java")))) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + + @Test + fun `should parse file with empty imported file`() { + // given + val projectViewFilePath = Paths.get("/projectview/file8ImportsEmpty.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets( + Option.of( + ProjectViewTargetsSection( + List.of(BuildTargetIdentifier("//included_target8.1")), + List.of( + BuildTargetIdentifier("//excluded_target8.1"), + BuildTargetIdentifier("//excluded_target8.2") + ) + ) + ) + ) + .bazelPath(Option.of(ProjectViewBazelPathSection(Paths.get("path8/to/bazel")))) + .debuggerAddress( + Option.of( + ProjectViewDebuggerAddressSection( + HostAndPort.fromString("0.0.0.8:8000") + ) + ) + ) + .javaPath(Option.of(ProjectViewJavaPathSection(Paths.get("path8/to/java")))) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + + @Test + fun `should parse file with three imported files`() { + // given + val projectViewFilePath = Paths.get("/projectview/file5ImportsFile1File2File3.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets( + Option.of( + ProjectViewTargetsSection( + List.of( + BuildTargetIdentifier("//included_target1.1"), + BuildTargetIdentifier("//included_target1.2"), + BuildTargetIdentifier("//included_target2.1"), + BuildTargetIdentifier("//included_target3.1") + ), + List.of( + BuildTargetIdentifier("//excluded_target1.1"), + BuildTargetIdentifier("//excluded_target2.1"), + BuildTargetIdentifier("//excluded_target5.1"), + BuildTargetIdentifier("//excluded_target5.2") + ) + ) + ) + ) + .bazelPath(Option.of(ProjectViewBazelPathSection(Paths.get("path3/to/bazel")))) + .debuggerAddress( + Option.of( + ProjectViewDebuggerAddressSection( + HostAndPort.fromString("0.0.0.3:8000") + ) + ) + ) + .javaPath(Option.of(ProjectViewJavaPathSection(Paths.get("path3/to/java")))) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + + @Test + fun `should parse file with nested imported files`() { + // given + val projectViewFilePath = Paths.get("/projectview/file6ImportsFile2File3File4.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets( + Option.of( + ProjectViewTargetsSection( + List.of( + BuildTargetIdentifier("//included_target1.1"), + BuildTargetIdentifier("//included_target1.2"), + BuildTargetIdentifier("//included_target2.1"), + BuildTargetIdentifier("//included_target3.1"), + BuildTargetIdentifier("//included_target4.1") + ), + List.of( + BuildTargetIdentifier("//excluded_target1.1"), + BuildTargetIdentifier("//excluded_target2.1"), + BuildTargetIdentifier("//excluded_target4.1"), + BuildTargetIdentifier("//excluded_target4.2") + ) + ) + ) + ) + .bazelPath(Option.of(ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) + .debuggerAddress( + Option.of( + ProjectViewDebuggerAddressSection( + HostAndPort.fromString("0.0.0.1:8000") + ) + ) + ) + .javaPath(Option.of(ProjectViewJavaPathSection(Paths.get("path1/to/java")))) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + } + + @Nested + @DisplayName("ProjectView parse(projectViewFilePath, defaultProjectViewFilePath) tests") + internal inner class ParseProjectViewFilePathDefaultProjectViewFilePathTest { + @Test + fun `should return failure for not existing default file`() { + // given + val projectViewFilePath = Paths.get("/projectview/file1.bazelproject") + val defaultProjectViewFilePath = Paths.get("/does/not/exist.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + assertThat(projectViewTry.isFailure).isTrue + assertThat(projectViewTry.cause.javaClass).isEqualTo( + FileNotFoundException::class.java + ) + assertThat(projectViewTry.cause.message) + .isEqualTo("/does/not/exist.bazelproject (No such file or directory)") + } + + @Test + fun `should return failure for not existing File`() { + // given + val projectViewFilePath = Paths.get("/does/not/exist.bazelproject") + val defaultProjectViewFilePath = Paths.get("/projectview/file1.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + assertThat(projectViewTry.isFailure).isTrue + assertThat(projectViewTry.cause.javaClass).isEqualTo( + FileNotFoundException::class.java + ) + assertThat(projectViewTry.cause.message) + .isEqualTo("/does/not/exist.bazelproject (No such file or directory)") + } + + @Test + fun `should return failure for not existing default file and not existing file`() { + // given + val projectViewFilePath = Paths.get("/does/not/exist.bazelproject") + val defaultProjectViewFilePath = Paths.get("/does/not/exist.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + assertThat(projectViewTry.isFailure).isTrue + assertThat(projectViewTry.cause.javaClass).isEqualTo( + FileNotFoundException::class.java + ) + assertThat(projectViewTry.cause.message) + .isEqualTo("/does/not/exist.bazelproject (No such file or directory)") + } + + @Test + fun `should return file1 for empty default file`() { + // given + val projectViewFilePath = Paths.get("/projectview/file1.bazelproject") + val defaultProjectViewFilePath = Paths.get("/projectview/empty.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets( + Option.of( + ProjectViewTargetsSection( + List.of( + BuildTargetIdentifier("//included_target1.1"), + BuildTargetIdentifier("//included_target1.2") + ), + List.of(BuildTargetIdentifier("//excluded_target1.1")) + ) + ) + ) + .bazelPath(Option.of(ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) + .debuggerAddress( + Option.of( + ProjectViewDebuggerAddressSection( + HostAndPort.fromString("0.0.0.1:8000") + ) + ) + ) + .javaPath(Option.of(ProjectViewJavaPathSection(Paths.get("path1/to/java")))) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + + @Test + fun `should return empty targets for default file without targets section`() { + // given + val projectViewFilePath = Paths.get("/projectview/empty.bazelproject") + val defaultProjectViewFilePath = Paths.get("/projectview/without/targets.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + assertThat(projectViewTry.isSuccess).isTrue + val projectView = projectViewTry.get() + assertThat(projectView.targets).isEmpty() + } + + @Test + fun `should return empty for default file without bazel path section`() { + // given + val projectViewFilePath = Paths.get("/projectview/empty.bazelproject") + val defaultProjectViewFilePath = Paths.get("/projectview/without/bazelpath.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + assertThat(projectViewTry.isSuccess).isTrue + val projectView = projectViewTry.get() + assertThat(projectView.bazelPath).isEmpty() + } + + @Test + fun `should return empty for default file without debugger address section`() { + // given + val projectViewFilePath = Paths.get("/projectview/empty.bazelproject") + val defaultProjectViewFilePath = Paths.get("/projectview/without/debuggeraddress.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + assertThat(projectViewTry.isSuccess).isTrue + val projectView = projectViewTry.get() + assertThat(projectView.debuggerAddress).isEmpty() + } + + @Test + fun `should return empty for default file without java path section`() { + // given + val projectViewFilePath = Paths.get("/projectview/empty.bazelproject") + val defaultProjectViewFilePath = Paths.get("/projectview/without/javapath.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + assertThat(projectViewTry.isSuccess).isTrue + val projectView = projectViewTry.get() + assertThat(projectView.javaPath).isEmpty() + } + + @Test + fun `should parse file and skip defaults`() { + // given + val projectViewFilePath = Paths.get("/projectview/file1.bazelproject") + val defaultProjectViewFilePath = Paths.get("/projectview/file2.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets( + Option.of( + ProjectViewTargetsSection( + List.of( + BuildTargetIdentifier("//included_target1.1"), + BuildTargetIdentifier("//included_target1.2") + ), + List.of(BuildTargetIdentifier("//excluded_target1.1")) + ) + ) + ) + .bazelPath(Option.of(ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) + .debuggerAddress( + Option.of( + ProjectViewDebuggerAddressSection( + HostAndPort.fromString("0.0.0.1:8000") + ) + ) + ) + .javaPath(Option.of(ProjectViewJavaPathSection(Paths.get("path1/to/java")))) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + + @Test + fun `should parse file and use defaults`() { + // given + val projectViewFilePath = Paths.get("/projectview/empty.bazelproject") + val defaultProjectViewFilePath = Paths.get("/projectview/file1.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets( + Option.of( + ProjectViewTargetsSection( + List.of( + BuildTargetIdentifier("//included_target1.1"), + BuildTargetIdentifier("//included_target1.2") + ), + List.of(BuildTargetIdentifier("//excluded_target1.1")) + ) + ) + ) + .bazelPath(Option.of(ProjectViewBazelPathSection(Paths.get("path1/to/bazel")))) + .debuggerAddress( + Option.of( + ProjectViewDebuggerAddressSection( + HostAndPort.fromString("0.0.0.1:8000") + ) + ) + ) + .javaPath(Option.of(ProjectViewJavaPathSection(Paths.get("path1/to/java")))) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + + @Test + fun `should parse file and use defaults with empty imported file`() { + // given + val projectViewFilePath = Paths.get("/projectview/empty.bazelproject") + val defaultProjectViewFilePath = Paths.get("/projectview/file8ImportsEmpty.bazelproject") + + // when + val projectViewTry = parser.parse(projectViewFilePath, defaultProjectViewFilePath) + + // then + val expectedProjectViewTry = ProjectView.builder() + .targets( + Option.of( + ProjectViewTargetsSection( + List.of(BuildTargetIdentifier("//included_target8.1")), + List.of( + BuildTargetIdentifier("//excluded_target8.1"), + BuildTargetIdentifier("//excluded_target8.2") + ) + ) + ) + ) + .bazelPath(Option.of(ProjectViewBazelPathSection(Paths.get("path8/to/bazel")))) + .debuggerAddress( + Option.of( + ProjectViewDebuggerAddressSection( + HostAndPort.fromString("0.0.0.8:8000") + ) + ) + ) + .javaPath(Option.of(ProjectViewJavaPathSection(Paths.get("path8/to/java")))) + .build() + assertThat(projectViewTry).isEqualTo(expectedProjectViewTry) + } + } +} diff --git a/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserMockTestImpl.java b/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserMockTestImpl.java deleted file mode 100644 index 5510a314d..000000000 --- a/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserMockTestImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.jetbrains.bsp.bazel.projectview.parser; - -import com.google.common.base.Charsets; -import com.google.common.io.CharStreams; -import io.vavr.control.Option; -import io.vavr.control.Try; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.file.Path; -import org.jetbrains.bsp.bazel.projectview.model.ProjectView; - -public class ProjectViewParserMockTestImpl extends ProjectViewParserImpl { - - @Override - public Try parse(Path projectViewFilePath, Path defaultProjectViewFilePath) { - return readFileContent(defaultProjectViewFilePath) - .flatMap( - defaultProjectViewFileContent -> - parseWithDefault(projectViewFilePath, defaultProjectViewFileContent)); - } - - private Try parseWithDefault( - Path projectViewFilePath, String defaultProjectViewFileContent) { - return readFileContent(projectViewFilePath) - .flatMap( - projectViewFileContent -> parse(projectViewFileContent, defaultProjectViewFileContent)) - .orElse(() -> parse(defaultProjectViewFileContent)); - } - - @Override - public Try parse(Path projectViewFilePath) { - return readFileContent(projectViewFilePath).flatMap(this::parse); - } - - private Try readFileContent(Path filePath) { - // we read file content instead of passing plain file due to bazel resources packaging - var inputStream = ProjectViewParserMockTestImpl.class.getResourceAsStream(filePath.toString()); - - return Option.of(inputStream) - .map(this::readInputStream) - .getOrElse(Try.failure(new IOException(filePath + " file does not exist!"))); - } - - private Try readInputStream(InputStream inputStream) { - return Try.success(new InputStreamReader(inputStream, Charsets.UTF_8)) - .mapTry(CharStreams::toString); - } -} diff --git a/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserMockTestImpl.kt b/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserMockTestImpl.kt new file mode 100644 index 000000000..0dbe2695e --- /dev/null +++ b/executioncontext/projectview/src/test/java/org/jetbrains/bsp/bazel/projectview/parser/ProjectViewParserMockTestImpl.kt @@ -0,0 +1,61 @@ +package org.jetbrains.bsp.bazel.projectview.parser + +import com.google.common.base.Charsets +import com.google.common.io.CharStreams +import io.vavr.control.Option +import io.vavr.control.Try +import org.jetbrains.bsp.bazel.projectview.model.ProjectView +import java.io.File +import java.io.IOException +import java.io.InputStream +import java.io.InputStreamReader +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths +import kotlin.io.path.writeText + +class ProjectViewParserMockTestImpl : ProjectViewParserImpl() { + + override fun parse(projectViewFilePath: Path, defaultProjectViewFilePath: Path): Try = + Try.success(copyResourcesFileToTmpFile(projectViewFilePath)) + .flatMap { parseWithCopiedProjectViewFile(it, defaultProjectViewFilePath) } + + private fun parseWithCopiedProjectViewFile( + copiedProjectViewFilePath: Path, + defaultProjectViewFile: Path + ): Try = + Try.success(copyResourcesFileToTmpFile(defaultProjectViewFile)) + .flatMap { super.parse(copiedProjectViewFilePath, it) } + + override fun parse(projectViewFilePath: Path): Try = + Try.success(copyResourcesFileToTmpFile(projectViewFilePath)) + .flatMap { super.parse(it) } + + private fun copyResourcesFileToTmpFile(resourcesFile: Path): Path { + val resourcesFileContent = readFileContent(resourcesFile) + + return createTempFileWithContentIfContentExists(resourcesFile, resourcesFileContent) + } + + // TODO @abrams27 - move to utils + private fun readFileContent(filePath: Path): String? { + // we read file content instead of passing plain file due to bazel resources packaging + val inputStream: InputStream? = + ProjectViewParserMockTestImpl::class.java.getResourceAsStream(filePath.toString()) + + return inputStream + ?.let { InputStreamReader(it, Charsets.UTF_8) } + ?.let { CharStreams.toString(it) } + } + + private fun createTempFileWithContentIfContentExists(path: Path, content: String?): Path = + content?.let { createTempFileWithContent(path, it) } ?: path + + private fun createTempFileWithContent(path: Path, content: String): Path { + val tempFile = File.createTempFile(path.toString(), "") + tempFile.deleteOnExit() + tempFile.writeText(content) + + return tempFile.toPath() + } +} diff --git a/junit5.bzl b/junit5.bzl index 4f68a014a..e0ad9927e 100644 --- a/junit5.bzl +++ b/junit5.bzl @@ -1,5 +1,6 @@ load("@rules_java//java:defs.bzl", "java_test") load("@bazel_tools//tools/build_defs/repo:jvm.bzl", "jvm_maven_import_external") +load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test") # External dependencies & java_junit5_test rule @@ -102,6 +103,44 @@ def java_junit5_test(name, srcs, test_package, deps = [], runtime_deps = [], **k **kwargs ) +def kt_junit5_test(name, srcs, test_package, deps = [], runtime_deps = [], **kwargs): + FILTER_KWARGS = [ + "main_class", + "use_testrunner", + "args", + ] + + for arg in FILTER_KWARGS: + if arg in kwargs.keys(): + kwargs.pop(arg) + + junit_console_args = [] + if test_package: + junit_console_args += ["--select-package", test_package] + else: + fail("must specify 'test_package'") + + kt_jvm_test( + name = name, + srcs = srcs, + main_class = "org.junit.platform.console.ConsoleLauncher", + args = junit_console_args, + deps = deps + [ + _format_maven_jar_dep_name(JUNIT_JUPITER_GROUP_ID, artifact_id) + for artifact_id in JUNIT_JUPITER_ARTIFACT_ID_LIST + ] + [ + _format_maven_jar_dep_name(JUNIT_PLATFORM_GROUP_ID, "junit-platform-suite-api"), + ] + [ + _format_maven_jar_dep_name(t[0], t[1]) + for t in JUNIT_EXTRA_DEPENDENCIES + ], + runtime_deps = runtime_deps + [ + _format_maven_jar_dep_name(JUNIT_PLATFORM_GROUP_ID, artifact_id) + for artifact_id in JUNIT_PLATFORM_ARTIFACT_ID_LIST + ], + **kwargs + ) + def _format_maven_jar_name(group_id, artifact_id): return ("%s_%s" % (group_id, artifact_id)).replace(".", "_").replace("-", "_")