Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
lihaoyi committed Nov 19, 2023
1 parent b6240a9 commit cd3d9ef
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 2 deletions.
43 changes: 43 additions & 0 deletions integration/feature/private-methods/repo/build.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import mill._

def pub = T {
priv()
}

private def priv = T {
"priv"
}

object foo extends Module {
def bar = T {
baz()
}
}

private def baz = T {
"bazOuter"
}

object qux extends Module {
object foo extends Module {
def bar = T {
baz()
}
}
private def baz = T {
"bazInner"
}
}

object cls extends cls
class cls extends Module {
object foo extends Module {
def bar = T {
baz()
}
}

private def baz = T {
"bazCls"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package mill.integration

import utest._

object PrivateMethodsTests extends IntegrationTestSuite {
val tests = Tests {
val wsRoot = initWorkspace()
"simple" - {
// Simple public target depending on private target works
val pub = evalStdout("show", "pub")
assert(pub.out == "\"priv\"")
assert(pub.isSuccess)

// Make sure calling private methods indirectly in a variety of scenarios works
// even when they're "not really private" due to
val fooBar = evalStdout("show", "foo.bar")
assert(fooBar.out == "\"bazOuter\"")
assert(fooBar.isSuccess)

val quxFooBar = evalStdout("show", "qux.foo.bar")
assert(quxFooBar.out == "\"bazInner\"")
assert(quxFooBar.isSuccess)

val clsFooBar = evalStdout("show", "cls.foo.bar")
assert(clsFooBar.out == "\"bazCls\"")
assert(clsFooBar.isSuccess)

// Make sure calling private methods directly fails
val priv = evalStdout("show", "priv")
assert(priv.err.contains("Cannot resolve priv"))
assert(priv.isSuccess == false)

val baz = evalStdout("show", "baz")
assert(baz.err.contains("Cannot resolve baz"))
assert(baz.isSuccess == false)

val quxBaz = evalStdout("show", "qux.baz")
assert(quxBaz.err.contains("Cannot resolve qux.baz"))
assert(quxBaz.isSuccess == false)

val clsBaz = evalStdout("show", "cls.baz")
assert(clsBaz.err.contains("Cannot resolve cls.baz"))
assert(clsBaz.isSuccess == false)
}
}
}
10 changes: 8 additions & 2 deletions main/eval/src/mill/eval/GroupEvaluator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import mill.eval.Evaluator.TaskResult
import mill.util._

import scala.collection.mutable
import scala.reflect.NameTransformer.decode
import scala.reflect.NameTransformer.{encode, decode}
import scala.util.DynamicVariable
import scala.util.control.NonFatal

Expand Down Expand Up @@ -98,7 +98,13 @@ private[mill] trait GroupEvaluator {
val methods = for {
c <- transitiveParents
m <- c.getDeclaredMethods
if decode(m.getName) == namedTask.ctx.segment.pathSegments.head
encodedTaskName = encode(namedTask.ctx.segment.pathSegments.head)
if m.getName == encodedTaskName ||
// Handle scenarios where private method names get mangled when they are
// not really JVM-private due to being accessed by Scala nested objects
// or classes https://github.com/scala/bug/issues/9306
m.getName == (c.getName.replace('.', '$') + "$$" + encodedTaskName) ||
m.getName == (c.getName.replace('.', '$') + "$" + encodedTaskName)
} yield m

val methodClass = methods.head.getDeclaringClass.getName
Expand Down
44 changes: 44 additions & 0 deletions tmp/build.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import mill._


def pub = T {
priv()
}

private def priv = T {
"priv"
}

object foo extends Module {
def bar = T {
baz()
}
}

private def baz = T {
"bazOuter"
}

object qux extends Module {
object foo extends Module {
def bar = T {
baz()
}
}
private def baz = T {
"bazInner"
}
}

object cls extends cls
class cls extends Module {
object foo extends Module {
def bar = T {
baz()
}
}

private def baz = T {
"bazCls"
}
}

0 comments on commit cd3d9ef

Please sign in to comment.