Написание пользовательских обработчиков аннотаций Lombok

Я хочу написать собственные обработчики аннотаций Lombok. Я знаю http://notatube.blogspot.de/2010/12/project-lombok-creating-custom.html. Но текущий jar-файл ломбока содержит не много файлов .class, а файлы с именами .SCL.lombok.

Я обнаружил, что файлы .SCL.lombok являются файлами .class, скрипт сборки Lombok переименовывает их при создании файла jar, а ShadowClassLoader способен загружать эти классы - и, похоже, отсюда и аббревиатура SCL. Кажется, причина этого заключается только в том, чтобы «избегать загрязнения пространства имен любого проекта с использованием jar-файла на основе SCL. Автозаполнение в IDE НЕ будет предлагать ничего, кроме фактического общедоступного API».

Я смог скомпилировать свой собственный обработчик только с помощью

  • распаковка содержимого lombok.jar
  • переименование файлов .SCL.lombok в .class
  • добавление полученного каталога в путь к классам компиляции

Кроме того, чтобы иметь возможность использовать свой собственный обработчик, мне нужно было создать новую толстую банку, содержащую как классы ломбока, так и мой собственный обработчик. Пользовательский загрузчик классов lombok по существу предотвращает добавление пользовательских обработчиков в другие несколько банок.

Это единственный способ расширить Ломбок? Или я что-то упускаю?

Я использую следующий скрипт сборки

apply plugin: 'java'

repositories {
    jcenter()
}

configurations {
    lombok
    compileOnly
}

def unpackedAndRenamedLombokDir = file("$buildDir/lombok")

task unpackAndRenameLombok {
    inputs.files configurations.lombok
    outputs.dir unpackedAndRenamedLombokDir
    doFirst {
        mkdir unpackedAndRenamedLombokDir
        delete unpackedAndRenamedLombokDir.listFiles()
    }
    doLast {
        copy {
            from zipTree(configurations.lombok.singleFile)
            into unpackedAndRenamedLombokDir
            rename "(.*)[.]SCL[.]lombok", '$1.class'
        }
    }
}

sourceSets {
    main {
        compileClasspath += configurations.compileOnly
        output.dir(unpackedAndRenamedLombokDir, builtBy: unpackAndRenameLombok)
    }
}

tasks.compileJava {
    dependsOn unpackAndRenameLombok
}

dependencies {
    compile files("${System.properties['java.home']}/../lib/tools.jar")
    compile "org.eclipse.jdt:org.eclipse.jdt.core:3.10.0"
    compile 'javax.inject:javax.inject:1'
    lombok 'org.projectlombok:lombok:1.16.6'

    compileOnly files(unpackedAndRenamedLombokDir)
}

person Tobias Schulte    schedule 22.02.2016    source источник


Ответы (2)


Тем временем Рейньер Звитсерлоот создал новую ветку git sclExpansionUpdate, содержащую обновленную версию ShadowClassLoader:

ShadowClassLoader теперь более дружелюбен к попыткам расширения ломбока.

Ваш (отдельный) jar/dir должен иметь файл с именем META-INF/ShadowClassLoader. Этот файл должен содержать строку «ломбок». Если у вас есть это, любые классы в этом банке/каталоге будут загружены в то же пространство, что и классы ломбока. Вы также можете переименовать файлы классов в .SCL.lombok, чтобы другие загрузчики не смогли их найти.

Я предполагаю, что это еще не попало в основную ветку, потому что она, конечно, не была так сильно протестирована - я только что попробовал ее для себя, и она содержит небольшую ошибку, которая не позволяет загружать требуемые META-INF/сервисы из расширений. Чтобы исправить это, вы должны заменить два вызова метода partOfShadow на inOwnBase:

[... line 443]
Enumeration<URL> sec = super.getResources(name);
while (sec.hasMoreElements()) {
    URL item = sec.nextElement();
    if (!inOwnBase(item, name)) vector.add(item); // <<-- HERE
}

if (altName != null) {
    Enumeration<URL> tern = super.getResources(altName);
    while (tern.hasMoreElements()) {
        URL item = tern.nextElement();
        if (!inOwnBase(item, altName)) vector.add(item); // <<-- AND HERE
    }
}

Я протестировал его с вышеуказанным исправлением, и, похоже, он работает нормально (хотя и не тестировался).

На заметку: с этим новым механизмом расширения теперь, наконец, также возможно иметь обработчики аннотаций расширений и аннотации в пространстве имен, отличном от «ломбока» — здорово!

person Balder    schedule 07.02.2017
comment
Прошло более 2 лет, все еще необходимо заменить эти два вызова метода partOfShadow() на inOwnBase()? partOfShadow(), по-видимому, делегирует основную часть работы inOwnBase(), поэтому я не вижу преимуществ этого изменения. Если это нужно, то зачем? - person Neeme Praks; 13.08.2019
comment
Теперь есть запрос на исправление ошибки в ShadowClassLoader github.com/rzwitserloot/lombok/pull/ 2204 - person Neeme Praks; 15.08.2019
comment
Вышло исправление, часть Lombok версии 1.18.10. - person Neeme Praks; 12.09.2019

Используя данные этого вопроса и другого ответа (Бальдера), нам удалось собрать собственный обработчик аннотаций Lombok: Симбок. Не стесняйтесь использовать это как образец для написания собственного.

Кстати, вместо того, чтобы писать собственный обработчик Lombok, вы также можете реализовать плагин javac -- это может быть проще.

person Neeme Praks    schedule 09.09.2019