@@ -41,6 +41,74 @@ private[async] trait TransformUtils {
41
41
def isAwait (fun : Tree ) =
42
42
fun.symbol == defn.Async_await
43
43
44
+ // Copy pasted from TreeInfo in the compiler.
45
+ // Using a quasiquote pattern like `case q"$fun[..$targs](...$args)" => is not
46
+ // sufficient since https://github.com/scala/scala/pull/3656 as it doesn't match
47
+ // constructor invocations.
48
+ class Applied (val tree : Tree ) {
49
+ /** The tree stripped of the possibly nested applications.
50
+ * The original tree if it's not an application.
51
+ */
52
+ def callee : Tree = {
53
+ def loop (tree : Tree ): Tree = tree match {
54
+ case Apply (fn, _) => loop(fn)
55
+ case tree => tree
56
+ }
57
+ loop(tree)
58
+ }
59
+
60
+ /** The `callee` unwrapped from type applications.
61
+ * The original `callee` if it's not a type application.
62
+ */
63
+ def core : Tree = callee match {
64
+ case TypeApply (fn, _) => fn
65
+ case AppliedTypeTree (fn, _) => fn
66
+ case tree => tree
67
+ }
68
+
69
+ /** The type arguments of the `callee`.
70
+ * `Nil` if the `callee` is not a type application.
71
+ */
72
+ def targs : List [Tree ] = callee match {
73
+ case TypeApply (_, args) => args
74
+ case AppliedTypeTree (_, args) => args
75
+ case _ => Nil
76
+ }
77
+
78
+ /** (Possibly multiple lists of) value arguments of an application.
79
+ * `Nil` if the `callee` is not an application.
80
+ */
81
+ def argss : List [List [Tree ]] = {
82
+ def loop (tree : Tree ): List [List [Tree ]] = tree match {
83
+ case Apply (fn, args) => loop(fn) :+ args
84
+ case _ => Nil
85
+ }
86
+ loop(tree)
87
+ }
88
+ }
89
+
90
+ /** Returns a wrapper that knows how to destructure and analyze applications.
91
+ */
92
+ def dissectApplied (tree : Tree ) = new Applied (tree)
93
+
94
+ /** Destructures applications into important subparts described in `Applied` class,
95
+ * namely into: core, targs and argss (in the specified order).
96
+ *
97
+ * Trees which are not applications are also accepted. Their callee and core will
98
+ * be equal to the input, while targs and argss will be Nil.
99
+ *
100
+ * The provided extractors don't expose all the API of the `Applied` class.
101
+ * For advanced use, call `dissectApplied` explicitly and use its methods instead of pattern matching.
102
+ */
103
+ object Applied {
104
+ def apply (tree : Tree ): Applied = new Applied (tree)
105
+
106
+ def unapply (applied : Applied ): Option [(Tree , List [Tree ], List [List [Tree ]])] =
107
+ Some ((applied.core, applied.targs, applied.argss))
108
+
109
+ def unapply (tree : Tree ): Option [(Tree , List [Tree ], List [List [Tree ]])] =
110
+ unapply(dissectApplied(tree))
111
+ }
44
112
private lazy val Boolean_ShortCircuits : Set [Symbol ] = {
45
113
import definitions .BooleanClass
46
114
def BooleanTermMember (name : String ) = BooleanClass .typeSignature.member(newTermName(name).encodedName)
0 commit comments