Skip to content

Commit 02b7aab

Browse files
committed
Updated apply to support all constants
1 parent b15b5df commit 02b7aab

File tree

1 file changed

+48
-17
lines changed

1 file changed

+48
-17
lines changed

src/main/scala/scoverage/plugin.scala

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ class ScoverageComponent(val global: Global)
133133
)
134134
}
135135

136+
def transformPartial(c: ClassDef) = {
137+
val template = c.children.head.asInstanceOf[Template]
138+
println(template.body.map(_.getClass))
139+
c
140+
}
141+
136142
def process(tree: Tree): Tree = {
137143
if (tree.hasSymbol) {
138144
// if (tree.symbol.isSynthetic)
@@ -156,11 +162,32 @@ class ScoverageComponent(val global: Global)
156162
case a: Apply if a.symbol.isCaseApplyOrUnapply =>
157163
treeCopy.Apply(a, a.fun, transformStatements(a.args))
158164

159-
/** This AST node corresponds to the following Scala code: fun(args)
160-
* todo decide if we should instrument the outer call, or just the param applys
161-
*/
165+
/**
166+
* Object creation from new.
167+
* Ignoring creation calls to anon functions
168+
*/
169+
case a: Apply if a.symbol.isConstructor && a.symbol.enclClass.isAnonymousFunction => tree
170+
case a: Apply if a.symbol.isConstructor => instrument(a)
171+
172+
/**
173+
* When an apply has no parameters, or is an application of purely literals
174+
* then we must instrument the outer call.
175+
*/
176+
case a: Apply if a.args.isEmpty => instrument(a)
177+
case a: Apply if a.args.forall(_.isInstanceOf[Literal]) => instrument(a)
178+
162179
case a: Apply =>
163-
treeCopy.Apply(a, a.fun, transformStatements(a.args))
180+
a.args match {
181+
// application of a single constant
182+
case Literal(const) :: Nil =>
183+
println("MISSED CONSTANT APPLY: " + a.toString() + " " + a.symbol + " ARGS: " + a.args)
184+
instrument(a)
185+
case _ =>
186+
println("OTHER APPLY: " + a.toString() + " " + a.symbol + " ARGS: " + a.args)
187+
treeCopy.Apply(a, a.fun, transformStatements(a.args))
188+
}
189+
190+
case assign: Assign => instrument(assign)
164191

165192
/** pattern match with syntax `Block(stats, expr)`.
166193
* This AST node corresponds to the following Scala code:
@@ -169,16 +196,15 @@ class ScoverageComponent(val global: Global)
169196
*
170197
* If the block is empty, the `expr` is set to `Literal(Constant(()))`.
171198
*/
172-
case b: Block => super.transform(tree)
173-
//treeCopy.Block(b, transformStatements(b.stats), transform(b.expr))
199+
case b: Block =>
200+
treeCopy.Block(b, transformStatements(b.stats), transform(b.expr))
174201

175202
case _: Import => super.transform(tree)
176-
case p: PackageDef => super.transform(tree)
177203

178204
// special support to ignore partial functions
179205
// todo re-enable but fix to only instrument the case statements of applyOrElse
180206
case c: ClassDef if c.symbol.isAnonymousFunction &&
181-
c.symbol.enclClass.superClass.nameString.contains("AbstractPartialFunction") => tree
207+
c.symbol.enclClass.superClass.nameString.contains("AbstractPartialFunction") => transformPartial(c)
182208

183209
// scalac generated classes, we just instrument the enclosed methods/statments
184210
// the location would stay as the source class
@@ -224,20 +250,13 @@ class ScoverageComponent(val global: Global)
224250
*/
225251
case d: DefDef if d.symbol.isStable && d.symbol.isGetter => tree
226252

227-
/** Getters are auto generated and should be ignored.
228-
*
229-
* Eg
230-
* <accessor> def cancellable: akka.actor.Cancellable
231-
* <accessor> private def _clientName: String =
232-
*/
233-
case d: DefDef if d.symbol.isGetter => tree
234-
235253
case d: DefDef if d.symbol.isStable =>
236254
println("STABLE DEF: " + d.toString() + " " + d.symbol)
237255
super.transform(tree)
238256

239257
/** Accessors are auto generated setters and getters.
240258
* Eg
259+
* <accessor> private def _clientName: String =
241260
* <accessor> def cancellable: akka.actor.Cancellable = PriceEngine.this.cancellable
242261
* <accessor> def cancellable_=(x$1: akka.actor.Cancellable): Unit = PriceEngine.this.cancellable = x$1
243262
*/
@@ -299,13 +318,26 @@ class ScoverageComponent(val global: Global)
299318
updateLocation(m.symbol)
300319
super.transform(tree)
301320

321+
case p: PackageDef => super.transform(tree)
322+
302323
// This AST node corresponds to the following Scala code: `return` expr
303324
case r: Return =>
304325
treeCopy.Return(r, transform(r.expr))
305326

306327
// This AST node corresponds to the following Scala code: expr: tpt
307328
case t: Typed => super.transform(tree)
308329

330+
/** pattern match with syntax `Select(qual, name)`.
331+
* This AST node corresponds to the following Scala code:
332+
*
333+
* qualifier.selector
334+
*
335+
* Should only be used with `qualifier` nodes which are terms, i.e. which have `isTerm` returning `true`.
336+
* Otherwise `SelectFromTypeTree` should be used instead.
337+
*
338+
* foo.Bar // represented as Select(Ident(<foo>), <Bar>)
339+
* Foo#Bar // represented as SelectFromTypeTree(Ident(<Foo>), <Bar>)
340+
*/
309341
// should only occur inside something we are instrumenting.
310342
case s: Select => super.transform(tree)
311343

@@ -358,7 +390,6 @@ class ScoverageComponent(val global: Global)
358390
treeCopy.ValDef(tree, v.mods, v.name, v.tpt, process(v.rhs))
359391

360392
case tapply: TypeApply => instrument(tapply)
361-
case assign: Assign => instrument(assign)
362393

363394
case _ =>
364395
println("Unexpected construct: " + tree.getClass + " " + tree.symbol)

0 commit comments

Comments
 (0)