Skip to content

Commit

Permalink
Merge pull request #10734 from som-snytt/issue/i20026-java-parse
Browse files Browse the repository at this point in the history
Java parses leading annotation
  • Loading branch information
SethTisue committed Apr 8, 2024
2 parents 1776aec + f9e0b1a commit df5e62c
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 14 deletions.
34 changes: 20 additions & 14 deletions src/compiler/scala/tools/nsc/javac/JavaParsers.scala
Expand Up @@ -445,16 +445,16 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
}
}

def modifiers(inInterface: Boolean): Modifiers = {
def modifiers(inInterface: Boolean, annots0: List[Tree] = Nil): Modifiers = {
var flags: Long = Flags.JAVA
// assumed true unless we see public/private/protected
var isPackageAccess = true
var annots: List[Tree] = Nil
var annots: List[Tree] = annots0
def addAnnot(sym: Symbol) = annots :+= New(sym.tpe)

while (true) {
in.token match {
case AT if (in.lookaheadToken != INTERFACE) =>
case AT if in.lookaheadToken != INTERFACE =>
in.nextToken()
val annot = annotation()
if (annot.nonEmpty) annots :+= annot
Expand Down Expand Up @@ -1086,28 +1086,34 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
else Some(Constant(l))
}

/** CompilationUnit ::= [package QualId semi] TopStatSeq
/** CompilationUnit ::= [[Annotation] package QualId semi] {Import} {TypeDecl} //TopStatSeq
*/
def compilationUnit(): Tree = {
val buf = ListBuffer.empty[Tree]
var pos = in.currentPos
val leadingAnnots = if (in.token == AT) annotations() else Nil
val pkg: RefTree =
if (in.token == AT || in.token == PACKAGE) {
annotations() // TODO: put these somewhere?
pos = in.currentPos
if (in.token == PACKAGE) {
if (!leadingAnnots.isEmpty) { // TODO: put these somewhere?
//if (unit.source.file.name != "package-info.java")
// syntaxError(pos, "package annotations must be in file package-info.java")
pos = in.currentPos
}
accept(PACKAGE)
val pkg = qualId().asInstanceOf[RefTree]
accept(SEMI)
pkg
} else {
qualId().asInstanceOf[RefTree].tap(_ => accept(SEMI))
}
else {
if (!leadingAnnots.isEmpty)
buf ++= typeDecl(modifiers(inInterface = false, annots0 = leadingAnnots))
Ident(nme.EMPTY_PACKAGE_NAME)
}
thisPackageName = gen.convertToTypeName(pkg) match {
case Some(t) => t.name.toTypeName
case _ => tpnme.EMPTY
}
val buf = new ListBuffer[Tree]
while (in.token == IMPORT)
buf ++= importDecl()
if (buf.isEmpty)
while (in.token == IMPORT)
buf ++= importDecl()
while (in.token != EOF && in.token != RBRACE) {
while (in.token == SEMI) in.nextToken()
if (in.token != EOF)
Expand Down
4 changes: 4 additions & 0 deletions test/files/neg/i20026.check
@@ -0,0 +1,4 @@
JTest.java:3: error: illegal start of type declaration
import java.util.*;
^
1 error
6 changes: 6 additions & 0 deletions test/files/neg/i20026/JTest.java
@@ -0,0 +1,6 @@

@Deprecated
import java.util.*;

public class JTest {
}
2 changes: 2 additions & 0 deletions test/files/neg/i20026/p.java
@@ -0,0 +1,2 @@
@Deprecated
package p;
6 changes: 6 additions & 0 deletions test/files/neg/i20026/test.scala
@@ -0,0 +1,6 @@

object Test extends App {
println {
new JTest
}
}
Empty file.
4 changes: 4 additions & 0 deletions test/files/pos/i20026/JFun.java
@@ -0,0 +1,4 @@
@FunctionalInterface
public interface JFun {
String f(String s);
}
4 changes: 4 additions & 0 deletions test/files/pos/i20026/JTest.java
@@ -0,0 +1,4 @@

@api.TestInstance(api.TestInstance.Lifecycle.PER_CLASS)
public class JTest {
}
6 changes: 6 additions & 0 deletions test/files/pos/i20026/KTest.java
@@ -0,0 +1,6 @@

import api.*;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class KTest {
}
20 changes: 20 additions & 0 deletions test/files/pos/i20026/TestInstance.java
@@ -0,0 +1,20 @@

package api;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface TestInstance {
enum Lifecycle {
PER_CLASS;
}
Lifecycle value();
}
6 changes: 6 additions & 0 deletions test/files/pos/i20026/test.scala
@@ -0,0 +1,6 @@

object Test extends App {
println {
(new JTest, new KTest, ((s: String) => s): JFun)
}
}

0 comments on commit df5e62c

Please sign in to comment.