Consider example:
// class you have no access to (e.g. some java class)
final class Foo() {
def foo(x: Int): Unit = ()
}
// write an adapter
trait FooAdapter:
def foo(x: String): Unit
object FooAdapter:
def apply(impl: Foo): FooAdapter = new FooAdapter { export impl.* }
The problem here is - you should write an interface by hand, which creates a lot of boilerplate for huge classes and there is no solution for this problem yet
I propose to create a language feature.
Consider keyword adapts
which generates code above.
trait FooAdapter adapts Foo
I guess alternative solution here is to create a macro annotation, but there is no way to create a trait or abstract class with Quotes API.
@adapter
trait FooAdapter:
type Adapted = Foo
@experimental
class adapter extends MacroAnnotation {
override def transform(using quotes: Quotes)(
tree: quotes.reflect.Definition
): List[quotes.reflect.Definition] =
import quotes.reflect.*
tree match
case cls @ ClassDef(name, constr, parents, valDef, stmts) =>
val tpt = stmts
.collectFirst { case TypeDef("Adapted", tpt: TypeTree) => tpt }
.getOrElse(report.errorAndAbort("error"))
val methodSymbols =
(tpt.tpe.typeSymbol.methodMembers.toSet -- TypeRepr.of[Object].typeSymbol.methodMembers).toList
List(
ClassDef(
cls = Symbol.newClass(
parent = Symbol.spliceOwner,
name = name,
parents = List(TypeRepr.of[Object]),
decls = classSym =>
methodSymbols.map { sym =>
Symbol.newMethod(
parent = classSym,
name = sym.name,
tpe = sym.info
)
},
selfType = None
),
parents = List(TypeTree.of[Object]),
body = methodSymbols.map(DefDef(_, _ => None))
),
// companion definition
)
case _ =>
report.errorAndAbort("error")