summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala
blob: 92bca1921381732911623568f7000c8fd8cff839 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* NSC -- new Scala compiler
 * Copyright 2005-2013 LAMP/EPFL
 * @author  Stephane Micheloud
 */


package scala.tools.nsc
package backend.jvm

import ch.epfl.lamp.fjbg._
import symtab.Flags

trait GenAndroid {
  self: GenJVM =>

  import global._
  import icodes._
  import opcodes._

  /** From the reference documentation of the Android SDK:
   *  The `Parcelable` interface identifies classes whose instances can be
   *  written to and restored from a `Parcel`. Classes implementing the
   *  `Parcelable` interface must also have a static field called `CREATOR`,
   *  which is an object implementing the `Parcelable.Creator` interface.
   */
  private val fieldName = newTermName("CREATOR")

  private lazy val AndroidParcelableInterface = rootMirror.getClassIfDefined("android.os.Parcelable")
  private lazy val AndroidCreatorClass        = rootMirror.getClassIfDefined("android.os.Parcelable$Creator")

  def isAndroidParcelableClass(sym: Symbol) =
    (AndroidParcelableInterface != NoSymbol) &&
    (sym.parentSymbols contains AndroidParcelableInterface)

  def addCreatorCode(codegen: BytecodeGenerator, block: BasicBlock) {
    import codegen._
    val fieldSymbol = (
      clasz.symbol.newValue(fieldName, NoPosition, Flags.STATIC | Flags.FINAL)
        setInfo AndroidCreatorClass.tpe
    )
    val methodSymbol = definitions.getMember(clasz.symbol.companionModule, fieldName)
    clasz addField new IField(fieldSymbol)
    block emit CALL_METHOD(methodSymbol, Static(false))
    block emit STORE_FIELD(fieldSymbol, true)
  }

  def legacyAddCreatorCode(codegen: BytecodeGenerator, clinit: JExtendedCode) {
    import codegen._
    val creatorType = javaType(AndroidCreatorClass)
    jclass.addNewField(PublicStaticFinal,
                       fieldName.toString,
                       creatorType)
    val moduleName = javaName(clasz.symbol)+"$"
    clinit.emitGETSTATIC(moduleName,
                         nme.MODULE_INSTANCE_FIELD.toString,
                         new JObjectType(moduleName))
    clinit.emitINVOKEVIRTUAL(moduleName, fieldName.toString,
                             new JMethodType(creatorType, Array()))
    clinit.emitPUTSTATIC(jclass.getName(), fieldName.toString, creatorType)
  }

}