Lombok: Izinkan penggunaan anotasi sebagai meta-anotasi

Dibuat pada 14 Jul 2015  ·  46Komentar  ·  Sumber: projectlombok/lombok

_Dimigrasikan dari Google Code (edisi 522)_

Komentar yang paling membantu

:bust_in_silhouette: oliver.

Sangat sering saya terus menggunakan kembali kumpulan anotasi yang sama atau bahkan konfigurasi anotasi tertentu di tempat yang berbeda dari aplikasi saya. Misalnya, asumsikan penggunaan berikut untuk secara otomatis membuat konstruktor all-args yang dianotasi dengan @ Autowired.

@ AllArgsConstructor(onConstructor = @ _(@ Autowired))

Ekspresi ini terasa agak teknis dan jika saya ingin beralih dari @ Autowired ke @ Inject, saya harus menelusuri semua penggunaan dan mengubahnya.

Jika @ AllArgsConstructor diizinkan pada anotasi juga, saya dapat memperkenalkan anotasi berikut:

@ Target (Jenis Elemen. JENIS)
@ Retensi(RetentionPolicy.SOURCE)
@ AllArgsConstructor(onConstructor = @ _(@ Autowired))
@ antarmuka AutowiredConstructor {

}

dan kemudian lanjutkan dan gunakan anotasi sebagai berikut:

@ AutowiredConstructor
kelas Komponen Saya {

akhir pribadi @ ketergantungan Ketergantungan NonNull;

// metode bisnis
}

Untuk mengaktifkan perilaku ini, diperlukan dua perubahan:

  1. Tambahkan ElementType.ANNOTATION ke anotasi yang saat ini diizinkan di tipe (@ AllArgsConstructor jelas bukan satu-satunya anotasi yang mungkin masuk akal).
  2. Ubah deteksi anotasi untuk melintasi hierarki anotasi.

Semua 46 komentar

:bust_in_silhouette: oliver.

Sangat sering saya terus menggunakan kembali kumpulan anotasi yang sama atau bahkan konfigurasi anotasi tertentu di tempat yang berbeda dari aplikasi saya. Misalnya, asumsikan penggunaan berikut untuk secara otomatis membuat konstruktor all-args yang dianotasi dengan @ Autowired.

@ AllArgsConstructor(onConstructor = @ _(@ Autowired))

Ekspresi ini terasa agak teknis dan jika saya ingin beralih dari @ Autowired ke @ Inject, saya harus menelusuri semua penggunaan dan mengubahnya.

Jika @ AllArgsConstructor diizinkan pada anotasi juga, saya dapat memperkenalkan anotasi berikut:

@ Target (Jenis Elemen. JENIS)
@ Retensi(RetentionPolicy.SOURCE)
@ AllArgsConstructor(onConstructor = @ _(@ Autowired))
@ antarmuka AutowiredConstructor {

}

dan kemudian lanjutkan dan gunakan anotasi sebagai berikut:

@ AutowiredConstructor
kelas Komponen Saya {

akhir pribadi @ ketergantungan Ketergantungan NonNull;

// metode bisnis
}

Untuk mengaktifkan perilaku ini, diperlukan dua perubahan:

  1. Tambahkan ElementType.ANNOTATION ke anotasi yang saat ini diizinkan di tipe (@ AllArgsConstructor jelas bukan satu-satunya anotasi yang mungkin masuk akal).
  2. Ubah deteksi anotasi untuk melintasi hierarki anotasi.

:bust_in_silhouette: thomas.darimont :jam8: 29 Agustus 2013 pukul 09:11 UTC

Ya, ini akan sangat berguna memang :)

:bust_in_silhouette: Maaartinus :jam8: 15 Desember 2013 pukul 15:24 UTC

Ini adalah permintaan yang sama dengan masalah #602. Saya tidak berpikir bahwa mengubah @ Target adalah ide yang bagus, tetapi sudah ada sintaks yang memungkinkan anotasi arbitrer bersarang (dan OP menggunakannya di atas). Jadi bisa terlihat seperti

@ Target (Jenis Elemen. JENIS)
@ Retensi(RetentionPolicy.SOURCE)

@ lombok.Metaannotation(@ _({
@ AllArgsConstructor(onConstructor = @ _(@ Autowired)),
@ SomeOtherFancyStuff(1, 2, 3)
)})

@ antarmuka AutowiredConstructor {
}

Jadi saya yakin sintaksnya tidak masalah, tetapi saya tidak tahu apakah fitur ini dapat diimplementasikan.

_Akhir migrasi_

@Maaartinus - @Target adalah ide yang buruk?

@olivergierke Tentu: 1. Saya merasa membingungkan, tapi itu subjektif. 2. Pada akhirnya, Anda harus menambahkan ElementType.ANNOTATION ke semua anotasi lombok karena mengapa tidak mengizinkan untuk membuat @CleanupUsingDispose atau @NoGetterNoSetter (yang terakhir adalah sesuatu yang benar-benar dapat saya gunakan beberapa kali).

Tapi itu tidak terlalu buruk, meskipun saya lebih suka sintaks Metaannotation . Namun, saya tidak tahu apakah ini mungkin dan mereka yang tampaknya sibuk.

Saya masih tidak berpikir saya mendapatkan Anda. Mengapa itu membingungkan? Membuat anotasi yang dapat dikomposisi adalah tujuan dari @Target(ANNOTATION) . Sampel Anda dari atas:

@lombok.Metaannotation(@__({
  @AllArgsConstructor(onConstructor = @_(@Autowired)),
  @SomeOtherFancyStuff(1, 2, 3)
)})
<strong i="7">@interface</strong> AutowiredConstructor {}

Akan sederhana ke:

@AllArgsConstructor(onConstructor = @_(@Autowired))
@SomeOtherFancyStuff(1, 2, 3)
<strong i="11">@interface</strong> AutowiredConstructor {}

Bagaimana itu lebih membingungkan atau lebih kompleks?

Sebagai catatan tambahan: Transformasi AST Groovy menyediakan fitur ini dalam bentuk AnnotationCollector .

Snapshots 2.5 goovy terbaru memberikan sedikit lebih banyak kontrol atas propagasi atribut anotasi melalui atribut mode pada AnnotationCollector .

Sementara itu, ini diduplikasi beberapa kali (#602, #774).

Apakah ada cara untuk membantu dengan yang satu ini? Saya membaca sekilas sumber dan mencoba menemukan tempat anotasi terdeteksi di tempat pertama tetapi tidak dapat menemukannya. Tidak masalah untuk mengotori tangan saya dengan beberapa petunjuk di mana harus melihat dengan tepat.

@olivergierke Anda bisa melihat ini: http://blog.jadonfowler.xyz/2015/06/20/custom-annotation-lombok.html

Saya mengamati dengan seksama kode lombok tadi malam - sepertinya infrastruktur lombok saat ini tidak mendukung mekanisme tipuan seperti yang Anda sarankan.
Sejauh yang saya bisa lihat, semua anotasi tampaknya langsung diterjemahkan ke transformasi AST yang kemudian dikompilasi ke dalam kode "boilerplate" yang harus Anda tulis.

Untuk mengimplementasikan fitur seperti itu, seseorang mungkin perlu menerapkan mekanisme transformasi yang terlebih dahulu mengumpulkan semua Anotasi yang dianotasi dengan @ MetaAnnotation dan mendaftarkan muatan anotasi yang didukung piggy dengan anotasi tertentu seperti @ AutowiredConstructor .
Maka Anda mungkin perlu menerapkan EclipseAnnotationHandler yang dapat menangani anotasi apa pun dan memeriksa apakah itu salah satu dari MetaAnnotation terdaftar. Jika bukan itu masalahnya, pawang kembali, sedangkan pawang mengganti penggunaan MetaAnnotation (misalnya @ AutowiredConstructor ) dengan anotasi yang didukung piggy yang terdaftar.
Kode untuk memperluas anotasi yang didukung piggy dapat ditemukan di sini (dengan onConstructor=...) sebagai contoh.

Mungkin @rspilker atau @rzwitserloot bisa menjelaskan lebih lanjut tentang ini.

Saya akan berpikir ini harus menjadi fitur inti lombok. Misalnya, anotasi @Data dikatakan setara dengan <strong i="6">@Getter</strong> <strong i="7">@Setter</strong> <strong i="8">@RequiredArgsConstructor</strong> <strong i="9">@ToString</strong> @EqualsAndHashCode . Jika anotasi lombok dapat dikomposisi, kita dapat mendefinisikan kelas @Data kita sendiri sesuai dengan kebutuhan kita sendiri. (Misalnya, saya tidak ingin @RequiredArgsConstructor. Ini tidak dapat digunakan dalam banyak kasus.)

Besar +1 ini.

Satu set kelas (entitas) saya memiliki anotasi ini:

<strong i="7">@Data</strong>
@EqualsAndHashCode(callSuper = false)
<strong i="8">@NoArgsConstructor</strong>

Kumpulan kelas (aktor) lainnya memiliki anotasi ini:

<strong i="12">@Slf4j</strong>
<strong i="13">@Singleton</strong>
@RequiredArgsConstructor(onConstructor = @__(@Inject))

Kode kita akan jauh lebih bersih (belum lagi rawan kesalahan) jika saya bisa menulis @MyEntity dan @MyActor .

Harap berhenti menambahkan +1 komentar. Sebagai gantinya, tekan tombol jempol ke atas di komentar paling atas.

Fitur ini akan membutuhkan resolusi pada tahap pemrosesan yang sangat awal. Saat ini hal itu tidak mungkin. Mungkin, karena kita sekarang memiliki sistem konfigurasi lombok, kita mungkin akan menemukan solusi yang berbeda.

@rspilker Apakah mendefinisikan anotasi di lombok.config perlu solusi juga?
Saya harap, tidak, tetapi kemudian, apakah itu benar-benar lebih buruk daripada mendefinisikan metaannotation dalam kode?

lombok.config:
meta.mypackage.NoEtters = @Getter(AccessLevel.NONE) @Setter(AccessLevel.NONE)

<strong i="8">@Getter</strong>
<strong i="9">@Setter</strong>
class SomeClass {
    private int aNormalPrivateInt;
    <strong i="10">@NoEtters</strong>
    private int aVeryPrivateInt;
}

Bahkan jika saya harus juga menentukan anotasi dalam file Java, itu worth it.

Bahkan jika itu tidak dapat dilakukan khusus untuk paket (sehingga anotherpackage.NoEtters akan melakukan hal yang sama), itu masih sepadan.

Halo,

apa status masalah ini?

Adakah peluang untuk menyediakan jangka waktu untuk fitur ini?

Ada kemajuan di sini? Saya akan menghargai sesuatu di sepanjang baris anotasi meta Spring. Kasus penggunaan utama di sebagian besar proyek klien saya adalah untuk membungkus dukungan JPA menjadi satu anotasi.

Saya merasa sangat sedih ketika saya melihat masalah berusia 5 tahun dengan upvotes terbanyak kedua dan 0 pekerjaan selesai.

Tidak perlu sedih! Lihat sumbernya, cari tahu solusi yang mungkin, dapatkan persetujuan untuk konsep Anda dari pengelola proyek, aaaaaand: implementasikan.

Open source tidak berarti Anda mendapatkan semua keinginan Anda secara gratis. Terkadang Anda harus bekerja untuk itu jika Anda menginginkan sesuatu.

Begitu sering saya melakukan hal yang sama dengan

<strong i="6">@Data</strong>
<strong i="7">@AllArgsConstructor</strong>
<strong i="8">@NoArgsConstructor</strong>
<strong i="9">@Builder</strong>
public <strong i="10">@interface</strong> DTO {
}

Baru saja menyelesaikan bukti konsep menggunakan sintaks yang disarankan @Maaartinus :
grafik
Anotasi itu sendiri hanyalah penanda dan tidak akan dihapus. Dengan cara itu juga dimungkinkan untuk menggunakan anotasi pihak ketiga misalnya @javax.persistence.Entity sebagai anotasi meta.
Saya dapat terus mengerjakannya jika @rspilker atau @rzwitserloot menyetujui konsep/sintaks ini.

@ Rawi01 - di mana kode Anda? Saya tidak dapat menemukannya di garpu Lombok Anda.

@prdoyle Saat ini tidak dipublikasikan, saya masih menunggu umpan balik dari salah satu pengelola. Versi saat ini hanya menangani jalur bahagia dan melempar pengecualian/penghentian jika ada sesuatu yang tidak seperti yang diharapkan sehingga tidak cocok untuk penggunaan dunia nyata.

@Rawi01 - yah, saya ingin melihatnya. Saya juga berpikir Anda akan lebih mungkin untuk mendapatkan umpan balik dari pengelola jika Anda menunjukkan mereka bekerja, kode yang dapat digabungkan, bahkan jika itu belum siap untuk diaktifkan.

Saya baru saja menerbitkan versi saat ini sebagai ekstensi: https://github.com/Rawi01/lombok-metaannotations
Masih perlu beberapa pekerjaan yang harus dilakukan tetapi fungsi dasar harus bekerja.

Saya mungkin sedikit memperluas cakupan tiket tetapi apakah akan sangat sulit untuk memperluas fungsionalitas untuk tidak hanya bereaksi pada anotasi yang ada tetapi jenis yang mengimplementasikan yang lain? Kasus penggunaan yang saya miliki adalah sebagai berikut: di perpustakaan jDDD kami mengekspos antarmuka yang mengekspresikan blok bangunan DDD. Ada juga model berbasis anotasi tetapi antarmuka memungkinkan kita untuk mengekspresikan batasan hubungan menggunakan obat generik. Salah satu antarmuka adalah Identifier . Implementasi biasanya terlihat seperti ini:

<strong i="7">@EqualsAndHashCode</strong>
@RequiredArgsConstructor(staticName = "of")
@NoArgsConstructor(access = AccessLevel.PRIVATE, force = true)
class SomeIdentifier implements Identifier { … }

Setelah menyatakan jenisnya sebagai pengidentifikasi melalui antarmuka, akan lebih keren jika saya dapat menghindari anotasi dengan mendaftar:

lombok.metaAnnotations = Identifier lombok.EqualsAndHashCode lombok.RequiredArgsConstructor(staticName = "of") lombok.NoArgsConstructor(access = lombok.AccessLevel.PRIVATE, force = true)

yaitu biarkan pemicu anotasi yang akan ditambahkan menjadi antarmuka alih-alih anotasi.

Itu seharusnya mungkin tetapi saya pikir kita harus fokus pada hal-hal dasar terlebih dahulu.

Saya melihat dua perdebatan besar di sini sebelum kita dapat melanjutkan:

  • Tentang sintaks dan implementasi
  • Tentang sihir voodoo

Lihat komentar berikutnya.

sihir voodoo

Ada 3 lapisan untuk ini.

Sebuah anotasi yang tidak memiliki arti di luar lombok

itu hanya penanda, tidak memiliki retensi runtime, dan tidak ada AP selain lombok yang melihatnya) - ini hanya berfungsi sebagai meta-anotasi, dengan lombok.config menjelaskan apa artinya.

Sebuah anotasi yang memiliki arti di luar lombok

@rawi01 : Dengan cara itu juga dimungkinkan untuk menggunakan anotasi pihak ketiga misalnya @javax.persistence.Entity sebagai anotasi meta.

Di sini Entitas memiliki arti yang melekat, tetapi, juga dapat berfungsi sebagai anotasi meta, menyebabkan lombok bertindak seolah-olah berbagai anotasi lombok, sebagaimana dikonfigurasi dalam lombok.config , juga ada pada apa pun yang dianotasi dengan @Entity .

Lombok dapat membuat template berdasarkan hampir semua hal

@odrotbohm : yaitu biarkan pemicu anotasi yang akan ditambahkan menjadi antarmuka alih-alih anotasi.

Saat Anda menelusuri daftar ini, aspek 'keajaiban voodoo' dari lombok menjadi lebih terasa.

Setiap kali lombok muncul di utas reddit, banyak argumen yang menurut saya agak muluk-muluk muncul: Mereka tampaknya merugikan - argumen yang berlaku untuk hampir semua perpustakaan, atau tampaknya tidak menjadi masalah. Penyakit yang dibayangkan, tidak ada yang tampak nyata.

Masalahnya, dan ini adalah pelajaran dari pengelompokan fokus: Hanya karena argumen yang digunakan orang untuk menjelaskan mengapa mereka tidak menyukai sesuatu adalah beban knalpot kuda, tidak membatalkan fakta bahwa mereka tidak menyukai hal itu. . Hanya saja mereka mengajukan alasan yang tidak adil (dan, mungkin, tidak mungkin meyakinkan orang-orang dengan akal sehat), dan tidak mau menjelaskan mengapa mereka sebenarnya tidak menyukainya. Biasanya mereka tidak tahu diri.

Saya punya firasat, sebagian besar didasarkan pada gagasan bahwa ini adalah satu-satunya argumen yang benar-benar berlaku hanya untuk lombok, sepertinya itu dapat menyebabkan masalah aktual, dan merupakan benang merah (hampir selalu bernama, tinggi dalam daftar , dan mendapat banyak 'saya juga' di komentar), yang saya tahu apa itu.

Lombok terlalu ajaib.

Sebagian, itulah yang harus kita jalani. Lombok pada dasarnya sedikit ajaib, ia melakukan hal-hal yang tampaknya mustahil bagi kebanyakan programmer java yang belum tahu tentang lombok. Berbagai spesifikasi menjelaskan bahwa apa yang dilakukan lombok sebenarnya tidak mungkin.

Namun, sihir tidak hitam dan putih. Ini nuansa abu-abu. Memiliki @Getter menghasilkan pengambil adalah sejelas yang kita bisa membuatnya: Anotasi itu sendiri menjelaskan apa yang dilakukannya, kode tidak akan dikompilasi tanpa lombok di classpath, memiliki lombok di classpath akan (biasanya) berarti pengambil _will_ itu muncul, dan javadoc dari anotasi menjelaskannya secara lebih rinci. Ketergantungan anotasi adalah toples sederhana yang dapat Anda cari di web sebagai upaya terakhir.

Saat Anda melihat daftar di atas, properti ini menjadi _way_ lebih buruk. Anotasi meta dasar sekarang berarti anotasi yang sebenarnya (hal yang Anda lihat dalam kode Anda) tidak lagi dalam lombok.jar , mungkin tidak terlalu jelas tentang apa yang dilakukannya pada dasarnya (Tidak ada yang sejelas @Getter , itulah inti dari fitur ini, bukan? Jelaskan sesuatu yang lebih abstrak dan umum. Tidak ada yang ingin melihat @GetterAndBuilderAndToStringAndJacksonizedAndInjectedAllArgsConstructor dalam kode sumber mereka!).

Tambahkan perilaku ke anotasi yang ada yang sudah memiliki arti yang terdefinisi dengan baik, seperti @Entity , dan sekarang kita benar-benar telah memasuki dunia sihir. Jika Anda tidak memiliki lombok di classpath Anda, atau Anda tidak memiliki lombok.config , kode Anda terus masuk akal semantik lengkap dengan semua deps yang tersedia, namun tidak dikompilasi sama sekali, atau, lebih buruk, memang, tetapi ke dalam file kelas yang tidak melakukan apa yang dimaksudkan penulis.

__Saya merasa cukup kuat bahwa ini adalah jembatan yang terlalu jauh; itu terlalu banyak dan kita tidak harus pergi ke sini.__

Namun, bagaimana kita menghentikannya? Bagaimana lombok tahu bahwa javax.persistence.Entity berarti sesuatu? Kami dapat mencoba untuk menegakkan bahwa ia memiliki retensi kode sumber saja (tetapi ini memerlukan resolusi, masalah besar), dan secara aktif menghapus anotasi dari AST untuk mencoba menyembunyikannya dari pemroses anotasi lain (tetapi kami mungkin tidak dapat melakukan ini dengan andal; lombok mungkin bukan prosesor pertama di baris).

Pilihan lain yang mungkin lebih bermanfaat adalah membuat tuntutan tertentu pada nama anotasi. Misalnya, lombok muncul di suatu tempat dalam struktur paketnya. Ini adalah sesuatu yang dapat kita periksa tanpa resolusi; kami bahkan dapat mendeteksi bahwa Anda memiliki salah satunya, kemudian perhatikan bahwa tidak ada definisi untuk arti anotasi ini di lombok.config Anda, dan malah menghasilkan kesalahan. Ini memecahkan masalah bahwa seseorang yang menginstal lombok tetapi tanpa lombok.config yang benar memiliki kesalahan kompilasi yang misterius.

Sintaksis

Apakah kita ingin memasukkan lebih banyak ke dalam gaya lombok.config, atau apakah kita ingin memasukkan lebih banyak ke dalam gaya 'anotasi' java?

Apakah kita ingin:

> cat lombok.config
lombok.toString.callSuper = true
lombok.fieldNameConstants.innerTypeName = Field

lombok.metaAnnotations += @com.foo.customcompanypkg.ServiceClass Log4j2("myTopic") AllArgsConstructor(onConstructor=?do we support this?) NoArgsConstructor(PRIVATE)

atau sesuatu seperti:

>cat lombok.config
lombok.toString.callSuper = true
lombok.fieldNameConstants.innerTypeName = Field

@com.foo.customcompanypkg.ServiceClass {
  @Log4j2("myTopic")
  @AllArgsConstructor([email protected])
  @NoArgsConstructor(access = AccessLevel.PRIVATE)
}

Saya akan berpikir yang terakhir jauh, jauh lebih baik, tapi mungkin itu hanya estetika pribadi. Yang terakhir mungkin membingungkan, dalam hal itu Anda dapat menulis kode Java lengkap di sana, tetapi itu tidak dapat terjadi ( @Foo(5+2) akan diizinkan di sini, dan tidak ada anotasi non-lombok yang dapat muncul di sini) . Di sisi lain, akan jauh lebih alami untuk menulis dan membaca daripada satu baris panjang.

semantik

Seberapa jauh kita pergi?

  • Apakah kita ingin mendukung kemampuan untuk memiliki dukungan parametrik yang luas, seperti menentukan onConstructor , enum untuk tingkat akses, default topik, dan banyak lagi?
  • Apakah kita ingin mendukung kemampuan untuk menyetel properti yang tidak dimiliki anotasi sebenarnya, karena itu masuk akal pada anotasi meta? Ada berbagai aspek yang dapat dikonfigurasi untuk penangan lombok yang sengaja dapat dikonfigurasi hanya melalui lombok.config, karena kami membayangkan bahwa jika Anda ingin mengubahnya, Anda ingin mengubahnya untuk semua. Seperti nama field logger.
  • Apakah kami mengizinkan meta-anotasi untuk menyertakan meta-anotasi lain untuk 'memperluas' secara efektif? yaitu mendefinisikan @com.foo.Bar sebagai termasuk @com.foo.Baz , di mana Baz sendiri merupakan meta-anotasi yang didefinisikan di tempat lain dalam rantai lombok.config ? Itu menyiratkan bahwa kita memerlukan konsep multi-pass (pertama kumpulkan semua def, dan baru kemudian urai kekacauan, menghasilkan kesalahan jika Anda memiliki loop).
  • Apakah kami mengizinkan parameterisasi? Di mana meta-anotasi mengambil argumen? Sesuatu seperti:

Diberikan:

package com.foo.company.lombokmeta;

public <strong i="27">@interface</strong> Model {
    String name();
}

maka ini diperbolehkan:

@com.foo.company.lombokmeta.Model(name) {
    @AllArgsConstructor(staticName = name)
    <strong i="31">@Getter</strong>
}

Pikirkan basis kode

Agar ini berfungsi, alat (IDE, kompiler, dll) perlu:

  • Memiliki lombok di classpath
  • Waspadalah terhadap lombok jika 'lombok di classpath' tidak cukup, misalnya lombok perlu diinstal di editor Anda.
  • Anotasi meta yang digunakan harus berada di classpath
  • Bagian lombok.config yang relevan harus ada dalam struktur direktori

Melihat hal di atas, saya pikir item pertama, kedua, dan ketiga diberi harga, atau mudah diselesaikan dalam basis kode modern, tetapi yang keempat adalah masalah. Sebagian besar perusahaan/basis kode memiliki lebih dari satu proyek. Beberapa menggunakan monorepo raksasa, dan biasanya memiliki direktori induk tunggal bersama yang dengan demikian memberikan kesempatan untuk memiliki satu ruang kerja-global lombok.config langsung dari kontrol sumber. Tetapi beberapa tidak, dan ini menimbulkan rintangan: Anda dapat 'mendistribusikan' meta-anotasi itu dengan konsep distribusi ketergantungan yang biasa (misalnya, banyak korps memiliki proyek 'util' yang selalu disertakan oleh semua proyek lain, didistribusikan melalui perusahaan sonatype maven distro atau yang tidak), tetapi Anda tidak dapat mendistribusikan lombok.config seperti itu. Kami sudah memiliki beberapa pekerjaan dasar yang dilakukan pada sistem 'termasuk' dan itu akan membantu (karena menyalin-menempelkan definisi meta-anno lengkap dari root lombok.config ke setiap proyek sehingga Anda dapat memeriksanya ke kontrol sumber akan sangat menyakitkan ). Dengan fitur include, setiap proyek masih membutuhkan lombok.config yang menyertakan yang lain, tetapi setidaknya sekarang hanya ada satu tempat untuk mengedit jika Anda ingin mengubahnya. Ini adalah masalah sistem konfigurasi yang melampaui permintaan fitur ini, tetapi permintaan fitur ini, dengan masalah seberapa 'ajaibnya', meningkatkan seberapa besar masalah yang melekat pada sistem konfigurasi itu menyakitkan.

@Rawi01 beberapa juta poin untuk mengerjakan hal ini. Luar biasa seperti biasa. Pertama-tama mari kita hash melalui desain yang kita inginkan dan meredakan ketakutan saya bahwa ini terlalu ajaib (apa dengan liburan, @rspilker dan saya tidak memiliki jalan-jalan mingguan seperti biasa selama 2 minggu ini - biasanya dia membantu dengan itu, juga :P), lalu sintaksnya.

java16 keluar pada bulan Maret. Kami terpaksa merilis versi lombok pada hari itu untuk menyertakan perbaikan untuk bisnis --add-opens (kami tidak ingin merilis perbaikan ini lebih awal dari hari rilis jdk16). Saya ingin tahu apakah kita dapat menargetkan rilis itu dan mungkin membaptis lombok v1.20 itu. Fitur ini memang terasa cukup berdampak untuk menjamin benjolan.

@odrotbohm (dalam komentar yang dihapus): Jika konfigurasi berubah menjadi berikut: (elided: contoh di mana definisi anotasi itu sendiri dianotasi dengan hal-hal lombok. juga elided: Pendapat pribadi mendalam tentang solusi anotasi-anotasi yang mustahil. )

__Ini tidak mungkin, seperti yang telah berulang kali dijelaskan. Baca Resolusi lagi lalu berhenti menyarankannya.__

Sangat menyedihkan untuk terus membaca 'oh, tapi hanya jika'. Ya. Sangat. Bukan solusi yang layak untuk masalah ini. Jika keinginan adalah bagian dari kekuatan kita, mari kita mulai dengan perdamaian dunia, bagaimana menurutmu? :)

Saya menghapus komentar yang menyarankannya sebelumnya tetapi ternyata perlu diulang. Dalam huruf tebal kali ini, mudah-mudahan itu akan membuat ide ini tidur.

Sisa komentar Anda sekarang tidak relevan, atau jika Anda tetap menggunakannya, didasarkan pada dugaan pribadi. Itu tidak mempengaruhi pendapat saya bahwa meta-anotasi sama sekali terlalu ajaib, jadi mungkin tidak layak untuk ditindaklanjuti.

Saat ini saya berpikir fitur ini dapat diterima, tetapi hanya jika nama paket anotasi meta menyertakan paket lombokmeta . Jika tidak, itu adalah kesalahan. Setiap anotasi lombokmeta yang ditemukan lombok di mana saja, akan menjadi kesalahan kecuali jika definisi untuk itu ditemukan dalam file konfigurasi.

Itu berarti bahwa setiap kebingungan tentang 'keajaiban' menghasilkan kesalahan yang menguraikan dengan tepat apa yang sedang terjadi dan di mana untuk membaca lebih lanjut, yang merupakan obatnya, sejauh menyangkut lombok, untuk keajaiban: Jika Anda (seorang programmer) memiliki tidak tahu apa yang terjadi dan tidak mendapatkan petunjuk nyata, itu salah lombok. Jika lombok menjelaskan apa yang terjadi dengan tautan dan semuanya, dan Anda memutuskan untuk beralih ke doa ('sihir jahat!') atau bersembunyi di balik kemalasan - kesalahan beralih ke programmer yang malas/berprasangka, dan dengan demikian, dapat diterima.

Ini juga memiliki manfaat yang cukup besar bahwa lombok akan selalu dapat menganalisis AST dengan sangat cepat untuknya: Anda tidak dapat mengimpor bintang secara rekursif. Entah Anda menulis @foo.whatever.something.lombokmeta.Thing , seperti pada, lombokmeta ada di sana atas nama anotasi, atau Anda menulis import something.lombokmeta.something; di bagian atas, impor bintang atau tidak. Kami dapat mendeteksi kedua kasus dengan sangat cepat.

Tetapi apakah terlalu membatasi untuk menuntut ini?

sihir voodoo
Lombok jelas sedikit ajaib tetapi tampaknya ada juga sekelompok orang yang tidak menyukainya dan pada saat yang sama menyukai kerangka kerja berbasis anotasi lainnya misalnya CDI karena seseorang menulis JSR. Itu tidak masuk akal tapi hei, begitulah keadaannya.

Saya memikirkan argumen Anda dan berpikir bahwa Anda benar segera setelah proyek menjadi lebih besar. Dalam proyek kecil, lebih mudah untuk berbagi informasi satu sama lain dan semua orang tahu bahwa @Entity juga menambahkan @Getter . Membatasi fitur ini ke beberapa kumpulan anotasi yang ditandai ( lombokmeta ) memungkinkan menambahkan beberapa javadoc untuk menjelaskan apa yang dilakukan anotasi meta yang jelas merupakan peningkatan. Karena ini juga merupakan versi minimal yang dapat diperpanjang nanti, saya setuju dengan Anda bahwa ini adalah bagaimana kita harus memulai.

Sintaksis
Saya juga lebih suka sintaks multi-baris tetapi saya juga akan menambahkan kunci konfigurasi biasa ( lombok.metaAnnotations += ) daripada menulis kode dalam file itu. Seseorang yang tidak tahu tentang meta-anotasi tidak akan tahu apa itu. Saya menyarankan agar kita mempertimbangkan setiap baris indentasi sebagai bagian dari baris sebelumnya dan kemudian menghapus jeda baris/spasi putih untuk menentukan nilai akhir. Ini meminimalkan perubahan sistem konfigurasi.

Sintaks WIP saya saat ini adalah seperti ini:

@fully.qualified.SourceAnnotation([parameter=default_value]*) [@fully.qualified.TargetAnnotation([parameter=value]*, [parameter=<bound parameter>]*)]+

di mana bound parameter adalah parameter yang disetel pada anotasi aktual atau nilai default anotasi sumber.

Semantik

Apakah kita ingin mendukung kemampuan untuk memiliki dukungan parametrik yang luas, seperti menentukan onConstructor, enum untuk tingkat akses, default topik, dan banyak lagi?

Saya harus memeriksanya tetapi jika saya ingat dengan benar implementasi saya saat ini sudah mendukung ini.

Apakah kita ingin mendukung kemampuan untuk menyetel properti yang tidak dimiliki anotasi sebenarnya, karena itu masuk akal pada anotasi meta? Ada berbagai aspek yang dapat dikonfigurasi untuk penangan lombok yang sengaja dapat dikonfigurasi hanya melalui lombok.config, karena kami membayangkan bahwa jika Anda ingin mengubahnya, Anda ingin mengubahnya untuk semua. Seperti nama field logger.

Saya tidak mengerti apa yang ingin Anda lakukan :senyum:

Apakah kami mengizinkan meta-anotasi untuk menyertakan meta-anotasi lain untuk 'memperluas' secara efektif? yaitu mendefinisikan @com.foo.Bar sebagai termasuk @com.foo.Baz, di mana Baz sendiri merupakan meta-anotasi yang didefinisikan di tempat lain dalam rantai lombok.config? Itu menyiratkan bahwa kita memerlukan konsep multi-pass (pertama kumpulkan semua def, dan baru kemudian urai kekacauan, menghasilkan kesalahan jika Anda memiliki loop).

Alasan utama untuk melakukan sesuatu seperti itu adalah untuk mengurangi duplikat baris konfigurasi. Karena tidak ada yang tidak dapat dilakukan tanpa fitur ini, saya tidak akan fokus pada yang satu ini. Jika ternyata mudah diterapkan maka bagus untuk dimiliki.

Apakah kami mengizinkan parameterisasi? Di mana meta-anotasi mengambil argumen?

Ini adalah sesuatu yang harus ada, jika tidak, kasus penggunaan terbatas.

Pikirkan basis kode

Jika saya menggunakan sesuatu di lombok.config Saya juga menambahkannya ke kontrol sumber. Jika ada proyek util yang berisi anotasi meta bersama dan tidak ada file konfigurasi di proyek saat ini, itu jelas tidak akan berfungsi seperti yang diharapkan. Saya suka ide untuk menggunakan nama paket terpisah lombokmeta untuk mendeteksi anotasi yang tidak dikonfigurasi dengan benar.


Semua contoh Anda hanya berisi anotasi target lombok, apakah itu disengaja? Fitur ini akan jauh lebih berguna jika tidak dibatasi seperti itu dan saya tidak melihat alasan mengapa harus demikian.

Saya tidak mengerti apa yang ingin Anda lakukan

Sebagai contoh, anotasi @Log4j memungkinkan Anda memilih nama bidang yang dihasilkan. Secara default adalah log , tetapi Anda dapat mengubahnya dengan lombok.config: lombok.log.fieldName = foo , misalnya. Anda tidak dapat mengubahnya dengan @Log4j(name = "foo") , namun - tidak ada annoparam seperti itu.

Alasan tidak ada annoparam adalah karena kami tidak menganggap 'setel nama bidang logger' adalah pengaturan yang ingin dikonfigurasi secara individual setiap kali Anda menggunakannya: Kami pikir nama logger, jika Anda ingin mengacaukannya sama sekali, adalah hal yang ingin Anda ganggu dengan cara yang seragam di beberapa basis kode (paket/proyek/ruang kerja). Oleh karena itu, ini dapat dikonfigurasi dalam lombok.config yang memiliki kemampuan untuk diterapkan ke seluruh paket/proyek/ruang kerja, tetapi tidak pada anotasi itu sendiri, karena tidak demikian.

Dengan anotasi meta, baris: 'anotasi itu sendiri dapat dikonfigurasi untuk penggunaan ini' dan 'lombok.config tidak dapat mengonfigurasi penggunaan individual, tetapi mengonfigurasi paket/proyek/ruang kerja sekaligus' jauh lebih kabur.

Saya menemukan ini jauh lebih tidak menjijikkan:

> cat lombok.config
@com.foo.chatservice.lombokmeta.BotCommand {
    @Log4j(fieldName = "logChannel")
}

Meskipun fieldName bukan annoparam dari @Log4j . Mungkin tidak ada gunanya memperumit masalah dengan ini, lupakan saya menyebutkannya.

Semua contoh Anda hanya berisi anotasi target lombok, apakah itu disengaja?

Ya. Lombok tidak dapat menambahkan hal lain dengan cara yang dapat disaksikan oleh prosesor anotasi yang sudah berjalan, bukan?

Saya pikir itu mungkin tetapi membutuhkan perubahan di semua penangan, bukan? Kayaknya banyak kerjaan :smile:

Ya. Lombok tidak dapat menambahkan hal lain dengan cara yang dapat disaksikan oleh prosesor anotasi yang sudah berjalan, bukan?

Benar, tapi itu sudah terjadi. Jika lombok bukan pemroses anotaton pertama, pemroses anotasi lain mungkin menghasilkan hasil yang salah karena mereka tidak tahu bidang, metode, jenis, dan anotasi baru yang ditambahkan oleh lombok. Jadi setiap orang yang menggunakan lebih dari satu prosesor seharusnya sudah menentukan urutannya.

Jadi setiap orang yang menggunakan lebih dari satu prosesor seharusnya sudah menentukan urutannya.

Mendefinisikan urutan adalah non-sepele. Ya, apa yang Anda katakan itu benar, dan ini telah menyebabkan kekacauan klaster yang cukup panjang dan sulit, misalnya dengan mapstruct, di mana kami (tim lombok dan tim mapstruct) bekerja sama untuk menciptakan skema yang sama sekali baru sehingga Pemroses Anotasi dapat mendaftarkan keduanya [A] yang mereka ada sedemikian rupa sehingga AP yang berjalan sebelumnya dapat melihat ini, dan [B] sistem janji di mana AP dapat mengatakan: Jangan lakukan apa pun, biarkan saya lari dulu, saya _berjanji_ Saya akan memaksa putaran kedua sehingga Anda bisa melakukan hal-hal Anda kemudian.

Saya tidak ingin menggali lubang itu lebih dalam.

Masalah dengan anotasi adalah: Kemungkinan anotasi berinteraksi dengan prosesor anotasi agak besar. Itu setengah dari titik anotasi di tempat pertama: Untuk memicu dan berinteraksi dengan AP (setengah lainnya adalah introspeksi reflektif runtime. Diakui, itu mungkin sedikit lebih besar dari setengah).

Itu sebabnya saya jauh lebih ragu-ragu tentang yang satu itu. Tidak ada perbaikan yang mudah; Anda tidak dapat dengan mudah memesan AP.

Mendefinisikan urutan adalah non-sepele.

Dia. Pemroses anotasi harus diurutkan dengan cara yang sama seperti di jalur kelas, jalur pemroses anotasi, atau flag -processor . Saya tidak sepenuhnya yakin tentang classpath tetapi saya memeriksa sumbernya dan sepertinya itu berbagi logika beban dengan fitur jalur kelas anotasi. Satu-satunya hal yang tidak bisa kita lakukan adalah mengubah urutan di lombok itu sendiri karena tidak dapat memutar kembali waktu dan membatalkan semua yang terjadi sebelumnya. Tapi kita bisa menampilkan peringatan dan sudah ada beberapa kode untuk melakukan itu.

Oof. Ini membuatnya begitu rumit. Tidak, kami tidak melakukan ini, bukan untuk rilis pertama.

Saat meluncurkan fitur ini, anotasi eksternal tidak diizinkan. Kita dapat mengunjungi kembali nanti dengan cukup mudah. Menarik karpet keluar dari bawah fitur ini nanti karena menyebabkan terlalu banyak masalah jauh lebih sulit, bahkan jika kita mulai eksperimental.

Untuk menguraikan mengapa saya pikir itu sangat rumit:

  • Lombok sendiri membutuhkan skema deteksi untuk mengetahui bahwa itu bukan prosesor anotasi pertama di lineup. Ingatlah bahwa ini mungkin memerlukan kode terpisah untuk setidaknya ecj dan javac karena saya pikir Anda biasanya tidak dapat memeriksanya.
  • Kemudian perlu memeriksa apakah semua prosesor yang mendahuluinya dikenali sebagai mendukung fitur round-delay. Satu-satunya prosesor yang saat ini mampu melakukan itu, adalah versi terbaru dari mapstruct. Jika demikian, tidak perlu mengangkat masalah apa pun. Agaknya kami dapat menghapus AP semacam itu dari daftar 'berlari sebelum kami'.
  • Skema deteksi ini sebenarnya tidak bisa error. Itu hanya perlu menyimpan ini di suatu tempat dan tidak melakukan apa-apa.
  • Fitur meta-anotasi tidak menyuntikkan anotasi sama sekali, setidaknya, bukan anotasi lombok: Ini hanya menggunakannya untuk memicu penangan, itu tidak benar-benar menambahkannya hanya untuk penangan untuk menghapusnya lagi, tampaknya aneh untuk melakukan itu. Namun, untuk annos non-lombok, itu AKAN menyuntikkannya, _AND_ mengambil dari lapisan kerangka kerja jika lombok bukan baris pertama. Jika tidak mengantre terlebih dahulu, meskipun kami tidak tahu apakah prosesor di depan kami terpengaruh, kami harus melakukan kesalahan dan memberikan saran tentang cara memastikan lombok berjalan terlebih dahulu.
  • Kami harus menyelidiki apakah kami perlu memungkinkan pengguna untuk menentukan daftar AP yang mereka tahu tidak mungkin terpengaruh oleh ini. Anotasi apa pun yang tujuannya adalah refleksi runtime tidak relevan (jadi apakah kita memerlukan daftar itu juga?), Seperti halnya AP apa pun yang tidak memindai anotasi sejak awal, yang lebih jarang tetapi terjadi. Dan tentu saja ada anggapan bahwa meta-anotasi mencakup anotasi non-lombok, tetapi tidak ada anotasi yang secara khusus memengaruhi AP yang berjalan sebelum lombok. Tetapi rasanya seperti banyak pekerjaan untuk mencoba menjelaskan kepada programmer apa yang perlu mereka lakukan: Di mana mengkonfigurasi hal ini dan apa yang menjamin ketika mereka melakukannya.

Saran tentang cara membuat lombok berjalan terlebih dahulu kemudian tidak sepele: Ya, kami dapat menjelaskan bahwa jika lombok adalah yang pertama di classpath, __and__ Anda tidak menggunakan sakelar -processor eksplisit, itu _harus_ baik-baik saja, tetapi kebanyakan programmer java tidak menjalankan javac , mereka menjalankan mvn atau gradle , dan jika Anda menggunakan modul, cara AP dijalankan dalam build modular sangat berbeda , jadi penjelasan sebenarnya tentang cara menjalankan lombok terlebih dahulu membutuhkan 10 penjelasan: non-modular dan modular (2 pilihan), dikalikan dengan sekitar 4 sistem build populer (javac, mvn, gradle, sbt, dan 'exotics'. Eclipse dan intellij biasanya juga dihitung, tetapi karena plugin/agen, kami selalu berada di urutan pertama pada platform tersebut).

Bundel itu bersama-sama dan saya menarik kesimpulan bahwa ini bukan ide yang baik untuk rilis pertama fitur baru ini, tetapi jika ada rute yang lebih mudah dan/atau ini dianggap cukup penting untuk menjamin upaya semacam ini, mungkin kita harus lakukan saja. Tampak sedikit diktator untuk menembak jatuhnya hanya berdasarkan imajinasi internal saya yang tidak dinyatakan

Jika kami ingin menerapkan mekanisme deteksi yang tepat termasuk daftar prosesor anotasi yang didukung yang dapat dikonfigurasi, beberapa pekerjaan tambahan diperlukan. Jika itu rumit untuk versi pertama, ada dua solusi lain yang mungkin:

  • Jika ada anotasi target yang bukan anotasi lombok lombok mencetak kesalahan misal Additional configuration required, please read https://projectlombok.org/... . Untuk menonaktifkannya, kunci konfigurasi baru lombok.isFirstAnnotationProcessor = true harus disetel.
  • Abaikan saja kasus ini dalam kode dan tambahkan saja ke dokumentasi. Hanya ada beberapa pemroses anotasi yang populer sehingga tidak semua orang terpengaruh dan ada juga kemungkinan pemroses anotasi sudah diurutkan dengan benar. Jika sesuatu tidak berfungsi dengan baik, mudah-mudahan akan ada posting stackoverflow dengan tautan ke dokumen :smile: Menulis dokumentasi jelas merupakan pekerjaan yang sulit.

Fitur meta-anotasi tidak menyuntikkan anotasi sama sekali, setidaknya, bukan anotasi lombok: Ini hanya menggunakannya untuk memicu penangan, itu tidak benar-benar menambahkannya hanya untuk penangan untuk menghapusnya lagi, tampaknya aneh untuk melakukan itu. Namun, untuk annos non-lombok, itu AKAN menyuntikkannya, _AND_ mengambil dari lapisan kerangka kerja jika lombok bukan baris pertama. Jika tidak mengantre terlebih dahulu, meskipun kami tidak tahu apakah prosesor di depan kami terpengaruh, kami harus melakukan kesalahan dan memberikan saran tentang cara memastikan lombok berjalan terlebih dahulu.

Membuat anotasi baru dan menghapusnya nanti adalah cara kerja draf saya saat ini. Ini mungkin tampak aneh tetapi jika tidak, Anda harus menangani sendiri pemesanan dan konflik dengan anotasi lombok lain yang ada. Anda juga harus menyelesaikan meta-anotasi bidang

misalnya

//<strong i="15">@PublicGetter</strong> => @Getter(AccessLevel.PUBLIC)
//<strong i="16">@NoGetter</strong> => @Getter(AccessLevel.NONE)

<strong i="17">@PublicGetter</strong>
public class Test {
    <strong i="18">@NoEtter</strong>
    private String test;
}

Jika pengendali meta-anotasi memanggil pengendali pengambil secara langsung @PublicGetter membuat pengambil publik, bahkan jika anotasi @NoEtter harus mencegahnya. Jika itu hanya mengganti anotasi, semuanya akan baik-baik saja.

Bundel itu bersama-sama dan saya menarik kesimpulan bahwa ini bukan ide yang baik untuk rilis pertama fitur baru ini, tetapi jika ada rute yang lebih mudah dan/atau ini dianggap cukup penting untuk menjamin upaya semacam ini, mungkin kita harus lakukan saja. Tampak agak diktator untuk hanya menembak jatuh berdasarkan imajinasi internal saya yang tidak dinyatakan stuck_out_tongue

Anda adalah pengelolanya, Anda dapat memutuskan fitur mana yang akan ditambahkan atau tidak. Jika kediktatoran Anda menjadi terlalu menindas maka saya masih bisa membuat handler meta-anotasi-plus saya sendiri :stuck_out_tongue:

Saya mengerti bahwa mendefinisikan anotasi khusus tidak dapat berfungsi. Namun memiliki anotasi khusus standar memiliki keuntungan membaginya antar proyek melalui mekanisme ketergantungan standar.
Saya pikir kita perlu berbagi itu karena saya ingin berbagi anotasi meta lombok di seluruh perusahaan/tim antar proyek. Ini penting karena semakin banyak tim menggunakan repositori berbeda untuk layanan mikro yang berbeda. Jadi, bahkan tim kecil dapat memiliki banyak repositori dan mereka ingin berbagi anotasi meta yang sama di pustaka "umum".

Sejauh yang saya tahu lombok.config memungkinkan sertakan dari jalur sistem file dan gelembung ke induknya. Ini bagus untuk banyak hal tetapi tidak begitu bagus untuk berbagi berbasis classpath.
Saat ini yang bisa saya lakukan adalah menyalin ketergantungan team-lombok.config melalui alat build (mis: maven) dan memasukkannya ke dalam lombok.config . Itu jauh dari ideal.
Saya membaca #791 yang menyatakan:

Kami tidak bermaksud untuk mencari lombok.config di classpath, karena itu berarti memasukkan lombok.config dalam file jar berarti semua pengaturan itu tiba-tiba berlaku untuk proyek itu.

Ini benar tetapi dapat diselesaikan dengan menambahkan tanda ke proyek lombok.config untuk menyertakan konfigurasi classpath.

Apa yang saya coba katakan adalah bahwa semakin banyak informasi yang Anda tambahkan ke lombok.config semakin banyak orang yang ingin membaginya di antara proyek-proyek. Penting untuk merencanakan sesuai ini dan membuat berbagi lebih mudah.

@Rawi01 menulis: Membuat anotasi baru dan menghapusnya nanti adalah cara kerja draf saya saat ini.

Jika akhirnya membuat proses lebih sederhana, lebih kuat, dan mungkin lebih banyak bukti di masa depan, maka menurut definisi (saya) solusi yang paling elegan, dan rasa estetika saya salah. Melanjutkan.

@Rawi01 Hanya ada beberapa prosesor anotasi yang populer...

Anda tahu, sekarang saya memikirkannya, apa yang terjadi jika kita selalu memaksakan babak baru jika kita menambahkan annos non-lombok? Atau, memaksa babak baru jika scan pemesanan AP kita menunjukkan lombok tidak berjalan duluan? Idenya adalah _jika_ AP berlari sebelum kita yang benar-benar ingin melihat annos itu, kemungkinan besar mereka akan mengambilnya di babak berikutnya dan melakukan apa pun yang seharusnya mereka lakukan. Ini bukan jaminan menyeluruh - AP yang berjalan lebih awal mungkin telah memutuskan bahwa ia telah mengumpulkan semua info yang diperlukan dari berbagai anotasi yang dipicunya, dan sudah menghasilkan data. Atau, putaran kedua membingungkannya dan membuatnya menghasilkan apa pun yang akan dihasilkannya berdasarkan data yang tidak lengkap.

Tapi saya yakin itu akan memperbaiki sebagian besar skenario. Kami hanya perlu mendaftar dari awal sehingga kami mungkin harus meninggalkan skema ini jika menyebabkan terlalu banyak masalah. Rasanya _tad_ berarti sedikit banyak memaksa komunitas untuk menguji hal ini, tetapi, itulah gunanya experimental . Ini bukan fitur yang diasosiasikan dengan paket lombok, tapi kami akan memerciki __experimental!__ semuanya; Saya tidak berpikir kita dapat sepenuhnya menilai dampak dari semua ini, atau menjamin keduanya bahwa kita tidak akan merusak fitur ini.

@gebezs menulis: Sejauh yang saya tahu lombok.config memungkinkan sertakan dari jalur sistem file dan gelembung ke induknya. Ini bagus untuk banyak hal tetapi tidak begitu bagus untuk berbagi berbasis classpath.

Yup, ini adalah masalah serius yang belum terpecahkan dengan permintaan fitur ini.

Kami tidak bermaksud untuk mencari lombok.config di classpath, karena itu berarti memasukkan lombok.config dalam file jar berarti semua pengaturan itu tiba-tiba berlaku untuk proyek itu.

Ini benar tetapi dapat diselesaikan dengan menambahkan flag ke proyek lombok.config untuk menyertakan konfigurasi classpath.

Komentar lebih menjelaskan mengapa kami tidak menyelidiki melakukan itu: Ini bukan slamdunk untuk melakukan ini. Namun, __itu mungkin ide yang cukup bagus__ – bagaimana jika definisi meta-anotasi __are__ diambil untuk ini? Seperti pada, entri lombok.config di classpath Anda dibaca, tetapi hanya untuk definisi meta-annos, bukan untuk pengaturan.

Satu masalah yang cukup besar adalah bahwa classpath sebagai konsep umum pada dasarnya tidak mendukung konsep 'daftar' file, jadi kita tidak bisa hanya memindai classpath untuk setiap lombok.config yang dimilikinya. Saya melihat 4 solusi untuk masalah ini:

  • Lihat di tempat yang sama dengan anno. Jika lombok memperhatikan bahwa @com.foo.lombokmeta.MetaAnno ada di mana saja dalam file sumber, lombok meminta classpath untuk file /com/foo/lombokmeta/lombok.config dan bertindak sesuai, dan akan error pada anotasi itu jika ada beberapa konfigurasi yang bertentangan.
  • Selalu cari di /lombok.config untuk SEMUA entri classpath. Kesalahan jika konflik.
  • Paksa pengguna untuk menulis lombok.config eksplisit di tempat biasa, tetapi izinkan fitur import dalam lombok.config yang berfungsi melalui classpath.
  • Singkirkan semua jazz ini, dan _do_ pergi dengan gagasan bahwa Anda membubuhi keterangan meta-anotasi. Ini menghujani parade menggunakannya untuk anotasi non-lombok seperti yang diinginkan @Rawi01 (karena mungkin tidak dikonfigurasi untuk diizinkan pada anotasi), dan membuat parameterisasi menjadi sulit, dan mengharuskan lombok untuk mengurai file kelas itu, yang menyebabkan masalah jika Anda edit meta-anno di editor Anda. Saya tidak suka opsi ini.

Saya sudah berpikir ini adalah sintaks unik 'layak' dalam lombok.config (bukan lombok.meta += .... , tetapi sintaksnya sendiri), dan ide ini lebih jauh menyoroti perlunya ini (dengan asumsi kita menggunakan salah satu dari yang pertama 3 pilihan).

Pertanyaan besarnya adalah: _can_ kita dengan mudah mengetahui apa itu classpath? Saya menduga kita mungkin bisa melakukan ini: Di ​​javac, ada filer, yang memungkinkan kita melakukan ini melalui API-nya sendiri, dan bahkan jika tidak, kemungkinan besar akan mencerminkan jalan kita ke apa yang kita butuhkan. Untuk intellij, yah, mereka pasti tahu CP proyek itu tidak masalah. Untuk Eclipse, ini jauh lebih sulit daripada yang Anda pikirkan, tetapi saya ingat bahwa kami telah melakukan beberapa kejahatan yang cukup gila untuk mengetahui direktori tempat file sumber berada (untuk lombok.config), tetapi Eclipse paling mengkhawatirkan saya untuk ide ini .

Saya tahu bahwa OSGi adalah topik yang sedikit berbeda tetapi mereka memiliki masalah yang sama: melintasi classpath untuk file. Ini bisa dilakukan dengan pustaka pemindai classpath tetapi bisa lambat. Jadi di dunia OSGi kita biasanya mengandalkan file META-INF/MANIFEST.MF . Seperti yang Anda ketahui bahwa file hanya berisi pasangan nilai kunci seperti Created-By: Apache Maven Bundle Plugin . Ini berarti dimungkinkan untuk menyimpan jalur di dalam toples itu seperti Service-Component: OSGI-INF/pkg.Cl1.xml,OSGI-INF/pkg.Cl2.xml . Entri Service-Component memberitahu sistem untuk membaca file pgk.Cl1.xml dan pkg.Cl2.xml dari toples yang sama, membaca xml sebagai definisi layanan dan memuat layanan. Ini memecahkan pemindaian classpath karena tidak diperlukan lagi karena semuanya dimulai dengan file META-INF/MANIFEST.MF . Jelas ada kelemahan besar: MANIFEST.MF sangat kompleks sehingga kita harus menggunakan alat waktu kompilasi untuk menghasilkannya karena pemeliharaan dengan tangan tidak mungkin dilakukan.

Tidak perlu berpegang pada MANIFEST.MF kita dapat menggunakan META-INF/lombok.meta atau apa pun yang terdengar terbaik.

Solusi ini akan memaksa pengembang perpustakaan untuk secara eksplisit mengekspor anotasi meta mereka dan mungkin akan membantu pengelola alat lombok untuk menemukannya dengan mudah.

Dan seperti yang saya katakan itu adalah dunia OSGi yang merupakan tempat yang bagus tetapi sedikit berbeda dari alam semesta Java lainnya.

Saya sama sekali tidak menyukai ide configure-by-classpath. Classpath adalah hasil dari pengaturan proyek/kompilasi, yang disampaikan, misalnya, melalui konfigurasi maven atau gradle.
Lombok, bagaimanapun, umumnya tidak terkait dengan classpath. Ia bekerja hanya selama kompilasi unit kompilasi saat ini. Jadi, itu hanya boleh dikonfigurasi oleh sumber dan pengaturan kompiler secara langsung.
Membiarkan classpath mempengaruhi konfigurasi Lombok memperkenalkan tingkat tipuan yang mungkin menyebabkan kebingungan: Mungkin Anda baru saja menambahkan dependensi baru, dan tiba-tiba file sumber Anda dikompilasi ke file kelas yang berbeda, karena dependensi baru mengandung lombok.config .

Ada jalan keluar: Izinkan Lombok untuk dikonfigurasi melalui konfigurasi maven/gradle. Setidaknya dengan maven Anda dapat menggunakan pom dasar/induk, yang dapat Anda bagikan di antara proyek.

Hubungan induk-dasar Maven adalah pewarisan sedangkan solusi classpath adalah komposisi. Saya menemukan komposisi jauh lebih fleksibel untuk proyek tetapi ini hanya pendapat saya.

Spring Boot memang memuat keajaiban dari classpath dan ini adalah kerangka kerja yang populer ( source ).

Saya pikir bahkan kemampuan untuk memasukkan file dari classpath akan sangat bagus. Sesuatu seperti musim semi classpath: dan classpath*: :

# finds all conf/lombok-meta.config files and imports them in the classpath's order
import classpath*:conf/lombok-meta.config
# finds the lombok-main.config (first in the classpath) and imports it
import classpath:lombok-main.config

classpath: dapat menampilkan peringatan atau dapat berhenti dengan kesalahan jika ditemukan banyak file.
Spring mendukung wildcard gaya semut ( classpath*:config/**/*.xml ) tetapi itu akan membutuhkan pemindaian classpath sehingga tidak diragukan lagi.

Dengan cara ini pengembang dapat memutuskan jalur mana yang ingin mereka ikuti.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat