diff --git a/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableInspector.scala b/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableInspector.scala index 58bdcb649ec..9362016c72f 100644 --- a/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableInspector.scala +++ b/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableInspector.scala @@ -46,7 +46,7 @@ final class EncodableInspector[C <: blackbox.Context](val c: C) { // Keep this as a string so it also works if the annotation is referenced indirectly. private val encodableStringAnnotationFqn = - "org.apache.texera.amber.EncodableStringAnn" + "org.apache.texera.amber.pybuilder.EncodableStringAnnotation" /** * If we are pointing at a getter/accessor, hop to its accessed field symbol when possible. @@ -110,10 +110,20 @@ final class EncodableInspector[C <: blackbox.Context](val c: C) { val symHasAnn = rawSym != null && rawSym != NoSymbol && { val accessed = safeAccessed(rawSym) - accessed != null && accessed != NoSymbol && accessed.annotations.exists(annIsEncodableString) + accessed != null && accessed != NoSymbol && + accessed.annotations.exists(annIsEncodableString) } - symHasAnn || (tree.tpe != null && typeHasEncodableString(tree.tpe)) + val methodReturnHasAnn = + rawSym != null && rawSym != NoSymbol && (rawSym match { + case m: MethodSymbol => + typeHasEncodableString(m.typeSignature.finalResultType) + case _ => + false + }) + + symHasAnn || methodReturnHasAnn || + (tree.tpe != null && typeHasEncodableString(tree.tpe)) } def isPythonTemplateBuilderArg(argExpr: c.Expr[Any]): Boolean = { diff --git a/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableStringAnnotation.java b/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableStringAnnotation.java index ea17e6d0130..f94c01f680a 100644 --- a/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableStringAnnotation.java +++ b/common/pybuilder/src/main/scala/org/apache/texera/amber/pybuilder/EncodableStringAnnotation.java @@ -29,6 +29,7 @@ ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE_USE, - ElementType.LOCAL_VARIABLE + ElementType.LOCAL_VARIABLE, + ElementType.METHOD }) public @interface EncodableStringAnnotation {} \ No newline at end of file diff --git a/common/pybuilder/src/test/scala/org/apache/texera/amber/pybuilder/PythonTemplateBuilderSpec.scala b/common/pybuilder/src/test/scala/org/apache/texera/amber/pybuilder/PythonTemplateBuilderSpec.scala index d2e423f810a..7347ba8c2fd 100644 --- a/common/pybuilder/src/test/scala/org/apache/texera/amber/pybuilder/PythonTemplateBuilderSpec.scala +++ b/common/pybuilder/src/test/scala/org/apache/texera/amber/pybuilder/PythonTemplateBuilderSpec.scala @@ -275,6 +275,22 @@ class PythonTemplateBuilderSpec extends AnyFunSuite { assert(builder.encode == "param-only") } + test("@StringUI method annotation triggers UI encoding") { + object Holder { + @EncodableStringAnnotation def uiText: String = "method" + } + val builder = pyb"${Holder.uiText}" + assert(builder.encode == decodeExpr("method")) + } + + test("@StringUI method annotation on def with parens triggers UI encoding") { + object Holder { + @EncodableStringAnnotation def uiText(): String = "method-parens" + } + val builder = pyb"${Holder.uiText()}" + assert(builder.encode == decodeExpr("method-parens")) + } + test("unannotated String does not become UI (stays raw python)") { val rawText: String = "raw" val builder = pyb"$rawText"