Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the JavaDoc generation #308

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,14 @@ fun String.callback(
functionDoc: String,
vararg signature: Parameter,
returnDoc: String = "",
see: Array<String> = emptyArray(),
since: String = "",
init: (CallbackFunction.() -> Unit)? = null
): CallbackType {
val callback = CallbackFunction(packageName, className, returns, *signature)
if (init != null)
callback.init()
callback.functionDoc = { it -> it.toJavaDoc(it.processDocumentation(functionDoc), it.signature.asSequence(), it.returns, returnDoc, since) }
callback.functionDoc = { it -> it.toJavaDoc(it.processDocumentation(functionDoc), it.signature.asSequence(), it.returns, returnDoc, see, since) }
Generator.register(callback)
Generator.register(CallbackInterface(callback))
return CallbackType(callback, this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class ConstantBlock<T : Any>(
var access: Access,
val constantType: ConstantType<T>,
val documentation: () -> String?,
val see: Array<String>,
vararg val constants: Constant<T>
) {

Expand Down Expand Up @@ -164,7 +165,7 @@ class ConstantBlock<T : Any>(
"""
}
}
}, *rootBlock.toArray(emptyArray())).let {
}, see, *rootBlock.toArray(emptyArray())).let {
it.noPrefix = noPrefix
it.generate(writer)
}
Expand All @@ -176,7 +177,7 @@ class ConstantBlock<T : Any>(
println()
val doc = documentation()
if (doc != null)
println(doc.toJavaDoc())
println(doc.toJavaDoc(see = see))

print("$t${access.modifier}static final ${constantType.javaType}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ class Func(
}.let { hiddenParameters ->
val documentation = nativeClass.processDocumentation("Unsafe version of: $javaDocLink")
println(if (hiddenParameters.any())
nativeClass.toJavaDoc(documentation, hiddenParameters, returns.nativeType, "", "")
nativeClass.toJavaDoc(documentation, hiddenParameters, returns.nativeType)
else
documentation.toJavaDoc()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ abstract class GeneratorTarget(
}

var documentation: String? = null
var see: Array<String> = emptyArray()
var since: String = ""

internal val preamble = Preamble()

Expand Down Expand Up @@ -210,7 +212,7 @@ abstract class GeneratorTarget(

val documentation = this@GeneratorTarget.documentation
if (documentation != null)
println(processDocumentation(documentation).toJavaDoc(indentation = ""))
println(processDocumentation(documentation).toJavaDoc(indentation = "", see = see, since = since))
}

abstract fun PrintWriter.generateJava()
Expand Down
145 changes: 102 additions & 43 deletions modules/generator/src/main/kotlin/org/lwjgl/generator/JavaDoc.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The first text sub-block is not wrapped in <p> because:

For the purposes of this transformation, the javadoc root is an implicit block.
*/
private fun String.cleanup(linePrefix: String = "$t * "): String {
private fun String.cleanup(linePrefix: String = ""): String {
val dom = trim().replace(REDUNDANT_WHITESPACE, "")
return StringBuilder(dom.length).layoutDOM(dom, linePrefix)
.replace(CLEANUP_PATTERN, linePrefix)
Expand Down Expand Up @@ -122,82 +122,141 @@ private fun StringBuilder.appendParagraph(linePrefix: String, text: String, star
append("</p>")
}

fun String.toJavaDoc(indentation: String = t, allowSingleLine: Boolean = true): String {
val clean = cleanup("$indentation * ")
private fun String.toJavaDoc(indentation: String = t, allowSingleLine: Boolean = true): String {
return if (allowSingleLine && indexOf('\n') == -1)
"$indentation/** $this */"
else {
val doc = StringBuilder().run {
this@toJavaDoc.lines().forEach { append("$indentation * $it\n") }
toString().removeSuffix("\n")
}

return if (allowSingleLine && clean.indexOf('\n') == -1)
"$indentation/** $clean */"
else
"$indentation/**\n$indentation * $clean\n$indentation */"
"$indentation/**\n$doc\n$indentation */"
}
}

/** Specialized conversion for methods. */
internal fun GeneratorTarget.toJavaDoc(documentation: String, params: Sequence<Parameter>, returns: NativeType, returnDoc: String, since: String): String {
if (documentation.isEmpty() && returnDoc.isEmpty() && since.isEmpty() && params.all { it.documentation == null })
fun String.toJavaDoc(indentation: String = t, allowSingleLine: Boolean = true, see: Array<String> = emptyArray(), since: String = "")
= toJavaDoc(if (this.isNotEmpty()) this@toJavaDoc.cleanup("") else "", see = see.map { BlockTagSee(it) }.toList(), since = if (since.isNotEmpty()) BlockTagSince(since) else null).toJavaDoc(indentation, allowSingleLine)

internal fun GeneratorTarget.toJavaDoc(documentation: String, params: Sequence<Parameter>, returns: NativeType, returnDoc: String = "", see: Array<String> = emptyArray(), since: String = ""): String {
if (documentation.isEmpty() && returnDoc.isEmpty() && see.isEmpty() && since.isEmpty() && params.all { it.documentation == null })
return ""

if (params.none() && returnDoc.isEmpty())
return documentation.toJavaDoc()
return documentation.toJavaDoc(see = see, since = since)

/* BlockTag - @param */
val lParams = mutableListOf<BlockTagParam>()
val returnsStructValue = !returnDoc.isEmpty() && returns is StructType

return StringBuilder("$t/**\n$t * ${documentation.cleanup()}").run {
val returnsStructValue = !returnDoc.isEmpty() && returns is StructType
if (params.any()) {
// Find maximum param name length
var alignment = params.map { it.name.length }.fold(0) { left, right -> Math.max(left, right) }
if (returnsStructValue)
alignment = Math.max(alignment, RESULT.length)

if (params.any()) {
// Find maximum param name length
var alignment = params.map { it.name.length }.fold(0) { left, right -> Math.max(left, right) }
if (returnsStructValue)
alignment = Math.max(alignment, RESULT.length)
val multilineAligment = paramMultilineAligment(alignment)

params.forEach {
lParams.add(BlockTagParam(it.name, it.documentation.let { if (it == null) "" else processDocumentation(it()) }, alignment, multilineAligment))
}

if (returnsStructValue)
lParams.add(BlockTagParam(RESULT, processDocumentation(returnDoc), alignment, multilineAligment))
}

val multilineAligment = paramMultilineAligment(alignment)
/* BlockTag - @return */
val tReturn = if (!returnDoc.isEmpty() && !returnsStructValue) BlockTagReturn(processDocumentation(returnDoc).cleanup()) else null

append("\n$t *")
/* BlockTag - @see */
val lSee = mutableListOf<BlockTagSee>()
if (!see.isEmpty())
see.forEach { lSee.add(BlockTagSee(it)) }

/* BlockTag - @since */
val tSince = if (!since.isEmpty()) BlockTagSince(since) else null

return toJavaDoc(documentation.cleanup(), lParams, tReturn, lSee, tSince).toJavaDoc()
}

private fun toJavaDoc(documentation: String, params: List<BlockTagParam> = emptyList(), returns: BlockTagReturn? = null, see: List<BlockTagSee> = emptyList(), since: BlockTagSince? = null): String {
return StringBuilder(documentation).run {
if (params.isNotEmpty()) {
if (isNotEmpty()) append("\n")
params.forEach {
printParam(this, it.name, it.documentation.let { if (it == null) "" else processDocumentation(it()) }, alignment, multilineAligment)
append("\n@param ")
it.print(this)
}
if (returnsStructValue)
printParam(this, RESULT, processDocumentation(returnDoc), alignment, multilineAligment)
}

if (!returnDoc.isEmpty() && !returnsStructValue) {
append("\n$t *")
append("\n$t * @return ")
append(processDocumentation(returnDoc).cleanup("$t * "))
if (returns != null) {
if (isNotEmpty()) append("\n")
append("\n@return ")
returns.print(this)
}

if (!since.isEmpty()) {
append("\n$t *")
append("\n$t * @since ")
append(since)
if (see.isNotEmpty()) {
if (isNotEmpty()) append("\n")
see.forEach {
append("\n@see ")
it.print(this)
}
}

append("\n$t */")
if (since != null) {
if (isNotEmpty()) append("\n")
append("\n@since ")
since.print(this)
}

toString()
}
}

private abstract class BlockTag(
val value: String
) {

open fun print(builder: StringBuilder) {
builder.append(value)
}

}

private class BlockTagParam(
name: String,
val documentation: String,
val alignment: Int,
val multilineAligment: String
) : BlockTag(name) {

override fun print(builder: StringBuilder) {
builder.append(value)

// Align
for (i in 0..(alignment - value.length))
builder.append(' ')

builder.append(documentation.cleanup(multilineAligment))
}

}

private class BlockTagReturn(value: String) : BlockTag(value)
private class BlockTagSee(value: String) : BlockTag(value)
private class BlockTagSince(value: String) : BlockTag(value)

// Used for aligning parameter javadoc when it spans multiple lines.
private fun paramMultilineAligment(alignment: Int): String {
val whitespace = " @param ".length + alignment + 1
return StringBuilder("$t *".length + whitespace).run {
append("$t *")
for (i in 0..whitespace - 1)
append(' ')

toString()
}
}

private fun printParam(builder: StringBuilder, name: String, documentation: String, alignment: Int, multilineAligment: String) {
builder.append("\n$t * @param $name")

// Align
for (i in 0..(alignment - name.length))
builder.append(' ')

builder.append(documentation.cleanup(multilineAligment))
}

enum class LinkMode {
SINGLE {
override fun print(multi: Boolean): String = if (multi) "One of:" else "Must be:"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -615,8 +615,8 @@ class NativeClass(

// DSL extensions

operator fun <T : Any> ConstantType<T>.invoke(documentation: String, vararg constants: Constant<T>, access: Access = Access.PUBLIC): ConstantBlock<T> {
val block = ConstantBlock(this@NativeClass, access, this, { processDocumentation(documentation) }, *constants)
operator fun <T : Any> ConstantType<T>.invoke(documentation: String, vararg constants: Constant<T>, see: Array<String> = emptyArray(), access: Access = Access.PUBLIC): ConstantBlock<T> {
val block = ConstantBlock(this@NativeClass, access, this, { processDocumentation(documentation) }, see, *constants)
constantBlocks.add(block)
return block
}
Expand All @@ -642,10 +642,10 @@ class NativeClass(
fun String.enum(documentation: String, expression: String) =
Constant(this, EnumValueExpression({ if (documentation.isEmpty()) null else processDocumentation(documentation) }, expression))

operator fun NativeType.invoke(name: String, documentation: String, vararg parameters: Parameter, returnDoc: String = "", since: String = "", noPrefix: Boolean = false) =
ReturnValue(this)(name, documentation, *parameters, returnDoc = returnDoc, since = since, noPrefix = noPrefix)
operator fun NativeType.invoke(name: String, documentation: String, vararg parameters: Parameter, returnDoc: String = "", see: Array<String> = emptyArray(), since: String = "", noPrefix: Boolean = false) =
ReturnValue(this)(name, documentation, *parameters, returnDoc = returnDoc, see = see, since = since, noPrefix = noPrefix)

operator fun ReturnValue.invoke(name: String, documentation: String, vararg parameters: Parameter, returnDoc: String = "", since: String = "", noPrefix: Boolean = false): Func {
operator fun ReturnValue.invoke(name: String, documentation: String, vararg parameters: Parameter, returnDoc: String = "", see: Array<String> = emptyArray(), since: String = "", noPrefix: Boolean = false): Func {
val func = Func(
returns = this,
simpleName = name,
Expand All @@ -656,6 +656,7 @@ class NativeClass(
parameters.asSequence().filter { it !== JNI_ENV && parameterFilter(it) },
this.nativeType,
returnDoc,
see,
since
)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -497,40 +497,49 @@ val Assimp = "Assimp".nativeClass(packageName = ASSIMP_PACKAGE, prefix = "ai", p
).noPrefix()

StringConstant(
"""
""",
"",

"AI_CONFIG_IMPORT_MD3_KEYFRAME".."IMPORT_MD3_KEYFRAME"
).noPrefix()

StringConstant(
"@see \\#AI_CONFIG_IMPORT_GLOBAL_KEYFRAME",
"",

"AI_CONFIG_IMPORT_MD2_KEYFRAME".."IMPORT_MD2_KEYFRAME",

"AI_CONFIG_IMPORT_MD2_KEYFRAME".."IMPORT_MD2_KEYFRAME"
see = arrayOf("#AI_CONFIG_IMPORT_GLOBAL_KEYFRAME")
).noPrefix()

StringConstant(
"@see \\#AI_CONFIG_IMPORT_GLOBAL_KEYFRAME",
"",

"AI_CONFIG_IMPORT_MDL_KEYFRAME".."IMPORT_MDL_KEYFRAME"
"AI_CONFIG_IMPORT_MDL_KEYFRAME".."IMPORT_MDL_KEYFRAME",

see = arrayOf("#AI_CONFIG_IMPORT_GLOBAL_KEYFRAME")
).noPrefix()

StringConstant(
"@see \\#AI_CONFIG_IMPORT_GLOBAL_KEYFRAME",
"",

"AI_CONFIG_IMPORT_MDC_KEYFRAME".."IMPORT_MDC_KEYFRAME",

"AI_CONFIG_IMPORT_MDC_KEYFRAME".."IMPORT_MDC_KEYFRAME"
see = arrayOf("#AI_CONFIG_IMPORT_GLOBAL_KEYFRAME")
).noPrefix()

StringConstant(
"@see \\#AI_CONFIG_IMPORT_GLOBAL_KEYFRAME",
"",

"AI_CONFIG_IMPORT_SMD_KEYFRAME".."IMPORT_SMD_KEYFRAME",

"AI_CONFIG_IMPORT_SMD_KEYFRAME".."IMPORT_SMD_KEYFRAME"
see = arrayOf("#AI_CONFIG_IMPORT_GLOBAL_KEYFRAME")
).noPrefix()

StringConstant(
"@see \\#AI_CONFIG_IMPORT_GLOBAL_KEYFRAME",
"",

"AI_CONFIG_IMPORT_UNREAL_KEYFRAME".."IMPORT_UNREAL_KEYFRAME"
"AI_CONFIG_IMPORT_UNREAL_KEYFRAME".."IMPORT_UNREAL_KEYFRAME",

see = arrayOf("#AI_CONFIG_IMPORT_GLOBAL_KEYFRAME")
).noPrefix()

StringConstant(
Expand Down Expand Up @@ -674,13 +683,11 @@ val Assimp = "Assimp".nativeClass(packageName = ASSIMP_PACKAGE, prefix = "ai", p
).noPrefix()

StringConstant(
"""
End of the imported time range.

@see \\#AI_CONFIG_IMPORT_LWS_ANIM_START
""",
"End of the imported time range.",

"AI_CONFIG_IMPORT_LWS_ANIM_END".."IMPORT_LWS_ANIM_END",

"AI_CONFIG_IMPORT_LWS_ANIM_END".."IMPORT_LWS_ANIM_END"
see = arrayOf("#AI_CONFIG_IMPORT_LWS_ANIM_START")
).noPrefix()

StringConstant(
Expand Down