agentskills.codes

Port a class/interface from java lucene into platform agnostic kotlin common lucene-kmp codebase

Install

mkdir -p .claude/skills/port && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/14298" && unzip -o skill.zip -d .claude/skills/port && rm skill.zip

Installs to .claude/skills/port

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Port a class/interface from java lucene into platform agnostic kotlin common lucene-kmp codebase
96 charsno explicit “when” trigger

About this skill

overall project description

I'm porting Apache Lucene from Java to platform agnostic kotlin common to make multiplatform library lucene-kmp which supports Kotlin/Android, Kotlin/Native(iOS, macOS, Linux), and Kotlin/JVM(desktop and server).

java package structure

For example, in core module, the root package is: lucene/lucene/core/src/java/org/apache/lucene/ core module's unit tests are in root package: lucene/lucene/core/src/test/org/apache/lucene/ And those root contains sub packages such as analysis, codecs, document, index, internal, search, store, util and their sub packages.

kmp package structure

For example, in core module, the root package for port destination is: lucene-kmp/core/src/commonMain/kotlin/org/gnit/lucenekmp/ lucene-kmp core module for unit tests are in the root package: lucene-kmp/core/src/commonTest/kotlin/org/gnit/lucenekmp/ And it contains sub packages such as analysis, codecs, document, index, internal, search, store, util, and especially the one which is not found in java lucene: jdkport

package name convention on porting process

For classes/interfaces in sub packages which is made by lucene, which is "analysis, codecs, document, index, internal, search, store, util", we will respect exact same java lucene's sub packagename for both "code" and "unit test".

For example, in case of code, org.apache.lucene.document.BinaryDocValuesField has been ported to org.gnit.lucenekmp.document.BinaryDocValuesField in case of unit test, org.apache.lucenep.util.TestUnicodeUtil has been ported to org.gnit.lucenekmp.util.TestUnicodeUtil

about jdkport package

During the porting process there was JDK classes which is used in Java lucene but have no equivalent pair in kotlin standard library (standard library of kotlin common). To smooth the porting process I decided to port also those JDK classes into "package org.gnit.lucenekmp.jdkport" which is located in lucene-kmp/core/src/commonMain/kotlin/org/gnit/lucenekmp/jdkport

There are some edge case such as Double. jdk and kotlin standard lib both has Double class but the some jdk Double functions are not found in kotlin ones. In such case, I created a kotlin file contains extension functions to fill the functionality pair gap. The file name convention for extension function is for example "for Double class, kt file is named DoubleExt.kt"

So for classes/intefaces in jdkport sub packages, we will NOT respect jdk package names but all JDK classes/interfaces will be ported to jdkport sub package. The name of the classes/interfaces will be kept exact same.

For example, java.util.BitSet which is used in lucene java but no equivalent exsits in kotlin std lib will be ported to org.gnit.lucenekmp.jdkport.BitSet java.lang.Character has been ported to org.gnit.lucenekmp.jdkport.Character java.net.Inet4Address has been ported to org.gnit.lucenekmp.jdkport.Inet4Address

naming convention for unit tests for those classes will be ClassNameTest, which is for example: org.gnit.lucenekmp.jdkport.CharacterTest and org.gnit.lucenekmp.jdkport.Inet4AddressTest

Port of Classloader.java and ServiceLoader.java is does as skeleton with no operation functions because I still did not decide how to walk around this JVM specific feature in kotlin common. So creating unit tests for Classloader and ServiceLoader is also skipped for now.

And because jdk package structure will be lost, for only jdk port class/interface, we add @Ported annotation to the class like @Ported(from = "java.lang.Character")

Steps to Port

Step 1. Create the exact same of the class/interface by replacing .java to .kt in the target package. e.g. ClazzToPort.java to ClazzToPort.kt Step 2. First copy import statements which starts with org.apache.lucene by replacing it with org.gnit.lucenekmp do not port jdk import statements at this time. Step 2.1: create empty class with LuceneTestCase inheritance and import statements with correct org.gnit.lucenekmp packagess Step 2.2: Create inner classes with proper inheritance and property members Step 2.3: Add property members and no-op functions in inner class and main class Step 2.4: Port and fill implementations of each no-op functions and try to follow as much java lucene behavior possible, run open_file_in_editor first and then get_file_problems for each time after porting a function and fix error. Step 3. run open_file_in_editor tool of jetbrains mcp server for the file, then run get_file_problems tool for the same file. get_file_problems may not emit diagnostics unless the file is opened in the editor first. unresolved reference compilation error means un-ported-dependency class/interface, leave current class as it is and start over from Step 1 for that class. Step 4. After import-statements-only class/interface file ClazzToPort.kt get no compilation error with open_file_in_editor + get_file_problems, start porting the body of the code. Step 5. During porting body of the class, if you find any jdk specific class used, try to find it in jdkport package and if you find import it and use it. Step 6. If you did not find jdkport class/interface, do one of the following: Case 1 -> Functional interface: interfaces in java.util.function should be replaced with kotlin function representation, e.g. Predicate<T> to be (T) -> Boolean, IntFunction<R> to be (Int) -> R Case 2 -> Collection operation such as .stream() or map should be replaced with idiomatic kotlin equivalents. array creation should be done with Array(size){ i-> entry } style. Case 3 -> java.lang.Thread related classes are mostly ported to jdkport so use it but if not found port it using kotlin coroutine Job and related coroutine building block mimicking the behavior as much as possible. Case 4 -> Large but mostly static method utility jdk classes such as java.lang.Math are ported partially. port only specific missing static method by adding that specific kotlin function to existing jdkport class. Case 5 -> Complex reflections or java.security or other jdk specific things which can not be translated into KMP common code should be bypassed by creating empty no-op class and functions throwing UnsupportedOperationException() Case 6 -> ClassLoader related logic, should be replaced with hard coded class names and constructors. see examples of existing already ported NamedSPILoader.java and NamedSPILoader.kt Case else -> go to Step 7 which is porting new jdk port Step 7. Create a empty kotlin class/interface jdkport and try to find if all the dependencies or super class, super interface is already in jdkport package, if not found, port super class/interface recursively.
Step 8. If all the super class/interface of the jdk class ported into jdkport package, start porting the jdkport class. Step 9. If there are no missing jdkport class, and if there are no un-ported-dependency class/interface from Java Lucene, port the code of the ClazzToPort.kt Step 10. After porting logic and behaviors code, run open_file_in_editor first, then run get_file_problems tool of jetbrains mcp server and edit and iterate over until all errors resolves. Step 11. Final parity pass: compare Java and Kotlin files side-by-side. Check for missing or misordered member properties, functions, and logic blocks. Add missing pieces and reorder Kotlin members/functions/logic to match Java ordering so both files stay side-by-side with full behavior and implementation parity. Step 12. Test execution order is mandatory: run and iterate on focused jvmTest first until all tests pass on JVM. Only after JVM is green, run focused macosX64Test (or active native target) as the final verification to detect Kotlin/Native-specific problems.

Non-negotiable defaults (do this without being asked)

  1. Side-by-side parity is default

    • Keep Java control flow shape, local variable order, comments, and key blocks in the same order as upstream Java.
    • For tests, keep parity for important inline blocks (e.g. custom scheduler object blocks, custom InfoStream blocks, latch/barrier choreography, and merge/thread coordination).
    • If a Java block cannot be copied 1:1 due to KMP constraints, keep the structure and intent, then add the smallest possible KMP-safe replacement.
  2. KMP common safety is default

    • In commonMain/commonTest, do not use JVM-only threading APIs or kotlin.concurrent.thread.
    • Replace Java/JVM thread usage with Kotlin coroutines (Job, CoroutineScope, launch, join) or jdkport concurrency primitives when they already exist.
    • For lock/coordination behavior, prefer existing jdkport constructs (e.g. ReentrantLock, CountDownLatch) where parity benefits from them.
  3. Compile-fix loop is mandatory

    • After each substantial edit chunk (or after each ported function for long files), run JetBrains open_file_in_editor first, then get_file_problems.
    • get_file_problems may not emit diagnostics unless the file is opened in the editor first.
    • Fix all errors immediately before continuing.
    • Keep iterating until there are zero errors in edited files.
    • Warnings can remain unless they indicate a parity/correctness issue.
  4. Kotlin API correctness while preserving parity

    • Keep Java intent but use Kotlin-correct API shapes:
      • anonymous subclass creation uses object : Type(...) { ... }
      • assertEquals(expected, actual, message) ordering for Kotlin test APIs
    • Do not keep Java call signatures when they are invalid in Kotlin.
  5. No prompt repetition policy

    • Assume the user always wants the above parity + KMP-safe behavior unless explicitly overridden.
    • Do not wait for reminders like “keep side by side”, “run get_file_problems”, or “replace thread usage in common”.

Code Style of Port

Style 1. Ease of side by side comparison: The property names, var/val names, method/function names, inner class


Content truncated.

Search skills

Search the agent skills registry