VS Code and Metals: Run 'Build import' to enable code navigation - visual-studio-code

I have a Scala- / Mill-Project that I wan't to import into VSCode.
The Metals Doctor gives me the following warnings:
Is there something missing in my project?
Here is my Mill configuration (build.sc):
import mill._
import mill.define.Target
import scalalib._
trait MyModule extends ScalaModule {
def scalaVersion = "2.13.1"
object version {
val cats = "2.0.0"
..
}
object libs {
val cats = ivy"org.typelevel::cats-core:${version.cats}"
..
}
object test extends Tests {
...
}
}
object entity extends MyModule {
override def ivyDeps = {
Agg(
libs.cats,
..
)
}
}
object macros extends MyModule {
..
}
Here is the whole project: https://github.com/pme123/zio-examples
The console output shows no warnings, here is the end:
...
time: connected to build server in 0.33s
time: imported build in 0.41s
time: indexed workspace in 3.85s
no build target: /Users/mpa/dev/Github/pme123/zio-examples/build.sc

This error/help message is misleading, as it presumes you are using Bloop, in which case re-importing solves the isssue (from experience). When you are using Mill's built-in BSP server, this won't change much.
Mill's recent 0.10.0-M4 release got a major BSP revamp. Also Metals improved it's Mill support. So you should have a better overall experience.
Here is some documentation: https://com-lihaoyi.github.io/mill/mill/Intro_to_Mill.html#_build_server_protocol_bsp

Related

How to organize code for multiple scala versions and differents dependencies

I want release library for 2.12 and 2.13 scala version. But it depends on another library, which exist for 2.12 only. For 2.13 I wrote my implementation for fast function:
2.12 code looks:
import com.dongxiguo.fastring.Fastring.Implicits._ //2.12 only
object Lib {
val a = fast"hello world"
}
2.13 code looks:
import mycompat.Implicits._ //2.13 only
object Lib {
val a = fast"hello world" //my implementation
}
So difference - only import ... in several files.
I can't understund how to organize code for differents scala version.
Having different imports is problematic, because that means you have different sources (and you need to maintain them). I think providing missing implementation of library in it's own original package will be better solution.
//main/scala-2.13/com/dongxiguo/fastring/Fastring/Implicits.scala
package com.dongxiguo.fastring.Fastring
object Implicits {
//your implementation of fast"Something"
}
As long as it is in scala-2.13 folder it will be compiled and used only for scala-2.13.
You need also different dependencies for 2.12 and 2.13 versions:
libraryDependencies ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 12)) => Seq("com.dongxiguo" %% "fastring" % "1.0.0")
case Some((2, 13)) => Seq()
case _ => Seq()
}
}
You will have same Lib implementation without any change for scala 2.13 and when fastring will be released for new scala version You will just remove those parts.
You can also create your own proxy object that will have distinct implementations for 2.12 and 2.13 in mycompat.Implicits._.
//main/scala-2.13/mycompat/Implicits.scala
package com.mycompat
object Implicits { /* proxy to fast"Something" from fastring library */ }
//main/scala-2.12/mycompat/Implicits.scala
package com.mycompat
object Implicits { /* your implementation of fast"Something" */ }
This is also good idea.
Based on lihaoyi and What are the Scala version-specific source directories in sbt? try something like so
src/main/scala/example/Hello.scala:
package example
object Hello extends Greeting with App {
println(greeting)
}
src/main/scala-2.11/example/Greeting.scala:
package example
trait Greeting {
lazy val greeting: String = "hello-from-2.11.12"
}
src/main/scala-2.13/example/Greeting.scala:
package example
trait Greeting {
lazy val greeting: String = "hello-from-2.13.1"
}
build.sbt:
crossScalaVersions := List("2.13.1", "2.11.12")
Now sbt ++2.11.12 run outputs
hello-from-2.11.12
whilst sbt ++2.13.1 run outputs
hello-from-2.13.1

Adding unit test to a legacy Scala project in IntelliJ

I have a legacy Scala project to work with using maven as build tool.
Initially there is core code only under folder structure src/main/scala/ with package x.y.z and a file Main.scala with code as:
object Main {
def cube(x: Int) = {
x * x * x
}
}
There are no tests for the code. So I manually added a folder structure as test/scala under src.
Then I copied the package as for core code, ie x.y.z and added MainTest.scala with test code as:
class MainTest extends FunSuite {
test("Main.cube") {
assert(Main.cube(3) === 27)
}
}
Running test gives error as:
Error:(8, 12) not found: value Main
assert(Main.cube(3) === 27)
Why do I get this error?
For below project structure MainTest.scala and Main.scala are in the same package x.y.z therefore no package import is required, However MainTempTest.scala and Main.scala are in different package therefore an explicit import has to be done import x.y.z.Main
src
-main
--scala
---x.y.z
----Main.scala
-test
--scala
---MainTempTest.scala
---x.y.z
----MainTest.scala

Mockito with Scala, any matcher resolved with multiple implementations

In our Scala project we use Mockito for testing purposes.
An annoying issue we have is that while using any matcher, it's always in can't resolve symbol any although it's not affect the code in builds or runtime.
There are two any implementation in Mockito (2.12):
def any[T](implicit evidence$11 : scala.reflect.ClassTag[T]) : T = { /* compiled code */ }
def any[T]() : T = { /* compiled code */ }
How can we "help" Mockito understand what any he should use?
For example:
This is a bit of self promotion but I just published a library called mockito-scala that solves this issue and many more, is part of the mockito ecosystem so hopefully should become the default when working with Scala, you can find it here https://github.com/mockito/mockito-scala with the information to get the dependency and what problems does it actually solves.
The syntax for the matcher is improved, in particular any now solves the correct type and it drops the parentheses so it reads better
Double check your build.sbt contains
libraryDependencies += "org.mockito" % "mockito-all" % "1.10.19" % Test
and you have the following import in your test file:
import org.mockito.Matchers.any
Here is a minimal working snippet (assuming ScalaTest):
import org.scalatest.FunSuite
import org.scalatest.mockito.MockitoSugar
import org.mockito.Mockito.when
import org.mockito.Matchers.any
class CalculatorTest extends FunSuite with MockitoSugar {
test("calculator add method") {
val calcMock = mock[Calculator]
when(calcMock.add(any[Int], any[Int])).thenReturn(10)
assert(calcMock.add(7, 3) == 10)
}
}
where trait Calculator { def add(a: Int, b: Int): Int }

Scalatest with eclipse shows errors while using Matchers

I have an eclipse scala project which uses maven. Eclipse plugins for ScalaIDE and Scalatest are installed. I have tests like:
import org.scalatest._
class ExampleSpec extends FlatSpec with Matchers {
feature("Feature A Test") {
scenario("Foo scenario 1") {
val a = FooClass().getResult()
a.count shouldBe 1 // IDE shows error: value shouldBe is not a member of Long
a(0).getString(0) shouldBe "FOO" // IDE shows error: value shouldBe is not a member of String
}
}
}
The maven compilation and the tests run fine, but in eclipse when I open this file, I see an error in eclipse wherever I am using a Matcher as mentioned in the comments above. Eg.
value shouldBe is not a member of Long
What am I missing? A scala test file shows hundreds of problems.
After adding the following dummy code:
case class Bar() {
def count = Array(Bar())
def getString(x: Int) = Array("aqq")
def apply[T](x: Int) = this
}
case class FooClass() {
def getResult() = Bar()
}
and changing FlatSpec to FeatureSpec as this is the syntax you are using in your ExampleSpec, the code compiles without any issues.
If it's still not the case for you I can suggest creating simple build.sbt and generating project with Eclipse sbt plugin.
I know this is old, but I had the same issue with eclipse (late 2018), and I was able to fix this by making sure the test was NOT in the default package. That is, add "package org.scalatest.examples.flatspec" to the beginning of your test, as an example, and move the test into that package.

Confusion regarding working of protected[some_scope] and inheritance in scala

This question is about protected scope of scala. Following code runs perfectly.
//In firstfile.scala
package A{
class test{
protected[test] var a=0
}
}
package B{
class test1 extends A.test{
println(a)
}
}
But when I put package B in some other file,then compilation fails saying not found value a
// In secondfile.scala
import A.test
package B{
class test1 extends test{
println(a)
}
}
I am running this code in intellij.
what can be the reason of this? Are not the two codes same?
I think you've found a bug. I can reproduce it in Eclipse with Scala IDE 2.0.0-beta9 with Scala 2.9.0-1. First, let's create Foo.scala:
package a
class Foo {
protected[Foo] var x = 0
}
and then Bar.scala:
package b
class Bar extends a.Foo {
println(x) // Error: Not found: value x
}
Eclipse telling us, there is an error. But after cleaning a project this error disappears. And I checked, with scalac everything compiles with first attempt (who would doubt).
Update:
I've opened a ticket #1000567 on Scala IDE bugtracker regarding this issue.