Another interesting question is: Which namespace are the members of the exported import shown to be in?
Suppose you've got this:
// DeclarationSite.scala
package object original_package {
class A
}
package object importing_package {
@exported import original_package._
}
// UsageSite.scala
import importing_package._
val a: A
// ...
So, what namespace is class A residing in (conceptually)?
That is, which namespace should be shown e.g. by IDE helpers or similar tools?
Possiblity 1: Let @exported mean that importing_package declares type aliases for all classes exported by original_package.
Then the above code could be rewritten to:
// DeclarationSite.scala
package object original_package { /* same as before */ }
package object importing_package {
type A = original_package.A
}
// UsageSite.scala: Same as before
In this setting, importing_package.A would be a type alias fo original_package.A.
Possibility 2: @exported has no direct effect at the declaration site.
Instead, when importing importing_package._ at the usage site, the compiler behaves as if you also had imported original_package._.
So the initial code snippet would be equal to:
// DeclarationSite.scala:
package object original_package { /* again, same as before */ }
package object importing_package {
import original_package._
}
// UsageSite.scala:
import importing_package._ // Same as above
import original_package._
So there would be no type called importing_package.A, but only the type orginial_package.A.
In this setting, the scaladoc of importing_package could just contain a linked named "This package also exports(/imports) original_package._" - which, when clicked, leads you to the scaladoc page of 'original_package'.
Personally, I'd strongly opt for the second approach, but that is up to discussion.
Variant 1 might be more 'transparent' to the user, regarding which types he can use in his code (he doesn't has to care what package the type 'A' is originally coming from).
Variant 2 is, in my opinion, is more easily to grasp regarding "what's really going on". The transformation done by the compiler can also be done "by hand" by the libraries end-user.
It is also, IMO, more closely to the motivation stated in the introduction of the pre-sip:
Replacing the long, error-prone import sequences at the start of an application's scala files with one, compact import (or, equivalently, a few, well defined import),
while maintaing the modularity possible with packages.
(Old question: Do we allow only
@exported import of packages (easy), or also of objects & vals (possibly hard)?
In the case of packages, handling recursive (and possibly circular)
@exported imports is relatively easy - because import order doesnt matter (correct me if I'm wrong):
When parsing "import A._" (at UsageSite.scala, for example), all
@exported imports of A get inserted after the "import A._" statement, and then the
@exported imports of the imports, and so, recursively,
until:
All packages we are currently looking at:
1) Contain no
@exported imports at all, or
2) Contain no
@exported imports
no already included at the usage site.
So when parsing "import A._", and package A imports package B, which, in turn, imports A, the last import needn't be followed, because package A is already being imported at the usage site.
Greetings.