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

Mark all the generated methods with an annotation #11407

Open
szhem opened this Issue Feb 19, 2019 · 3 comments

Comments

Projects
None yet
3 participants
@szhem
Copy link

szhem commented Feb 19, 2019

Introduce a runtime annotation inserted on all the generated methods by scalac.

It will help to distinguish user-written methods and compiler-generated methods from each other that can be useful for code analysis tools e.g. code coverage ones.

For example, jacoco uses bytecode instrumentation to analyze code coverage (so that theoretically any language that runs on top of jvm can benefit from it) and such an annotation available at runtime can be pretty useful to exclude compiler-generated methods and fields from the coverage reports.

@hrhino

This comment has been minimized.

Copy link
Member

hrhino commented Feb 19, 2019

Shouldn't we be marking synthetic methods as ACC_SYNTHETIC anyways? Does JaCoCo ignore that flag?

@szhem

This comment has been minimized.

Copy link
Author

szhem commented Feb 19, 2019

JaCoCo is pretty flexible and can be extended to support it, but care should be taken when marking generated methods with ACC_SYNTHETIC.

Here are some details
Consider java8 lambda expression (18:36 on the timeline)

... that is translated into invokedynamic instruction (18:56 on the timeline)

... that calls generated synthetic method lambda$fun$0 (19:12 on the timeline)

... that in its order has ACC_SYNTHETIC flag set and contains instructions of the user provided code.

So in case of simple exclusion of the ACC_SYNTHETIC methods (19:53 on the timeline) coverage report will not include user-provided code
.

On the other hand in case of preserving synthetic method and a little bit of "hacking" the tools shows 100% coverage (20:24 on the timeline)
.

Generally speaking ACC_SYNTHETIC is fine for compiler-generated code that does not include instructions of user-provided code (e.g. case classes, mix-ins, auto-generated accessors, etc.)

@Godin

This comment has been minimized.

Copy link

Godin commented Feb 19, 2019

@hrhino @szhem while JaCoCo ignores all methods with attribute synthetic except ones that represent bodies of lambda expressions in Java and ones that represent suspending functions and contain default arguments in Kotlin,

IMO you can't mark generated equals, hashCode etc in case classes as synthetic, because then they won't be accessible from Java - here is example to back these words:

given javap -v -p Example.class

{
  public Example();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: return

  public static void add();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=2, locals=2, args_size=0
         0: return
}

attempt to compile Test.java

class Test {
  void test1() {
    new Example();
  }

  void test2() {
    new Example().add();
  }
}

results in

$ javac -cp . Test.java
Test.java:7: error: cannot find symbol
    new Example().add();
                 ^
  symbol:   method add()
  location: class Example
1 error

For the reference this ticket is triggered by the following discussion started by @szhem in JaCoCo Mailing List - https://groups.google.com/d/msg/jacoco/npl9SUL8_WA/jzoprA4pAwAJ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.