Skip to content

Commit 3efd62a

Browse files
committed
First impl attempt
1 parent 09d3d33 commit 3efd62a

File tree

5 files changed

+84
-11
lines changed

5 files changed

+84
-11
lines changed

compiler/src/dotty/tools/dotc/core/Flags.scala

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ object Flags {
77

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

168168
private inline val FirstFlag = 2
169169
private inline val FirstNotPickledFlag = 48
170-
private inline val MaxFlag = 63
170+
private inline val MaxFlag = 64
171171

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

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

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

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

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

438441
/** All possible flags */
439442
val AnyFlags: FlagSet = flagRange(FirstFlag, MaxFlag)

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

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,27 @@ object JavaParsers {
826826
addCompanionObject(statics, cls)
827827
}
828828

829+
def unnamedClassDecl(priorTypes: List[Tree], start: Offset): List[Tree] = {
830+
val name = source.name.replaceAll("\\.java$", "").nn.toTypeName
831+
val (statics, body) = typeBodyDecls(CLASS, name, Nil)
832+
833+
val (priorStatics, priorBody) = priorTypes.partition {
834+
case t: TypeDef => t.mods.is(Flags.JavaStatic)
835+
case _: ModuleDef => true
836+
case _ => false
837+
}
838+
839+
val cls = atSpan(start, 0) {
840+
TypeDef(name, makeTemplate(
841+
parents = Nil,
842+
stats = priorBody ::: body,
843+
tparams = Nil,
844+
needsDummyConstr = true)
845+
).withMods(Modifiers(Flags.Private | Flags.Final | Flags.JavaUnnamedClass))
846+
}
847+
addCompanionObject(priorStatics ::: statics, cls)
848+
}
849+
829850
def recordDecl(start: Offset, mods: Modifiers): List[Tree] =
830851
accept(RECORD)
831852
val nameOffset = in.offset
@@ -1067,16 +1088,37 @@ object JavaParsers {
10671088
val buf = new ListBuffer[Tree]
10681089
while (in.token == IMPORT)
10691090
buf ++= importDecl()
1091+
1092+
val afterImports = in.offset
1093+
val typesBuf = new ListBuffer[Tree]
1094+
10701095
while (in.token != EOF && in.token != RBRACE) {
10711096
while (in.token == SEMI) in.nextToken()
10721097
if (in.token != EOF) {
10731098
val start = in.offset
10741099
val mods = modifiers(inInterface = false)
10751100
adaptRecordIdentifier() // needed for typeDecl
1076-
buf ++= typeDecl(start, mods)
1101+
1102+
in.token match {
1103+
case ENUM | INTERFACE | AT | CLASS | RECORD => typesBuf ++= typeDecl(start, mods)
1104+
case _ =>
1105+
if (thisPackageName == tpnme.EMPTY_PACKAGE) {
1106+
// upon encountering non-types directly at a compilation unit level in an unnamed package,
1107+
// the entire compilation unit is treated as a JEP-445 unnamed class
1108+
//TODO support @annotated members of unnamed class
1109+
val cls = unnamedClassDecl(priorTypes = typesBuf.toList, start = afterImports)
1110+
typesBuf.clear()
1111+
typesBuf ++= cls
1112+
} else {
1113+
in.nextToken()
1114+
syntaxError(em"illegal start of type declaration", skipIt = true)
1115+
List(errorTypeTree)
1116+
}
1117+
}
10771118
}
10781119
}
1079-
val unit = atSpan(start) { PackageDef(pkg, buf.toList) }
1120+
1121+
val unit = atSpan(start) { PackageDef(pkg, (buf ++ typesBuf).toList) }
10801122
accept(EOF)
10811123
unit match
10821124
case PackageDef(Ident(nme.EMPTY_PACKAGE), Nil) => EmptyTree

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class CompilationTests {
3131
@Test def pos: Unit = {
3232
implicit val testGroup: TestGroup = TestGroup("compilePos")
3333
var tests = List(
34-
compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Wunused:all", "-Xlint:private-shadow", "-Xlint:type-parameter-shadow"), FileFilter.include(TestSources.posLintingAllowlist)),
34+
/*compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Wunused:all", "-Xlint:private-shadow", "-Xlint:type-parameter-shadow"), FileFilter.include(TestSources.posLintingAllowlist)),
3535
compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init"), FileFilter.exclude(TestSources.posLintingAllowlist)),
3636
compileFilesInDir("tests/pos-deep-subtype", allowDeepSubtypes),
3737
compileFilesInDir("tests/pos-special/sourcepath/outer", defaultOptions.and("-sourcepath", "tests/pos-special/sourcepath")),
@@ -42,9 +42,9 @@ class CompilationTests {
4242
compileFile("tests/pos-special/utf16encoded.scala", defaultOptions.and("-encoding", "UTF16")),
4343
compileDir("tests/pos-special/i18589", defaultOptions.and("-Ysafe-init").without("-Ycheck:all")),
4444
// Run tests for legacy lazy vals
45-
compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Ylegacy-lazy-vals", "-Ycheck-constraint-deps"), FileFilter.include(TestSources.posLazyValsAllowlist)),
45+
compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Ylegacy-lazy-vals", "-Ycheck-constraint-deps"), FileFilter.include(TestSources.posLazyValsAllowlist)), */
4646
compileDir("tests/pos-special/java-param-names", defaultOptions.withJavacOnlyOptions("-parameters")),
47-
compileDir("tests/pos-special/stdlib", defaultOptions),
47+
/* compileDir("tests/pos-special/stdlib", defaultOptions),*/
4848
)
4949

5050
if scala.util.Properties.isJavaAtLeast("16") then

compiler/test/dotty/tools/dotc/parsing/JavaJep445ParserTest.scala

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class JavaJep445ParserTest extends DottyTest {
2020
|
2121
|import some.pkg.*;
2222
|
23-
|private volatile int x = 0;
23+
|//private volatile int x = 0;
2424
|private String s = "s";
2525
|
2626
|void main() {}
@@ -44,6 +44,29 @@ class JavaJep445ParserTest extends DottyTest {
4444
|
4545
|interface Inner {}
4646
|
47+
|static class InnerStatic {}
48+
|
49+
|void main() {}
50+
|""".stripMargin
51+
52+
val parser =
53+
JavaParsers.JavaParser(SourceFile.virtual("MyUnnamed.java", code))
54+
val tree = parser.parse()
55+
56+
println(tree.show)
57+
58+
fail("TODO")
59+
}
60+
61+
@Test def `treats leading top-level annotated vars as members of unnamed class`: Unit = {
62+
val code =
63+
s"""
64+
|
65+
|import some.pkg.*;
66+
|
67+
|@MyAnnotation
68+
|int x = 0;
69+
|
4770
|void main() {}
4871
|""".stripMargin
4972

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
@MyAnnotation
3+
int myInt = 10;
4+
5+
void main() {}

0 commit comments

Comments
 (0)