From d07ce7cae87da8f1c28c261f3b17ad20d6511ef1 Mon Sep 17 00:00:00 2001
From: love2hina
Date: Sun, 13 Feb 2022 17:25:20 +0900
Subject: [PATCH] =?UTF-8?q?Enum=E5=80=A4=E3=81=AE=E5=87=BA=E5=8A=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
refs #19
---
build.gradle.kts | 2 +-
.../kotlin/sharon/SmartXMLStreamWriter.kt | 11 +-
.../net/love2hina/kotlin/sharon/Utility.kt | 34 -----
.../love2hina/kotlin/sharon/data/ClassInfo.kt | 8 +-
.../kotlin/sharon/data/EnumEntryInfo.kt | 35 +++++
.../love2hina/kotlin/sharon/data/EnumInfo.kt | 44 ++++++
.../kotlin/sharon/data/JavadocInfo.kt | 60 ++++++++
.../kotlin/sharon/data/MethodInfo.kt | 19 +--
.../kotlin/sharon/parser/ClassVisitor.kt | 23 +--
.../kotlin/sharon/parser/ConditionVisitor.kt | 6 +-
.../kotlin/sharon/parser/EnumVisitor.kt | 142 ++++++++++++++++++
.../kotlin/sharon/parser/FunctionVisitor.kt | 23 +--
.../love2hina/kotlin/sharon/parser/Parser.kt | 128 +++-------------
src/main/powershell/DocumentGenerator.ps1 | 27 +++-
src/main/powershell/TargetInfo.psm1 | 114 ++++++++++++++
...tTarget.java => ParseTestClassTarget.java} | 8 +-
.../kotlin/sharon/ParseTestEnumTarget.java | 24 +++
template/test.xlsx | Bin 24570 -> 28524 bytes
18 files changed, 482 insertions(+), 226 deletions(-)
create mode 100644 src/main/kotlin/net/love2hina/kotlin/sharon/data/EnumEntryInfo.kt
create mode 100644 src/main/kotlin/net/love2hina/kotlin/sharon/data/EnumInfo.kt
create mode 100644 src/main/kotlin/net/love2hina/kotlin/sharon/parser/EnumVisitor.kt
rename src/test/java/net/love2hina/kotlin/sharon/{ParseTestTarget.java => ParseTestClassTarget.java} (89%)
create mode 100644 src/test/java/net/love2hina/kotlin/sharon/ParseTestEnumTarget.java
diff --git a/build.gradle.kts b/build.gradle.kts
index f4f6213..0c689de 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -35,7 +35,7 @@ plugins {
}
group = "net.love2hina"
-version = "0.2.0-alpha1"
+version = "0.3.0-SNAPSHOT"
val versions: Map by extra
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/SmartXMLStreamWriter.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/SmartXMLStreamWriter.kt
index ff13a94..7415609 100644
--- a/src/main/kotlin/net/love2hina/kotlin/sharon/SmartXMLStreamWriter.kt
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/SmartXMLStreamWriter.kt
@@ -34,8 +34,7 @@ internal class SmartXMLStreamWriter(file: File): XMLStreamWriter, Closeable {
private fun outputIndent() {
xmlWriter.writeCharacters(lineSeparator)
- if (level > 0)
- xmlWriter.writeCharacters(" ".repeat(indentSize * level))
+ if (level > 0) { xmlWriter.writeCharacters(" ".repeat(indentSize * level)) }
}
private fun outputElementBody() {
@@ -139,15 +138,15 @@ internal class SmartXMLStreamWriter(file: File): XMLStreamWriter, Closeable {
}
override fun writeAttribute(localName: String, value: String?) {
- if (value != null) xmlWriter.writeAttribute(localName, value)
+ if (value != null) { xmlWriter.writeAttribute(localName, value) }
}
override fun writeAttribute(namespaceURI: String?, localName: String, value: String?) {
- if (value != null) xmlWriter.writeAttribute(namespaceURI, localName, value)
+ if (value != null) { xmlWriter.writeAttribute(namespaceURI, localName, value) }
}
override fun writeAttribute(prefix: String?, namespaceURI: String?, localName: String, value: String?) {
- if (value != null) xmlWriter.writeAttribute(prefix, namespaceURI, localName, value)
+ if (value != null) { xmlWriter.writeAttribute(prefix, namespaceURI, localName, value) }
}
override fun writeComment(data: String?) {
@@ -179,7 +178,7 @@ internal class SmartXMLStreamWriter(file: File): XMLStreamWriter, Closeable {
else -> {
// 複数行出力
lines.stream()
- .forEach{
+ .forEach {
outputElementBody()
xmlWriter.writeCharacters(it.trim())
}
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/Utility.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/Utility.kt
index be71504..2c517c4 100644
--- a/src/main/kotlin/net/love2hina/kotlin/sharon/Utility.kt
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/Utility.kt
@@ -2,8 +2,6 @@ package net.love2hina.kotlin.sharon
import com.github.javaparser.ast.Modifier
import com.github.javaparser.ast.NodeList
-import com.github.javaparser.ast.comments.Comment
-import net.love2hina.kotlin.sharon.data.*
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty
@@ -51,35 +49,3 @@ internal fun getModifier(modifiers: NodeList): String =
.reduce(StringBuilder(),
{ a: StringBuilder, i: String -> a.appendSeparator(COMMA, i) },
{ a: StringBuilder, b: StringBuilder -> a.appendSeparator(COMMA, b) }).toString()
-
-internal fun getCommentContents(comment: Comment): String =
- comment.content.split(REGEXP_NEWLINE)
- .stream().map { l ->
- val m = REGEXP_BLOCK_COMMENT.find(l)
- if (m != null)
- (m.groups as MatchNamedGroupCollection)["content"]?.value ?: ""
- else l
- }
- .reduce(StringBuilder(),
- { b, l -> b.appendNewLine(l) },
- { b1, b2 -> b1.appendNewLine(b2) })
- .toString()
-
-internal fun pushJavadocComment(content: String, name: String?, start: Int, range: IntRange, info: JavadocInfo ): Int {
-
- if (start < range.start) {
- val value = content.substring(start, range.start).trim()
-
- when {
- info.parseTag(name, value) -> {}
- name == null -> {
- info.description.appendNewLine(value)
- }
- else -> {
- info.description.appendNewLine("@$name $value")
- }
- }
- }
-
- return range.endInclusive + 1
-}
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/data/ClassInfo.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/data/ClassInfo.kt
index e98e9fb..82fc027 100644
--- a/src/main/kotlin/net/love2hina/kotlin/sharon/data/ClassInfo.kt
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/data/ClassInfo.kt
@@ -27,15 +27,12 @@ internal data class ClassInfo(
/*
* @see
- * {@link}
- * {@linkplain}
- * {@docRoot}
*/
): JavadocInfo {
- override fun parseTag(name: String?, value: String): Boolean {
- return when (name) {
+ override fun parseTag(name: String?, value: String): Boolean
+ = when (name) {
"param" -> {
val r = Regex("^<(?\\w+)>(?:\\s+(?.*))?$")
val m = r.find(value)
@@ -65,6 +62,5 @@ internal data class ClassInfo(
}
else -> false
}
- }
}
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/data/EnumEntryInfo.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/data/EnumEntryInfo.kt
new file mode 100644
index 0000000..7b74bc6
--- /dev/null
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/data/EnumEntryInfo.kt
@@ -0,0 +1,35 @@
+package net.love2hina.kotlin.sharon.data
+
+import net.love2hina.kotlin.sharon.setProperty
+
+internal data class EnumEntryInfo(
+
+ /** 説明 */
+ override val description: StringBuilder = StringBuilder(),
+
+ /** since */
+ var since: String? = null,
+
+ /** deprecated */
+ var deprecated: String? = null,
+
+ /** serial */
+ var serial: String? = null,
+
+ /*
+ * @see
+ * @serialField
+ */
+
+): JavadocInfo {
+
+ override fun parseTag(name: String?, value: String): Boolean
+ = when (name) {
+ "since", "deprecated", "serial" -> {
+ this.setProperty(name, value)
+ true
+ }
+ else -> false
+ }
+
+}
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/data/EnumInfo.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/data/EnumInfo.kt
new file mode 100644
index 0000000..a1e4726
--- /dev/null
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/data/EnumInfo.kt
@@ -0,0 +1,44 @@
+package net.love2hina.kotlin.sharon.data
+
+import net.love2hina.kotlin.sharon.setProperty
+
+internal data class EnumInfo(
+
+ /** 説明 */
+ override val description: StringBuilder = StringBuilder(),
+
+ /** since */
+ var since: String? = null,
+
+ /** deprecated */
+ var deprecated: String? = null,
+
+ /** serial */
+ var serial: String? = null,
+
+ /** author */
+ val author: MutableList = mutableListOf(),
+
+ /** version */
+ var version: String? = null,
+
+ /*
+ * @see
+ */
+
+): JavadocInfo {
+
+ override fun parseTag(name: String?, value: String): Boolean
+ = when (name) {
+ "author" -> {
+ author.addAll(value.split(", "))
+ true
+ }
+ "since", "deprecated", "serial", "version" -> {
+ this.setProperty(name, value)
+ true
+ }
+ else -> false
+ }
+
+}
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/data/JavadocInfo.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/data/JavadocInfo.kt
index 3d58e38..412ccc8 100644
--- a/src/main/kotlin/net/love2hina/kotlin/sharon/data/JavadocInfo.kt
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/data/JavadocInfo.kt
@@ -1,5 +1,9 @@
package net.love2hina.kotlin.sharon.data
+import com.github.javaparser.ast.comments.Comment
+import net.love2hina.kotlin.sharon.appendNewLine
+import java.util.Optional
+
internal interface JavadocInfo {
val description: StringBuilder
@@ -7,3 +11,59 @@ internal interface JavadocInfo {
fun parseTag(name: String?, value: String): Boolean
}
+
+internal fun Optional.parseJavadoc(info: JavadocInfo) {
+ this.ifPresent {
+ if (it.isJavadocComment) {
+ val content = getCommentContents(it)
+ var index = 0
+ var name: String? = null
+
+ // Javadocをパースする
+ for (match in REGEXP_ANNOTATION.findAll(content)) {
+ index = pushJavadocComment(content, name, index, match.range, info)
+ name = (match.groups as MatchNamedGroupCollection)["name"]!!.value
+ }
+ pushJavadocComment(content, name, index, IntRange(content.length, content.length), info)
+ }
+ else if (it.isBlockComment) {
+ val content = getCommentContents(it)
+ info.description.appendNewLine(content)
+ }
+ else {
+ info.description.appendNewLine(it.content)
+ }
+ }
+}
+
+private fun getCommentContents(comment: Comment): String =
+ comment.content.split(REGEXP_NEWLINE)
+ .stream().map { l ->
+ val m = REGEXP_BLOCK_COMMENT.find(l)
+ if (m != null)
+ (m.groups as MatchNamedGroupCollection)["content"]?.value ?: ""
+ else l
+ }
+ .reduce(StringBuilder(),
+ { b, l -> b.appendNewLine(l) },
+ { b1, b2 -> b1.appendNewLine(b2) })
+ .toString()
+
+private fun pushJavadocComment(content: String, name: String?, start: Int, range: IntRange, info: JavadocInfo ): Int {
+
+ if (start < range.start) {
+ val value = content.substring(start, range.start).trim()
+
+ when {
+ info.parseTag(name, value) -> {}
+ name == null -> {
+ info.description.appendNewLine(value)
+ }
+ else -> {
+ info.description.appendNewLine("@$name $value")
+ }
+ }
+ }
+
+ return range.endInclusive + 1
+}
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/data/MethodInfo.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/data/MethodInfo.kt
index a6f1551..01d98b7 100644
--- a/src/main/kotlin/net/love2hina/kotlin/sharon/data/MethodInfo.kt
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/data/MethodInfo.kt
@@ -20,20 +20,16 @@ internal data class MethodInfo(
val throws: HashMap = LinkedHashMap(),
/*
- * see
-@since
-@deprecated
-@serialData
-{@link}
-{@linkplain}
-{@inheritDoc}
-{@docRoot}
- * */
+ * see
+ * @since
+ * @deprecated
+ * @serialData
+ */
): JavadocInfo {
- override fun parseTag(name: String?, value: String): Boolean {
- return when (name) {
+ override fun parseTag(name: String?, value: String): Boolean
+ = when (name) {
"param" -> {
val r = Regex("^(?:(?\\w+)|<(?\\w+)>)(?:\\s+(?.*))?$")
val m = r.find(value)
@@ -86,6 +82,5 @@ internal data class MethodInfo(
}
else -> false
}
- }
}
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/parser/ClassVisitor.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/parser/ClassVisitor.kt
index f15d0c4..5b6189d 100644
--- a/src/main/kotlin/net/love2hina/kotlin/sharon/parser/ClassVisitor.kt
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/parser/ClassVisitor.kt
@@ -23,27 +23,7 @@ internal fun Parser.Visitor.visitInClass(n: ClassOrInterfaceDeclaration, arg: Vo
}
// コメントの解析
- n.comment.ifPresent {
- if (it.isJavadocComment) {
- val content = getCommentContents(it)
- var index = 0
- var name: String? = null
-
- // Javadocをパースする
- for (match in REGEXP_ANNOTATION.findAll(content)) {
- index = pushJavadocComment(content, name, index, match.range, classInfo)
- name = (match.groups as MatchNamedGroupCollection)["name"]!!.value
- }
- pushJavadocComment(content, name, index, IntRange(content.length, content.length), classInfo)
- }
- else if (it.isBlockComment) {
- val content = getCommentContents(it)
- classInfo.description.appendNewLine(content)
- }
- else {
- classInfo.description.appendNewLine(it.content)
- }
- }
+ n.comment.parseJavadoc(classInfo)
// 出力開始
writer.writeStartElement("class")
@@ -90,7 +70,6 @@ internal fun Parser.Visitor.visitInClass(n: ClassOrInterfaceDeclaration, arg: Vo
// アノテーション
n.annotations.forEach { it.accept(this, arg) }
-
// メンバー
n.members.forEach { it.accept(this, arg) }
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/parser/ConditionVisitor.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/parser/ConditionVisitor.kt
index b04171c..47dfda4 100644
--- a/src/main/kotlin/net/love2hina/kotlin/sharon/parser/ConditionVisitor.kt
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/parser/ConditionVisitor.kt
@@ -93,8 +93,7 @@ internal fun Parser.Visitor.visitInSwitch(n: SwitchStmt, arg: Void?) {
// 条件エントリ
for (i in n.entries) {
- if (!caseContinue)
- writer.writeStartElement("case")
+ if (!caseContinue) { writer.writeStartElement("case") }
// コメント
i.comment.ifPresent { it.accept(this, arg) }
@@ -110,8 +109,7 @@ internal fun Parser.Visitor.visitInSwitch(n: SwitchStmt, arg: Void?) {
writer.writeEndElement()
caseContinue = i.statements.isEmpty()
- if (!caseContinue)
- writer.writeEndElement()
+ if (!caseContinue) { writer.writeEndElement() }
}
writer.writeEndElement()
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/parser/EnumVisitor.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/parser/EnumVisitor.kt
new file mode 100644
index 0000000..c5301fd
--- /dev/null
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/parser/EnumVisitor.kt
@@ -0,0 +1,142 @@
+package net.love2hina.kotlin.sharon.parser
+
+import com.github.javaparser.ast.body.EnumConstantDeclaration
+import com.github.javaparser.ast.body.EnumDeclaration
+import com.github.javaparser.ast.expr.*
+import net.love2hina.kotlin.sharon.data.*
+import net.love2hina.kotlin.sharon.*
+
+/**
+ * Enum定義.
+ *
+ * `enum enum_name`
+ */
+internal fun Parser.Visitor.visitInEnum(n: EnumDeclaration, arg: Void?) {
+ val enumName = n.name.asString()
+
+ // Enum情報
+ val enumInfo = EnumInfo()
+
+ // 実体解析
+ // コメントの解析
+ n.comment.parseJavadoc(enumInfo)
+
+ // 出力開始
+ writer.writeStartElement("enum")
+ writer.writeAttribute("modifier", getModifier(n.modifiers))
+ writer.writeAttribute("name", enumName)
+ writer.writeAttribute("fullname", packageStack.getFullName(enumName))
+
+ packageStack.push(enumName)
+
+ // インターフェース
+ n.implementedTypes.forEach {
+ writer.writeEmptyElement("implements")
+ writer.writeAttribute("name", it.name.asString())
+ }
+
+ // Javadoc
+ writer.writeStartElement("javadoc")
+ writer.writeAttribute("since", enumInfo.since)
+ writer.writeAttribute("deprecated", enumInfo.deprecated)
+ writer.writeAttribute("serial", enumInfo.serial)
+ writer.writeAttribute("version", enumInfo.version)
+ enumInfo.author.forEach {
+ writer.writeStartElement("author")
+ writer.writeStrings(it)
+ writer.writeEndElement()
+ }
+ writer.writeEndElement()
+ // 説明の出力
+ writer.writeStartElement("description")
+ writer.writeStrings(enumInfo.description.toString())
+ writer.writeEndElement()
+
+ // アノテーション
+ n.annotations.forEach { it.accept(this, arg) }
+ // エントリー
+ n.entries.forEach { it.accept(this, arg) }
+ // メンバー
+ n.members.forEach { it.accept(this, arg) }
+
+ packageStack.pop()
+ writer.writeEndElement()
+}
+
+/**
+ * Enum値定義.
+ */
+internal fun Parser.Visitor.visitInEnumConstant(n: EnumConstantDeclaration, arg: Void?) {
+ val valueName = n.name.asString()
+
+ // エントリ情報
+ val entryInfo = EnumEntryInfo()
+
+ // 実体解析
+ // コメントの解析
+ n.comment.parseJavadoc(entryInfo)
+
+ // TODO
+ // n.getClassBody().forEach(p -> p.accept(this, arg));
+
+ // 出力開始
+ writer.writeStartElement("entry")
+ writer.writeAttribute("name", valueName)
+
+ // Javadoc
+ writer.writeStartElement("javadoc")
+ writer.writeAttribute("since", entryInfo.since)
+ writer.writeAttribute("deprecated", entryInfo.deprecated)
+ writer.writeAttribute("serial", entryInfo.serial)
+ writer.writeEndElement()
+ // 説明の出力
+ writer.writeStartElement("description")
+ writer.writeStrings(entryInfo.description.toString())
+ writer.writeEndElement()
+
+ // アノテーション
+ n.annotations.forEach { it.accept(this, arg) }
+ // パラメーター
+ n.arguments.forEach {
+ writer.writeStartElement("argument")
+ when (it) {
+ is NullLiteralExpr -> {
+ writer.writeAttribute("type", "null")
+ }
+ is BooleanLiteralExpr -> {
+ writer.writeAttribute("type", "boolean")
+ writer.writeStrings(it.value.toString())
+ }
+ is CharLiteralExpr -> {
+ writer.writeAttribute("type", "char")
+ writer.writeStrings(it.value)
+ }
+ is IntegerLiteralExpr -> {
+ writer.writeAttribute("type", "integer")
+ writer.writeStrings(it.value)
+ }
+ is LongLiteralExpr -> {
+ writer.writeAttribute("type", "long")
+ writer.writeStrings(it.value)
+ }
+ is DoubleLiteralExpr -> {
+ writer.writeAttribute("type", "double")
+ writer.writeStrings(it.value)
+ }
+ is StringLiteralExpr -> {
+ writer.writeAttribute("type", "string")
+ writer.writeStrings(it.value)
+ }
+ is TextBlockLiteralExpr -> {
+ writer.writeAttribute("type", "textblock")
+ writer.writeStrings(it.value)
+ }
+ else -> {
+ writer.writeAttribute("type", "composite")
+ }
+ }
+ writer.writeEndElement()
+ }
+
+ writer.writeEndElement()
+}
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/parser/FunctionVisitor.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/parser/FunctionVisitor.kt
index 1fd577a..0feb916 100644
--- a/src/main/kotlin/net/love2hina/kotlin/sharon/parser/FunctionVisitor.kt
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/parser/FunctionVisitor.kt
@@ -42,28 +42,7 @@ internal fun Parser.Visitor.visitInFunction(n: MethodDeclaration, arg: Void?) {
}
// コメントの解析
- n.comment.ifPresent {
- if (it.isJavadocComment) {
- // Javadocコメントから、*を取り除く
- val content = getCommentContents(it)
- var index = 0
- var name: String? = null
-
- // Javadocをパースする
- for (match in REGEXP_ANNOTATION.findAll(content)) {
- index = pushJavadocComment(content, name, index, match.range, methodInfo)
- name = (match.groups as MatchNamedGroupCollection)["name"]!!.value
- }
- pushJavadocComment(content, name, index, IntRange(content.length, content.length), methodInfo)
- }
- else if (it.isBlockComment) {
- val content = getCommentContents(it)
- methodInfo.description.appendNewLine(content)
- }
- else {
- methodInfo.description.appendNewLine(it.content)
- }
- }
+ n.comment.parseJavadoc(methodInfo)
// 出力開始
writer.writeStartElement("method")
diff --git a/src/main/kotlin/net/love2hina/kotlin/sharon/parser/Parser.kt b/src/main/kotlin/net/love2hina/kotlin/sharon/parser/Parser.kt
index 458cbb0..839151e 100644
--- a/src/main/kotlin/net/love2hina/kotlin/sharon/parser/Parser.kt
+++ b/src/main/kotlin/net/love2hina/kotlin/sharon/parser/Parser.kt
@@ -179,40 +179,8 @@ internal class Parser(
// n.comment.ifPresent { it.accept(this, arg) }
}
- /**
- * Enum定義.
- *
- * `enum enum_name`
- */
- override fun visit(n: EnumDeclaration?, arg: Void?) {
- val name = n!!.name.asString()
-
- writer.writeStartElement("enum")
- writer.writeAttribute("modifier", getModifier(n.modifiers))
- writer.writeAttribute("name", name)
- writer.writeAttribute("fullname", packageStack.getFullName(name))
-
- // TODO
- // n.entries.forEach { it.accept(this, arg) }
- // n.getImplementedTypes().forEach(p -> p.accept(this, arg));
- // n.getMembers().forEach(p -> p.accept(this, arg));
- // n.getAnnotations().forEach(p -> p.accept(this, arg));
- // n.getComment().ifPresent(l -> l.accept(this, arg));
-
- writer.writeEndElement()
- }
-
- /**
- * Enum値定義.
- */
- override fun visit(n: EnumConstantDeclaration?, arg: Void?) {
- // TODO
- // n.getArguments().forEach(p -> p.accept(this, arg));
- // n.getClassBody().forEach(p -> p.accept(this, arg));
- // n.getName().accept(this, arg);
- // n.getAnnotations().forEach(p -> p.accept(this, arg));
- // n.getComment().ifPresent(l -> l.accept(this, arg));
- }
+ override fun visit(n: EnumDeclaration?, arg: Void?) = visitInEnum(n!!, arg)
+ override fun visit(n: EnumConstantDeclaration?, arg: Void?) = visitInEnumConstant(n!!, arg)
/**
* アノテーション定義.
@@ -421,8 +389,8 @@ internal class Parser(
// コメント
n.comment.ifPresent { it.accept(this, arg) }
- // 式
- n.expression.accept(this, arg)
+ // TODO: 式
+ // n.expression.accept(this, arg)
}
/**
@@ -453,80 +421,18 @@ internal class Parser(
n!!.comment.ifPresent { it.accept(this, arg) }
}
- /**
- * nullリテラル値.
- */
- override fun visit(n: NullLiteralExpr?, arg: Void?) {
- // コメント
- n!!.comment.ifPresent { it.accept(this, arg) }
- }
-
- /**
- * Booleanリテラル値.
- */
- override fun visit(n: BooleanLiteralExpr?, arg: Void?) {
- // コメント
- n!!.comment.ifPresent { it.accept(this, arg) }
- }
-
- /**
- * Charリテラル値.
- */
- override fun visit(n: CharLiteralExpr?, arg: Void?) {
- // コメント
- n!!.comment.ifPresent { it.accept(this, arg) }
- }
-
- /**
- * Integerリテラル値.
- */
- override fun visit(n: IntegerLiteralExpr?, arg: Void?) {
- // コメント
- n!!.comment.ifPresent { it.accept(this, arg) }
- }
-
- /**
- * Longリテラル値.
- */
- override fun visit(n: LongLiteralExpr?, arg: Void?) {
- // コメント
- n!!.comment.ifPresent { it.accept(this, arg) }
- }
-
- /**
- * Doubleリテラル値.
- */
- override fun visit(n: DoubleLiteralExpr?, arg: Void?) {
- // コメント
- n!!.comment.ifPresent { it.accept(this, arg) }
- }
-
- /**
- * Stringリテラル値.
- */
- override fun visit(n: StringLiteralExpr?, arg: Void?) {
- // コメント
- n!!.comment.ifPresent { it.accept(this, arg) }
- }
-
- /**
- * TextBlockリテラル値.
- */
- override fun visit(n: TextBlockLiteralExpr?, arg: Void?) {
- // コメント
- n!!.comment.ifPresent { it.accept(this, arg) }
- }
+ override fun visit(n: NullLiteralExpr?, arg: Void?) = error("使われない")
+ override fun visit(n: BooleanLiteralExpr?, arg: Void?) = error("使われない")
+ override fun visit(n: CharLiteralExpr?, arg: Void?) = error("使われない")
+ override fun visit(n: IntegerLiteralExpr?, arg: Void?) = error("使われない")
+ override fun visit(n: LongLiteralExpr?, arg: Void?) = error("使われない")
+ override fun visit(n: DoubleLiteralExpr?, arg: Void?) = error("使われない")
+ override fun visit(n: StringLiteralExpr?, arg: Void?) = error("使われない")
+ override fun visit(n: TextBlockLiteralExpr?, arg: Void?) = error("使われない")
override fun visit(n: IfStmt?, arg: Void?) = visitInIf(n!!, arg)
override fun visit(n: SwitchStmt?, arg: Void?) = visitInSwitch(n!!, arg)
-
- /**
- * caseステートメント.
- */
- override fun visit(n: SwitchEntry?, arg: Void?) {
- // 使われない
- throw IllegalAccessException()
- }
+ override fun visit(n: SwitchEntry?, arg: Void?) = error("使われない")
override fun visit(n: ForStmt?, arg: Void?) = visitInFor(n!!, arg)
override fun visit(n: ForEachStmt?, arg: Void?) = visitInForEach(n!!, arg)
@@ -575,8 +481,8 @@ internal class Parser(
// コメント
n.comment.ifPresent { it.accept(this, arg) }
- // 式
- n.expression.accept(this, arg)
+ // TODO: 式
+ // n.expression.accept(this, arg)
}
/**
@@ -587,8 +493,8 @@ internal class Parser(
// コメント
n.comment.ifPresent { it.accept(this, arg) }
- // 式
- n.expression.ifPresent { it.accept(this, arg) }
+ // TODO: 式
+ // n.expression.ifPresent { it.accept(this, arg) }
}
override fun visit(n: NodeList<*>?, arg: Void?) {
diff --git a/src/main/powershell/DocumentGenerator.ps1 b/src/main/powershell/DocumentGenerator.ps1
index 21c5a66..d7f6c25 100644
--- a/src/main/powershell/DocumentGenerator.ps1
+++ b/src/main/powershell/DocumentGenerator.ps1
@@ -50,7 +50,13 @@ class DocumentGenerator: System.IDisposable {
hidden [XPathNavigator] $xpath
DocumentGenerator() {
- $this.excel.Visible = $true
+ if ($global:DebugPreference -ne 'SilentlyContinue') {
+ # デバッグが有効なら表示する
+ $this.excel.Visible = $true
+ }
+
+ # 警告表示を無効化
+ $this.excel.DisplayAlerts = $false
# テンプレートを開く
$this.bookTemplate = $this.excel.Workbooks.Open($script:FileTemplate, 0, $true)
@@ -82,8 +88,14 @@ class DocumentGenerator: System.IDisposable {
Remove-Item -Path $script:FileDocument
}
- # 保存する
- $this.bookDocument.SaveAs($script:FileDocument)
+ if ($this.bookDocument.WorkSheets.Count -gt 1) {
+ # 先頭シートを削除する
+ $this.bookDocument.WorkSheets.Item(1).Delete()
+
+ # 保存する
+ $this.bookDocument.SaveAs($script:FileDocument)
+ }
+
$this.bookDocument.Close($false)
}
@@ -171,7 +183,7 @@ class DocumentGenerator: System.IDisposable {
# 親シートはなし
$parSheetFmt = $null
}
- 'type|class' {
+ 'type|class|enum' {
# テンプレートルートに追加
$this.format.entries += $curSheetFmt
# 親シートを設定
@@ -235,6 +247,13 @@ class DocumentGenerator: System.IDisposable {
return [ClassTargetInfo]::new($node)
})
}
+ 'enum' {
+ # 列挙型情報
+ $targetCursor = [RootTargetEnumerable]::new($parent, 'enum', [Func[XPathNavigator, TargetInfo]]{
+ param([XPathNavigator] $node)
+ return [EnumTargetInfo]::new($node)
+ })
+ }
'method' {
# メソッド
$targetCursor = [RootTargetEnumerable]::new($parent, 'method', [Func[XPathNavigator, TargetInfo]]{
diff --git a/src/main/powershell/TargetInfo.psm1 b/src/main/powershell/TargetInfo.psm1
index f888e8f..7583816 100644
--- a/src/main/powershell/TargetInfo.psm1
+++ b/src/main/powershell/TargetInfo.psm1
@@ -123,6 +123,120 @@ class ClassTargetInfo : TargetInfo {
}
+class EnumTargetInfo : TargetInfo {
+
+ # 修飾子
+ [string] $modifier
+ # 名前
+ [string] $name
+ # 完全名
+ [string] $fullname
+ # インターフェース
+ [string[]] $implements
+
+ # since(Javadoc)
+ [string] $since
+ # deprecated(Javadoc)
+ [string] $deprecated
+ # serial(Javadoc)
+ [string] $serial
+ # version(Javadoc)
+ [string] $version
+ # author(Javadoc)
+ [string[]] $author
+
+ # 説明
+ [string] $description
+
+ # エントリー
+ [TargetEnumerable] $entries
+ # フィールド
+ [TargetEnumerable] $fields
+ # メソッド
+ [TargetEnumerable] $methods
+
+ EnumTargetInfo([XPathNavigator] $node) : base($node) {
+
+ $this.modifier = $node.Evaluate('@modifier')
+ $this.name = $node.Evaluate('@name')
+ $this.fullname = $node.Evaluate('@fullname')
+
+ $this.implements = [TargetInfo]::EvaluateStringArray($node, 'implements/@name')
+
+ $this.since = $node.Evaluate('javadoc/@since')
+ $this.deprecated = $node.Evaluate('javadoc/@deprecated')
+ $this.serial = $node.Evaluate('javadoc/@serial')
+ $this.version = $node.Evaluate('javadoc/@version')
+
+ $this.author = [TargetInfo]::EvaluateStringArray($node, 'javadoc/author/text()')
+
+ $this.description = $node.Evaluate('description/text()')
+
+ $this.entries = [TargetEnumerable]::new($node, 'entry', [Func[XPathNavigator, TargetInfo]]{
+ param([XPathNavigator] $_node)
+ return [EnumEntryTargetInfo]::new($_node)
+ })
+ $this.fields = [TargetEnumerable]::new($node, 'field', [Func[XPathNavigator, TargetInfo]]{
+ param([XPathNavigator] $_node)
+ return [FieldTargetInfo]::new($_node)
+ })
+ $this.methods = [TargetEnumerable]::new($node, 'method', [Func[XPathNavigator, TargetInfo]]{
+ param([XPathNavigator] $_node)
+ return [MethodTargetInfo]::new($_node)
+ })
+ }
+
+}
+
+class EnumEntryTargetInfo : TargetInfo {
+
+ # 名前
+ [string] $name
+
+ # since(Javadoc)
+ [string] $since
+ # deprecated(Javadoc)
+ [string] $deprecated
+ # serial(Javadoc)
+ [string] $serial
+
+ # 説明
+ [string] $description
+
+ # 引数
+ [TargetEnumerable] $arguments
+
+ EnumEntryTargetInfo([XPathNavigator] $node) : base($node) {
+
+ $this.name = $node.Evaluate('@name')
+
+ $this.since = $node.Evaluate('javadoc/@since')
+ $this.deprecated = $node.Evaluate('javadoc/@deprecated')
+ $this.serial = $node.Evaluate('javadoc/@serial')
+
+ $this.description = $node.Evaluate('description/text()')
+
+ $this.arguments = [TargetEnumerable]::new($node, 'argument', [Func[XPathNavigator, TargetInfo]]{
+ param([XPathNavigator] $_node)
+ return [ArgumentTargetInfo]::new($_node)
+ })
+ }
+}
+
+class ArgumentTargetInfo : TargetInfo {
+
+ # 型
+ [string] $type
+ # 値
+ [string] $value
+
+ ArgumentTargetInfo([XPathNavigator] $node) : base($node) {
+
+ $this.type = $node.Evaluate('@type')
+ $this.value = $node.Evaluate('text()')
+ }
+}
+
class FieldTargetInfo : TargetInfo {
# コメント
diff --git a/src/test/java/net/love2hina/kotlin/sharon/ParseTestTarget.java b/src/test/java/net/love2hina/kotlin/sharon/ParseTestClassTarget.java
similarity index 89%
rename from src/test/java/net/love2hina/kotlin/sharon/ParseTestTarget.java
rename to src/test/java/net/love2hina/kotlin/sharon/ParseTestClassTarget.java
index 8c903c5..d30886d 100644
--- a/src/test/java/net/love2hina/kotlin/sharon/ParseTestTarget.java
+++ b/src/test/java/net/love2hina/kotlin/sharon/ParseTestClassTarget.java
@@ -12,10 +12,10 @@
*
*
* @author webmaster@love2hina.net
- * @since 2022/02/09
- * @version 1.0.0
+ * @since 0.1.0
+ * @version 0.2.0
*/
-public class ParseTestTarget extends Object implements java.io.Serializable {
+public class ParseTestClassTarget extends Object implements java.io.Serializable {
/** フィールド */
private int fieldInt = 0, fieldInt2 = 2;
@@ -39,7 +39,7 @@ public enum MyEnum {
* @throws Exception 例外
*/
@MyAnnotation
- public int method(ParseTestTarget this, final String name, Ty amount) throws Exception {
+ public int method(ParseTestClassTarget this, final String name, Ty amount) throws Exception {
/// # 出力
System.out.println("Hello, world!");
diff --git a/src/test/java/net/love2hina/kotlin/sharon/ParseTestEnumTarget.java b/src/test/java/net/love2hina/kotlin/sharon/ParseTestEnumTarget.java
new file mode 100644
index 0000000..9c53c94
--- /dev/null
+++ b/src/test/java/net/love2hina/kotlin/sharon/ParseTestEnumTarget.java
@@ -0,0 +1,24 @@
+package net.love2hina.kotlin.sharon;
+
+/**
+ * テスト列挙型.
+ *
+ * @author webmaster@love2hina.net
+ * @since 0.2.0
+ * @version 0.2.0
+ */
+public enum ParseTestEnumTarget {
+ /** 通常定義 */
+ NORMAL,
+ /** コンストラクタ定義 */
+ CONSTRUCTOR("value");
+
+ public final String value;
+
+ ParseTestEnumTarget() {
+ value = null;
+ }
+ ParseTestEnumTarget(String v) {
+ value = v;
+ }
+}
diff --git a/template/test.xlsx b/template/test.xlsx
index 8ee29493f165636712c336097e1851de0b5ac983..0cf3c39c3fc259355261af7ec305759c00db3103 100644
GIT binary patch
delta 15642
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
delta 12828
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