Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse annotation in jointly compiled Java source files and honour @Deprecated #8781

Merged
merged 2 commits into from May 8, 2020

Conversation

dwijnand
Copy link
Member

@dwijnand dwijnand commented Mar 2, 2020

Rebased (with a small merge conflict) @hrhino's work in #5892 & extended it to handle @Deprecated.

Fixes scala/bug#8928 ("Java parser skips over annotations"), though limited to no args annotations and annotations with literal arguments.
Fixes scala/bug#9617 ("Deprecations from Java may be not taken into account in mixed projects") which is the joint-compilation variant of scala/bug#10752 (which was just fixed).
Fixes scala/bug#8883 ("Treat java / scala deprecated annotations more uniformly") (IMO) with the deprecated attribute adding the java annotation & Symbol#isDeprecated considering both.

@scala-jenkins scala-jenkins added this to the 2.12.12 milestone Mar 2, 2020
@dwijnand dwijnand force-pushed the 2.12/annotation-parsing-and-Deprecated branch from ed48b8e to 2fbee71 Compare March 2, 2020 16:20
@retronym

This comment has been minimized.

Copy link
Member

@hrhino hrhino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for (hopefully) getting this over the finish line. Third time's the charm.

src/compiler/scala/tools/nsc/javac/JavaParsers.scala Outdated Show resolved Hide resolved
src/compiler/scala/tools/nsc/javac/JavaParsers.scala Outdated Show resolved Hide resolved
src/compiler/scala/tools/nsc/typechecker/Typers.scala Outdated Show resolved Hide resolved
test/files/run/t8928/Array_0.java Outdated Show resolved Hide resolved
@dwijnand dwijnand force-pushed the 2.12/annotation-parsing-and-Deprecated branch from df76334 to cc25950 Compare March 24, 2020 08:51
@retronym

This comment has been minimized.

@dwijnand

This comment has been minimized.

@lrytz

This comment has been minimized.

@dwijnand dwijnand added the release-notes worth highlighting in next release notes label Mar 31, 2020
@lrytz
Copy link
Member

lrytz commented Mar 31, 2020

Suggestions by @retronym how we could handle annotation arguments that scalac fails to interpret:

  • have an opt-in warning
  • drop the annotation
  • replace the argument with a dummy value
  • add a synthetic no argument constructor to the annotation and drop all arguments

@hrhino reminded us that on JDK 11+, Java's @Deprecated has optional since and forRemoval parameters. It would be good to keep the annotation even if some arguments cannot be interpreted.

@dwijnand dwijnand force-pushed the 2.12/annotation-parsing-and-Deprecated branch from cc25950 to 5ef207b Compare April 22, 2020 15:58
@dwijnand
Copy link
Member Author

  • drop the annotation

I implemented this solution, using new JavaTokenData {}.copyFrom(in). Feedback welcome.

@dwijnand dwijnand requested review from retronym and lrytz April 22, 2020 16:00
@lrytz
Copy link
Member

lrytz commented Apr 24, 2020

The change to drop annotations looks good. Maybe add add a test that shows annotations are dropped in mixed compilation?

I also think an opt-in warning would be good.

Also, I was confused how references to Java compile-time constants work - now I remember, they are handled by the Java parser, which assigns a constant type to such fields where possible: #5487.

So unfortunately that means we need a way to silently drop annotatnions during type checking, for the case when the argument is not a compile-time constant:

public class C {
  public static @interface Ann {
    String value();
  }

  @Ann("a") public static int x0 = 0; // ok
  @Ann("a" + "b") public static int x1 = 1; // ok, dropped
  @Ann(C.konst) public static int x2 = 2; // ok
  @Ann(C.nokst) public static int x3 = 3; // error when type-checking

  public static final String konst = "muk";
  public static final String nokst = "muk" + "y";
}

with -Xprint:parser

    @new Ann(value = "a") <static> var x0: Int = _;
    <static> var x1: Int = _;
    @new Ann(value = C.konst) <static> var x2: Int = _;
    @new Ann(value = C.nokst) <static> var x3: Int = _;
    <static> val konst: String("muk") = _;
    <static> val nokst: String = _

and later

C.java:12: error: annotation argument needs to be a constant; found: C.nokst
  @Ann(C.nokst) public static int x3 = 3; // error when type-checking
         ^

hrhino and others added 2 commits April 24, 2020 18:08
This causes the java parser to get somewhat more complex, but
allows for macros and compiler plugins to correctly inspect
java-defined classes for annotations.

Moved a few utility methods into {Parsers,Scanners}Common as well,
so I can reuse them in the java ones.

This involves a change to the t4788 tests, as SAnnotation now
correctly has RetentionPolicy.SOURCE, and is therefore ignored
by the check in BCodeHelpers#BCAnnotGen.shouldEmitAnnotation;
also, ASM Textifier emits an // invisible marker now that
CAnnotation has RetentionPolicy.CLASS. I'm not sure what the
chances that anyone is relying upon this behavior are, but
since it does the Right Thing for separate compilation runs,
they probably should not be too disappointed.

The new tests are run-tests not just pos-tests at the suggestion
of retronym, to ensure that everything works the same at runtime
as it does at compile time. As a matter of fact, it doesn't: the
compile-time universe maintains ordering of annotation values in
the tree, while the runtime universe uses java reflection to get
at the values and therefore cannot know of their order. The test
contains one exception for that.

Review by densh, retronym

Fixes scala/bug#8928

Co-authored-by: Jason Zaugg <jzaugg@gmail.com>
Co-authored-by: Dale Wijnand <dale.wijnand@gmail.com>
@dwijnand dwijnand force-pushed the 2.12/annotation-parsing-and-Deprecated branch from 5ef207b to 3c89087 Compare April 24, 2020 21:54
@dwijnand
Copy link
Member Author

Maybe add add a test that shows annotations are dropped in mixed compilation?

😕 That proved harder to do than expected (to me) using partest's existing machinery. The reason is it's not possible to have java sources that scalac compile and javac doesn't later compile (in this case putting the annotations that scalac dropped. The two options in partest are either:

  1. scalac *.scala *.java and then javac *.java, the default with both file types, or
  2. javac *.java only, by separating the java files into their own file "grouping", with a numeric suffix, like Foo_1.java.

Any suggestions? Lukas suggests @retronym or @hrhino might have a good suggestion, but also that there's no need to spend too much time on it.

I also think an opt-in warning would be good.

⚠️ Still TODO. I started looking around for where to define such an option and what to call it and spent about an hour reading through a bunch of settings code...

Suggestions (on both) welcome. 😄

So unfortunately that means we need a way to silently drop annotatnions during type checking, for the case when the argument is not a compile-time constant:

Done! ✅

@lrytz
Copy link
Member

lrytz commented Apr 27, 2020

where to define such an option and what to call it

how about an -Xlint?

@dwijnand
Copy link
Member Author

where to define such an option and what to call it

how about an -Xlint?

Discussed in the team today: decided not to add it for now (misc reasons: very niche, mostly @Deprecated, unsure if it should be Xlint, can't think of an obvious name).

So this is GTG now.

@som-snytt
Copy link
Contributor

Missed opportunity for -Xlint:dwijnand. Anyway, it takes way longer than an hour to read through -Xlint code.

Copy link
Member

@lrytz lrytz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Thanks @dwijnand & @hrhino.

@lrytz lrytz merged commit 85ec3c5 into scala:2.12.x May 8, 2020
@dwijnand dwijnand deleted the 2.12/annotation-parsing-and-Deprecated branch May 11, 2020 05:47
@retronym
Copy link
Member

This triggered a spurious kind error with @Ann(List.class) in Java sources. Fixed in #8981

@retronym
Copy link
Member

One more: #8982

@retronym retronym changed the title Annotation parsing & @Deprecated Parse annotation in jointly compiled Java source files and honour @Deprecated Jul 2, 2020
michelou pushed a commit to michelou/dotty that referenced this pull request Feb 5, 2021
* A port of fixes from scala/scala#8781 with improvements.
* Some of improvements come from scala/scala#8982.
* There are small changes to typer to allow for single elements of any
  type T be used where array of T is expected inside of java annotations
  arguments as it is correct in java and is used in 2 files in scala
  standard library.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
java interop release-notes worth highlighting in next release notes
Projects
None yet
7 participants