Contributions are welcome and accepted. Please create issues or pull requests!
Note
This project is developed on Codeberg; Due to technical limitations, pull requests aren't accepted from GitHub—any commit on the codeberg repository immeidately overrides any unmerged changes on GitHub. Migrating your repository to Codeberg is easy, and you can create an account simply by logging in with your GitHub one.
Don't worry too much about this part, tweaking an API to match the style guide is a relatively easy task.
- APIs should be thread-safe and immutable by default.
- Expensive operations should be
suspend funs. - To create a new API, always declare an interface or (for immutable data) a data class. If possible, declare it as a
fun interface(see Interfaces, Functional Interfaces, or Typealiases below).- Never expose non-
annotation, non-dataclasses as public API, especiallyabstractones. - Take care when exposing
dataclasses as public API: if you intend on giving them more properties, annotate them with@ExperimentalSpockApi, and the constructor with@JvmOverloads; The automatically-generatedcopyfunction will break when adding more properties. - Prefer composition (e.g. interface delegation) over inheritance.
- Never expose non-
- Implementations should be instantiated via extension functions (e.g.
ByteArray.appender()) or functions named the same or as if they were a subtype of as the interface (e.g.ByteAppender(),NonThrowingByteAppender()). - If an implementation accepts a lambda as a parameter (e.g.
EverlastingMutex(producer: (Descriptor) -> Product)), it should be implemented, with the lambda markedcrossinline. Otherwise, declare a private class (usually calledFooImpl).- Mark the implementation class (or if inline, the function) with the
@authorKDoc tag.
- Mark the implementation class (or if inline, the function) with the
- Always expose everything necessary for users to reimplement a built-in API. If some API is lower-level and should not be used except for this specific purpsoe, mark it with
@RawSpockApi. - If an API allows easily breaking the contract of another, mark it with
@DelicateSpockApi. - If you're unsure about an API, mark it with
@ExperimentalSpockApi. - Document your APIs, and always use the
@sinceKDoc tag.- When removing the
@ExprimentalSpockApiannotation, don't change the@sincetag. - When breaking ABI or API compatibility, reset the
@sincetag.
- When removing the
- Always use
@Throwswhen applicable, including the@throwsKDoc tag. - Prefer descriptive type parameter names; for example,
KeyandValueare better thanKandV.- Prefer an existing type variable convention (
KandVfor maps) over creating your own.
- Prefer an existing type variable convention (
- Except for
: Any, prefer usingwherefor type variables. - For type variables, prefer using
T & AnyoverT : Any, unless you use a type that explicitly boundsTto extendAny(not be nullable).
- First, decide on your interface's contract.
- If you intend on declaring extensions on the interface, or having a complex contract, do not use a typealias.
- If you're unsure about a member function's signature, mark it with
@ExperimentalSpockApi. - If you're sure about the current API, but not sure if you want to add more functions later, mark it with
@RequiresSubclassOptIn(ExperimentalSpockApi::class). - Do not insist on only having one function.
- Do not insist on using an
operator fun invoke. - Do not insist on using a function in favor or a property.
- If the interface can be made functional, make it so.
- See the Kotlin documentation on the topic.
- Prefer nullability over
::prop.isInitialized. - Prefer
Flagoverlateinit var: Unit.
Tip
All commands are also available as IntelliJ run configurations in the .run directory.
./gradlew allTests --quiet --stacktrace./gradlew :docs:dokkaGenerate --stacktraceImportant
Do not commit the docs/history directory yourself;
It'll be generated automatically.
A link to the rendered documentation will be provided in the console,
in the form of localhost:PORT/spock/docs/current/index.html,
usually on port 63342.
./gradlew :example:jvmRun --quiet --stacktraceNote
Replace Platform below with your operating system; for example, LinuxX64.
./gradlew :example:runDebugExecutablePlatform --quiet --stacktrace./gradlew :example:runReleaseExecutablePlatform --quiet --stacktrace./gradlew :example:wasmJsBrowserDevelopmentRun --quiet --stacktrace./gradlew :example:wasmJsBrowserDevelopmentRun --quiet --stacktrace./gradlew apiDump --quiet --stacktrace./gradlew koverHtmlReport --quiet --stacktrace