Skip to content

Commit e1d9ea4

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 e1d9ea4

File tree

6 files changed

+83
-53
lines changed

6 files changed

+83
-53
lines changed

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

-1
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

+14-14
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

+32-27
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.*
@@ -27,6 +28,9 @@ object JavaParsers {
2728

2829
import ast.untpd.*
2930

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

3236
val definitions: Definitions = ctx.definitions
@@ -89,16 +93,16 @@ object JavaParsers {
8993

9094
// --------- tree building -----------------------------
9195

92-
def scalaAnnotationDot(name: Name): Select = Select(scalaDot(nme.annotation), name)
93-
9496
def javaDot(name: Name): Tree =
9597
Select(rootDot(nme.java), name)
9698

9799
def javaLangDot(name: Name): Tree =
98100
Select(javaDot(nme.lang), name)
99101

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

103107
/** Tree representing `java.lang.Record` */
104108
def javaLangRecord(): Tree = javaLangDot(tpnme.Record)
@@ -107,6 +111,8 @@ object JavaParsers {
107111
AppliedTypeTree(scalaDot(tpnme.Array), List(tpt))
108112

109113
def makeTemplate(parents: List[Tree], stats: List[Tree], tparams: List[TypeDef], needsDummyConstr: Boolean): Template = {
114+
def UnitTpt(): Tree = TypeTree(defn.UnitType)
115+
110116
def pullOutFirstConstr(stats: List[Tree]): (Tree, List[Tree]) = stats match {
111117
case (meth: DefDef) :: rest if meth.name == nme.CONSTRUCTOR => (meth, rest)
112118
case first :: rest =>
@@ -120,10 +126,9 @@ object JavaParsers {
120126
// can call it.
121127
// This also avoids clashes between the constructor parameter names and member names.
122128
if (needsDummyConstr) {
123-
val fakeFlags = Flags.JavaDefined | Flags.PrivateLocal | Flags.Invisible
124129
if (constr1 == EmptyTree) constr1 = makeConstructor(List(), Nil, Parsers.unimplementedExpr)
125130
stats1 = constr1 :: stats1
126-
constr1 = makeConstructor(List(scalaDot(tpnme.Unit)), tparams, EmptyTree, fakeFlags)
131+
constr1 = makeConstructor(List(UnitTpt()), tparams, EmptyTree, fakeFlags)
127132
}
128133
else if (constr1 == EmptyTree) {
129134
constr1 = makeConstructor(List(), tparams, EmptyTree)
@@ -134,11 +139,11 @@ object JavaParsers {
134139
def makeSyntheticParam(count: Int, tpt: Tree): ValDef =
135140
makeParam(nme.syntheticParamName(count), tpt)
136141
def makeParam(name: TermName, tpt: Tree): ValDef =
137-
ValDef(name, tpt, EmptyTree).withMods(Modifiers(Flags.JavaDefined | Flags.Param))
142+
ValDef(name, tpt, EmptyTree).withFlags(Flags.JavaDefined | Flags.Param)
138143

139144
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))
145+
val vparams = formals.zipWithIndex.map { case (p, i) => makeSyntheticParam(i + 1, p).withAddedFlags(flags) }
146+
DefDef(nme.CONSTRUCTOR, joinParams(tparams, List(vparams)), TypeTree(), body).withFlags(flags)
142147
}
143148

144149
// ------------- general parsing ---------------------------
@@ -307,7 +312,7 @@ object JavaParsers {
307312
if (in.token == QMARK) {
308313
val offset = in.offset
309314
in.nextToken()
310-
val hi = if (in.token == EXTENDS) { in.nextToken() ; typ() } else javaLangObject()
315+
val hi = if (in.token == EXTENDS) { in.nextToken() ; typ() } else ObjectTpt()
311316
val lo = if (in.token == SUPER) { in.nextToken() ; typ() } else EmptyTree
312317
atSpan(offset) {
313318
/*
@@ -508,7 +513,7 @@ object JavaParsers {
508513
atSpan(in.offset) {
509514
annotations()
510515
val name = identForType()
511-
val hi = if (in.token == EXTENDS) { in.nextToken() ; bound() } else javaLangObject()
516+
val hi = if (in.token == EXTENDS) { in.nextToken() ; bound() } else ObjectTpt()
512517
TypeDef(name, TypeBoundsTree(EmptyTree, hi)).withMods(Modifiers(flags))
513518
}
514519

@@ -569,7 +574,7 @@ object JavaParsers {
569574
if in.token == IDENTIFIER && in.name == jnme.RECORDid then
570575
in.token = RECORD
571576

572-
def termDecl(start: Offset, mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = {
577+
def termDecl(start: Offset, mods: Modifiers, parentToken: Int): List[Tree] = {
573578
val inInterface = definesInterface(parentToken)
574579
val tparams = if (in.token == LT) typeParams(Flags.JavaDefined | Flags.Param) else List()
575580
val isVoid = in.token == VOID
@@ -741,11 +746,11 @@ object JavaParsers {
741746
ValDef(name, tpt2, if (mods.is(Flags.Param)) EmptyTree else unimplementedExpr).withMods(mods1)
742747
}
743748

744-
def memberDecl(start: Offset, mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = in.token match
749+
def memberDecl(start: Offset, mods: Modifiers, parentToken: Int): List[Tree] = in.token match
745750
case CLASS | ENUM | RECORD | INTERFACE | AT =>
746751
typeDecl(start, if definesInterface(parentToken) then mods | Flags.JavaStatic else mods)
747752
case _ =>
748-
termDecl(start, mods, parentToken, parentTParams)
753+
termDecl(start, mods, parentToken)
749754

750755
def makeCompanionObject(cdef: TypeDef, statics: List[Tree]): Tree =
751756
atSpan(cdef.span) {
@@ -818,9 +823,9 @@ object JavaParsers {
818823
typ()
819824
}
820825
else
821-
javaLangObject()
826+
ObjectTpt()
822827
val interfaces = interfacesOpt()
823-
val (statics, body) = typeBody(CLASS, name, tparams)
828+
val (statics, body) = typeBody(CLASS, name)
824829
val cls = atSpan(start, nameOffset) {
825830
TypeDef(name, makeTemplate(superclass :: interfaces, body, tparams, needsDummyConstr = true)).withMods(mods)
826831
}
@@ -835,7 +840,7 @@ object JavaParsers {
835840
val header = formalParams()
836841
val superclass = javaLangRecord() // records always extend java.lang.Record
837842
val interfaces = interfacesOpt() // records may implement interfaces
838-
val (statics, body) = typeBody(RECORD, name, tparams)
843+
val (statics, body) = typeBody(RECORD, name)
839844

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

@@ -883,8 +888,8 @@ object JavaParsers {
883888
repsep(() => typ(), COMMA)
884889
}
885890
else
886-
List(javaLangObject())
887-
val (statics, body) = typeBody(INTERFACE, name, tparams)
891+
List(ObjectTpt())
892+
val (statics, body) = typeBody(INTERFACE, name)
888893
val iface = atSpan(start, nameOffset) {
889894
TypeDef(
890895
name,
@@ -893,14 +898,14 @@ object JavaParsers {
893898
addCompanionObject(statics, iface)
894899
}
895900

896-
def typeBody(leadingToken: Int, parentName: Name, parentTParams: List[TypeDef]): (List[Tree], List[Tree]) = {
901+
def typeBody(leadingToken: Int, parentName: Name): (List[Tree], List[Tree]) = {
897902
accept(LBRACE)
898-
val defs = typeBodyDecls(leadingToken, parentName, parentTParams)
903+
val defs = typeBodyDecls(leadingToken, parentName)
899904
accept(RBRACE)
900905
defs
901906
}
902907

903-
def typeBodyDecls(parentToken: Int, parentName: Name, parentTParams: List[TypeDef]): (List[Tree], List[Tree]) = {
908+
def typeBodyDecls(parentToken: Int, parentName: Name): (List[Tree], List[Tree]) = {
904909
val inInterface = definesInterface(parentToken)
905910
val statics = new ListBuffer[Tree]
906911
val members = new ListBuffer[Tree]
@@ -916,7 +921,7 @@ object JavaParsers {
916921
else {
917922
adaptRecordIdentifier()
918923
if (in.token == ENUM || in.token == RECORD || definesInterface(in.token)) mods |= Flags.JavaStatic
919-
val decls = memberDecl(start, mods, parentToken, parentTParams)
924+
val decls = memberDecl(start, mods, parentToken)
920925
(if (mods.is(Flags.JavaStatic) || inInterface && !(decls exists (_.isInstanceOf[DefDef])))
921926
statics
922927
else
@@ -926,15 +931,15 @@ object JavaParsers {
926931
(statics.toList, members.toList)
927932
}
928933
def annotationParents: List[Tree] = List(
929-
javaLangObject(),
934+
ObjectTpt(),
930935
Select(javaLangDot(nme.annotation), tpnme.Annotation)
931936
)
932937
def annotationDecl(start: Offset, mods: Modifiers): List[Tree] = {
933938
accept(AT)
934939
accept(INTERFACE)
935940
val nameOffset = in.offset
936941
val name = identForType()
937-
val (statics, body) = typeBody(AT, name, List())
942+
val (statics, body) = typeBody(AT, name)
938943
val constructorParams = body.collect {
939944
case dd: DefDef =>
940945
makeParam(dd.name, dd.tpt)
@@ -969,7 +974,7 @@ object JavaParsers {
969974
val (statics, body) =
970975
if (in.token == SEMI) {
971976
in.nextToken()
972-
typeBodyDecls(ENUM, name, List())
977+
typeBodyDecls(ENUM, name)
973978
}
974979
else
975980
(List(), List())
@@ -1093,7 +1098,7 @@ object JavaParsers {
10931098
*/
10941099
class OutlineJavaParser(source: SourceFile)(using Context) extends JavaParser(source) with OutlineParserCommon {
10951100
override def skipBracesHook(): Option[Tree] = None
1096-
override def typeBody(leadingToken: Int, parentName: Name, parentTParams: List[TypeDef]): (List[Tree], List[Tree]) = {
1101+
override def typeBody(leadingToken: Int, parentName: Name): (List[Tree], List[Tree]) = {
10971102
skipBraces()
10981103
(List(EmptyValDef), List(EmptyTree))
10991104
}

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

+12
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

+11-2
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

+14-9
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)