Skip to content
This repository has been archived by the owner on Jan 2, 2022. It is now read-only.

feat: grab more plugin declarations #1

Merged
merged 8 commits into from
Jul 25, 2020

Conversation

programadorthi
Copy link
Contributor

@programadorthi programadorthi commented Jul 18, 2020

Added support to customize matches to grab more gradle plugin declarations. Some people use raw text when applying plugins. Other are using Kotlin DSL and constant fields to reuse plugin names in whole project. So, it was added fields to the plugin extension that they can be used to match plugin declarations.

For instance:

// BuildPlugins.kt
object BuildPluginIds {
    const val androidApplication = "com.android.application"
}

Kotlin DSL:

// .gradle.kts (app module)
plugins {
    id(BuildPluginIds.androidApplication)
}

// .gradle.kts (a kotlin jvm library)
plugins {
    kotlin(BuildPluginIds.kotlinJVM)
}

// .gradle.kts (an android library)
apply(plugin = BuildPluginIds.androidLibrary)

Groovy DSL:

// .gradle (app module)
plugins {
    id BuildPluginIds.androidApplication
}

// .gradle (an android library)
apply plugin: BuildPluginIds.androidLibrary

As the plugin only matches the raw text, looking for "com.android.application" by instance will never match. So, we need ask the plugin user how to matches plugins declarations in this way:

// settings.gradle
magicModules {
    rawApplicationPlugin = ["BuildPluginIds.androidApplication"]
    rawLibraryPlugins = [
        "BuildPluginIds.androidLibrary",
        "BuildPluginIds.kotlinJVM",
        "BuildPluginIds.androidDynamicFeature"
    ]
}
// settings.gradle.kts
configure<io.labs.dotanuki.magicmodules.MagicModulesExtension>() {
    rawApplicationPlugin = listOf("BuildPluginIds.androidApplication")
    rawLibraryPlugins = listOf(
        "BuildPluginIds.androidLibrary",
        "BuildPluginIds.kotlinJVM",
        "BuildPluginIds.androidDynamicFeature"
    )
}

rawApplicationPlugin - how to matches application plugins? default value is ["com.android.application"].
rawLibraryPlugins - how to matches library plugins? default values are ["com.android.library", "kotlin", "com.android.dynamic-feature", "jvm"]

There is a extra field called rawLibraryUsingApplyFrom used in scenarios when users that create a base script and apply to other modules. E.g:

// shared/kotlin.gradle
apply plugin: 'kotlin'
// shared/library.gradle
apply plugin: 'com.android.library'
// build.gradle (any kotlin library)
apply from: '../kotlin.gradle'

dependencies {
    ...
}
// build.gradle (any android library)
apply from: '../library.gradle'

dependencies {
    ...
}

So, just config the property setting how to grab them:

// settings.gradle
magicModules {
    ...
    rawLibraryUsingApplyFrom = [
        "../kotlin.gradle",
         "../library.gradle"
    ]
}
// settings.gradle.kts
configure<io.labs.dotanuki.magicmodules.MagicModulesExtension>() {
    ...
    rawLibraryUsingApplyFrom = listOf(
        "../kotlin.gradle",
         "../library.gradle"
    )
}

Copy link
Member

@ubiratansoares ubiratansoares left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@programadorthi Thanks for the PR! Looks REALLY good, you've managed to tackle one improvement I was just too lazy to deliver 😹

I've requested two small changes, most cosmetic. I've added one question as well.

gradle.settingsEvaluated {
val parsedStructure = ProjectStructureParser(extension).parse(settingsDir)
val processedScripts = BuildScriptsProcessor.process(parsedStructure)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you share the practical reasons why the instances now are created per settings evaluation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason is that plugin configurations are lazy. When we apply a plugin, the apply function is called at the same time and only default values are available in the configuration lifecycle. So, we have to use a lazy function as doLast, settingsEvaluated, in this case, to get custom values.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me!

private const val NO_NAME_ASSIGNED = ""
private val APPLY_FROM_LINE_REGEX = """^\s*apply\s*\(?from\s*[:=]\s*['"]?""".toRegex()
private val PLUGIN_LINE_REGEX =
"""^\s*((apply\s*\(?\s*plugin)|(id\s*[('"])|(kotlin\s*\())""".toRegex()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏👏👏👏👏

import io.labs.dotanuki.magicmodules.internal.model.GradleModuleType
import io.labs.dotanuki.magicmodules.internal.model.GradleProjectStructure
import io.labs.dotanuki.magicmodules.internal.util.e
import io.labs.dotanuki.magicmodules.internal.util.i
import io.labs.dotanuki.magicmodules.internal.util.logger
import java.io.File

internal class ProjectStructureParser {
internal class ProjectStructureParser(private val magicModulesExtension: MagicModulesExtension) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will prefer not depend on the extension here. Could you please change this constructor and pass the list of raw plugins directly?

I know we'll have to wire things at plugin entry point level, but I think this abstraction becomes better!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright. I'll change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a data class to parse the raw contents to Parser. Reasons:

  1. Avoid ProjectStructureParser constructor with 3 parameters of the same type;
  2. Avoid constructor to have long parameter list;
  3. Improve maintenance.

created a data class to avoid mistakes and help with maintenance
created a data class to avoid mistakes and help with maintenance
@ubiratansoares ubiratansoares merged commit b50999c into dotanuki-labs:master Jul 25, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants