@@ -98,6 +98,8 @@ object JavaParsers {
98
98
99
99
def javaLangObject (): Tree = javaLangDot(tpnme.Object )
100
100
101
+ def javaLangRecord (): Tree = javaLangDot(tpnme.Record )
102
+
101
103
def arrayOf (tpt : Tree ): AppliedTypeTree =
102
104
AppliedTypeTree (scalaDot(tpnme.Array ), List (tpt))
103
105
@@ -555,6 +557,10 @@ object JavaParsers {
555
557
556
558
def definesInterface (token : Int ): Boolean = token == INTERFACE || token == AT
557
559
560
+ def adaptRecordIdentifier (): Unit =
561
+ if in.token == IDENTIFIER && in.name == jnme.RECORDid then
562
+ in.token = RECORD
563
+
558
564
def termDecl (start : Offset , mods : Modifiers , parentToken : Int , parentTParams : List [TypeDef ]): List [Tree ] = {
559
565
val inInterface = definesInterface(parentToken)
560
566
val tparams = if (in.token == LT ) typeParams(Flags .JavaDefined | Flags .Param ) else List ()
@@ -581,6 +587,16 @@ object JavaParsers {
581
587
TypeTree (), methodBody()).withMods(mods)
582
588
}
583
589
}
590
+ } else if (in.token == LBRACE && rtptName != nme.EMPTY && parentToken == RECORD ) {
591
+ /*
592
+ record RecordName(T param1, ...) {
593
+ RecordName { // <- here
594
+ // methodBody
595
+ }
596
+ }
597
+ */
598
+ methodBody()
599
+ Nil
584
600
}
585
601
else {
586
602
var mods1 = mods
@@ -717,12 +733,11 @@ object JavaParsers {
717
733
ValDef (name, tpt2, if (mods.is(Flags .Param )) EmptyTree else unimplementedExpr).withMods(mods1)
718
734
}
719
735
720
- def memberDecl (start : Offset , mods : Modifiers , parentToken : Int , parentTParams : List [TypeDef ]): List [Tree ] = in.token match {
721
- case CLASS | ENUM | INTERFACE | AT =>
736
+ def memberDecl (start : Offset , mods : Modifiers , parentToken : Int , parentTParams : List [TypeDef ]): List [Tree ] = in.token match
737
+ case CLASS | ENUM | RECORD | INTERFACE | AT =>
722
738
typeDecl(start, if (definesInterface(parentToken)) mods | Flags .JavaStatic else mods)
723
739
case _ =>
724
740
termDecl(start, mods, parentToken, parentTParams)
725
- }
726
741
727
742
def makeCompanionObject (cdef : TypeDef , statics : List [Tree ]): Tree =
728
743
atSpan(cdef.span) {
@@ -804,6 +819,48 @@ object JavaParsers {
804
819
addCompanionObject(statics, cls)
805
820
}
806
821
822
+ def recordDecl (start : Offset , mods : Modifiers ): List [Tree ] =
823
+ accept(RECORD )
824
+ val nameOffset = in.offset
825
+ val name = identForType()
826
+ val tparams = typeParams()
827
+ val header = formalParams()
828
+ val superclass = javaLangRecord() // records always extend java.lang.Record
829
+ val interfaces = interfacesOpt() // records may implement interfaces
830
+ val (statics, body) = typeBody(RECORD , name, tparams)
831
+
832
+ // We need to generate accessors for every param, if no method with the same name is already defined
833
+
834
+ var fieldsByName = header.map(v => (v.name, (v.tpt, v.mods.annotations))).toMap
835
+
836
+ for case DefDef (name, paramss, tpt, rhs) <- body
837
+ if paramss.isEmpty && fieldsByName.contains(name)
838
+ do
839
+ fieldsByName -= name
840
+ end for
841
+
842
+ val accessors =
843
+ (for (name, (tpt, annots)) <- fieldsByName yield
844
+ DefDef (name, Nil , tpt, unimplementedExpr).withMods(Modifiers (Flags .JavaDefined | Flags .Method | Flags .Synthetic ))
845
+ ).toList
846
+
847
+ // generate the canonical constructor
848
+ val canonicalConstructor = makeConstructor(header, tparams)
849
+
850
+ // return the trees, probably with addCompanionObject (like classDecl)
851
+ val recordTypeDef = atSpan(start, nameOffset) {
852
+ TypeDef (name,
853
+ makeTemplate(
854
+ parents = superclass :: interfaces,
855
+ stats = canonicalConstructor :: accessors ::: body,
856
+ tparams = tparams,
857
+ false
858
+ )
859
+ )
860
+ }
861
+ addCompanionObject(statics, recordTypeDef)
862
+ end recordDecl
863
+
807
864
def interfaceDecl (start : Offset , mods : Modifiers ): List [Tree ] = {
808
865
accept(INTERFACE )
809
866
val nameOffset = in.offset
@@ -846,7 +903,7 @@ object JavaParsers {
846
903
else if (in.token == SEMI )
847
904
in.nextToken()
848
905
else {
849
- if (in.token == ENUM || definesInterface(in.token)) mods |= Flags .JavaStatic
906
+ if (in.token == ENUM || in.token == RECORD || definesInterface(in.token)) mods |= Flags .JavaStatic
850
907
val decls = memberDecl(start, mods, parentToken, parentTParams)
851
908
(if (mods.is(Flags .JavaStatic ) || inInterface && ! (decls exists (_.isInstanceOf [DefDef ])))
852
909
statics
@@ -952,6 +1009,7 @@ object JavaParsers {
952
1009
case INTERFACE => interfaceDecl(start, mods)
953
1010
case AT => annotationDecl(start, mods)
954
1011
case CLASS => classDecl(start, mods)
1012
+ case RECORD => recordDecl(start, mods)
955
1013
case _ => in.nextToken(); syntaxError(em " illegal start of type declaration " , skipIt = true ); List (errorTypeTree)
956
1014
}
957
1015
0 commit comments