Skip to content

Commit fa89a96

Browse files
committed
create dummy first constructor for Java classes
The dummy constructor is needed so that the real constructors see the import of the companion object. The constructor has a parameter of type Unit so that no Java code can call it.
1 parent 6fc23da commit fa89a96

File tree

4 files changed

+26
-22
lines changed

4 files changed

+26
-22
lines changed

src/dotty/tools/dotc/parsing/JavaParsers.scala

+26-21
Original file line numberDiff line numberDiff line change
@@ -112,29 +112,34 @@ object JavaParsers {
112112
def makePackaging(pkg: RefTree, stats: List[Tree]): PackageDef =
113113
atPos(pkg.pos) { PackageDef(pkg, stats) }
114114

115-
def makeTemplate(parents: List[Tree], stats: List[Tree], tparams: List[TypeDef]) = {
115+
def makeTemplate(parents: List[Tree], stats: List[Tree], tparams: List[TypeDef], needsDummyConstr: Boolean) = {
116116
def pullOutFirstConstr(stats: List[Tree]): (Tree, List[Tree]) = stats match {
117117
case (meth: DefDef) :: rest if meth.name.isConstructorName => (meth, rest)
118118
case first :: rest =>
119119
val (constr, tail) = pullOutFirstConstr(rest)
120120
(constr, first :: tail)
121121
case nil => (EmptyTree, nil)
122122
}
123-
val (constr, stats1) = pullOutFirstConstr(stats)
124-
val constr1 = if(constr == EmptyTree) makeConstructor(List(), tparams) else constr.asInstanceOf[DefDef]
125-
Template(constr1, parents, EmptyValDef, stats1)
123+
var (constr1, stats1) = pullOutFirstConstr(stats)
124+
if(constr1 == EmptyTree) constr1 = makeConstructor(List(), tparams)
125+
// A dummy first constructor is needed for Java classes so that the real constructors see the
126+
// import of the companion object. The constructor has parameter of type Unit so no Java code
127+
// can call it.
128+
if(needsDummyConstr) {
129+
stats1 = constr1 :: stats1
130+
constr1 = makeConstructor(List(scalaDot(tpnme.Unit)), tparams, Flags.JavaDefined | Flags.PrivateLocal)
131+
}
132+
Template(constr1.asInstanceOf[DefDef], parents, EmptyValDef, stats1)
126133
}
127134

128135
def makeSyntheticParam(count: Int, tpt: Tree): ValDef =
129136
makeParam(nme.syntheticParamName(count), tpt)
130-
def makeParam(name: String, tpt: Tree): ValDef =
131-
makeParam(name.toTermName, tpt)
132-
def makeParam(name: TermName, tpt: Tree, flags: FlagSet = Flags.Param): ValDef =
133-
ValDef(Modifiers(flags | Flags.JavaDefined), name, tpt, EmptyTree)
137+
def makeParam(name: TermName, tpt: Tree): ValDef =
138+
ValDef(Modifiers(Flags.JavaDefined | Flags.PrivateLocalParamAccessor), name, tpt, EmptyTree)
134139

135-
def makeConstructor(formals: List[Tree], tparams: List[TypeDef]) = {
140+
def makeConstructor(formals: List[Tree], tparams: List[TypeDef], flags: FlagSet = Flags.JavaDefined) = {
136141
val vparams = mapWithIndex(formals)((p, i) => makeSyntheticParam(i + 1, p))
137-
DefDef(Modifiers(Flags.JavaDefined), nme.CONSTRUCTOR, tparams, List(vparams), TypeTree(), EmptyTree)
142+
DefDef(Modifiers(flags), nme.CONSTRUCTOR, tparams, List(vparams), TypeTree(), EmptyTree)
138143
}
139144

140145
// ------------- general parsing ---------------------------
@@ -447,7 +452,7 @@ object JavaParsers {
447452
PostfixOp(t, nme.raw.STAR)
448453
}
449454
}
450-
varDecl(Position(in.offset), Modifiers(Flags.JavaDefined | Flags.Param), t, ident().toTermName, dontAddMutable = true)
455+
varDecl(Position(in.offset), Modifiers(Flags.JavaDefined | Flags.Param), t, ident().toTermName)
451456
}
452457

453458
def optThrows(): Unit = {
@@ -571,12 +576,12 @@ object JavaParsers {
571576
buf.toList
572577
}
573578

574-
def varDecl(pos: Position, mods: Modifiers, tpt: Tree, name: TermName, dontAddMutable: Boolean = false): ValDef = {
579+
def varDecl(pos: Position, mods: Modifiers, tpt: Tree, name: TermName): ValDef = {
575580
val tpt1 = optArrayBrackets(tpt)
576581
if (in.token == EQUALS && !(mods is Flags.Param)) skipTo(COMMA, SEMI)
577-
val mods1 = if (mods is Flags.Final) mods &~ Flags.Final else if(dontAddMutable) mods else mods | Flags.Mutable
582+
val mods1 = if(mods is Flags.Final) mods else mods | Flags.Mutable
578583
atPos(pos) {
579-
ValDef(mods1, name, tpt1, EmptyTree)
584+
ValDef(mods1, name, tpt1, if(mods is Flags.Param) EmptyTree else unimplementedExpr)
580585
}
581586
}
582587

@@ -590,7 +595,7 @@ object JavaParsers {
590595
def makeCompanionObject(cdef: TypeDef, statics: List[Tree]): Tree =
591596
atPos(cdef.pos) {
592597
ModuleDef((cdef.mods & (Flags.AccessFlags | Flags.JavaDefined)).toTermFlags, cdef.name.toTermName,
593-
makeTemplate(List(), statics, List()))
598+
makeTemplate(List(), statics, List(), false))
594599
}
595600

596601
private val wild = Ident(nme.WILDCARD) withPos Position(-1)
@@ -689,7 +694,7 @@ object JavaParsers {
689694
val interfaces = interfacesOpt()
690695
val (statics, body) = typeBody(CLASS, name, tparams)
691696
addCompanionObject(statics, atPos(offset) {
692-
TypeDef(mods, name, makeTemplate(superclass :: interfaces, body, tparams))
697+
TypeDef(mods, name, makeTemplate(superclass :: interfaces, body, tparams, true))
693698
})
694699
}
695700

@@ -709,7 +714,7 @@ object JavaParsers {
709714
addCompanionObject(statics, atPos(offset) {
710715
TypeDef(mods | Flags.Trait | Flags.Interface | Flags.Abstract,
711716
name, tparams,
712-
makeTemplate(parents, body, tparams))
717+
makeTemplate(parents, body, tparams, false))
713718
})
714719
}
715720

@@ -763,12 +768,12 @@ object JavaParsers {
763768
val name = identForType()
764769
val (statics, body) = typeBody(AT, name, List())
765770
val constructorParams = body.collect {
766-
case dd: DefDef => makeParam(dd.name, dd.tpt, Flags.PrivateLocalParamAccessor)
771+
case dd: DefDef => makeParam(dd.name, dd.tpt)
767772
}
768773
val constr = DefDef(Modifiers(Flags.JavaDefined), nme.CONSTRUCTOR,
769774
List(), List(constructorParams), TypeTree(), EmptyTree)
770775
val body1 = body.filterNot(_.isInstanceOf[DefDef])
771-
val templ = makeTemplate(annotationParents, constr :: body1, List())
776+
val templ = makeTemplate(annotationParents, constr :: body1, List(), false)
772777
addCompanionObject(statics, atPos(offset) {
773778
TypeDef(mods | Flags.Abstract, name, templ)
774779
})
@@ -808,7 +813,7 @@ object JavaParsers {
808813
unimplementedExpr),
809814
DefDef(
810815
Modifiers(Flags.JavaDefined | Flags.JavaStatic | Flags.Method), nme.valueOf, List(),
811-
List(List(makeParam("x", TypeTree(StringType)))),
816+
List(List(makeParam("x".toTermName, TypeTree(StringType)))),
812817
enumType,
813818
unimplementedExpr))
814819
accept(RBRACE)
@@ -821,7 +826,7 @@ object JavaParsers {
821826
List(Literal(Constant(null)),Literal(Constant(0))))
822827
addCompanionObject(consts ::: statics ::: predefs, atPos(offset) {
823828
TypeDef(mods | Flags.Enum, name, List(),
824-
makeTemplate(superclazz :: interfaces, body, List()))
829+
makeTemplate(superclazz :: interfaces, body, List(), true))
825830
})
826831
}
827832

test/dotc/tests.scala

-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ class tests extends CompilerTest {
135135
val javaDir = "./tests/disabled/java-interop/"
136136
@Test def java_all = compileFiles(javaDir+"pos/")
137137

138-
@Test def java_2409 = compileDir(javaDir+"failing/t2409")
139138
@Test def java_1751 = compileDir(javaDir+"failing/t1751")
140139
@Test def java_294 = compileDir(javaDir+"failing/t294")
141140

0 commit comments

Comments
 (0)