1

I have a class AppComponents in AppLoader.scala in projectDir/app

My tests are in projectDir/test/ControllerSpec/UserControllerSpec.scala

In UserControllerSpec.scala, I tried to create an instance of AppComponents but the compiler couldn't find the AppComponents class

override def components: BuiltInComponents = new AppComponents(context) //doesn't compile

But if I include statement package app in Apploader.scala then the compiler is able to find AppComponents and the above code compiles.

I don't understand this behavior.

halfer
  • 19,824
  • 17
  • 99
  • 186
Manu Chadha
  • 15,555
  • 19
  • 91
  • 184

1 Answers1

1

Top-level definitions outside a packaging are assumed to be injected into a special empty package. That package cannot be named and therefore cannot be imported. However, members of the empty package are visible to each other without qualification.

So AppComponents should only be visible to other classes/traits/etc. outside a package. Because

if I include statement package app in Apploader.scala then the compiler is able to find AppComponents

it looks like UserControllerSpec does declare a package and can't see the empty package's members.

This behavior is probably for consistency with Java, see answers to Import package with no name Java.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • Alexey, you Genius! Yes. UserControllerSpec is in a package! – Manu Chadha Jun 07 '18 at 12:43
  • I'll add that I don't think there's ever a good reason not to have a package declaration in a Scala file. In Java you could want to simplify directory structure, but in Scala you can have both. – Alexey Romanov Jun 07 '18 at 12:51
  • There was an interesting side-effect which I didn't observer earlier. If I declare my `Apploader` class in a package then obviously I'll have to access it using `packagename.classname`. I realised it later. I had to change entry in `application.conf` to `play.application.loader="app.AppLoader"` – Manu Chadha Jun 20 '18 at 08:15