Skip to content

Commit

Permalink
SI-8479 Fix constructor default args under scaladoc
Browse files Browse the repository at this point in the history
The `DocDef` node hid the `DefDef` constructor from the scrutinee
of the namer when determining if the class had constructor defaults
or not.

The current pattern for fixing these bugs is to delegate the check
to `TreeInfo`, and account for the wrapper `DocDef` node. I've
followed that pattern, but expressed my feelings about this approach
in a TODO comment.

Before this patch, the enclosed test failed with:

     error: not enough arguments for constructor SparkContext: (master: String, appName: String)SparkContext
  • Loading branch information
retronym committed Apr 7, 2014
1 parent 5720e97 commit c4561c1
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 4 deletions.
10 changes: 10 additions & 0 deletions src/compiler/scala/tools/nsc/ast/TreeInfo.scala
Expand Up @@ -21,13 +21,23 @@ abstract class TreeInfo extends scala.reflect.internal.TreeInfo {

import definitions.ThrowableClass

// TODO these overrides, and the slow trickle of bugs that they solve (e.g. SI-8479),
// suggest that we should pursue an alternative design in which the DocDef nodes
// are eliminated from the tree before typer, and instead are modelled as tree
// attachments.

/** Is tree legal as a member definition of an interface?
*/
override def isInterfaceMember(tree: Tree): Boolean = tree match {
case DocDef(_, definition) => isInterfaceMember(definition)
case _ => super.isInterfaceMember(tree)
}

override def isConstructorWithDefault(t: Tree) = t match {
case DocDef(_, definition) => isConstructorWithDefault(definition)
case _ => super.isConstructorWithDefault(t)
}

/** Is tree a pure (i.e. non-side-effecting) definition?
*/
override def isPureDef(tree: Tree): Boolean = tree match {
Expand Down
5 changes: 1 addition & 4 deletions src/compiler/scala/tools/nsc/typechecker/Namers.scala
Expand Up @@ -663,10 +663,7 @@ trait Namers extends MethodSynthesis {
val m = ensureCompanionObject(tree, caseModuleDef)
m.moduleClass.updateAttachment(new ClassForCaseCompanionAttachment(tree))
}
val hasDefault = impl.body exists {
case DefDef(_, nme.CONSTRUCTOR, _, vparamss, _, _) => mexists(vparamss)(_.mods.hasDefault)
case _ => false
}
val hasDefault = impl.body exists treeInfo.isConstructorWithDefault
if (hasDefault) {
val m = ensureCompanionObject(tree)
m.updateAttachment(new ConstructorDefaultsAttachment(tree, null))
Expand Down
5 changes: 5 additions & 0 deletions src/reflect/scala/reflect/internal/TreeInfo.scala
Expand Up @@ -50,6 +50,11 @@ abstract class TreeInfo {
case _ => false
}

def isConstructorWithDefault(t: Tree) = t match {
case DefDef(_, nme.CONSTRUCTOR, _, vparamss, _, _) => mexists(vparamss)(_.mods.hasDefault)
case _ => false
}

/** Is tree a pure (i.e. non-side-effecting) definition?
*/
def isPureDef(tree: Tree): Boolean = tree match {
Expand Down
1 change: 1 addition & 0 deletions test/scaladoc/run/SI-8479.check
@@ -0,0 +1 @@
Done.
32 changes: 32 additions & 0 deletions test/scaladoc/run/SI-8479.scala
@@ -0,0 +1,32 @@
import scala.tools.nsc.doc.model._
import scala.tools.nsc.doc.base._
import scala.tools.nsc.doc.base.comment._
import scala.tools.partest.ScaladocModelTest
import java.net.{URI, URL}
import java.io.File

object Test extends ScaladocModelTest {

override def code =
"""
|object Test {
| val x = new SparkContext(master = "")
|}
|
|class SparkContext(config: Any) {
|
| /** Scaladoc comment */
| def this(
| master: String,
| appName: String = "") = this(null)
|}
|
|
""".stripMargin

override def scaladocSettings = ""

def testModel(rootPackage: Package) {
// it didn't crash
}
}

0 comments on commit c4561c1

Please sign in to comment.