Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,8 @@ trait BCodeHelpers extends BCodeIdiomatic {
case e => List(e)
}
}
for(arg <- flatArgs) {
for arg <- flatArgs do
emitArgument(arrAnnotV, null, arg, bcodeStore)(innerClasesStore)
}
arrAnnotV.visitEnd()
/*
case sb @ ScalaSigBytes(bytes) =>
Expand All @@ -340,6 +339,9 @@ trait BCodeHelpers extends BCodeIdiomatic {
val nestedVisitor = av.visitAnnotation(name, desc)
emitAssocs(nestedVisitor, assocs, bcodeStore)(innerClasesStore)

case Inlined(_, _, expansion) =>
emitArgument(av, name, arg = expansion, bcodeStore)(innerClasesStore)

case t =>
report.error(em"Annotation argument is not a constant", t.sourcePos)
}
Expand Down
45 changes: 38 additions & 7 deletions compiler/test/dotty/tools/AnnotationsTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@ import vulpix.TestConfiguration

import org.junit.Test

import dotc.ast.Trees._
import dotc.core.Decorators._
import dotc.core.Contexts._
import dotc.core.Phases._
import dotc.core.Types._
import dotc.core.Symbols._
import dotc.ast.Trees.*
import dotc.ast.tpd
import dotc.core.Decorators.*
import dotc.core.Contexts.*
import dotc.core.Constants.*
import dotc.core.Phases.*
import dotc.core.Types.*
import dotc.core.Symbols.*

import java.io.File
import java.nio.file._
import java.nio.file.*

class AnnotationsTest:
def augmentedClassPath(path: Path) = s"${path}${File.pathSeparator}${TestConfiguration.basicClasspath}"

@Test def annotTreeNotErased: Unit =
withJavaCompiled(
Expand Down Expand Up @@ -95,3 +98,31 @@ class AnnotationsTest:
val term: TermSymbol = requiredClass("java.lang.invoke.MethodHandle").requiredMethod("invokeExact")
assert(term.hasAnnotation(defn.NativeAnnot), i"${term.annotations}")
}

@Test def `inlined annot arg is retrieved`: Unit =
val javaSources =
VirtualJavaSource("Param.java",
"""|import java.lang.annotation.*;
|@Inherited @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME)
|public @interface Param { String[] value(); }""".stripMargin)
:: Nil
val scalaSources =
"""object Bar { inline transparent def bar() = Array("a", "b", "c") }"""
:: "@Param(Bar.bar()) class Foo"
:: Nil
withJavaCompiled(javaSources*): javaOutputDir =>
inCompilerContext(augmentedClassPath(javaOutputDir), scalaSources = scalaSources*):
val cls = requiredClass("Foo")
val param = requiredClass("Param")
val annots = cls.annotations
assert(annots.size == 2, i"$annots") // includes SourceFile
val annot = annots.find(_.symbol == param).getOrElse(assert(false, s"Missing $param"))
assert(annot.arguments.size == 1, i"${annot.arguments}")
extension (t: tpd.Tree)
def stripNamedArg = tpd.stripNamedArg(t)
def stripInlined = tpd.stripInlined(t)
annot.arguments(0).stripNamedArg.stripInlined match
case Apply(Apply(_, List(Typed(SeqLiteral(ks, _), _))), _) =>
assert(ks.length == 3, i"$ks")
assert(ks.map(_.tpe).collect { case ConstantType(Constant(s: String)) => s } == List("a", "b", "c"))
case bad => assert(false, s"Bad arg $bad")
10 changes: 10 additions & 0 deletions tests/pos/i24894a/Bar_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
object Bar {
import quoted.*

inline transparent def bar(): Array[String] = ${ macroBar() }
def macroBar()(using Quotes): Expr[Array[String]] = {
val l = Range(0, 200, 10).map(_.toString).map(Expr(_)).toList
'{ Array[String](${ Varargs(l) }*) }
//'{ Array[String]("hello", "world") }
}
}
2 changes: 2 additions & 0 deletions tests/pos/i24894a/Foo_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@Param(Bar.bar()) class Foo
@Param(Array("hi", "bi")) class Baz
15 changes: 15 additions & 0 deletions tests/pos/i24894a/Param.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

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;

@Inherited
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Param {

String[] value();

}
9 changes: 9 additions & 0 deletions tests/pos/i24894b/Bar_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
object Bar {
import quoted.*

transparent inline def bar(): String = ${ macroBar() }
def macroBar()(using Quotes): Expr[String] = {
val s = "hello".reverse
Expr(s)
}
}
1 change: 1 addition & 0 deletions tests/pos/i24894b/Foo_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@Deprecated(since = Bar.bar()) class Foo
18 changes: 18 additions & 0 deletions tests/pos/i24894c/OutputTimeUnit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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;
import java.util.concurrent.TimeUnit;

@Inherited
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface OutputTimeUnit {

/**
* @return Time unit to use.
*/
TimeUnit value();

}
11 changes: 11 additions & 0 deletions tests/pos/i24894c/i21881.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class C:

//final val Seconds = java.util.concurrent.TimeUnit.SECONDS
//inline val Seconds = java.util.concurrent.TimeUnit.SECONDS // not a literal
inline transparent def Seconds = java.util.concurrent.TimeUnit.SECONDS

@OutputTimeUnit(Seconds)
def f(): Unit = ()

@OutputTimeUnit(java.util.concurrent.TimeUnit.SECONDS)
def ok(): Unit = ()
Loading