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 3efd62a
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 11 deletions.
13 changes: 8 additions & 5 deletions compiler/src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ object Flags {

/** A FlagSet represents a set of flags. Flags are encoded as follows:
* The first two bits indicate whether a flag set applies to terms,
* to types, or to both. Bits 2..63 are available for properties
* to types, or to both. Bits 2..64 are available for properties
* and can be doubly used for terms and types.
*/
opaque type FlagSet = Long
Expand Down Expand Up @@ -167,9 +167,9 @@ object Flags {

private inline val FirstFlag = 2
private inline val FirstNotPickledFlag = 48
private inline val MaxFlag = 63
private inline val MaxFlag = 64

private val flagName = Array.fill(64, 2)("")
private val flagName = Array.fill(MaxFlag + 1, 2)("")

private def isDefinedAsFlag(idx: Int) = flagName(idx).exists(_.nonEmpty)

Expand All @@ -196,7 +196,7 @@ object Flags {
/** The undefined flag set */
val UndefinedFlags: FlagSet = FlagSet(~KINDFLAGS)

/** Three flags with given index between 2 and 63.
/** Three flags with given index between 2 and 64.
* The first applies to both terms and types. the second is a term flag, and
* the third is a type flag. Installs given name(s) as the name(s) of the flags.
* @param name The name to be used for the term flag
Expand Down Expand Up @@ -433,7 +433,10 @@ object Flags {
/** Symbol is a constructor proxy (either companion, or apply method) */
val (ConstructorProxy @ _, _, _) = newFlags(62, "<constructor proxy>") // (could be merged with Lifted)

// --------- Combined Flag Sets and Conjunctions ----------------------
/** Symbol is is JEP-445 Java unnamed class */
val (JavaUnnamedClass@_, _, _) = newFlags(63, "<unnamed>")

// --------- Combined Flag Sets and Conjunctions ----------------------

/** All possible flags */
val AnyFlags: FlagSet = flagRange(FirstFlag, MaxFlag)
Expand Down
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 | Flags.JavaUnnamedClass))
}
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
6 changes: 3 additions & 3 deletions compiler/test/dotty/tools/dotc/CompilationTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class CompilationTests {
@Test def pos: Unit = {
implicit val testGroup: TestGroup = TestGroup("compilePos")
var tests = List(
compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Wunused:all", "-Xlint:private-shadow", "-Xlint:type-parameter-shadow"), FileFilter.include(TestSources.posLintingAllowlist)),
/*compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Wunused:all", "-Xlint:private-shadow", "-Xlint:type-parameter-shadow"), FileFilter.include(TestSources.posLintingAllowlist)),
compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init"), FileFilter.exclude(TestSources.posLintingAllowlist)),
compileFilesInDir("tests/pos-deep-subtype", allowDeepSubtypes),
compileFilesInDir("tests/pos-special/sourcepath/outer", defaultOptions.and("-sourcepath", "tests/pos-special/sourcepath")),
Expand All @@ -42,9 +42,9 @@ class CompilationTests {
compileFile("tests/pos-special/utf16encoded.scala", defaultOptions.and("-encoding", "UTF16")),
compileDir("tests/pos-special/i18589", defaultOptions.and("-Ysafe-init").without("-Ycheck:all")),
// Run tests for legacy lazy vals
compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Ylegacy-lazy-vals", "-Ycheck-constraint-deps"), FileFilter.include(TestSources.posLazyValsAllowlist)),
compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Ylegacy-lazy-vals", "-Ycheck-constraint-deps"), FileFilter.include(TestSources.posLazyValsAllowlist)), */
compileDir("tests/pos-special/java-param-names", defaultOptions.withJavacOnlyOptions("-parameters")),
compileDir("tests/pos-special/stdlib", defaultOptions),
/* compileDir("tests/pos-special/stdlib", defaultOptions),*/
)

if scala.util.Properties.isJavaAtLeast("16") then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class JavaJep445ParserTest extends DottyTest {
|
|import some.pkg.*;
|
|private volatile int x = 0;
|//private volatile int x = 0;
|private String s = "s";
|
|void main() {}
Expand All @@ -44,6 +44,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 3efd62a

Please sign in to comment.