2

This is (I think) a different question from Type not found: type .. when type is in src_managed folder.

I am building from sbt, 1.1.1, I have set up a code generation task in sbt that is runnign as expected and creaing a number of files with the same structure.

package com.a3.traffic
package object Vendor

And they are imported in other files as:

import com.a3.traffic.Vendor._

The files are generated under src_managed. I have tried two different setups

src_managed / main / Vendor

src_managed / main / scala / com / a3 / traffic / Vendor

In both cases I get the following error:

[error] /Users/luis/IdeaProjects/SparkTrafficAllocation/core/src/main/scala/com/a3/traffic/Params.scala:5:28: object Vendor is not a member of package com.a3.traffic
[error] import com.a3.traffic.Vendor._      

I can fix that by moving the generatd code to src / main / scala / com / a3 / traffic / Vendor (that is with the rest of my code) but then I get this.

[error] /Users/luis/IdeaProjects/SparkTrafficAllocation/core/target/scala-2.11/src_managed/main/scala/com/a3/traffic /Vendor/Vendor.scala:3:16: package is already defined as package object Vendor
[error] package object Vendor {

I find this quite puzzling. The objects defined in src_managed can not be seen from my code, but it can see what is in the package.How can I make the objects in src_managed available to the rest of the package?

EDIT I created a minimal project to show this https://github.com/sisamon/MinimalApp

EDIT 2 I am using a name / package.scala / package.scala => object name as the original name.scala case class / case object was not working.

Luis Sisamon
  • 101
  • 7
  • Can you share a sample repo which we can reproduce the problem?, This is quite weird. I had done it a couple of times and it always works. By any chance had you modify something in **SBT** related to the compile classpath - by default the _src_managed_ folder is always present for compilation, and as long as the objects defined there are in a package and are public you may be able to use them. As you can see in this simple demo I made, I use all objects created in the generated file in my `Main.scala` file. – Luis Miguel Mejía Suárez Jan 02 '19 at 15:24
  • Also, the las error message is quite weird, it says that the the `package object Vendor` is already defined. When you did the experiment of moving the generated file to the rest of the code, did you disable the code generation and deleted the old one? - that way you can check if given that, it will work as expected. – Luis Miguel Mejía Suárez Jan 02 '19 at 15:27
  • No, i did not (for this experiment) For "production"i will do as such but I was really curious about why it was not finding the objects.It is not really so weird as the object Vendor is in both the managed and unmanaged source directories. I will try to build a smaller project that still shows the problem. The one I am using is fairly complex. Thanks! – Luis Sisamon Jan 02 '19 at 16:13
  • Ok, when you have it edit the question with the link, I will take a look as soon as I can. Also I just noticed I forgot to add the link to the [demo](https://github.com/BalmungSan/fastpath-demo) I mentioned in my first comment. – Luis Miguel Mejía Suárez Jan 02 '19 at 16:19
  • Your `Vendor` class should actually be named `SparkTrafficAllocation/core/target/scala-2.11/src_managed/main/scala/com/a3/traffic/package.scala`. It should contain `package com.a3.traffic` \n `package object Vendor { ... }` – Aki Jan 02 '19 at 19:33
  • ... and package objects (since they are actual packages) usually start with lower case letters – Aki Jan 02 '19 at 19:40
  • @aki, fixed the file name and lowercase convention but it made no difference – Luis Sisamon Jan 02 '19 at 21:56
  • @LuisSisamon sorry for late response, I was hoping you to tag me after the edit. The link is broken - did you manage to solve it? – Luis Miguel Mejía Suárez Jan 03 '19 at 13:50
  • @LuisMiguelMejíaSuárez sorry, I forgot to tag and to make repo public. – Luis Sisamon Jan 03 '19 at 16:46

1 Answers1

2

The problem is in here.

def generator (x: Country) = {
  generateADT("Vendor", x.vendor)
  generateADT("InstallationType", x.installationType)
}

Remember that your task MUST returns a Seq with the ALL Files that were generated!.

And, your generateADT each return a Seq of one File, and as such, you are returning only the Seq of the last call (which in this case is InstallationType), that is why your Vendor is not found!

You can check that by commenting the second line, which will make the first line the return, in that case the Vendor will be found!

There a couple of ways to fix this, the most simple & elegant (IMHO) would be this:

def generator (x: Country): List[File] =
  List(
    ("Vendor", x.vendor),
    ("InstallationType", x.installationType)
  ).map((generateADT _).tupled)

def generateADT (base: String, d: Descriptor): File = {
  // ...
  // The path really does not matter, as long as it is inside the src_managed folder.
  val adtFile = (sourceManaged in Compile).value / s"${base}.scala"
  IO.writeLines(adtFile, code)
  adtFile
}

PS: As an advice, you should explicitly put the return type of all functions/methods. Not only it will help the type inference of other things, also it will avoid a couple of compile errors and will increase the readability of your code.

  • Yes I should have typed the function with the return value. This effectively fixes the problem, but I still do not get why i had the second problem, seeing them after i copied them into my main code. There is clearly something I do not get about the scope rules. – Luis Sisamon Jan 03 '19 at 21:47
  • @LuisSisamon I think _(and this is only pure speculation)_, that **SBT** still compiles everything inside the `src_managed` folder before compiling the normal source code. And for the source code it only puts in scope the files which it knows it have to use - or it is only black magic, who knows is **SBT**. – Luis Miguel Mejía Suárez Jan 03 '19 at 23:41