Есть ли чистый способ указать тип параметра Closure в Groovy? - PullRequest
5 голосов
/ 31 октября 2019

Мне известно о @ClosureParams аннотации. Похоже, что он охватывает только более сложные варианты использования. Я ищу что-то вроде , описанное здесь в разделе , аннотирующем замыкания . Что похоже на следующий фрагмент:

void doSomething(MyType src, @ClosureParams(MyType) Closure cl) { ... }

Этот пример больше не компилируется с более поздними версиями Groovy, к сожалению (сейчас я нахожусь на 2.5.8). Я знаю, что могу получить эквивалент с помощью:

void doSomething(MyType src, @ClosureParams(FirstParam) Closure cl) { ... }

Мой вариант использования не имеет никакого другого аргумента, кроме самого замыкания, хотя:

void doSomething(@ClosureParams(/* how? */) Closure cl) { ... }

Я могу взломать его как:

void doSomething(@ClosureParams(SecondParam) Closure cl, MyType ignore = null) { ... }

Это далеко не чисто, не так ли?

Я тоже могу пойти:

void doSomething(@ClosureParams(value = SimpleType, options = ['com.somepackage.MyType']) Closure cl) { ... }

Это не только уродливо и шумно, но и с типом, указанным в виде строкипредотвращает работу некоторых функций IDE. Например, MyType refactor-rename или поиск типов использования здесь не будут приниматься.

Я полагаю, что нет более чистого способа добиться этого, поэтому тип можно указать в качестве типа. не строка и без лишних ненужных аргументов, не так ли?

Что-то вроде оригинального сообщения Cédric Champeau в сообщении в блоге, указанном выше, будет идеальным. Который в моем случае будет выглядеть так:

void doSomething(@ClosureParams(MyType) Closure cl) { ... }

1 Ответ

1 голос
/ 31 октября 2019

Вы можете рассмотреть FromAbstractTypeMethods подсказку подписи вместо SimpleType. Он довольно многословен в использовании, но дает вам преимущества, отсутствующие в классе подсказок SimpleType - вы можете легко реорганизовать типы, определенные в классе подписей, а также найти классы, используемые в подсказке подписи. Основным недостатком является то, что вам нужно создавать дополнительный абстрактный класс для каждой подсказки сигнатуры замыкания, а имя класса, содержащего сигнатуры в качестве абстрактных методов, должно быть определено как константная строка (та же проблема существует с подсказкой SimpleType подписи. ) Однако вы получаете метод с одним параметром doSomething, без добавления второго параметра null, чтобы можно было использовать SecondParam подсказку подписи.

package com.example

import groovy.transform.Immutable
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FromAbstractTypeMethods

class MyClass {
    static void doSomething(@ClosureParams(value = FromAbstractTypeMethods, options = ["com.example.MySignatures"]) Closure cl) {
        cl.call()
    }

    static void main(String[] args) {
        doSomething {
            println it.name
        }
    }
}

@Immutable
class MyType {
    String name
    int x
    int y
}

abstract class MySignatures {
    abstract void firstSignature(MyType myType)
    abstract void secondSignature(MyType myType, String str)
}

enter image description here

Я предполагаю, что простой и чистый вариант @ClosureParams(String) был удален, чтобы удовлетворить другие более сложные варианты использования. API аннотации ClosureParams исправлен и ограничивает options массивом строк. Может быть, этого можно достичь путем реализации собственного ClosureSignatureHint - я пробовал это несколько месяцев назад, но я не мог заставить IntelliJ IDEA использовать свой собственный класс для предоставления подсказок подписи.

...