@@ -237,10 +237,85 @@ class ScoverageInstrumentationComponent(val global: Global, extraAfterPhase: Opt
237
237
}
238
238
}
239
239
240
- def isUndefinedParameterInScalaJs (symbol : Symbol ): Boolean = {
241
- isScalaJsEnabled && symbol != null && symbol.isSynthetic && symbol.isMethod &&
242
- symbol.nameString.contains(" $default$" ) &&
243
- symbol.tpe.resultType.annotations.exists(_.symbol.nameString == " uncheckedVariance" )
240
+ // Copied from
241
+ // https://github.com/scala-js/scala-js/blob/4619d906baef7feb5d0b6d555d5b33044669434e/compiler/src/main/scala/org/scalajs/nscplugin/GenJSCode.scala#L2696-L2721
242
+ private def isJSDefaultParam (sym : Symbol ): Boolean = {
243
+ if (isCtorDefaultParam(sym)) {
244
+ isJSCtorDefaultParam(sym)
245
+ } else {
246
+ sym.hasFlag(reflect.internal.Flags .DEFAULTPARAM ) &&
247
+ isJSType(sym.owner) && {
248
+ /* If this is a default parameter accessor on a
249
+ * non-native JS class, we need to know if the method for which we
250
+ * are the default parameter is exposed or not.
251
+ * We do this by removing the $default suffix from the method name,
252
+ * and looking up a member with that name in the owner.
253
+ * Note that this does not work for local methods. But local methods
254
+ * are never exposed.
255
+ * Further note that overloads are easy, because either all or none
256
+ * of them are exposed.
257
+ */
258
+ def isAttachedMethodExposed = {
259
+ val methodName = nme.defaultGetterToMethod(sym.name)
260
+ val ownerMethod = sym.owner.info.decl(methodName)
261
+ ownerMethod.filter(isExposed).exists
262
+ }
263
+
264
+ ! isNonNativeJSClass(sym.owner) || isAttachedMethodExposed
265
+ }
266
+ }
267
+ }
268
+
269
+ private lazy val JSTypeAnnot = rootMirror.getRequiredClass(" scala.scalajs.js.annotation.internal.JSType" )
270
+ private lazy val ExposedJSMemberAnnot = rootMirror.getRequiredClass(" scala.scalajs.js.annotation.internal.ExposedJSMember" )
271
+ private lazy val JSNativeAnnotation = rootMirror.getRequiredClass(" scala.scalajs.js.native" )
272
+
273
+ private def isJSType (sym : Symbol ): Boolean =
274
+ sym.hasAnnotation(JSTypeAnnot )
275
+
276
+ def isNonNativeJSClass (sym : Symbol ): Boolean =
277
+ ! sym.isTrait && isJSType(sym) && ! sym.hasAnnotation(JSNativeAnnotation )
278
+
279
+ private def isExposed (sym : Symbol ): Boolean = {
280
+ ! sym.isBridge && {
281
+ if (sym.isLazy)
282
+ sym.isAccessor && sym.accessed.hasAnnotation(ExposedJSMemberAnnot )
283
+ else
284
+ sym.hasAnnotation(ExposedJSMemberAnnot )
285
+ }
286
+ }
287
+
288
+ private def isJSCtorDefaultParam (sym : Symbol ) = {
289
+ isCtorDefaultParam(sym) &&
290
+ isJSType(patchedLinkedClassOfClass(sym.owner))
291
+ }
292
+
293
+ private def patchedLinkedClassOfClass (sym : Symbol ): Symbol = {
294
+ /* Work around a bug of scalac with linkedClassOfClass where package
295
+ * objects are involved (the companion class would somehow exist twice
296
+ * in the scope, making an assertion fail in Symbol.suchThat).
297
+ * Basically this inlines linkedClassOfClass up to companionClass,
298
+ * then replaces the `suchThat` by a `filter` and `head`.
299
+ */
300
+ val flatOwnerInfo = {
301
+ // inline Symbol.flatOwnerInfo because it is protected
302
+ if (sym.needsFlatClasses)
303
+ sym.info
304
+ sym.owner.rawInfo
305
+ }
306
+ val result = flatOwnerInfo.decl(sym.name).filter(_ isCoDefinedWith sym)
307
+ if (! result.isOverloaded) result
308
+ else result.alternatives.head
309
+ }
310
+
311
+ private def isCtorDefaultParam (sym : Symbol ) = {
312
+ sym.hasFlag(reflect.internal.Flags .DEFAULTPARAM ) &&
313
+ sym.owner.isModuleClass &&
314
+ nme.defaultGetterToMethod(sym.name) == nme.CONSTRUCTOR
315
+ }
316
+
317
+ def isUndefinedParameterInScalaJs (sym : Symbol ): Boolean = {
318
+ isScalaJsEnabled && sym != null && isJSDefaultParam(sym)
244
319
}
245
320
def isClassIncluded (symbol : Symbol ): Boolean = coverageFilter.isClassIncluded(symbol.fullNameString)
246
321
def isFileIncluded (source : SourceFile ): Boolean = coverageFilter.isFileIncluded(source)
0 commit comments