manifold-systems / manifold

Manifold is a Java compiler plugin, its features include Metaprogramming, Properties, Extension Methods, Operator Overloading, Templates, a Preprocessor, and more.
http://manifold.systems/
Apache License 2.0
2.37k stars 124 forks source link

Using manifold in spock to prompt for method not found #452

Closed 007idle closed 1 year ago

007idle commented 1 year ago

Describe the bug Using manifold in spock to prompt for extension method not found

To Reproduce Steps to reproduce the behavior:

  1. gradle libs file (libs.versions.toml)

[versions] javaVersion = '17' lombokVersion = '1.18.26' manifoldVersion = '2023.1.8' spockVersion = '2.1-groovy-3.0' groovyVersion = '3.0.10'

[libraries] lombok = { module = "org.projectlombok:lombok", version.ref = "lombokVersion" } manifold = { module = 'systems.manifold:manifold-ext', version.ref = "manifoldVersion" } spock-core = { module = "org.spockframework:spock-core", version.ref = "spockVersion" } spock-groovy = { module = "org.codehaus.groovy:groovy-all", version.ref = "groovyVersion" }

[bundles]

test = ['spock-core', 'spock-groovy']

setting.gradle content:

rootProject.name = "base"

dependencyResolutionManagement { versionCatalogs { libs { from(files("./libs.versions.toml")) } }

}

  1. build.gradle

buildscript { repositories { mavenLocal() maven { url 'https://mirrors.cloud.tencent.com/nexus/repository/maven-public/' } mavenCentral() maven { url 'https://plugins.gradle.org/m2/' } } ext { localMavenRepository = 'file://E:\maven-resp' }

} plugins { id "java" id "maven-publish" id "groovy" }

repositories { mavenLocal { it.url = localMavenRepository } mavenCentral() maven { url "https://mirrors.cloud.tencent.com/nexus/repository/maven-public/" } } targetCompatibility = 17 sourceCompatibility = 17

archivesBaseName = 'base' group = "com.z.solon" version = "1.0.0"

configurations { testImplementation.extendsFrom annotationProcessor }

dependencies {

annotationProcessor libs.lombok
compileOnly libs.lombok

testCompileOnly libs.lombok
testAnnotationProcessor libs.lombok

annotationProcessor libs.manifold
compileOnly libs.manifold

testCompileOnly libs.manifold
testAnnotationProcessor libs.manifold

testImplementation libs.bundles.test

}

compileJava { options.encoding = "UTF-8" options.compilerArgs = ['-Xlint:all', '-Xlint:-processing', "-parameters"] } if (JavaVersion.current() != JavaVersion.VERSION_1_8 && sourceSets.main.allJava.files.any { it.name == "module-info.java" }) { tasks.withType(JavaCompile) { // if you DO define a module-info.java file: options.compilerArgs += ['-Xplugin:Manifold no-bootstrap', '--module-path', it.classpath.asPath] }

} else { tasks.withType(JavaCompile) { // If you DO NOT define a module-info.java file: options.compilerArgs += ['-Xplugin:Manifold no-bootstrap'] }

}

tasks.compileJava { classpath += files(sourceSets.main.output.resourcesDir) //adds build/resources/main to javac's classpath dependsOn processResources }

jar { manifest { attributes "Maintainer": "com.z" attributes 'Contains-Sources': 'java,class' }

} test { useJUnitPlatform() }

  1. my extendsion class

package base.extensions.java.lang.String;

import java.lang.reflect.Type; import manifold.ext.rt.api.Extension; import manifold.ext.rt.api.This;

@Extension public class StringExt {

public static boolean empty(@This String str) { return str == null || str.trim().length() == 0; }

public static boolean nonEmpty(@This String str) { return !empty(str); }

public static String str(@This String value) { return empty(value) ? "" : value; }

public static String str(@This String value, String defaultVal) { return empty(value) ? defaultVal : value; }

}

  1. spock test case

package com.z.solon

import spock.lang.Specification

class StrSpec extends Specification {

void setup() {
    println("--------")
}

def "test"() {
    when:
    def s = val.empty()
    def strVal = val.str()
    then:
    s == res
    strVal == resStr
    where:
    val  || res   | resStr
    null || true  | ""
    "11" || false | "11"
}

}

Expected behavior spock test case pass

Screenshots If applicable, add screenshots to help explain your problem (drag/drop them here).

Desktop (please complete the following information):

Additional context Add any other context about the problem here.

Stack trace

No signature of method: java.lang.String.empty() is applicable for argument types: () values: [] Possible solutions: isEmpty(), every(), every(groovy.lang.Closure), wait(), length(), next() groovy.lang.MissingMethodException: No signature of method: java.lang.String.empty() is applicable for argument types: () values: [] Possible solutions: isEmpty(), every(), every(groovy.lang.Closure), wait(), length(), next() at com.z.solon.StrSpec.test(StrSpec.groovy:21)

rsmckinney commented 1 year ago

The dependencies are duplicating libs in difference scopes (compileOnly and annotationProcessor). Just use annotationProcessor for both manifold and lombok, remove the compileOnly/testCompileOnly ones. Essentially, the manifold libs in your case must equate to:

 dependencies {
    // manifold-ext-rt
    implementation 'systems.manifold:manifold-ext-rt:2023.1.10'

    // manifold-ext
    annotationProcessor group: 'systems.manifold', name: 'manifold-ext', version: '2023.1.10'
    testAnnotationProcessor group: 'systems.manifold', name: 'manifold-ext', version: '2023.1.10'
} 

Same goes for lombok usage.

007idle commented 1 year ago

First of all, thank you for your reply. Then, after adjusting the dependencies, the test still failed. The build.gradle like this:

buildscript { repositories { mavenLocal() maven { url 'https://mirrors.cloud.tencent.com/nexus/repository/maven-public/' } mavenCentral() maven { url 'https://plugins.gradle.org/m2/' } } ext { localMavenRepository = 'file://E:\maven-resp' }

} plugins { id "java" id "maven-publish" id "groovy" }

repositories { mavenLocal { it.url = localMavenRepository } mavenCentral() maven { url "https://mirrors.cloud.tencent.com/nexus/repository/maven-public/" } } targetCompatibility = 17 sourceCompatibility = 17

archivesBaseName = 'base' group = "com.z.solon" version = "1.0.0"

configurations { testImplementation.extendsFrom annotationProcessor }

dependencies {

annotationProcessor libs.lombok
implementation libs.lombok
testAnnotationProcessor libs.lombok

// implementation libs.manifoldRt // annotationProcessor libs.manifold // testAnnotationProcessor libs.manifold

// manifold-ext-rt
implementation 'systems.manifold:manifold-ext-rt:2023.1.10'
// manifold-ext
annotationProcessor group: 'systems.manifold', name: 'manifold-ext', version: '2023.1.10'
testAnnotationProcessor group: 'systems.manifold', name: 'manifold-ext', version: '2023.1.10'

testImplementation libs.bundles.test

}

compileJava { options.encoding = "UTF-8" options.compilerArgs = ['-Xlint:all', '-Xlint:-processing', "-parameters"] } if (JavaVersion.current() != JavaVersion.VERSION_1_8 && sourceSets.main.allJava.files.any { it.name == "module-info.java" }) { tasks.withType(JavaCompile) { // if you DO define a module-info.java file: options.compilerArgs += ['-Xplugin:Manifold no-bootstrap', '--module-path', it.classpath.asPath] } } else { tasks.withType(JavaCompile) { // If you DO NOT define a module-info.java file: options.compilerArgs += ['-Xplugin:Manifold no-bootstrap'] } }

tasks.compileJava { classpath += files(sourceSets.main.output.resourcesDir) //adds build/resources/main to javac's classpath dependsOn processResources }

jar { manifest { attributes "Maintainer": "com.z" attributes 'Contains-Sources': 'java,class' }

} test { useJUnitPlatform() }

rsmckinney commented 1 year ago

No problem.

Take out:

implementation libs.lombok

You only need annotationProcessor dependency for lombok.

007idle commented 1 year ago

In my latest testing, I found that the extension method of Manifold cannot be used directly in Groovy, but can be used indirectly. It's not related to Lombok or Spock