All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.squareup.sqldelight.gradle.SqlDelightAndroidPlugin.kt Maven / Gradle / Ivy

There is a newer version: 1.0.0-alpha5
Show newest version
/*
 * Copyright (C) 2016 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.sqldelight.gradle

import com.android.build.gradle.AppExtension
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.LibraryExtension
import com.android.build.gradle.LibraryPlugin
import com.android.build.gradle.api.BaseVariant
import com.android.build.gradle.internal.errors.SyncIssueHandlerImpl
import com.android.build.gradle.options.SyncOptions.EvaluationMode.STANDARD
import com.android.builder.core.DefaultManifestParser
import com.squareup.sqldelight.VERSION
import com.squareup.sqldelight.core.SqlDelightPropertiesFile
import com.squareup.sqldelight.core.lang.MigrationFileType
import com.squareup.sqldelight.core.lang.SqlDelightFileType
import org.gradle.api.DomainObjectSet
import org.gradle.api.Project
import java.io.File

class SqlDelightAndroidPlugin : SqlDelightPlugin() {
  override fun apply(project: Project) {
    project.extensions.create("sqldelight", SqlDelightExtension::class.java)
    if (!project.plugins.hasPlugin("android")) {
      throw IllegalStateException(
          """
      Kotlin projects need to apply the sqldelight kotlin plugin:

      buildscript {
        dependencies {
          classpath "com.squareup.sqldelight:gradle-plugin:$VERSION
        }
      }

      apply plugin: "com.squareup.sqldelight"
      """.trimIndent()
      )
    }

    project.plugins.all {
      when (it) {
        is AppPlugin -> {
          val extension = project.extensions.getByType(AppExtension::class.java)
          configureAndroid(project, extension.applicationVariants)
        }
        is LibraryPlugin -> {
          val extension = project.extensions.getByType(LibraryExtension::class.java)
          configureAndroid(project, extension.libraryVariants)
        }
      }
    }
  }

  private fun  configureAndroid(project: Project, variants: DomainObjectSet) {
    val compileDeps = project.configurations.getByName("api").dependencies
    if (System.getProperty("sqldelight.skip.runtime") != "true") {
      compileDeps.add(project.dependencies.create("com.squareup.sqldelight:runtime-jdk:$VERSION"))
    }

    var packageName: String? = null
    val sourceSets = mutableListOf>()
    val buildDirectory = listOf("generated", "source", "sqldelight").fold(project.buildDir, ::File)

    variants.all {
      val taskName = "generate${it.name.capitalize()}SqlDelightInterface"
      val task = project.tasks.create(taskName, SqlDelightTask::class.java)
      task.group = "sqldelight"
      task.outputDirectory = buildDirectory
      task.description = "Generate Android interfaces for working with ${it.name} database tables"
      task.source(it.sourceSets.map { "src/${it.name}/${SqlDelightFileType.FOLDER_NAME}" })
      task.include("**${File.separatorChar}*.${SqlDelightFileType.defaultExtension}")
      task.include("**${File.separatorChar}*.${MigrationFileType.defaultExtension}")
      task.packageName = it.packageName(project)
      task.sourceFolders = it.sourceSets.map { File("${project.projectDir}/src/${it.name}/${SqlDelightFileType.FOLDER_NAME}") }

      sourceSets.add(task.sourceFolders.map { it.toRelativeString(project.projectDir) })
      packageName = task.packageName

      it.registerJavaGeneratingTask(task, task.outputDirectory)
    }

    project.afterEvaluate {
      val ideaDir = File(project.rootDir, ".idea")
      if (ideaDir.exists()) {
        val propsDir =
          File(ideaDir, "sqldelight/${project.projectDir.toRelativeString(project.rootDir)}")
        propsDir.mkdirs()

        val properties = SqlDelightPropertiesFile(
            packageName = packageName!!,
            sourceSets = sourceSets,
            outputDirectory = buildDirectory.toRelativeString(project.projectDir)
        )
        properties.toFile(File(propsDir, SqlDelightPropertiesFile.NAME))
      }

      val extension = project.extensions.getByType(SqlDelightExtension::class.java)
      addMigrationTasks(
          project = project,
          sourceSet = sourceSets.flatten().distinct().map { File(project.projectDir, it) },
          schemaOutputDirectory = extension.schemaOutputDirectory
              ?: File(project.projectDir, "src/main/sqldelight")
      )
    }
  }

  /**
   * Theres no external api to get the package name. There is to get the application id, but thats
   * the post build package for the play store, and not the package name that should be used during
   * compilation. Think R.java, we want to be using the same namespace as it.
   *
   * There IS an internal api for doing this.
   * [BaseVariantImpl.getVariantData().getVariantConfiguration().getPackageFromManifest()],
   * and so this code just emulates that behavior.
   *
   * Package name is enforced identical by agp across multiple source sets, so taking the first
   * package name we find is fine.
   */
  private fun BaseVariant.packageName(project: Project): String {
    return sourceSets.map { it.manifestFile }
        .filter { it.exists() }
        .mapNotNull {
          DefaultManifestParser(it, { true }, SyncIssueHandlerImpl(STANDARD, project.logger))
              .`package`
        }
        .first()
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy