Skip to content

Commit

Permalink
First impl attempt
Browse files Browse the repository at this point in the history
  • Loading branch information
povder committed Oct 31, 2023
1 parent 09d3d33 commit c44bb8d
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 3 deletions.
46 changes: 44 additions & 2 deletions compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,27 @@ object JavaParsers {
addCompanionObject(statics, cls)
}

def unnamedClassDecl(priorTypes: List[Tree], start: Offset): List[Tree] = {
val name = source.name.replaceAll("\\.java$", "").nn.toTypeName
val (statics, body) = typeBodyDecls(CLASS, name, Nil)

val (priorStatics, priorBody) = priorTypes.partition {
case t: TypeDef => t.mods.is(Flags.JavaStatic)
case _: ModuleDef => true
case _ => false
}

val cls = atSpan(start, 0) {
TypeDef(name, makeTemplate(
parents = Nil,
stats = priorBody ::: body,
tparams = Nil,
needsDummyConstr = true)
).withMods(Modifiers(Flags.Private | Flags.Final))
}
addCompanionObject(priorStatics ::: statics, cls)
}

def recordDecl(start: Offset, mods: Modifiers): List[Tree] =
accept(RECORD)
val nameOffset = in.offset
Expand Down Expand Up @@ -1067,16 +1088,37 @@ object JavaParsers {
val buf = new ListBuffer[Tree]
while (in.token == IMPORT)
buf ++= importDecl()

val afterImports = in.offset
val typesBuf = new ListBuffer[Tree]

while (in.token != EOF && in.token != RBRACE) {
while (in.token == SEMI) in.nextToken()
if (in.token != EOF) {
val start = in.offset
val mods = modifiers(inInterface = false)
adaptRecordIdentifier() // needed for typeDecl
buf ++= typeDecl(start, mods)

in.token match {
case ENUM | INTERFACE | AT | CLASS | RECORD => typesBuf ++= typeDecl(start, mods)
case _ =>
if (thisPackageName == tpnme.EMPTY_PACKAGE) {
// upon encountering non-types directly at a compilation unit level in an unnamed package,
// the entire compilation unit is treated as a JEP-445 unnamed class
//TODO support @annotated members of unnamed class
val cls = unnamedClassDecl(priorTypes = typesBuf.toList, start = afterImports)
typesBuf.clear()
typesBuf ++= cls
} else {
in.nextToken()
syntaxError(em"illegal start of type declaration", skipIt = true)
List(errorTypeTree)
}
}
}
}
val unit = atSpan(start) { PackageDef(pkg, buf.toList) }

val unit = atSpan(start) { PackageDef(pkg, (buf ++ typesBuf).toList) }
accept(EOF)
unit match
case PackageDef(Ident(nme.EMPTY_PACKAGE), Nil) => EmptyTree
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class JavaJep445ParserTest extends DottyTest {
|import some.pkg.*;
|
|private volatile int x = 0;
|private String s = "s";
|@Magic
|protected String s = "s";
|
|void main() {}
|""".stripMargin
Expand All @@ -44,6 +45,29 @@ class JavaJep445ParserTest extends DottyTest {
|
|interface Inner {}
|
|static class InnerStatic {}
|
|void main() {}
|""".stripMargin

val parser =
JavaParsers.JavaParser(SourceFile.virtual("MyUnnamed.java", code))
val tree = parser.parse()

println(tree.show)

fail("TODO")
}

@Test def `treats leading top-level annotated vars as members of unnamed class`: Unit = {
val code =
s"""
|
|import some.pkg.*;
|
|@MyAnnotation
|int x = 0;
|
|void main() {}
|""".stripMargin

Expand Down
5 changes: 5 additions & 0 deletions tests/pos-java21+/jep445/UnnamedStartsWithAnnotatedField.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

@MyAnnotation
int myInt = 10;

void main() {}

0 comments on commit c44bb8d

Please sign in to comment.