Skip to content
This repository has been archived by the owner on Aug 19, 2020. It is now read-only.

Generate accessors for ArtifactHandler #1020

Merged
merged 5 commits into from
Dec 5, 2018
Merged

Generate accessors for ArtifactHandler #1020

merged 5 commits into from
Dec 5, 2018

Conversation

mkobit
Copy link
Contributor

@mkobit mkobit commented Aug 8, 2018

issue #889

Signed-off-by: Mike Kobit [email protected]

Context

#889

Contributor Checklist

  • Base the PR against the develop branch
  • Make sure that all commits are signed off to indicate that you agree to the terms of Developer Certificate of Origin.
  • Provide integration tests to verify changes from a user perspective
  • Provide unit tests to verify logic
  • Ensure that tests pass locally: ./gradlew check --parallel

@mkobit
Copy link
Contributor Author

mkobit commented Aug 8, 2018

This doesn't entirely address all use cases but hits some of them. For example, something like

val myConfig by configurations.creating
artifacts {
    myConfig(something)
}

Wouldn't work (right now).

Want me to tackle that in this MR or a different one? What are the desired supported DSL invocations?

@JLLeitschuh
Copy link
Contributor

@mkobit Any chance this can be updated so that it can be merged?

@mkobit
Copy link
Contributor Author

mkobit commented Oct 19, 2018

@JLLeitschuh I was going to wait for some feedback before I spent more time on this. I wasn't sure if the direction going forward is to use myConfiguration.outgoing.artifact(someThing) instead of the artifacts {} block. I'm in favor of reducing the amount of ways to do something, so for me I'd like to see clarification around that before I add more here. I would even be in favor of deprecation of ArtifactHandler.

@eskatos
Copy link
Member

eskatos commented Nov 6, 2018

@mkobit, the target code changed a lot, would you be willing to rebase on top of develop and fix the conflicts? the added coverage shouldn't cause trouble

@mkobit
Copy link
Contributor Author

mkobit commented Nov 6, 2018

@eskatos yes, I'll try and tackle it in the next couple of days

@mkobit
Copy link
Contributor Author

mkobit commented Nov 19, 2018

I'm trying to work through this now, but converting it to the AccessorFragments byte code is proving to be more challenging for me than I would like. I'm basically cargo-culting what you guys have done for DependencyHandler while also trying to strip down output from a javap -c -p -verbose SomeClass.class, where SomeClass.class is coming from the copy/pasted logic I have added into buildSrc since it seems easier for me to find the byte code.

I have, for the non-Action consuming method:

AccessorFragment(
    source = name.run {
      """
                  /**
                   * Adds an artifact to the '$original' configuration.
                   *
                   * @param artifactNotation the group of the module to be added as a dependency.
                   * @return The artifact.
                   *
                   * @see [ArtifactHandler.add]
                   */
                  fun ArtifactHandler.`$kotlinIdentifier`(artifactNotation: Any): PublishArtifact =
                      add("$stringLiteral", artifactNotation)
              """
    },
    bytecode = {
      publicStaticMethod(signature) {
        ALOAD(0)
        LDC(name.original)
        ALOAD(1)
        INVOKEINTERFACE(GradleTypeName.artifactHandler, "add", "(Ljava/lang/String;Ljava/lang/Object;)Lorg/gradle/api/artifacts/PublishArtifact;")
        ARETURN()
      }
    },
    metadata = {
      writer.writeFunctionOf(
          receiverType = GradleType.artifactHandler,
          returnType = GradleType.publishArtifact,
          name = propertyName,
          functionFlags = publicFunctionFlags,
          parameters = {
            visitParameter("artifactNotation", KotlinType.any)
          },
          signature = signature
      )
    },
    signature = JvmMethodSignature(
        name.original,
        "(Lorg/gradle/api/artifacts/dsl/ArtifactHandler;Ljava/lang/Object;)Lorg/gradle/api/artifacts/PublishArtifact;"
    )
)

and testing that seems to work.

Then, for the other method, I am obviously missing something:

AccessorFragment(
    source = name.run {
      """
                    /**
                     * Adds an artifact to the '$original' configuration.
                     *
                     * @param artifactNotation the group of the module to be added as a dependency.
                     * @param configureAction The action to execute to configure the artifact.
                     * @return The artifact.
                     *
                     * @see [ArtifactHandler.add]
                     */
                    fun ArtifactHandler.`$kotlinIdentifier`(
                        artifactNotation: Any,
                        configureAction:  ConfigurablePublishArtifact.() -> Unit): PublishArtifact =
                            add("$stringLiteral", artifactNotation, configureAction)
                """
    },
    bytecode = {
      publicStaticMethod(signature) {
        ALOAD(0)
        LDC(propertyName)
        ALOAD(1)
        ALOAD(2)
        INVOKEINTERFACE(GradleTypeName.artifactHandler, "add", "(Ljava/lang/String;Ljava/lang/Object;Lorg/gradle/api/Action;)Lorg/gradle/api/artifacts/PublishArtifact;")
        ARETURN()
      }
    },
    metadata = {
      writer.writeFunctionOf(
          receiverType = GradleType.artifactHandler,
          returnType = GradleType.publishArtifact,
          name = propertyName,
          functionFlags = publicFunctionFlags,
          parameters = {
            visitParameter("artifactNotation", KotlinType.any)
            visitParameter("configureAction", actionTypeOf(GradleType.configurablePublishArtifact))
          },
          signature = signature
      )
    },
    signature = JvmMethodSignature(
        name.original,
        "(Lorg/gradle/api/artifacts/dsl/ArtifactHandler;Ljava/lang/Object;Lkotlin/jvm/functions/Function1<-Lorg/gradle/api/artifacts/ConfigurablePublishArtifact;Lkotlin/Unit;>;)Lorg/gradle/api/artifacts/PublishArtifact;"
    )
)

leads to

Caused by: java.lang.ArrayIndexOutOfBoundsException: 210
	at org.jetbrains.org.objectweb.asm.Type.getArgumentTypes(Type.java:343)
	at org.jetbrains.org.objectweb.asm.MethodWriter.visitMaxs(MethodWriter.java:1464)
	at org.gradle.kotlin.dsl.support.bytecode.AsmExtensionsKt.method(AsmExtensions.kt:118)
	at org.gradle.kotlin.dsl.support.bytecode.AsmExtensionsKt.publicStaticMethod(AsmExtensions.kt:90)
	at org.gradle.kotlin.dsl.support.bytecode.KotlinMetadataKt.publicStaticMethod(KotlinMetadata.kt:96)
	at org.gradle.kotlin.dsl.support.bytecode.KotlinMetadataKt.publicStaticMethod$default(KotlinMetadata.kt:93)
	at org.gradle.kotlin.dsl.accessors.AccessorFragmentsKt$fragmentsForConfiguration$1$23.invoke(AccessorFragments.kt:454)
	at org.gradle.kotlin.dsl.accessors.AccessorFragmentsKt$fragmentsForConfiguration$1$23.invoke(AccessorFragments.kt)
	at org.gradle.kotlin.dsl.accessors.EmitterKt.emitClassFor(Emitter.kt:78)
	at org.gradle.kotlin.dsl.accessors.EmitterKt.access$emitClassFor(Emitter.kt:1)
	at org.gradle.kotlin.dsl.accessors.EmitterKt$emitAccessorsFor$emittedClassNames$1.invoke(Emitter.kt:47)
	at org.gradle.kotlin.dsl.accessors.EmitterKt$emitAccessorsFor$emittedClassNames$1.invoke(Emitter.kt)
	at kotlin.sequences.TransformingSequence$iterator$1.next(Sequences.kt:174)
	at kotlin.sequences.SequencesKt___SequencesKt.toCollection(_Sequences.kt:691)
	at kotlin.sequences.SequencesKt___SequencesKt.toMutableList(_Sequences.kt:721)
	at kotlin.sequences.SequencesKt___SequencesKt.toList(_Sequences.kt:712)
	at org.gradle.kotlin.dsl.accessors.EmitterKt.emitAccessorsFor(Emitter.kt:48)
	at org.gradle.kotlin.dsl.accessors.AccessorsClassPathKt.buildAccessorsFor(AccessorsClassPath.kt:147)
	at org.gradle.kotlin.dsl.accessors.AccessorsClassPathKt$buildAccessorsClassPathFor$$inlined$let$lambda$1.invoke(AccessorsClassPath.kt:68)
	at org.gradle.kotlin.dsl.accessors.AccessorsClassPathKt$buildAccessorsClassPathFor$$inlined$let$lambda$1.invoke(AccessorsClassPath.kt)
	at org.gradle.kotlin.dsl.accessors.AccessorsClassPathKt$cachedAccessorsClassPathFor$cacheDir$1.invoke(AccessorsClassPath.kt:97)
	at org.gradle.kotlin.dsl.accessors.AccessorsClassPathKt$cachedAccessorsClassPathFor$cacheDir$1.invoke(AccessorsClassPath.kt)
	at org.gradle.kotlin.dsl.cache.ScriptCache.initializeCacheDir(ScriptCache.kt:113)
	at org.gradle.kotlin.dsl.cache.ScriptCache.access$initializeCacheDir(ScriptCache.kt:37)
	at org.gradle.kotlin.dsl.cache.ScriptCache$cacheDirFor$1.execute(ScriptCache.kt:60)
	at org.gradle.kotlin.dsl.cache.ScriptCache$cacheDirFor$1.execute(ScriptCache.kt:37)
	at org.gradle.cache.internal.DefaultPersistentDirectoryCache$Initializer.initialize(DefaultPersistentDirectoryCache.java:98)
	at org.gradle.cache.internal.FixedSharedModeCrossProcessCacheAccess$1.run(FixedSharedModeCrossProcessCacheAccess.java:85)
	at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.doWriteAction(DefaultFileLockManager.java:207)
	at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.writeFile(DefaultFileLockManager.java:197)
	at org.gradle.cache.internal.FixedSharedModeCrossProcessCacheAccess.open(FixedSharedModeCrossProcessCacheAccess.java:83)
	at org.gradle.cache.internal.DefaultCacheAccess.open(DefaultCacheAccess.java:141)
	at org.gradle.cache.internal.DefaultPersistentDirectoryStore.open(DefaultPersistentDirectoryStore.java:78)

Any suggestions for working through this?

@bamboo
Copy link
Member

bamboo commented Nov 19, 2018

@mkobit my workflow was to write the Kotlin code I wanted to generate around this code and use the Show Kotlin Bytecode IntelliJ command on it.

@mkobit
Copy link
Contributor Author

mkobit commented Nov 19, 2018

Thanks for the tip @bamboo - I haven't dove deeply into JVM byte code operations before so I definitely learned a few things while working on this.

I think this is in a ready-for-review state now.

/**
* Configures the artifacts.
*/
inline operator fun invoke(configuration: ArtifactHandlerScope.() -> Unit) =
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this return the PublishArtifact?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Returns Unit like the DependencyHandlerScope - I followed the same style that was there, but would be alright with marking the return as explicit

Copy link
Member

Choose a reason for hiding this comment

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

Let's keep things uniform. If you feel strongly about it @JLLeitschuh, please open a separate issue with a motivation keeping api/dsl uniformity in mind.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was just checking, I couldn't tell from reading the code what was returned. I don't feel strongly either way.

Copy link
Member

@eskatos eskatos left a comment

Choose a reason for hiding this comment

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

First review pass, I'll get back to this again later

/**
* Configures the artifacts.
*/
inline operator fun invoke(configuration: ArtifactHandlerScope.() -> Unit) =
Copy link
Member

Choose a reason for hiding this comment

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

Let's keep things uniform. If you feel strongly about it @JLLeitschuh, please open a separate issue with a motivation keeping api/dsl uniformity in mind.

@JLLeitschuh
Copy link
Contributor

@mkobit DCO is failing on these, you may need to use an interactive rebase to add the sign-off on some of these commits.

@mkobit
Copy link
Contributor Author

mkobit commented Nov 27, 2018

Thanks @JLLeitschuh - I guess I need a way to automate that...

Copy link
Member

@eskatos eskatos left a comment

Choose a reason for hiding this comment

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

Thank you @mkobit!

@eskatos eskatos merged commit 9046d5e into gradle:develop Dec 5, 2018
@mkobit mkobit deleted the mk/889-generate-artifact-handler-accessors branch December 7, 2018 21:59
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants