From e6d9a957a9a89f494f3630d920c7ad2cf214a32f Mon Sep 17 00:00:00 2001 From: kasiaMarek Date: Wed, 5 Feb 2025 10:01:23 +0100 Subject: [PATCH 1/2] feat: add test cases discovery for TestNG --- .../metals/debug/BuildTargetClasses.scala | 5 ++ .../testProvider/TestSuitesProvider.scala | 9 +++ .../frameworks/AnnotationTestFinder.scala | 54 ++++++++++++++++++ .../frameworks/JunitTestFinder.scala | 54 +----------------- .../frameworks/TestNGTestFinder.scala | 5 ++ .../src/main/scala/tests/QuickBuild.scala | 3 + .../TestSuitesProviderSuite.scala | 55 +++++++++++++++++++ 7 files changed, 134 insertions(+), 51 deletions(-) create mode 100644 metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/AnnotationTestFinder.scala create mode 100644 metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/TestNGTestFinder.scala diff --git a/metals/src/main/scala/scala/meta/internal/metals/debug/BuildTargetClasses.scala b/metals/src/main/scala/scala/meta/internal/metals/debug/BuildTargetClasses.scala index 1b50eac9f4c..96eaae2571e 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/debug/BuildTargetClasses.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/debug/BuildTargetClasses.scala @@ -236,6 +236,7 @@ object TestFramework { case "munit" => MUnit case "ScalaTest" => Scalatest case "weaver-cats-effect" => WeaverCatsEffect + case "TestNG" => TestNG case _ => Unknown } .getOrElse(Unknown) @@ -261,6 +262,10 @@ case object WeaverCatsEffect extends TestFramework(true) { def names: List[String] = List("weaver.BaseCatsSuite") } +case object TestNG extends TestFramework(true) { + def names: List[String] = List("mill.testng.TestNGFramework") +} + case object Unknown extends TestFramework(false) { def names: List[String] = Nil } diff --git a/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesProvider.scala b/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesProvider.scala index aa50dbd832b..67904a9bfcc 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesProvider.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesProvider.scala @@ -26,12 +26,14 @@ import scala.meta.internal.metals.debug.JUnit4 import scala.meta.internal.metals.debug.MUnit import scala.meta.internal.metals.debug.Scalatest import scala.meta.internal.metals.debug.TestFramework +import scala.meta.internal.metals.debug.TestNG import scala.meta.internal.metals.debug.Unknown import scala.meta.internal.metals.debug.WeaverCatsEffect import scala.meta.internal.metals.testProvider.TestExplorerEvent._ import scala.meta.internal.metals.testProvider.frameworks.JunitTestFinder import scala.meta.internal.metals.testProvider.frameworks.MunitTestFinder import scala.meta.internal.metals.testProvider.frameworks.ScalatestTestFinder +import scala.meta.internal.metals.testProvider.frameworks.TestNGTestFinder import scala.meta.internal.metals.testProvider.frameworks.WeaverCatsEffectTestFinder import scala.meta.internal.mtags import scala.meta.internal.mtags.GlobalSymbolIndex @@ -65,6 +67,7 @@ final class TestSuitesProvider( private val index = new TestSuitesIndex private val junitTestFinder = new JunitTestFinder + private val testNGTestFinder = new TestNGTestFinder private val munitTestFinder = new MunitTestFinder(trees, symbolIndex, semanticdbs) private val scalatestTestFinder = @@ -334,6 +337,12 @@ final class TestSuitesProvider( suiteName = suite.fullyQualifiedName, symbol = suite.symbol, ) + case TestNG => + testNGTestFinder.findTests( + doc = semanticdb, + path = path, + suiteSymbol = suite.symbol, + ) case Unknown => Vector.empty } diff --git a/metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/AnnotationTestFinder.scala b/metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/AnnotationTestFinder.scala new file mode 100644 index 00000000000..910e0ce3ada --- /dev/null +++ b/metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/AnnotationTestFinder.scala @@ -0,0 +1,54 @@ +package scala.meta.internal.metals.testProvider.frameworks + +import scala.reflect.NameTransformer + +import scala.meta.internal.metals.MetalsEnrichments._ +import scala.meta.internal.metals.testProvider.TestCaseEntry +import scala.meta.internal.mtags +import scala.meta.internal.semanticdb.SymbolInformation +import scala.meta.internal.semanticdb.TextDocument +import scala.meta.internal.semanticdb.TypeRef +import scala.meta.io.AbsolutePath + +trait AnnotationTestFinder { + def expectedAnnotationSymbol: String + + def findTests( + doc: TextDocument, + path: AbsolutePath, + suiteSymbol: mtags.Symbol, + ): Vector[TestCaseEntry] = { + val uri = path.toURI + + def isMethodWithTestAnnotation(symbol: SymbolInformation) = { + symbol.kind == SymbolInformation.Kind.METHOD && symbol.annotations + .exists(_.tpe match { + case TypeRef(_, annotationSymbol, _) => + annotationSymbol == expectedAnnotationSymbol + case _ => false + }) + } + + def isValid(symbol: SymbolInformation): Boolean = + isMethodWithTestAnnotation(symbol) && symbol.symbol.startsWith( + suiteSymbol.value + ) + + doc.symbols + .collect { + case symbol if isValid(symbol) => + doc + .toLocation(uri, symbol.symbol) + .map { location => + val encodedName = NameTransformer.encode(symbol.displayName) + TestCaseEntry( + encodedName, + symbol.displayName, + location, + ) + } + } + .flatten + .toVector + } +} diff --git a/metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/JunitTestFinder.scala b/metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/JunitTestFinder.scala index da6ea3ebae7..45046f3142b 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/JunitTestFinder.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/JunitTestFinder.scala @@ -1,56 +1,8 @@ package scala.meta.internal.metals.testProvider.frameworks -import scala.reflect.NameTransformer - -import scala.meta.internal.metals.MetalsEnrichments._ -import scala.meta.internal.metals.testProvider.TestCaseEntry -import scala.meta.internal.mtags -import scala.meta.internal.semanticdb.SymbolInformation -import scala.meta.internal.semanticdb.TextDocument -import scala.meta.internal.semanticdb.TypeRef -import scala.meta.io.AbsolutePath - -class JunitTestFinder { - import JunitTestFinder._ - - def findTests( - doc: TextDocument, - path: AbsolutePath, - suiteSymbol: mtags.Symbol, - ): Vector[TestCaseEntry] = { - val uri = path.toURI - - def isMethodWithTestAnnotation(symbol: SymbolInformation) = - symbol.kind == SymbolInformation.Kind.METHOD && symbol.annotations - .exists(_.tpe match { - case TypeRef(_, annotationSymbol, _) => - annotationSymbol == junitAnnotationSymbol - case _ => false - }) - - def isValid(symbol: SymbolInformation): Boolean = { - isMethodWithTestAnnotation(symbol) && symbol.symbol.startsWith( - suiteSymbol.value - ) - } - - doc.symbols - .collect { - case symbol if isValid(symbol) => - doc - .toLocation(uri, symbol.symbol) - .map { location => - val encodedName = NameTransformer.encode(symbol.displayName) - TestCaseEntry( - encodedName, - symbol.displayName, - location, - ) - } - } - .flatten - .toVector - } +class JunitTestFinder extends AnnotationTestFinder { + override def expectedAnnotationSymbol: String = + JunitTestFinder.junitAnnotationSymbol } object JunitTestFinder { diff --git a/metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/TestNGTestFinder.scala b/metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/TestNGTestFinder.scala new file mode 100644 index 00000000000..15849f19d73 --- /dev/null +++ b/metals/src/main/scala/scala/meta/internal/metals/testProvider/frameworks/TestNGTestFinder.scala @@ -0,0 +1,5 @@ +package scala.meta.internal.metals.testProvider.frameworks + +class TestNGTestFinder extends AnnotationTestFinder { + override def expectedAnnotationSymbol: String = "org/testng/annotations/Test#" +} diff --git a/tests/unit/src/main/scala/tests/QuickBuild.scala b/tests/unit/src/main/scala/tests/QuickBuild.scala index 497da95a65f..a700de2b154 100644 --- a/tests/unit/src/main/scala/tests/QuickBuild.scala +++ b/tests/unit/src/main/scala/tests/QuickBuild.scala @@ -290,6 +290,9 @@ object QuickBuild { "com.disneystreaming::weaver-cats" -> Config.TestFramework( List("weaver.framework.CatsEffect") ), + "com.lihaoyi:mill-contrib-testng" -> Config.TestFramework( + List("mill.testng.TestNGFramework") + ), ) /** diff --git a/tests/unit/src/test/scala/tests/testProvider/TestSuitesProviderSuite.scala b/tests/unit/src/test/scala/tests/testProvider/TestSuitesProviderSuite.scala index 943feecc5cf..d6d612a7292 100644 --- a/tests/unit/src/test/scala/tests/testProvider/TestSuitesProviderSuite.scala +++ b/tests/unit/src/test/scala/tests/testProvider/TestSuitesProviderSuite.scala @@ -1020,6 +1020,61 @@ class TestSuitesProviderSuite extends BaseLspSuite("testSuitesFinderSuite") { }, ) + checkEvents( + "testNG", + List( + "org.testng:testng:7.7.1", + "com.lihaoyi:mill-contrib-testng:0.12.1", + ), + s"""|/app/src/main/scala/a/b/TestNG.scala + |package a.b + | + |import org.testng.annotations.Test + | + |class TestNG { + | @Test + | def testOK(): Unit = { + | assert(true) + | } + |} + | + |""".stripMargin, + "app/src/main/scala/a/b/TestNG.scala", + () => { + List( + rootBuildTargetUpdate( + "app", + targetUri, + List[TestExplorerEvent]( + AddTestSuite( + "a.b.TestNG", + "TestNG", + "a/b/TestNG#", + QuickLocation( + classUriFor("app/src/main/scala/a/b/TestNG.scala"), + (4, 6, 4, 12), + ).toLsp, + canResolveChildren = true, + ), + AddTestCases( + "a.b.TestNG", + "TestNG", + List( + TestCaseEntry( + "testOK", + QuickLocation( + classUriFor("app/src/main/scala/a/b/TestNG.scala"), + (6, 8, 6, 14), + ).toLsp, + ) + ).asJava, + ), + ).asJava, + ) + ) + }, + ) + /** * Discovers all tests in project or test cases in file * From 8a3970293cff07202eb6c7e38978aace827deda0 Mon Sep 17 00:00:00 2001 From: kasiaMarek Date: Thu, 13 Feb 2025 10:48:38 +0100 Subject: [PATCH 2/2] refactor: use bloop config test framework --- build.sbt | 3 +- .../metals/debug/BuildTargetClasses.scala | 64 +++++++------------ .../internal/metals/debug/DebugProvider.scala | 6 +- .../debug/server/TestSuiteDebugAdapter.scala | 4 +- .../metals/testProvider/TestSuitesIndex.scala | 7 +- .../testProvider/TestSuitesProvider.scala | 32 +++++----- project/V.scala | 2 +- .../tests/mill/MillDebugDiscoverySuite.scala | 11 ++-- .../tests/mill/MillServerCodeLensSuite.scala | 4 +- .../main/scala/tests/BuildServerLayout.scala | 14 ++-- 10 files changed, 66 insertions(+), 81 deletions(-) diff --git a/build.sbt b/build.sbt index 1b3e7617326..13303717050 100644 --- a/build.sbt +++ b/build.sbt @@ -471,6 +471,8 @@ lazy val metals = project "org.scala-lang.modules" %% "scala-xml" % "2.3.0", ("org.virtuslab.scala-cli" % "scala-cli-bsp" % V.scalaCli) .exclude("ch.epfl.scala", "bsp4j"), + // For test frameworks + "ch.epfl.scala" %% "bloop-config" % V.bloopConfig, ), buildInfoPackage := "scala.meta.internal.metals", buildInfoKeys := Seq[BuildInfoKey]( @@ -760,7 +762,6 @@ lazy val unit = project Test / javaOptions += "-Xmx2G", libraryDependencies ++= List( "io.get-coursier" %% "coursier" % V.coursier, // for jars - "ch.epfl.scala" %% "bloop-config" % V.bloopConfig, "org.scalameta" %% "munit" % V.munit, ), buildInfoPackage := "tests", diff --git a/metals/src/main/scala/scala/meta/internal/metals/debug/BuildTargetClasses.scala b/metals/src/main/scala/scala/meta/internal/metals/debug/BuildTargetClasses.scala index 96eaae2571e..d6c50615058 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/debug/BuildTargetClasses.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/debug/BuildTargetClasses.scala @@ -12,6 +12,7 @@ import scala.meta.internal.metals.debug.BuildTargetClasses.TestSymbolInfo import scala.meta.internal.semanticdb.Scala.Descriptor import scala.meta.internal.semanticdb.Scala.Symbols +import bloop.config.Config.TestFramework import ch.epfl.scala.{bsp4j => b} /** @@ -186,7 +187,7 @@ final class BuildTargetClasses(val buildTargets: BuildTargets)(implicit ) } { // item.getFramework() can return null! - val framework = TestFramework(Option(item.getFramework())) + val framework = TestFrameworkUtils.from(Option(item.getFramework())) val testInfo = BuildTargetClasses.TestSymbolInfo(className, framework) classes(target).testClasses.put(symbol, testInfo) } @@ -225,49 +226,32 @@ final class BuildTargetClasses(val buildTargets: BuildTargets)(implicit } } -sealed abstract class TestFramework(val canResolveChildren: Boolean) { - def names: List[String] -} +object TestFrameworkUtils { + val WeaverTestFramework: TestFramework = TestFramework( + List("weaver.framework.CatsEffect") + ) + private lazy val supportedFrameworks = Set( + TestFramework.JUnit, + TestFramework.munit, + TestFramework.ScalaTest, + WeaverTestFramework, + TestFramework.TestNG, + ) -object TestFramework { - def apply(framework: Option[String]): TestFramework = framework + def from(framework: Option[String]): TestFramework = framework .map { - case "JUnit" => JUnit4 - case "munit" => MUnit - case "ScalaTest" => Scalatest - case "weaver-cats-effect" => WeaverCatsEffect - case "TestNG" => TestNG - case _ => Unknown + case "JUnit" => TestFramework.JUnit + case "munit" => TestFramework.munit + case "ScalaTest" => TestFramework.ScalaTest + case "weaver-cats-effect" => WeaverTestFramework + case "TestNG" => TestFramework.TestNG + case _ => TestFramework(Nil) } - .getOrElse(Unknown) -} - -case object JUnit4 extends TestFramework(true) { - def names: List[String] = List("com.novocode.junit.JUnitFramework") -} - -case object MUnit extends TestFramework(true) { - def names: List[String] = List("munit.Framework") -} + .getOrElse(TestFramework(Nil)) -case object Scalatest extends TestFramework(true) { - def names: List[String] = - List( - "org.scalatest.tools.Framework", - "org.scalatest.tools.ScalaTestFramework", - ) -} - -case object WeaverCatsEffect extends TestFramework(true) { - def names: List[String] = List("weaver.BaseCatsSuite") -} - -case object TestNG extends TestFramework(true) { - def names: List[String] = List("mill.testng.TestNGFramework") -} - -case object Unknown extends TestFramework(false) { - def names: List[String] = Nil + def canResolveTests(framework: TestFramework): Boolean = supportedFrameworks( + framework + ) } object BuildTargetClasses { diff --git a/metals/src/main/scala/scala/meta/internal/metals/debug/DebugProvider.scala b/metals/src/main/scala/scala/meta/internal/metals/debug/DebugProvider.scala index 6da90a82451..17b025ef652 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/debug/DebugProvider.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/debug/DebugProvider.scala @@ -58,6 +58,7 @@ import scala.meta.internal.metals.testProvider.TestSuitesProvider import scala.meta.internal.mtags.OnDemandSymbolIndex import scala.meta.io.AbsolutePath +import bloop.config.Config import ch.epfl.scala.bsp4j.BuildTargetIdentifier import ch.epfl.scala.bsp4j.DebugSessionParams import ch.epfl.scala.bsp4j.ScalaMainClass @@ -392,7 +393,7 @@ class DebugProvider( private def discoverTests( id: BuildTargetIdentifier, testClasses: b.ScalaTestSuites, - ): Future[Map[TestFramework, List[Discovered]]] = { + ): Future[Map[Config.TestFramework, List[Discovered]]] = { val symbolInfosList = for { selection <- testClasses.getSuites().asScala.toList @@ -595,7 +596,8 @@ class DebugProvider( request.requestData.copy( suites = request.requestData.suites.map { suite => testProvider.getFramework(buildTarget, suite) match { - case JUnit4 | MUnit => + case Config.TestFramework.JUnit | + Config.TestFramework.munit => suite.copy(tests = suite.tests.map(escapeTestName)) case _ => suite } diff --git a/metals/src/main/scala/scala/meta/internal/metals/debug/server/TestSuiteDebugAdapter.scala b/metals/src/main/scala/scala/meta/internal/metals/debug/server/TestSuiteDebugAdapter.scala index fe20632a80b..9a3349667cd 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/debug/server/TestSuiteDebugAdapter.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/debug/server/TestSuiteDebugAdapter.scala @@ -7,13 +7,13 @@ import scala.concurrent.ExecutionContext import scala.meta.internal.metals.JdkSources import scala.meta.internal.metals.MetalsEnrichments._ -import scala.meta.internal.metals.debug.TestFramework import scala.meta.internal.metals.debug.server.testing.FingerprintInfo import scala.meta.internal.metals.debug.server.testing.LoggingEventHandler import scala.meta.internal.metals.debug.server.testing.TestInternals import scala.meta.internal.metals.debug.server.testing.TestServer import scala.meta.io.AbsolutePath +import bloop.config.Config import ch.epfl.scala.bsp4j.ScalaTestSuites import ch.epfl.scala.debugadapter.CancelableFuture import ch.epfl.scala.debugadapter.DebuggeeListener @@ -31,7 +31,7 @@ class TestSuiteDebugAdapter( testClasses: ScalaTestSuites, project: DebugeeProject, userJavaHome: Option[String], - discoveredTests: Map[TestFramework, List[Discovered]], + discoveredTests: Map[Config.TestFramework, List[Discovered]], )(implicit ec: ExecutionContext) extends MetalsDebuggee() { diff --git a/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesIndex.scala b/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesIndex.scala index 8c018863a3c..26747175d6b 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesIndex.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesIndex.scala @@ -3,11 +3,12 @@ package scala.meta.internal.metals.testProvider import scala.collection.concurrent.TrieMap import scala.meta.internal.metals.debug.BuildTargetClasses -import scala.meta.internal.metals.debug.TestFramework +import scala.meta.internal.metals.debug.TestFrameworkUtils import scala.meta.internal.metals.testProvider.TestExplorerEvent._ import scala.meta.internal.mtags import scala.meta.io.AbsolutePath +import bloop.config.Config import ch.epfl.scala.bsp4j.BuildTarget import org.eclipse.{lsp4j => l} @@ -36,7 +37,7 @@ private[testProvider] final case class TestEntry( private[testProvider] final case class TestSuiteDetails( fullyQualifiedName: FullyQualifiedName, - framework: TestFramework, + framework: Config.TestFramework, className: ClassName, symbol: mtags.Symbol, location: l.Location, @@ -46,7 +47,7 @@ private[testProvider] final case class TestSuiteDetails( className = className.value, symbol = symbol.value, location = location, - canResolveChildren = framework.canResolveChildren, + canResolveChildren = TestFrameworkUtils.canResolveTests(framework), ) def asRemoveEvent: TestExplorerEvent = RemoveTestSuite( diff --git a/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesProvider.scala b/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesProvider.scala index 67904a9bfcc..446bd0be6ad 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesProvider.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/testProvider/TestSuitesProvider.scala @@ -22,13 +22,7 @@ import scala.meta.internal.metals.UserConfiguration import scala.meta.internal.metals.clients.language.MetalsLanguageClient import scala.meta.internal.metals.codelenses.CodeLens import scala.meta.internal.metals.debug.BuildTargetClasses -import scala.meta.internal.metals.debug.JUnit4 -import scala.meta.internal.metals.debug.MUnit -import scala.meta.internal.metals.debug.Scalatest -import scala.meta.internal.metals.debug.TestFramework -import scala.meta.internal.metals.debug.TestNG -import scala.meta.internal.metals.debug.Unknown -import scala.meta.internal.metals.debug.WeaverCatsEffect +import scala.meta.internal.metals.debug.TestFrameworkUtils import scala.meta.internal.metals.testProvider.TestExplorerEvent._ import scala.meta.internal.metals.testProvider.frameworks.JunitTestFinder import scala.meta.internal.metals.testProvider.frameworks.MunitTestFinder @@ -44,6 +38,7 @@ import scala.meta.internal.semanticdb.TextDocument import scala.meta.internal.semanticdb.TextDocuments import scala.meta.io.AbsolutePath +import bloop.config.Config import ch.epfl.scala.bsp4j.BuildTarget import ch.epfl.scala.bsp4j.ScalaPlatform import ch.epfl.scala.{bsp4j => b} @@ -281,7 +276,9 @@ final class TestSuitesProvider( metadata <- index.getMetadata(path).toList events = { val suites = metadata.entries.map(_.suiteDetails).distinct - val canResolve = suites.exists(_.framework.canResolveChildren) + val canResolve = suites.exists(suite => + TestFrameworkUtils.canResolveTests(suite.framework) + ) if (canResolve) getTestCasesForSuites(path, suites, textDocument) else Seq.empty } @@ -310,40 +307,40 @@ final class TestSuitesProvider( .map { semanticdb => suites.flatMap { suite => val testCases = suite.framework match { - case JUnit4 => + case Config.TestFramework.JUnit => junitTestFinder.findTests( doc = semanticdb, path = path, suiteSymbol = suite.symbol, ) - case MUnit => + case Config.TestFramework.munit => munitTestFinder.findTests( doc = semanticdb, path = path, suiteName = suite.fullyQualifiedName, symbol = suite.symbol, ) - case Scalatest => + case Config.TestFramework.ScalaTest => scalatestTestFinder.findTests( doc = semanticdb, path = path, suiteName = suite.fullyQualifiedName, symbol = suite.symbol, ) - case WeaverCatsEffect => + case TestFrameworkUtils.WeaverTestFramework => weaverCatsEffect.findTests( doc = semanticdb, path = path, suiteName = suite.fullyQualifiedName, symbol = suite.symbol, ) - case TestNG => + case Config.TestFramework.TestNG => testNGTestFinder.findTests( doc = semanticdb, path = path, suiteSymbol = suite.symbol, ) - case Unknown => Vector.empty + case _ => Vector.empty } if (testCases.nonEmpty) { @@ -394,7 +391,8 @@ final class TestSuitesProvider( if (isExplorerEnabled) { val addedTestCases = addedEntries.mapValues { _.flatMap { entry => - val canResolve = entry.suiteDetails.framework.canResolveChildren + val canResolve = + TestFrameworkUtils.canResolveTests(entry.suiteDetails.framework) if (canResolve && buffers.contains(entry.path)) getTestCasesForSuites(entry.path, Vector(entry.suiteDetails), None) else Nil @@ -571,9 +569,9 @@ final class TestSuitesProvider( def getFramework( target: BuildTarget, selection: ScalaTestSuiteSelection, - ): TestFramework = getFromCache(target, selection.className) + ): Config.TestFramework = getFromCache(target, selection.className) .map(_.suiteDetails.framework) - .getOrElse(Unknown) + .getOrElse(Config.TestFramework(Nil)) def getFromCache( target: BuildTarget, diff --git a/project/V.scala b/project/V.scala index e5d196867a8..6a38353389c 100644 --- a/project/V.scala +++ b/project/V.scala @@ -20,7 +20,7 @@ object V { val ammonite = "3.0.0-2-6342755f" val betterMonadicFor = "0.3.1" val bloop = "2.0.8" - val bloopConfig = "2.3.1" + val bloopConfig = "2.3.2" val bsp = "2.2.0-M2" val coursier = "2.1.24" // changing coursier interfaces version may be not binary compatible. diff --git a/tests/slow/src/test/scala/tests/mill/MillDebugDiscoverySuite.scala b/tests/slow/src/test/scala/tests/mill/MillDebugDiscoverySuite.scala index 568b343a7da..f92e06e15be 100644 --- a/tests/slow/src/test/scala/tests/mill/MillDebugDiscoverySuite.scala +++ b/tests/slow/src/test/scala/tests/mill/MillDebugDiscoverySuite.scala @@ -8,9 +8,8 @@ import scala.meta.internal.metals.JsonParser._ import scala.meta.internal.metals.MetalsEnrichments._ import scala.meta.internal.metals.ScalaTestSuiteSelection import scala.meta.internal.metals.ScalaTestSuites -import scala.meta.internal.metals.debug.JUnit4 -import scala.meta.internal.metals.debug.Scalatest +import bloop.config.Config.TestFramework import ch.epfl.scala.bsp4j.TestParamsDataKind import tests.BaseDapSuite import tests.BaseMillServerSuite @@ -65,7 +64,7 @@ class MillDebugDiscoverySuite |} |""".stripMargin, scala, - Some(Scalatest), + Some(TestFramework.ScalaTest), ) ) _ <- server.didOpen("a/src/Main.scala") @@ -113,7 +112,7 @@ class MillDebugDiscoverySuite |} |""".stripMargin, scala, - Some(JUnit4), + Some(TestFramework.JUnit), ) ) _ <- server.didOpen(fooPath) @@ -154,7 +153,7 @@ class MillDebugDiscoverySuite |} |""".stripMargin, scalaVersion, - Some(Scalatest), + Some(TestFramework.ScalaTest), ) ) _ <- server.didOpen(fooPath) @@ -207,7 +206,7 @@ class MillDebugDiscoverySuite |} |""".stripMargin, scalaVersion, - Some(Scalatest), + Some(TestFramework.ScalaTest), ) ) debugger <- diff --git a/tests/slow/src/test/scala/tests/mill/MillServerCodeLensSuite.scala b/tests/slow/src/test/scala/tests/mill/MillServerCodeLensSuite.scala index 6a6cc9e6626..9ab3157966b 100644 --- a/tests/slow/src/test/scala/tests/mill/MillServerCodeLensSuite.scala +++ b/tests/slow/src/test/scala/tests/mill/MillServerCodeLensSuite.scala @@ -1,9 +1,9 @@ package tests.mill import scala.meta.internal.metals.ServerCommands -import scala.meta.internal.metals.debug.MUnit import scala.meta.internal.metals.{BuildInfo => V} +import bloop.config.Config.TestFramework import tests.BaseCodeLensLspSuite import tests.MillBuildLayout import tests.MillServerInitializer @@ -32,7 +32,7 @@ class MillServerCodeLensSuite |class Foo extends munit.FunSuite {} |""".stripMargin, V.scala3, - testDep = Some(MUnit), + testDep = Some(TestFramework.munit), ) ) diff --git a/tests/unit/src/main/scala/tests/BuildServerLayout.scala b/tests/unit/src/main/scala/tests/BuildServerLayout.scala index 938eb8d07f2..72612e265c1 100644 --- a/tests/unit/src/main/scala/tests/BuildServerLayout.scala +++ b/tests/unit/src/main/scala/tests/BuildServerLayout.scala @@ -1,11 +1,9 @@ package tests -import scala.meta.internal.metals.debug.JUnit4 -import scala.meta.internal.metals.debug.MUnit -import scala.meta.internal.metals.debug.Scalatest -import scala.meta.internal.metals.debug.TestFramework import scala.meta.internal.metals.{BuildInfo => V} +import bloop.config.Config.TestFramework + trait BuildToolLayout { def apply(sourceLayout: String, scalaVersion: String): String } @@ -65,9 +63,11 @@ object MillBuildLayout extends BuildToolLayout { ): String = { val optDepModule = testDep.map { - case Scalatest => ("ScalaTest", "org.scalatest::scalatest:3.2.16") - case MUnit => ("Munit", "org.scalameta::munit::0.7.29") - case JUnit4 => ("Junit4", "com.github.sbt:junit-interface:0.13.2") + case TestFramework.ScalaTest => + ("ScalaTest", "org.scalatest::scalatest:3.2.16") + case TestFramework.munit => ("Munit", "org.scalameta::munit::0.7.29") + case TestFramework.JUnit => + ("Junit4", "com.github.sbt:junit-interface:0.13.2") case testFramework => throw new RuntimeException( s"No implementation for layout for $testFramework"