Skip to content

Commit

Permalink
fix: cannot find Scala companion module from Java
Browse files Browse the repository at this point in the history
To find Scala companion mudule from Java, we should strip module suffix
`$`.
This provides workaround for scala#17255, but it requires some refinment to fully fix it
because not-fully-qualified type like the following example still fails
to compile due to missing symbol.

```java
package example;

public class Bar {
    private static final Foo$ MOD = Foo$.MODULE;
}
```

This is because `pre` in `javaFindMember` for `Foo` in the case above is `<root>`,
not `example` and therefore `pre.findMember` looks for `<root>.Foo` instead
of `example.Foo`.

I'm not sure whether the qualifier is intentionally dropped.
  • Loading branch information
i10416 committed Feb 24, 2024
1 parent 8e2f92a commit 646e62e
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 7 deletions.
22 changes: 15 additions & 7 deletions compiler/src/dotty/tools/dotc/core/ContextOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,18 @@ object ContextOps:
final def javaFindMember(name: Name, pre: Type, lookInCompanion: Boolean, required: FlagSet = EmptyFlags, excluded: FlagSet = EmptyFlags): Denotation =
assert(ctx.isJava)
inContext(ctx) {

import dotty.tools.dotc.core.NameOps.*
val preSym = pre.typeSymbol

// 1. Try to search in current type and parents.
val directSearch = pre.findMember(name, pre, required, excluded)
val directSearch =
if name.isTypeName && name.endsWith(StdNames.str.MODULE_SUFFIX) then
pre.findMember(name.stripModuleClassSuffix, pre, required, excluded) match
case NoDenotation => NoDenotation
case k: SymDenotation =>
k.companionModule.denot
else
pre.findMember(name, pre, required, excluded)

// 2. Try to search in companion class if current is an object.
def searchCompanionClass = if lookInCompanion && preSym.is(Flags.Module) then
Expand All @@ -81,11 +88,12 @@ object ContextOps:
val pre1 = bc.companionModule.namedType
pre1.findMember(name, pre1, required, excluded)
}.find(_.exists).getOrElse(NoDenotation)

if preSym.isClass then
directSearch orElse searchCompanionClass orElse searchSuperCompanionObjects
else
directSearch
val result =
if preSym.isClass then
directSearch orElse searchCompanionClass orElse searchSuperCompanionObjects
else
directSearch
result
}

/** A fresh local context with given tree and owner.
Expand Down
1 change: 1 addition & 0 deletions compiler/test/dotc/pos-test-pickling.blacklist
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ i16649-irrefutable.scala
strict-pattern-bindings-3.0-migration.scala
i17186b.scala
i11982a.scala
i17255

# Tree is huge and blows stack for printing Text
i7034.scala
Expand Down
6 changes: 6 additions & 0 deletions tests/pos/i17255/Bar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package example;


public class Bar {
private static final example.Foo$ MOD = example.Foo$.MODULE$;
}
5 changes: 5 additions & 0 deletions tests/pos/i17255/Foo.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package example

case class Foo(i: Int)

object Foo

0 comments on commit 646e62e

Please sign in to comment.