Skip to content

Commit becac43

Browse files
committed
Refactor genMethod and friends.
All the cases that produce no `js.MethodDef` at all are now handled directly in `genMethod`. This allows `genMethodWithCurrentLocalNameScope` to return a `js.MethodDef` instead of an `Option[js.MethodDef]`. In addition, we compute `jsParams` only once, with the same code for all cases.
1 parent e37a082 commit becac43

File tree

1 file changed

+47
-42
lines changed

1 file changed

+47
-42
lines changed

compiler/src/main/scala/org/scalajs/nscplugin/GenJSCode.scala

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,9 +1747,37 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
17471747

17481748
// Generate a method -------------------------------------------------------
17491749

1750+
/** Maybe gen JS code for a method definition.
1751+
*
1752+
* Some methods are not emitted at all:
1753+
*
1754+
* - Primitives, since they are never actually called (with exceptions)
1755+
* - Abstract methods in non-native JS classes
1756+
* - Default accessor of a native JS constructor
1757+
* - Constructors of hijacked classes
1758+
* - Methods with the {{{@JavaDefaultMethod}}} annotation mixed in classes.
1759+
*/
17501760
def genMethod(dd: DefDef): Option[js.MethodDef] = {
1751-
withNewLocalNameScope {
1752-
genMethodWithCurrentLocalNameScope(dd)
1761+
val sym = dd.symbol
1762+
val isAbstract = isAbstractMethod(dd)
1763+
1764+
if (scalaPrimitives.isPrimitive(sym)) {
1765+
None
1766+
} else if (isAbstract && isNonNativeJSClass(currentClassSym)) {
1767+
// #4409: Do not emit abstract methods in non-native JS classes
1768+
None
1769+
} else if (isJSNativeCtorDefaultParam(sym)) {
1770+
None
1771+
} else if (sym.isClassConstructor && isHijackedClass(sym.owner)) {
1772+
None
1773+
} else if (scalaUsesImplClasses && !isImplClass(sym.owner) &&
1774+
!isAbstract && sym.hasAnnotation(JavaDefaultMethodAnnotation)) {
1775+
// Do not emit trait impl forwarders with @JavaDefaultMethod
1776+
None
1777+
} else {
1778+
withNewLocalNameScope {
1779+
Some(genMethodWithCurrentLocalNameScope(dd))
1780+
}
17531781
}
17541782
}
17551783

@@ -1758,42 +1786,30 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
17581786
* of the Scala method, as described in `JSEncoding`, to support
17591787
* overloading.
17601788
*
1761-
* Some methods are not emitted at all:
1762-
* * Primitives, since they are never actually called (with exceptions)
1763-
* * Abstract methods
1764-
* * Constructors of hijacked classes
1765-
* * Methods with the {{{@JavaDefaultMethod}}} annotation mixed in classes.
1766-
*
17671789
* Constructors are emitted by generating their body as a statement.
17681790
*
17691791
* Interface methods with the {{{@JavaDefaultMethod}}} annotation produce
17701792
* default methods forwarding to the trait impl class method.
17711793
*
17721794
* Other (normal) methods are emitted with `genMethodDef()`.
17731795
*/
1774-
def genMethodWithCurrentLocalNameScope(dd: DefDef): Option[js.MethodDef] = {
1796+
def genMethodWithCurrentLocalNameScope(dd: DefDef): js.MethodDef = {
17751797
implicit val pos = dd.pos
1776-
val DefDef(mods, name, _, vparamss, _, rhs) = dd
17771798
val sym = dd.symbol
17781799

17791800
withPerMethodBodyState(sym) {
1780-
assert(vparamss.isEmpty || vparamss.tail.isEmpty,
1781-
"Malformed parameter list: " + vparamss)
1782-
val params = if (vparamss.isEmpty) Nil else vparamss.head map (_.symbol)
1783-
17841801
val methodName = encodeMethodSym(sym)
17851802
val originalName = originalNameOfMethod(sym)
17861803

1787-
val isAbstract = isAbstractMethod(dd)
1788-
1789-
def jsParams = params.map(genParamDef(_))
1804+
val jsParams = {
1805+
val vparamss = dd.vparamss
1806+
assert(vparamss.isEmpty || vparamss.tail.isEmpty,
1807+
"Malformed parameter list: " + vparamss)
1808+
val params = if (vparamss.isEmpty) Nil else vparamss.head.map(_.symbol)
1809+
params.map(genParamDef(_))
1810+
}
17901811

1791-
if (scalaPrimitives.isPrimitive(sym)) {
1792-
None
1793-
} else if (isAbstract && isNonNativeJSClass(currentClassSym)) {
1794-
// #4409: Do not emit abstract methods in non-native JS classes
1795-
None
1796-
} else if (isAbstract) {
1812+
if (isAbstractMethod(dd)) {
17971813
val body = if (scalaUsesImplClasses &&
17981814
sym.hasAnnotation(JavaDefaultMethodAnnotation)) {
17991815
/* For an interface method with @JavaDefaultMethod, make it a
@@ -1814,17 +1830,9 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
18141830
} else {
18151831
None
18161832
}
1817-
Some(js.MethodDef(js.MemberFlags.empty, methodName, originalName,
1833+
js.MethodDef(js.MemberFlags.empty, methodName, originalName,
18181834
jsParams, toIRType(sym.tpe.resultType), body)(
1819-
OptimizerHints.empty, None))
1820-
} else if (isJSNativeCtorDefaultParam(sym)) {
1821-
None
1822-
} else if (sym.isClassConstructor && isHijackedClass(sym.owner)) {
1823-
None
1824-
} else if (scalaUsesImplClasses && !isImplClass(sym.owner) &&
1825-
sym.hasAnnotation(JavaDefaultMethodAnnotation)) {
1826-
// Do not emit trait impl forwarders with @JavaDefaultMethod
1827-
None
1835+
OptimizerHints.empty, None)
18281836
} else {
18291837
def isTraitImplForwarder = dd.rhs match {
18301838
case app: Apply => isImplClass(app.symbol.owner)
@@ -1853,7 +1861,7 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
18531861
val namespace = js.MemberNamespace.Constructor
18541862
js.MethodDef(
18551863
js.MemberFlags.empty.withNamespace(namespace), methodName,
1856-
originalName, jsParams, jstpe.NoType, Some(genStat(rhs)))(
1864+
originalName, jsParams, jstpe.NoType, Some(genStat(dd.rhs)))(
18571865
optimizerHints, None)
18581866
} else {
18591867
val resultIRType = toIRType(sym.tpe.resultType)
@@ -1866,8 +1874,8 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
18661874
else js.MemberNamespace.Public
18671875
}
18681876
}
1869-
genMethodDef(namespace, methodName, originalName, params,
1870-
resultIRType, rhs, optimizerHints)
1877+
genMethodDef(namespace, methodName, originalName, jsParams,
1878+
resultIRType, dd.rhs, optimizerHints)
18711879
}
18721880
}
18731881

@@ -1889,7 +1897,7 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
18891897
}
18901898
}
18911899

1892-
Some(methodDefWithoutUselessVars)
1900+
methodDefWithoutUselessVars
18931901
}
18941902
}
18951903
}
@@ -1972,13 +1980,11 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
19721980
* `this`.
19731981
*/
19741982
def genMethodDef(namespace: js.MemberNamespace, methodName: js.MethodIdent,
1975-
originalName: OriginalName, paramsSyms: List[Symbol],
1983+
originalName: OriginalName, jsParams: List[js.ParamDef],
19761984
resultIRType: jstpe.Type, tree: Tree,
19771985
optimizerHints: OptimizerHints): js.MethodDef = {
19781986
implicit val pos = tree.pos
19791987

1980-
val jsParams = paramsSyms.map(genParamDef(_))
1981-
19821988
val bodyIsStat = resultIRType == jstpe.NoType
19831989

19841990
def genBodyWithinReturnableScope(): js.Tree = tree match {
@@ -5823,8 +5829,7 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
58235829
tryingToGenMethodAsJSFunction := true
58245830
) {
58255831
try {
5826-
genMethodWithCurrentLocalNameScope(applyDef).getOrElse(
5827-
abort(s"Oops, $applyDef did not produce a method"))
5832+
genMethodWithCurrentLocalNameScope(applyDef)
58285833
} catch {
58295834
case e: CancelGenMethodAsJSFunction =>
58305835
fail(e.getMessage)

0 commit comments

Comments
 (0)