From a5c49c6e911d9adea4b942302b0b6a50a98d7be5 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 20 Oct 2022 11:43:59 +0200 Subject: [PATCH 1/2] Parse native in Java bytecode as @native --- .../dotty/tools/dotc/core/classfile/ClassfileParser.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 0b5fda49d63c..1d3875af647d 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -275,6 +275,7 @@ class ClassfileParser( def complete(denot: SymDenotation)(using Context): Unit = { val sym = denot.symbol val isEnum = (jflags & JAVA_ACC_ENUM) != 0 + val isNative = (jflags & JAVA_ACC_NATIVE) != 0 val isConstructor = name eq nme.CONSTRUCTOR /** Strip leading outer param from constructor and trailing access tag for @@ -313,6 +314,10 @@ class ClassfileParser( val isVarargs = denot.is(Flags.Method) && (jflags & JAVA_ACC_VARARGS) != 0 denot.info = sigToType(sig, isVarargs = isVarargs) if (isConstructor) normalizeConstructorParams() + if isNative then + attrCompleter.annotations ::= Annotation.deferredSymAndTree(defn.NativeAnnot) { + New(defn.NativeAnnot.typeRef, Nil) + } denot.info = translateTempPoly(attrCompleter.complete(denot.info, isVarargs)) if (isConstructor) normalizeConstructorInfo() From d9648b3ea89930f516de76b3f1e5fde9678ad56d Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 24 Oct 2022 16:05:56 +0100 Subject: [PATCH 2/2] Also parse transient/volatile & test --- .../tools/dotc/core/classfile/ClassfileParser.scala | 10 +++++++--- compiler/test/dotty/tools/AnnotationsTests.scala | 6 ++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 1d3875af647d..4763cd25ff41 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -276,6 +276,8 @@ class ClassfileParser( val sym = denot.symbol val isEnum = (jflags & JAVA_ACC_ENUM) != 0 val isNative = (jflags & JAVA_ACC_NATIVE) != 0 + val isTransient = (jflags & JAVA_ACC_TRANSIENT) != 0 + val isVolatile = (jflags & JAVA_ACC_VOLATILE) != 0 val isConstructor = name eq nme.CONSTRUCTOR /** Strip leading outer param from constructor and trailing access tag for @@ -315,9 +317,11 @@ class ClassfileParser( denot.info = sigToType(sig, isVarargs = isVarargs) if (isConstructor) normalizeConstructorParams() if isNative then - attrCompleter.annotations ::= Annotation.deferredSymAndTree(defn.NativeAnnot) { - New(defn.NativeAnnot.typeRef, Nil) - } + attrCompleter.annotations ::= Annotation.deferredSymAndTree(defn.NativeAnnot)(New(defn.NativeAnnot.typeRef, Nil)) + if isTransient then + attrCompleter.annotations ::= Annotation.deferredSymAndTree(defn.TransientAnnot)(New(defn.TransientAnnot.typeRef, Nil)) + if isVolatile then + attrCompleter.annotations ::= Annotation.deferredSymAndTree(defn.VolatileAnnot)(New(defn.VolatileAnnot.typeRef, Nil)) denot.info = translateTempPoly(attrCompleter.complete(denot.info, isVarargs)) if (isConstructor) normalizeConstructorInfo() diff --git a/compiler/test/dotty/tools/AnnotationsTests.scala b/compiler/test/dotty/tools/AnnotationsTests.scala index 59e9f3129294..3998bf7c93c0 100644 --- a/compiler/test/dotty/tools/AnnotationsTests.scala +++ b/compiler/test/dotty/tools/AnnotationsTests.scala @@ -89,3 +89,9 @@ class AnnotationsTest: s"A missing annotation while parsing a Java class should be silently ignored but: ${ctx.reporter.summary}") } } + + @Test def hasNativeAnnot: Unit = + inCompilerContext(TestConfiguration.basicClasspath) { + val term: TermSymbol = requiredClass("java.lang.invoke.MethodHandle").requiredMethod("invokeExact") + assert(term.hasAnnotation(defn.NativeAnnot), i"${term.annotations}") + }