Skip to content

Commit 04d6598

Browse files
committed
restore print test for java tasty.
Also do not make a fake param accessor for the fake param of the fake constructor.
1 parent de2e8e6 commit 04d6598

File tree

6 files changed

+84
-53
lines changed

6 files changed

+84
-53
lines changed

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
510510
def scalaRuntimeDot(name: Name)(using SourceFile): Select = Select(scalaDot(nme.runtime), name)
511511
def scalaUnit(implicit src: SourceFile): Select = scalaDot(tpnme.Unit)
512512
def scalaAny(implicit src: SourceFile): Select = scalaDot(tpnme.Any)
513-
def javaDotLangDot(name: Name)(implicit src: SourceFile): Select = Select(Select(Ident(nme.java), nme.lang), name)
514513

515514
def captureRoot(using Context): Select =
516515
Select(scalaDot(nme.caps), nme.CAPTURE_ROOT)

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,37 +1069,37 @@ class TreeUnpickler(reader: TastyReader,
10691069
selfInfo = if (self.isEmpty) NoType else self.tpt.tpe
10701070
).integrateOpaqueMembers
10711071

1072-
val (constr, stats0) =
1072+
val constr =
10731073
if nextByte == SPLITCLAUSE then
10741074
assert(unpicklingJava, s"unexpected SPLITCLAUSE at $start")
10751075
val tag = readByte()
10761076
def ta = ctx.typeAssigner
10771077
val flags = Flags.JavaDefined | Flags.PrivateLocal | Flags.Invisible
1078-
val pflags = Flags.JavaDefined | Flags.Param
1079-
val tdefRefs = tparams.map(_.symbol.asType)
10801078
val ctorCompleter = new LazyType {
10811079
def complete(denot: SymDenotation)(using Context) =
10821080
val sym = denot.symbol
1083-
lazy val tparamSyms: List[TypeSymbol] = tparams.map: tdef =>
1081+
val pflags = flags | Flags.Param
1082+
val tparamRefs = tparams.map(_.symbol.asType)
1083+
lazy val derivedTparamSyms: List[TypeSymbol] = tparams.map: tdef =>
10841084
val completer = new LazyType {
10851085
def complete(denot: SymDenotation)(using Context) =
1086-
denot.info = tdef.symbol.asType.info.subst(tdefRefs, tparamSyms.map(_.typeRef))
1086+
denot.info = tdef.symbol.asType.info.subst(tparamRefs, derivedTparamRefs)
10871087
}
1088-
newSymbol(sym, tdef.name, pflags, completer, coord = cls.coord)
1089-
val paramSym =
1088+
newSymbol(sym, tdef.name, Flags.JavaDefined | Flags.Param, completer, coord = cls.coord)
1089+
lazy val derivedTparamRefs: List[Type] = derivedTparamSyms.map(_.typeRef)
1090+
val vparamSym =
10901091
newSymbol(sym, nme.syntheticParamName(1), pflags, defn.UnitType, coord = cls.coord)
1091-
val paramSymss = tparamSyms :: List(paramSym) :: Nil
1092+
val vparamSymss: List[List[Symbol]] = List(vparamSym) :: Nil
1093+
val paramSymss =
1094+
if derivedTparamSyms.nonEmpty then derivedTparamSyms :: vparamSymss else vparamSymss
10921095
val res = effectiveResultType(sym, paramSymss)
10931096
denot.info = methodType(paramSymss, res)
10941097
denot.setParamss(paramSymss)
10951098
}
10961099
val ctorSym = newSymbol(ctx.owner, nme.CONSTRUCTOR, flags, ctorCompleter, coord = coordAt(start))
1097-
val accSym = newSymbol(cls, nme.syntheticParamName(1), flags, defn.UnitType, coord = ctorSym.coord)
1098-
val ctorDef = tpd.DefDef(ctorSym, EmptyTree)
1099-
val accessor = tpd.ValDef(accSym, ElidedTree(accSym.info))
1100-
(ctorDef.setDefTree, accessor.setDefTree :: Nil)
1100+
tpd.DefDef(ctorSym, EmptyTree).setDefTree // fake primary constructor
11011101
else
1102-
readIndexedDef().asInstanceOf[DefDef] -> Nil
1102+
readIndexedDef().asInstanceOf[DefDef]
11031103
val mappedParents: LazyTreeList =
11041104
if parents.exists(_.isInstanceOf[InferredTypeTree]) then
11051105
// parents were not read fully, will need to be read again later on demand
@@ -1110,7 +1110,7 @@ class TreeUnpickler(reader: TastyReader,
11101110

11111111
val lazyStats = readLater(end, rdr => {
11121112
val stats = rdr.readIndexedStats(localDummy, end)
1113-
tparams ++ vparams ++ stats0 ++ stats
1113+
tparams ++ vparams ++ stats
11141114
})
11151115
defn.patchStdLibClass(cls)
11161116
NamerOps.addConstructorProxies(cls)

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

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Scanners.Offset
1212
import Parsers.*
1313
import core.*
1414
import Contexts.*
15+
import Symbols.defn
1516
import Names.*
1617
import Types.*
1718
import ast.Trees.*
@@ -22,11 +23,15 @@ import dotty.tools.dotc.util.SourceFile
2223
import util.Spans.*
2324

2425
import scala.collection.mutable.{ListBuffer, LinkedHashMap}
26+
import dotty.tools.dotc.ast.untpd
2527

2628
object JavaParsers {
2729

2830
import ast.untpd.*
2931

32+
33+
val fakeFlags = Flags.JavaDefined | Flags.PrivateLocal | Flags.Invisible
34+
3035
class JavaParser(source: SourceFile)(using Context) extends ParserCommon(source) {
3136

3237
val definitions: Definitions = ctx.definitions
@@ -89,16 +94,16 @@ object JavaParsers {
8994

9095
// --------- tree building -----------------------------
9196

92-
def scalaAnnotationDot(name: Name): Select = Select(scalaDot(nme.annotation), name)
93-
9497
def javaDot(name: Name): Tree =
9598
Select(rootDot(nme.java), name)
9699

97100
def javaLangDot(name: Name): Tree =
98101
Select(javaDot(nme.lang), name)
99102

100-
/** Tree representing `java.lang.Object` */
101-
def javaLangObject(): Tree = javaLangDot(tpnme.Object)
103+
/** Synthetic tree representing `java.lang.Object`.
104+
* The typer will type all references to `java.lang.Object` as `FromJavaObject`.
105+
*/
106+
def ObjectTpt(): Tree = TypeTree(defn.FromJavaObjectType) // javaLangDot(tpnme.Object)
102107

103108
/** Tree representing `java.lang.Record` */
104109
def javaLangRecord(): Tree = javaLangDot(tpnme.Record)
@@ -107,6 +112,8 @@ object JavaParsers {
107112
AppliedTypeTree(scalaDot(tpnme.Array), List(tpt))
108113

109114
def makeTemplate(parents: List[Tree], stats: List[Tree], tparams: List[TypeDef], needsDummyConstr: Boolean): Template = {
115+
def UnitTpt(): Tree = TypeTree(defn.UnitType)
116+
110117
def pullOutFirstConstr(stats: List[Tree]): (Tree, List[Tree]) = stats match {
111118
case (meth: DefDef) :: rest if meth.name == nme.CONSTRUCTOR => (meth, rest)
112119
case first :: rest =>
@@ -120,10 +127,9 @@ object JavaParsers {
120127
// can call it.
121128
// This also avoids clashes between the constructor parameter names and member names.
122129
if (needsDummyConstr) {
123-
val fakeFlags = Flags.JavaDefined | Flags.PrivateLocal | Flags.Invisible
124130
if (constr1 == EmptyTree) constr1 = makeConstructor(List(), Nil, Parsers.unimplementedExpr)
125131
stats1 = constr1 :: stats1
126-
constr1 = makeConstructor(List(scalaDot(tpnme.Unit)), tparams, EmptyTree, fakeFlags)
132+
constr1 = makeConstructor(List(UnitTpt()), tparams, EmptyTree, fakeFlags)
127133
}
128134
else if (constr1 == EmptyTree) {
129135
constr1 = makeConstructor(List(), tparams, EmptyTree)
@@ -134,11 +140,11 @@ object JavaParsers {
134140
def makeSyntheticParam(count: Int, tpt: Tree): ValDef =
135141
makeParam(nme.syntheticParamName(count), tpt)
136142
def makeParam(name: TermName, tpt: Tree): ValDef =
137-
ValDef(name, tpt, EmptyTree).withMods(Modifiers(Flags.JavaDefined | Flags.Param))
143+
ValDef(name, tpt, EmptyTree).withFlags(Flags.JavaDefined | Flags.Param)
138144

139145
def makeConstructor(formals: List[Tree], tparams: List[TypeDef], body: Tree, flags: FlagSet = Flags.JavaDefined): DefDef = {
140-
val vparams = formals.zipWithIndex.map { case (p, i) => makeSyntheticParam(i + 1, p).withMods(Modifiers(flags)) }
141-
DefDef(nme.CONSTRUCTOR, joinParams(tparams, List(vparams)), TypeTree(), body).withMods(Modifiers(flags))
146+
val vparams = formals.zipWithIndex.map { case (p, i) => makeSyntheticParam(i + 1, p).withAddedFlags(flags) }
147+
DefDef(nme.CONSTRUCTOR, joinParams(tparams, List(vparams)), TypeTree(), body).withFlags(flags)
142148
}
143149

144150
// ------------- general parsing ---------------------------
@@ -307,7 +313,7 @@ object JavaParsers {
307313
if (in.token == QMARK) {
308314
val offset = in.offset
309315
in.nextToken()
310-
val hi = if (in.token == EXTENDS) { in.nextToken() ; typ() } else javaLangObject()
316+
val hi = if (in.token == EXTENDS) { in.nextToken() ; typ() } else ObjectTpt()
311317
val lo = if (in.token == SUPER) { in.nextToken() ; typ() } else EmptyTree
312318
atSpan(offset) {
313319
/*
@@ -508,7 +514,7 @@ object JavaParsers {
508514
atSpan(in.offset) {
509515
annotations()
510516
val name = identForType()
511-
val hi = if (in.token == EXTENDS) { in.nextToken() ; bound() } else javaLangObject()
517+
val hi = if (in.token == EXTENDS) { in.nextToken() ; bound() } else ObjectTpt()
512518
TypeDef(name, TypeBoundsTree(EmptyTree, hi)).withMods(Modifiers(flags))
513519
}
514520

@@ -569,7 +575,7 @@ object JavaParsers {
569575
if in.token == IDENTIFIER && in.name == jnme.RECORDid then
570576
in.token = RECORD
571577

572-
def termDecl(start: Offset, mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = {
578+
def termDecl(start: Offset, mods: Modifiers, parentToken: Int): List[Tree] = {
573579
val inInterface = definesInterface(parentToken)
574580
val tparams = if (in.token == LT) typeParams(Flags.JavaDefined | Flags.Param) else List()
575581
val isVoid = in.token == VOID
@@ -741,11 +747,11 @@ object JavaParsers {
741747
ValDef(name, tpt2, if (mods.is(Flags.Param)) EmptyTree else unimplementedExpr).withMods(mods1)
742748
}
743749

744-
def memberDecl(start: Offset, mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = in.token match
750+
def memberDecl(start: Offset, mods: Modifiers, parentToken: Int): List[Tree] = in.token match
745751
case CLASS | ENUM | RECORD | INTERFACE | AT =>
746752
typeDecl(start, if definesInterface(parentToken) then mods | Flags.JavaStatic else mods)
747753
case _ =>
748-
termDecl(start, mods, parentToken, parentTParams)
754+
termDecl(start, mods, parentToken)
749755

750756
def makeCompanionObject(cdef: TypeDef, statics: List[Tree]): Tree =
751757
atSpan(cdef.span) {
@@ -818,9 +824,9 @@ object JavaParsers {
818824
typ()
819825
}
820826
else
821-
javaLangObject()
827+
ObjectTpt()
822828
val interfaces = interfacesOpt()
823-
val (statics, body) = typeBody(CLASS, name, tparams)
829+
val (statics, body) = typeBody(CLASS, name)
824830
val cls = atSpan(start, nameOffset) {
825831
TypeDef(name, makeTemplate(superclass :: interfaces, body, tparams, needsDummyConstr = true)).withMods(mods)
826832
}
@@ -835,7 +841,7 @@ object JavaParsers {
835841
val header = formalParams()
836842
val superclass = javaLangRecord() // records always extend java.lang.Record
837843
val interfaces = interfacesOpt() // records may implement interfaces
838-
val (statics, body) = typeBody(RECORD, name, tparams)
844+
val (statics, body) = typeBody(RECORD, name)
839845

840846
// We need to generate accessors for every param, if no method with the same name is already defined
841847

@@ -883,8 +889,8 @@ object JavaParsers {
883889
repsep(() => typ(), COMMA)
884890
}
885891
else
886-
List(javaLangObject())
887-
val (statics, body) = typeBody(INTERFACE, name, tparams)
892+
List(ObjectTpt())
893+
val (statics, body) = typeBody(INTERFACE, name)
888894
val iface = atSpan(start, nameOffset) {
889895
TypeDef(
890896
name,
@@ -893,14 +899,14 @@ object JavaParsers {
893899
addCompanionObject(statics, iface)
894900
}
895901

896-
def typeBody(leadingToken: Int, parentName: Name, parentTParams: List[TypeDef]): (List[Tree], List[Tree]) = {
902+
def typeBody(leadingToken: Int, parentName: Name): (List[Tree], List[Tree]) = {
897903
accept(LBRACE)
898-
val defs = typeBodyDecls(leadingToken, parentName, parentTParams)
904+
val defs = typeBodyDecls(leadingToken, parentName)
899905
accept(RBRACE)
900906
defs
901907
}
902908

903-
def typeBodyDecls(parentToken: Int, parentName: Name, parentTParams: List[TypeDef]): (List[Tree], List[Tree]) = {
909+
def typeBodyDecls(parentToken: Int, parentName: Name): (List[Tree], List[Tree]) = {
904910
val inInterface = definesInterface(parentToken)
905911
val statics = new ListBuffer[Tree]
906912
val members = new ListBuffer[Tree]
@@ -916,7 +922,7 @@ object JavaParsers {
916922
else {
917923
adaptRecordIdentifier()
918924
if (in.token == ENUM || in.token == RECORD || definesInterface(in.token)) mods |= Flags.JavaStatic
919-
val decls = memberDecl(start, mods, parentToken, parentTParams)
925+
val decls = memberDecl(start, mods, parentToken)
920926
(if (mods.is(Flags.JavaStatic) || inInterface && !(decls exists (_.isInstanceOf[DefDef])))
921927
statics
922928
else
@@ -926,15 +932,15 @@ object JavaParsers {
926932
(statics.toList, members.toList)
927933
}
928934
def annotationParents: List[Tree] = List(
929-
javaLangObject(),
935+
ObjectTpt(),
930936
Select(javaLangDot(nme.annotation), tpnme.Annotation)
931937
)
932938
def annotationDecl(start: Offset, mods: Modifiers): List[Tree] = {
933939
accept(AT)
934940
accept(INTERFACE)
935941
val nameOffset = in.offset
936942
val name = identForType()
937-
val (statics, body) = typeBody(AT, name, List())
943+
val (statics, body) = typeBody(AT, name)
938944
val constructorParams = body.collect {
939945
case dd: DefDef =>
940946
makeParam(dd.name, dd.tpt)
@@ -969,7 +975,7 @@ object JavaParsers {
969975
val (statics, body) =
970976
if (in.token == SEMI) {
971977
in.nextToken()
972-
typeBodyDecls(ENUM, name, List())
978+
typeBodyDecls(ENUM, name)
973979
}
974980
else
975981
(List(), List())
@@ -1093,7 +1099,7 @@ object JavaParsers {
10931099
*/
10941100
class OutlineJavaParser(source: SourceFile)(using Context) extends JavaParser(source) with OutlineParserCommon {
10951101
override def skipBracesHook(): Option[Tree] = None
1096-
override def typeBody(leadingToken: Int, parentName: Name, parentTParams: List[TypeDef]): (List[Tree], List[Tree]) = {
1102+
override def typeBody(leadingToken: Int, parentName: Name): (List[Tree], List[Tree]) = {
10971103
skipBraces()
10981104
(List(EmptyValDef), List(EmptyTree))
10991105
}

compiler/src/dotty/tools/dotc/printing/OutlinePrinter.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ object OutlinePrinter:
2121
*/
2222
class OutlinePrinter private (_ctx: Context) extends RefinedPrinter(_ctx) {
2323

24+
/** print the symbol infos of type params for the fake java constructor */
25+
def shouldShowInfo(tsym: Symbol): Boolean =
26+
tsym != NoSymbol && {
27+
val ctor = tsym.owner
28+
ctor.isAllOf(JavaDefined | PrivateLocal | Invisible) && ctor.isConstructor
29+
}
30+
31+
override def paramsText[T <: Untyped](params: ParamClause[T]): Text = (params: @unchecked) match
32+
case untpd.TypeDefs(tparams) if shouldShowInfo(tparams.head.symbol) =>
33+
"[" ~ toText(tparams.map(_.symbol.info), ", ") ~ "]"
34+
case _ => super.paramsText(params)
35+
2436
/* Typical patterns seen in output of typer for Java code, plus the output of unpickling an ELIDED tree */
2537
def isElidableExpr[T <: Untyped](tree: Tree[T]): Boolean = tree match {
2638
case tree if tree.isEmpty => false

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import config.{Config, Feature}
2828
import dotty.tools.dotc.util.SourcePosition
2929
import dotty.tools.dotc.ast.untpd.{MemberDef, Modifiers, PackageDef, RefTree, Template, TypeDef, ValOrDefDef}
3030
import cc.{CaptureSet, CapturingType, toCaptureSet, IllegalCaptureRef}
31+
import dotty.tools.dotc.parsing.JavaParsers
3132

3233
class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
3334

@@ -1015,10 +1016,18 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
10151016
val (params, rest) = impl.body partition {
10161017
case stat: TypeDef => stat.symbol.is(Param)
10171018
case stat: ValOrDefDef =>
1018-
stat.symbol.is(ParamAccessor) && !stat.symbol.isSetter
1019+
val sym = stat.symbol
1020+
sym.is(ParamAccessor) && !sym.isSetter
1021+
|| sym.isAllOf(JavaParsers.fakeFlags | Param)
10191022
case _ => false
10201023
}
1021-
params ::: rest
1024+
val params0 =
1025+
if constr.symbol.isAllOf(JavaParsers.fakeFlags) then
1026+
// filter out fake param accessors
1027+
params.filterNot(_.symbol.isAllOf(JavaParsers.fakeFlags | Param))
1028+
else
1029+
params
1030+
params0 ::: rest
10221031
}
10231032
else impl.body
10241033

compiler/src/dotty/tools/dotc/transform/Pickler.scala

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ class Pickler extends Phase {
8787
Pickler.ParallelPickling && !ctx.settings.YtestPickler.value &&
8888
!ctx.settings.YjavaTasty.value // disable parallel pickling when `-Yjava-tasty` is set (internal testing only)
8989

90+
private def printerContext(isOutline: Boolean)(using Context): Context =
91+
if isOutline then ctx.fresh.setPrinterFn(OutlinePrinter(_))
92+
else ctx
93+
9094
override def run(using Context): Unit = {
9195
val unit = ctx.compilationUnit
9296
pickling.println(i"unpickling in run ${ctx.runId}")
@@ -95,7 +99,8 @@ class Pickler extends Phase {
9599
cls <- dropCompanionModuleClasses(topLevelClasses(unit.tpdTree))
96100
tree <- sliceTopLevel(unit.tpdTree, cls)
97101
do
98-
if ctx.settings.YtestPickler.value then beforePickling(cls) = tree.show
102+
if ctx.settings.YtestPickler.value then beforePickling(cls) =
103+
tree.show(using printerContext(unit.typedAsJava))
99104

100105
val sourceRelativePath =
101106
val reference = ctx.settings.sourceroot.value
@@ -243,16 +248,16 @@ class Pickler extends Phase {
243248
pickling.println("************* entered toplevel ***********")
244249
val rootCtx = ctx
245250
for ((cls, (unit, unpickler)) <- unpicklers) do
246-
if unit.typedAsJava then
251+
val testJava = unit.typedAsJava
252+
if testJava then
247253
if unpickler.unpickler.nameAtRef.contents.exists(_ == nme.FromJavaObject) then
248254
report.error(em"Pickled reference to FromJavaObject in Java defined $cls in ${cls.source}")
249-
else
250-
val unpickled = unpickler.rootTrees
251-
val freshUnit = CompilationUnit(rootCtx.compilationUnit.source)
252-
freshUnit.needsCaptureChecking = unit.needsCaptureChecking
253-
freshUnit.knowsPureFuns = unit.knowsPureFuns
254-
inContext(rootCtx.fresh.setCompilationUnit(freshUnit)):
255-
testSame(i"$unpickled%\n%", beforePickling(cls), cls)
255+
val unpickled = unpickler.rootTrees
256+
val freshUnit = CompilationUnit(rootCtx.compilationUnit.source)
257+
freshUnit.needsCaptureChecking = unit.needsCaptureChecking
258+
freshUnit.knowsPureFuns = unit.knowsPureFuns
259+
inContext(printerContext(testJava)(using rootCtx.fresh.setCompilationUnit(freshUnit))):
260+
testSame(i"$unpickled%\n%", beforePickling(cls), cls)
256261

257262
private def testSame(unpickled: String, previous: String, cls: ClassSymbol)(using Context) =
258263
import java.nio.charset.StandardCharsets.UTF_8

0 commit comments

Comments
 (0)