Skip to content

Commit 9fca170

Browse files
committed
Java parses leading annotation
1 parent cc55381 commit 9fca170

File tree

7 files changed

+56
-10
lines changed

7 files changed

+56
-10
lines changed

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

+16-10
Original file line numberDiff line numberDiff line change
@@ -440,11 +440,11 @@ object JavaParsers {
440440
}
441441
}
442442

443-
def modifiers(inInterface: Boolean): Modifiers = {
443+
def modifiers(inInterface: Boolean, annots0: List[Tree] = Nil): Modifiers = {
444444
var flags: FlagSet = Flags.JavaDefined
445445
// assumed true unless we see public/private/protected
446446
var isPackageAccess = true
447-
var annots = new ListBuffer[Tree]
447+
var annots = ListBuffer.from[Tree](annots0)
448448
def addAnnot(tpt: Tree) =
449449
annots += atSpan(in.offset) {
450450
in.nextToken()
@@ -453,7 +453,7 @@ object JavaParsers {
453453

454454
while (true)
455455
in.token match {
456-
case AT if (in.lookaheadToken != INTERFACE) =>
456+
case AT if in.lookaheadToken != INTERFACE =>
457457
in.nextToken()
458458
annotation() match {
459459
case Some(anno) => annots += anno
@@ -1080,24 +1080,30 @@ object JavaParsers {
10801080
/** CompilationUnit ::= [package QualId semi] TopStatSeq
10811081
*/
10821082
def compilationUnit(): Tree = {
1083-
val start = in.offset
1083+
val buf = ListBuffer.empty[Tree]
1084+
var start = in.offset
1085+
val leadingAnnots = if (in.token == AT) annotations() else Nil
10841086
val pkg: RefTree =
1085-
if (in.token == AT || in.token == PACKAGE) {
1086-
annotations()
1087+
if in.token == PACKAGE then
1088+
if !leadingAnnots.isEmpty then
1089+
//if (unit.source.file.name != "package-info.java")
1090+
// syntaxError(pos, "package annotations must be in file package-info.java")
1091+
start = in.offset
10871092
accept(PACKAGE)
10881093
val pkg = qualId()
10891094
accept(SEMI)
10901095
pkg
1091-
}
10921096
else
1097+
if !leadingAnnots.isEmpty then
1098+
buf ++= typeDecl(start, modifiers(inInterface = false, annots0 = leadingAnnots))
10931099
Ident(nme.EMPTY_PACKAGE)
10941100
thisPackageName = convertToTypeName(pkg) match {
10951101
case Some(t) => t.name.toTypeName
10961102
case _ => tpnme.EMPTY
10971103
}
1098-
val buf = new ListBuffer[Tree]
1099-
while (in.token == IMPORT)
1100-
buf ++= importDecl()
1104+
if (buf.isEmpty)
1105+
while in.token == IMPORT do
1106+
buf ++= importDecl()
11011107
while (in.token != EOF && in.token != RBRACE) {
11021108
while (in.token == SEMI) in.nextToken()
11031109
if (in.token != EOF) {

tests/pos/i20026/Empty.java

Whitespace-only changes.

tests/pos/i20026/JFun.java

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@FunctionalInterface
2+
public interface JFun {
3+
String f(String s);
4+
}

tests/pos/i20026/JTest.java

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
@api.TestInstance(api.TestInstance.Lifecycle.PER_CLASS)
3+
public class JTest {
4+
}

tests/pos/i20026/KTest.java

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
import api.*;
3+
4+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
5+
public class KTest {
6+
}

tests/pos/i20026/TestInstance.java

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
package api;
3+
4+
import java.lang.annotation.Documented;
5+
import java.lang.annotation.ElementType;
6+
import java.lang.annotation.Inherited;
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.RetentionPolicy;
9+
import java.lang.annotation.Target;
10+
11+
@Target(ElementType.TYPE)
12+
@Retention(RetentionPolicy.RUNTIME)
13+
@Inherited
14+
@Documented
15+
public @interface TestInstance {
16+
enum Lifecycle {
17+
PER_CLASS;
18+
}
19+
Lifecycle value();
20+
}

tests/pos/i20026/test.scala

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
object Test extends App {
3+
println {
4+
new JTest
5+
}
6+
}

0 commit comments

Comments
 (0)