diff --git a/.gitignore b/.gitignore index 22bf8a731..dd9706ab3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # gradle +.kotlin/ .gradle/ build/ out/ @@ -41,3 +42,7 @@ docs/web/[0-9]* # Affinity Photo *.af~lock~ *.af~lock~:com.dropbox.ignored + +node_modules/ +**/.vitepress/cache/ +**/.vitepress/dist/ diff --git a/build.gradle.kts b/build.gradle.kts index fd4585681..42544a016 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -31,6 +31,14 @@ val distDirFile = distDir.asFile val docsBuildDir = layout.buildDirectory.dir("docs").get().asFile val docletJarFile = layout.projectDirectory.file("buildSrc/build/libs/buildSrc.jar").asFile +repositories { + mavenCentral() +} + +val docletClasspath = configurations.detachedConfiguration( + dependencies.create("com.google.code.gson:gson:2.9.0") +) + // Root-level properties (available in root gradle.properties) val modIdProvider = providers.gradleProperty("mod_id") val channelProvider = providers.gradleProperty("channel").orElse("release") @@ -109,8 +117,8 @@ if (isVersionedProject && hasMinecraftVersion) { source(documentationSources) classpath = documentationClasspath destinationDir = File(docsBuildDir, "python/JsMacrosAC") - options.doclet = "com.jsmacrosce.doclet.pydoclet.Main" - options.docletpath = mutableListOf(docletJarFile) + options.doclet = "com.jsmacrosce.doclet.core.pydoclet.Main" + options.docletpath = (listOf(docletJarFile) + docletClasspath.files).toMutableList() (options as CoreJavadocOptions).addStringOption("v", project.version.toString()) } @@ -128,8 +136,8 @@ if (isVersionedProject && hasMinecraftVersion) { source(documentationSources) classpath = documentationClasspath destinationDir = File(docsBuildDir, "typescript/headers") - options.doclet = "com.jsmacrosce.doclet.tsdoclet.Main" - options.docletpath = mutableListOf(docletJarFile) + options.doclet = "com.jsmacrosce.doclet.core.tsdoclet.Main" + options.docletpath = (listOf(docletJarFile) + docletClasspath.files).toMutableList() (options as CoreJavadocOptions).addStringOption("v", project.version.toString()) } @@ -147,8 +155,8 @@ if (isVersionedProject && hasMinecraftVersion) { source(documentationSources) classpath = documentationClasspath destinationDir = File(docsBuildDir, "web") - options.doclet = "com.jsmacrosce.doclet.webdoclet.Main" - options.docletpath = mutableListOf(docletJarFile) + options.doclet = "com.jsmacrosce.doclet.core.webdoclet.Main" + options.docletpath = (listOf(docletJarFile) + docletClasspath.files).toMutableList() (options as CoreJavadocOptions).addStringOption("v", project.version.toString()) (options as CoreJavadocOptions).addStringOption("mcv", mcVersion) (options as StandardJavadocDocletOptions).links( @@ -170,10 +178,39 @@ if (isVersionedProject && hasMinecraftVersion) { } } + tasks.register("generateVitepressDoc", Javadoc::class.java) { + group = "documentation" + description = "Generates the vitepress documentation for the project" + source(documentationSources) + classpath = documentationClasspath + destinationDir = File(docsBuildDir, "vitepress") + options.doclet = "com.jsmacrosce.doclet.core.mddoclet.Main" + options.docletpath = (listOf(docletJarFile) + docletClasspath.files).toMutableList() + (options as CoreJavadocOptions).addStringOption("v", project.version.toString()) + (options as CoreJavadocOptions).addStringOption("mcv", mcVersion) + (options as StandardJavadocDocletOptions).links( + "https://docs.oracle.com/javase/8/docs/api/", + "https://www.javadoc.io/doc/org.slf4j/slf4j-api/1.7.30/", + "https://javadoc.io/doc/com.neovisionaries/nv-websocket-client/latest/" + ) + } + + tasks.register("copyVitepressDoc", Copy::class.java) { + group = "documentation" + description = "Copies the vitepress documentation to the build folder" + dependsOn("generateVitepressDoc") + from(rootProject.file("docs/vitepress")) + into(File(docsBuildDir, "vitepress")) + inputs.property("version", project.version.toString()) + filesMatching("index.md") { + expand(mapOf("version" to project.version.toString())) + } + } + tasks.register("createDistDocs", Copy::class.java) { group = "distribution" description = "Packages generated documentation into the dist directory" - dependsOn("prepareDist", "copyPyDoc", "copyTSDoc", "copyWebDoc") + dependsOn("prepareDist", "copyPyDoc", "copyTSDoc", "copyWebDoc", "copyVitepressDoc") from(docsBuildDir) into(distDirFile) } diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/DocletCategory.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/DocletCategory.java new file mode 100644 index 000000000..0bced3196 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/DocletCategory.java @@ -0,0 +1,17 @@ +package com.jsmacrosce.doclet; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface DocletCategory { + /** + * The category name used for organizing classes or events. + */ + String value(); +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/BasicDocCommentParser.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/BasicDocCommentParser.java new file mode 100644 index 000000000..b79798ed3 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/BasicDocCommentParser.java @@ -0,0 +1,101 @@ +package com.jsmacrosce.doclet.core; + +import com.sun.source.doctree.DocCommentTree; +import com.sun.source.doctree.DocTree; +import com.sun.source.doctree.ParamTree; +import com.sun.source.doctree.ReferenceTree; +import com.sun.source.doctree.ReturnTree; +import com.sun.source.doctree.SeeTree; +import com.sun.source.doctree.SinceTree; +import com.sun.source.doctree.TextTree; +import com.sun.source.doctree.DeprecatedTree; +import com.sun.source.doctree.LinkTree; +import com.sun.source.doctree.LiteralTree; +import com.sun.source.util.DocTrees; +import com.jsmacrosce.doclet.core.model.DocComment; +import com.jsmacrosce.doclet.core.model.DocTag; +import com.jsmacrosce.doclet.core.model.DocTagKind; + +import javax.lang.model.element.Element; +import java.util.ArrayList; +import java.util.List; + +public class BasicDocCommentParser implements DocCommentParser { + private final DocTrees docTrees; + + public BasicDocCommentParser(DocTrees docTrees) { + this.docTrees = docTrees; + } + + @Override + public DocComment parse(Element element) { + DocCommentTree tree = docTrees.getDocCommentTree(element); + boolean isDeprecated = element.getAnnotation(Deprecated.class) != null; + if (tree == null) { + if (isDeprecated) { + return new DocComment("", "", List.of(new DocTag(DocTagKind.DEPRECATED, null, ""))); + } + return new DocComment("", "", List.of()); + } + + String summary = renderText(tree.getFirstSentence()); + String description = renderText(tree.getFullBody()); + List tags = new ArrayList<>(); + + for (DocTree tag : tree.getBlockTags()) { + switch (tag.getKind()) { + case PARAM -> { + ParamTree param = (ParamTree) tag; + DocTagKind kind = param.isTypeParameter() ? DocTagKind.TEMPLATE : DocTagKind.PARAM; + tags.add(new DocTag(kind, param.getName().getName().toString(), renderText(param.getDescription()))); + } + case RETURN -> { + ReturnTree ret = (ReturnTree) tag; + tags.add(new DocTag(DocTagKind.RETURN, null, renderText(ret.getDescription()))); + } + case SINCE -> { + SinceTree since = (SinceTree) tag; + tags.add(new DocTag(DocTagKind.SINCE, null, renderText(since.getBody()))); + } + case DEPRECATED -> { + DeprecatedTree dep = (DeprecatedTree) tag; + tags.add(new DocTag(DocTagKind.DEPRECATED, null, renderText(dep.getBody()))); + } + case SEE -> { + SeeTree see = (SeeTree) tag; + for (DocTree ref : see.getReference()) { + if (ref.getKind() == DocTree.Kind.REFERENCE) { + String signature = ((ReferenceTree) ref).getSignature(); + tags.add(new DocTag(DocTagKind.SEE, null, signature)); + } else { + tags.add(new DocTag(DocTagKind.SEE, null, ref.toString())); + } + } + } + default -> tags.add(new DocTag(DocTagKind.OTHER, null, tag.toString())); + } + } + + if (isDeprecated && tags.stream().noneMatch(tag -> tag.kind() == DocTagKind.DEPRECATED)) { + tags.add(new DocTag(DocTagKind.DEPRECATED, null, "")); + } + + return new DocComment(summary, description, tags); + } + + private String renderText(List trees) { + StringBuilder builder = new StringBuilder(); + for (DocTree tree : trees) { + switch (tree.getKind()) { + case TEXT -> builder.append(((TextTree) tree).getBody()); + case CODE -> builder.append("`").append(((LiteralTree) tree).getBody()).append("`"); + case LINK, LINK_PLAIN -> { + String signature = ((LinkTree) tree).getReference().getSignature(); + builder.append("{@link ").append(signature).append("}"); + } + default -> builder.append(tree.toString()); + } + } + return builder.toString().trim(); + } +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/BasicTypeResolver.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/BasicTypeResolver.java new file mode 100644 index 000000000..6d6767690 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/BasicTypeResolver.java @@ -0,0 +1,384 @@ +package com.jsmacrosce.doclet.core; + +import com.jsmacrosce.doclet.core.model.TypeKind; +import com.jsmacrosce.doclet.core.model.TypeRef; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.IntersectionType; +import javax.lang.model.type.NoType; +import javax.lang.model.type.PrimitiveType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.UnionType; +import javax.lang.model.type.WildcardType; +import java.util.ArrayList; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class BasicTypeResolver implements TypeResolver { + private static final Set JAVA_ALIASES = Set.of( + "java.lang.Array", + "java.lang.Class", + "java.util.Collection", + "java.util.List", + "java.util.Map", + "java.util.Set" + ); + private static final Map JAVA_NUMBER_TYPES = Map.of( + "java.lang.Integer", "int", + "java.lang.Float", "float", + "java.lang.Long", "long", + "java.lang.Short", "short", + "java.lang.Character", "char", + "java.lang.Byte", "byte", + "java.lang.Double", "double", + "java.lang.Number", "number" + ); + private static final Map FUNCTIONAL_INTERFACES = Map.of( + "java.util.function.Consumer", "MethodWrapper<$0>", + "java.util.function.BiConsumer", "MethodWrapper<$0, $1>", + "java.util.function.Function", "MethodWrapper<$0, any, $1>", + "java.util.function.BiFunction", "MethodWrapper<$0, $1, $2>", + "java.util.function.Predicate", "MethodWrapper<$0, any, boolean>", + "java.util.function.BiPredicate", "MethodWrapper<$0, $1, boolean>", + "java.util.function.Supplier", "MethodWrapper", + "java.util.Comparator", "MethodWrapper<$0, $0, int>", + "java.lang.Runnable", "MethodWrapper" + ); + + private Map typeScriptAliases = Map.of(); + private boolean pythonAliasEnabled = true; + private final Set resolving = Collections.newSetFromMap(new IdentityHashMap<>()); + + public void setTypeScriptAliases(Map typeScriptAliases) { + this.typeScriptAliases = typeScriptAliases == null ? Map.of() : typeScriptAliases; + } + + public void setPythonAliasEnabled(boolean pythonAliasEnabled) { + this.pythonAliasEnabled = pythonAliasEnabled; + } + + @Override + public TypeRef resolve(TypeMirror type) { + if (type == null) { + return new TypeRef(TypeKind.UNKNOWN, "unknown", "unknown", List.of(), false, false, null, false); + } + if (!resolving.add(type)) { + // Handle self-referential type parameters (e.g., B extends SomeClass) + // by returning a TYPEVAR without bounds to avoid infinite recursion + if (type.getKind() == javax.lang.model.type.TypeKind.TYPEVAR) { + TypeVariable typeVar = (TypeVariable) type; + String name = typeVar.asElement().getSimpleName().toString(); + return new TypeRef(TypeKind.TYPEVAR, name, name, List.of(), false, false, null, false); + } + return new TypeRef(TypeKind.UNKNOWN, type.toString(), type.toString(), List.of(), false, false, null, false); + } + try { + return switch (type.getKind()) { + case BOOLEAN, BYTE, SHORT, INT, LONG, CHAR, FLOAT, DOUBLE -> + new TypeRef(TypeKind.PRIMITIVE, type.toString(), type.toString(), List.of(), false, false, null, false); + case VOID, NONE -> new TypeRef(TypeKind.VOID, "void", "void", List.of(), false, false, null, false); + case ARRAY -> { + ArrayType arrayType = (ArrayType) type; + TypeRef component = resolve(arrayType.getComponentType()); + yield new TypeRef(TypeKind.ARRAY, component.name(), component.qualifiedName(), List.of(component), true, false, null, false); + } + case DECLARED -> resolveDeclared((DeclaredType) type); + case TYPEVAR -> resolveTypeVar((TypeVariable) type); + case WILDCARD -> resolveWildcard((WildcardType) type); + case INTERSECTION -> resolveIntersection((IntersectionType) type); + case UNION -> resolveUnion((UnionType) type); + default -> new TypeRef(TypeKind.UNKNOWN, type.toString(), type.toString(), List.of(), false, false, null, false); + }; + } finally { + resolving.remove(type); + } + } + + private TypeRef resolveDeclared(DeclaredType type) { + Element el = type.asElement(); + String qualifiedName = getQualifiedName(el); + String displayName = getDisplayName(el); + List params = new ArrayList<>(); + for (TypeMirror arg : type.getTypeArguments()) { + params.add(resolve(arg)); + } + return new TypeRef(TypeKind.DECLARED, displayName, qualifiedName, params, false, false, null, false); + } + + private TypeRef resolveTypeVar(TypeVariable type) { + String name = type.asElement().getSimpleName().toString(); + TypeMirror bound = type.getUpperBound(); + TypeRef bounds = bound == null || bound.toString().equals("java.lang.Object") ? null : resolve(bound); + return new TypeRef(TypeKind.TYPEVAR, name, name, List.of(), false, false, bounds, false); + } + + private TypeRef resolveWildcard(WildcardType type) { + TypeMirror bound = type.getExtendsBound(); + if (bound == null) { + bound = type.getSuperBound(); + } + TypeRef bounds = bound == null ? null : resolve(bound); + return new TypeRef(TypeKind.WILDCARD, "?", "?", List.of(), false, false, bounds, false); + } + + private TypeRef resolveIntersection(IntersectionType type) { + List bounds = new ArrayList<>(); + for (TypeMirror bound : type.getBounds()) { + bounds.add(resolve(bound)); + } + return new TypeRef(TypeKind.INTERSECTION, "&", "&", bounds, false, false, null, false); + } + + private TypeRef resolveUnion(UnionType type) { + List bounds = new ArrayList<>(); + for (TypeMirror bound : type.getAlternatives()) { + bounds.add(resolve(bound)); + } + return new TypeRef(TypeKind.UNION, "|", "|", bounds, false, false, null, false); + } + + private String getQualifiedName(Element element) { + Element current = element; + StringBuilder name = new StringBuilder(); + while (current != null && current.getKind() != ElementKind.PACKAGE) { + if (current instanceof TypeElement typeElement) { + if (!name.isEmpty()) { + name.insert(0, "."); + } + name.insert(0, typeElement.getSimpleName()); + } + current = current.getEnclosingElement(); + } + if (current instanceof PackageElement pkg) { + String pkgName = pkg.getQualifiedName().toString(); + if (!pkgName.isEmpty()) { + name.insert(0, pkgName + "."); + } + } + return name.toString(); + } + + private String getDisplayName(Element element) { + StringBuilder name = new StringBuilder(); + Element current = element; + while (current != null && current.getKind() != ElementKind.PACKAGE) { + if (current instanceof TypeElement typeElement) { + if (!name.isEmpty()) { + name.insert(0, "."); + } + name.insert(0, typeElement.getSimpleName()); + } + current = current.getEnclosingElement(); + } + return name.toString(); + } + + @Override + public String format(TypeRef type, TargetLanguage target) { + return format(type, target, false); + } + + @Override + public String format(TypeRef type, TargetLanguage target, boolean paramType) { + if (type == null) { + return "any"; + } + return switch (target) { + case TYPESCRIPT -> formatTypeScript(type, paramType); + case PYTHON -> formatPython(type); + case MARKDOWN, HTML -> formatJavaLike(type); + }; + } + + private String formatTypeScript(TypeRef type, boolean paramType) { + return switch (type.kind()) { + case PRIMITIVE -> switch (type.name()) { + case "boolean" -> "boolean"; + case "byte", "short", "int", "long", "float", "double", "char" -> + paramType ? type.name() : "number"; + default -> "number"; + }; + case VOID -> "void"; + case ARRAY -> { + String component = formatTypeScript(type.typeArgs().get(0), paramType); + yield paramType ? component + "[]" : "JavaArray<" + component + ">"; + } + case DECLARED -> { + String alias = typeScriptAliases.get(type.qualifiedName()); + if (alias != null) { + yield alias; + } + + if (type.qualifiedName().startsWith("net.minecraft.")) { + yield maskMinecraftType(type, paramType); + } + + if (paramType && FUNCTIONAL_INTERFACES.containsKey(type.qualifiedName())) { + yield formatFunctionalInterface(type, paramType); + } + + String base = mapDeclaredTypeScript(type, paramType); + if (!type.typeArgs().isEmpty()) { + base = base + "<" + joinTypes(type.typeArgs(), TargetLanguage.TYPESCRIPT, paramType) + ">"; + } + yield base; + } + case TYPEVAR -> type.name(); + case WILDCARD -> "any"; + case INTERSECTION -> "(" + joinTypes(type.typeArgs(), TargetLanguage.TYPESCRIPT, paramType, " & ") + ")"; + case UNION -> "(" + joinTypes(type.typeArgs(), TargetLanguage.TYPESCRIPT, paramType, " | ") + ")"; + default -> "any"; + }; + } + + private String mapDeclaredTypeScript(TypeRef type, boolean paramType) { + String qualifiedName = type.qualifiedName(); + if ("com.jsmacrosce.jsmacros.core.event.BaseEvent".equals(qualifiedName)) { + return "Events.BaseEvent"; + } + if (JAVA_NUMBER_TYPES.containsKey(qualifiedName)) { + return paramType ? JAVA_NUMBER_TYPES.get(qualifiedName) : "number"; + } + return switch (qualifiedName) { + case "java.lang.String" -> "string"; + case "java.lang.Boolean" -> "boolean"; + case "java.lang.Object" -> "any"; + default -> { + if (JAVA_ALIASES.contains(qualifiedName)) { + String base = "Java" + simpleName(qualifiedName); + if (paramType && base.equals("JavaClass")) { + base = "JavaClassArg"; + } + yield base; + } + yield "Packages." + toTsQualified(type); + } + }; + } + + private String toTsQualified(TypeRef type) { + String qualifiedName = type.qualifiedName(); + String name = type.name(); + if (qualifiedName.endsWith(name)) { + String pkg = qualifiedName.substring(0, qualifiedName.length() - name.length()); + return pkg + name.replace('.', '$'); + } + return qualifiedName.replace('.', '$'); + } + + private String formatPython(TypeRef type) { + return switch (type.kind()) { + case PRIMITIVE -> switch (type.name()) { + case "boolean" -> "bool"; + case "byte", "short", "int", "long", "char" -> "int"; + case "float", "double" -> "float"; + default -> "int"; + }; + case VOID -> "None"; + case ARRAY -> "list[" + formatPython(type.typeArgs().get(0)) + "]"; + case DECLARED -> { + String base = mapDeclaredPython(type.qualifiedName()); + if (!type.typeArgs().isEmpty()) { + base = base + "[" + joinTypes(type.typeArgs(), TargetLanguage.PYTHON) + "]"; + } + yield base; + } + case TYPEVAR -> type.name(); + case WILDCARD -> "object"; + case INTERSECTION, UNION -> "object"; + default -> "object"; + }; + } + + private String mapDeclaredPython(String qualifiedName) { + if (!pythonAliasEnabled) { + return simpleName(qualifiedName); + } + return switch (qualifiedName) { + case "java.lang.String" -> "str"; + case "java.lang.Boolean" -> "bool"; + case "java.lang.Integer", "java.lang.Long", "java.lang.Short", "java.lang.Byte" -> "int"; + case "java.lang.Float", "java.lang.Double" -> "float"; + case "java.lang.Object" -> "object"; + default -> simpleName(qualifiedName); + }; + } + + private String formatJavaLike(TypeRef type) { + return switch (type.kind()) { + case PRIMITIVE, VOID, TYPEVAR -> type.name(); + case ARRAY -> formatJavaLike(type.typeArgs().get(0)) + "[]"; + case DECLARED -> { + String base = simpleName(type.qualifiedName()); + if (!type.typeArgs().isEmpty()) { + base = base + "<" + joinTypes(type.typeArgs(), TargetLanguage.MARKDOWN) + ">"; + } + yield base; + } + case WILDCARD -> "?"; + case INTERSECTION -> "(" + joinTypes(type.typeArgs(), TargetLanguage.MARKDOWN, false, " & ") + ")"; + case UNION -> "(" + joinTypes(type.typeArgs(), TargetLanguage.MARKDOWN, false, " | ") + ")"; + default -> type.name(); + }; + } + + private String joinTypes(List types, TargetLanguage target) { + return joinTypes(types, target, false); + } + + private String joinTypes(List types, TargetLanguage target, boolean paramType) { + return joinTypes(types, target, paramType, ", "); + } + + private String joinTypes(List types, TargetLanguage target, boolean paramType, String separator) { + StringBuilder builder = new StringBuilder(); + for (TypeRef ref : types) { + builder.append(format(ref, target, paramType)).append(separator); + } + if (!types.isEmpty()) { + builder.setLength(builder.length() - separator.length()); + } + return builder.toString(); + } + + private String simpleName(String qualifiedName) { + int idx = qualifiedName.lastIndexOf('.'); + return idx == -1 ? qualifiedName : qualifiedName.substring(idx + 1); + } + + private String formatFunctionalInterface(TypeRef type, boolean paramType) { + String template = FUNCTIONAL_INTERFACES.get(type.qualifiedName()); + if (template == null) { + return formatTypeScript(type, paramType); + } + String res = template; + if (!type.typeArgs().isEmpty()) { + int size = type.typeArgs().size(); + for (int i = 0; i < size; i++) { + res = res.replace("$" + i, formatTypeScript(type.typeArgs().get(i), true)); + } + } + return res; + } + + private String maskMinecraftType(TypeRef type, boolean paramType) { + StringBuilder raw = new StringBuilder(type.qualifiedName()); + if (!type.typeArgs().isEmpty()) { + raw.append("<").append(joinTypes(type.typeArgs(), TargetLanguage.TYPESCRIPT, paramType)).append(">"); + } + String cleaned = raw.toString() + .replace("/* ", "") + .replace(" */ any", "") + .replace(" */", ""); + return "/* " + cleaned + " */ any"; + } +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/DocCommentParser.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/DocCommentParser.java new file mode 100644 index 000000000..81ae74016 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/DocCommentParser.java @@ -0,0 +1,9 @@ +package com.jsmacrosce.doclet.core; + +import com.jsmacrosce.doclet.core.model.DocComment; + +import javax.lang.model.element.Element; + +public interface DocCommentParser { + DocComment parse(Element element); +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/DocletModelBuilder.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/DocletModelBuilder.java new file mode 100644 index 000000000..c3e8bff79 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/DocletModelBuilder.java @@ -0,0 +1,655 @@ +package com.jsmacrosce.doclet.core; + +import com.jsmacrosce.doclet.DocletCategory; +import com.jsmacrosce.doclet.DocletDeclareType; +import com.jsmacrosce.doclet.DocletIgnore; +import com.jsmacrosce.doclet.DocletReplaceParams; +import com.jsmacrosce.doclet.DocletReplaceReturn; +import com.jsmacrosce.doclet.DocletReplaceTypeParams; +import com.jsmacrosce.doclet.core.model.ClassDoc; +import com.jsmacrosce.doclet.core.model.ClassKind; +import com.jsmacrosce.doclet.core.model.DeclaredTypeDoc; +import com.jsmacrosce.doclet.core.model.DocComment; +import com.jsmacrosce.doclet.core.model.DocTag; +import com.jsmacrosce.doclet.core.model.DocTagKind; +import com.jsmacrosce.doclet.core.model.DocletModel; +import com.jsmacrosce.doclet.core.model.MemberDoc; +import com.jsmacrosce.doclet.core.model.MemberKind; +import com.jsmacrosce.doclet.core.model.PackageDoc; +import com.jsmacrosce.doclet.core.model.ParamDoc; +import com.jsmacrosce.doclet.core.model.TypeRef; +import com.jsmacrosce.doclet.core.util.ElementNameUtils; + +import com.sun.source.util.DocTrees; +import jdk.javadoc.doclet.DocletEnvironment; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.util.Elements; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeKind; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.HashSet; +import java.util.LinkedHashSet; + +public class DocletModelBuilder { + private final TypeResolver typeResolver; + private final DocCommentParser docCommentParser; + private final List declaredTypes = new ArrayList<>(); + private DocTrees docTrees; + private Elements elementUtils; + private Set objectMethods = Set.of(); + private Set objectMethodNames = Set.of(); + + public DocletModelBuilder( + TypeResolver typeResolver, + DocCommentParser docCommentParser + ) { + this.typeResolver = typeResolver; + this.docCommentParser = docCommentParser; + } + + public DocletModel build(DocletEnvironment environment) { + this.docTrees = environment.getDocTrees(); + this.elementUtils = environment.getElementUtils(); + initObjectMethods(); + + Map> packages = new HashMap<>(); + Map> mixinInterfaces = collectMixinInterfaces(environment); + + for (Element element : environment.getIncludedElements()) { + if (!(element instanceof TypeElement type)) { + addDeclaredType(element); + continue; + } + + if (type.getAnnotation(DocletIgnore.class) != null) { + continue; + } + + addDeclaredType(type); + + String packageName = ElementNameUtils.getPackageName(type); + String displayName = ElementNameUtils.getDisplayClassName(type); + String qualifiedName = ElementNameUtils.getQualifiedName(type); + + String group = "Class"; + String alias = null; + boolean eventCancellable = false; + String eventFilterer = null; + String category = null; + AnnotationMirror library = findAnnotation(type, "Library"); + AnnotationMirror event = findAnnotation(type, "Event"); + if (library != null) { + group = "Library"; + alias = String.valueOf(getAnnotationValue(library, "value")); + } else if (event != null) { + group = "Event"; + alias = String.valueOf(getAnnotationValue(event, "value")); + Object cancellableValue = getAnnotationValue(event, "cancellable"); + eventCancellable = Boolean.TRUE.equals(cancellableValue); + Object filtererValue = getAnnotationValue(event, "filterer"); + if (filtererValue instanceof DeclaredType declared) { + String name = declared.asElement().getSimpleName().toString(); + if (!"EventFilterer".equals(name)) { + eventFilterer = name; + } + } else if (filtererValue instanceof TypeMirror mirror && mirror.getKind() == TypeKind.DECLARED) { + String name = ((DeclaredType) mirror).asElement().getSimpleName().toString(); + if (!"EventFilterer".equals(name)) { + eventFilterer = name; + } + } + } + DocletCategory categoryAnnotation = type.getAnnotation(DocletCategory.class); + if (categoryAnnotation != null) { + category = categoryAnnotation.value(); + } + + ClassKind kind = switch (type.getKind()) { + case INTERFACE -> ClassKind.INTERFACE; + case ENUM -> ClassKind.ENUM; + case ANNOTATION_TYPE -> ClassKind.ANNOTATION; + default -> ClassKind.CLASS; + }; + + List typeParams = new ArrayList<>(); + for (TypeParameterElement param : type.getTypeParameters()) { + typeParams.add(typeResolver.resolve(param.asType())); + } + + List extendsTypes = new ArrayList<>(); + if (type.getSuperclass() != null && type.getSuperclass().getKind() != javax.lang.model.type.TypeKind.NONE) { + String sup = type.getSuperclass().toString(); + if (!"java.lang.Object".equals(sup)) { + extendsTypes.add(typeResolver.resolve(type.getSuperclass())); + } + } + List implementsTypes = new ArrayList<>(); + Set implemented = new HashSet<>(); + for (var iface : type.getInterfaces()) { + TypeRef resolved = typeResolver.resolve(iface); + if (implemented.add(resolved.qualifiedName())) { + implementsTypes.add(resolved); + } + } + + Set superMcTypes = new LinkedHashSet<>(); + Set superTypes = new LinkedHashSet<>(); + collectSuperTypes(type, superTypes, superMcTypes, new HashSet<>()); + + boolean directExtendsMc = isMinecraftType(type.getSuperclass()); + List mixins = mixinInterfaces.get(qualifiedName); + if (mixins != null) { + for (TypeMirror iface : mixins) { + TypeRef resolved = typeResolver.resolve(iface); + if (implemented.add(resolved.qualifiedName())) { + implementsTypes.add(resolved); + } + } + } + if (directExtendsMc && !superMcTypes.isEmpty()) { + for (TypeElement mcType : superMcTypes) { + String mcQualified = ElementNameUtils.getQualifiedName(mcType); + List extraMixins = mixinInterfaces.get(mcQualified); + if (extraMixins == null) { + continue; + } + for (TypeMirror iface : extraMixins) { + TypeRef resolved = typeResolver.resolve(iface); + if (implemented.add(resolved.qualifiedName())) { + implementsTypes.add(resolved); + } + if (iface.getKind() == TypeKind.DECLARED) { + superTypes.add((TypeElement) ((DeclaredType) iface).asElement()); + } + } + } + } + + List modifiers = new ArrayList<>(); + for (Modifier modifier : type.getModifiers()) { + modifiers.add(modifier.toString()); + } + + DocComment classComment = docCommentParser.parse(type); + List members = new ArrayList<>(); + List instanceMethods = new ArrayList<>(); + + Set eventSkipNames = new HashSet<>(); + if ("Event".equals(group)) { + Map> eventMethodsByName = new HashMap<>(); + for (Element enclosed : type.getEnclosedElements()) { + if (enclosed.getKind() != ElementKind.METHOD) { + continue; + } + if (!enclosed.getModifiers().contains(Modifier.PUBLIC)) { + continue; + } + ExecutableElement method = (ExecutableElement) enclosed; + eventMethodsByName.computeIfAbsent(method.getSimpleName().toString(), key -> new ArrayList<>()) + .add(method); + } + for (Map.Entry> entry : eventMethodsByName.entrySet()) { + String name = entry.getKey(); + if (!objectMethodNames.contains(name)) { + continue; + } + boolean allObjectMethods = true; + for (ExecutableElement method : entry.getValue()) { + if (!isObjectMethod(method, type)) { + allObjectMethods = false; + break; + } + } + if (allObjectMethods) { + eventSkipNames.add(name); + } + } + } + + for (Element enclosed : type.getEnclosedElements()) { + if (enclosed.getAnnotation(DocletIgnore.class) != null) { + continue; + } + addDeclaredType(enclosed); + if (!enclosed.getModifiers().contains(Modifier.PUBLIC)) { + continue; + } + if (enclosed.getKind() == ElementKind.FIELD || enclosed.getKind() == ElementKind.ENUM_CONSTANT) { + members.add(buildField(enclosed)); + } else if (enclosed.getKind() == ElementKind.METHOD) { + ExecutableElement method = (ExecutableElement) enclosed; + String methodName = method.getSimpleName().toString(); + if ("Event".equals(group) && eventSkipNames.contains(methodName)) { + continue; + } + if (!"Event".equals(group) && isObjectMethod(method, type)) { + continue; + } + if (isObfuscated(method, type, superMcTypes)) { + continue; + } + members.add(buildMethod(method)); + if (!method.getModifiers().contains(Modifier.STATIC)) { + instanceMethods.add(method); + } + } else if (enclosed.getKind() == ElementKind.CONSTRUCTOR) { + members.add(buildConstructor((ExecutableElement) enclosed)); + } + } + + if (!"Event".equals(group)) { + addSuperMethods(type, superTypes, superMcTypes, instanceMethods, members); + } + + members.sort(Comparator.comparing(MemberDoc::name, String.CASE_INSENSITIVE_ORDER)); + + ClassDoc classDoc = new ClassDoc( + displayName, + qualifiedName, + packageName, + kind, + group, + alias, + category, + eventCancellable, + eventFilterer, + typeParams, + extendsTypes, + implementsTypes, + modifiers, + classComment, + members + ); + + packages.computeIfAbsent(packageName, key -> new ArrayList<>()).add(classDoc); + } + + List packageDocs = new ArrayList<>(); + for (Map.Entry> entry : packages.entrySet()) { + entry.getValue().sort(Comparator.comparing(ClassDoc::qualifiedName, String.CASE_INSENSITIVE_ORDER)); + packageDocs.add(new PackageDoc(entry.getKey(), entry.getValue())); + } + packageDocs.sort(Comparator.comparing(PackageDoc::name, String.CASE_INSENSITIVE_ORDER)); + + return new DocletModel(packageDocs, declaredTypes); + } + + private void initObjectMethods() { + TypeElement objectElement = elementUtils.getTypeElement("java.lang.Object"); + if (objectElement == null) { + objectMethods = Set.of(); + objectMethodNames = Set.of(); + return; + } + Set methods = new HashSet<>(); + Set names = new HashSet<>(); + for (Element element : objectElement.getEnclosedElements()) { + if (element.getKind() != ElementKind.METHOD) { + continue; + } + if (!element.getModifiers().contains(Modifier.PUBLIC) || element.getModifiers().contains(Modifier.STATIC)) { + continue; + } + ExecutableElement method = (ExecutableElement) element; + methods.add(method); + names.add(method.getSimpleName().toString()); + } + objectMethods = methods; + objectMethodNames = names; + } + + private boolean isObjectMethod(ExecutableElement method, TypeElement owner) { + if (!objectMethodNames.contains(method.getSimpleName().toString())) { + return false; + } + if (docTrees != null && docTrees.getDocCommentTree(method) != null) { + return false; + } + for (ExecutableElement objectMethod : objectMethods) { + if (elementUtils.overrides(method, objectMethod, owner)) { + return true; + } + } + return false; + } + + private void collectSuperTypes( + TypeElement type, + Set superTypes, + Set superMcTypes, + Set visited + ) { + if (!visited.add(type)) { + return; + } + if (!type.getKind().isInterface()) { + TypeMirror superType = type.getSuperclass(); + if (superType != null && superType.getKind() == TypeKind.DECLARED) { + TypeElement superElement = (TypeElement) ((DeclaredType) superType).asElement(); + if (isMinecraftType(superType)) { + superMcTypes.add(superElement); + } else { + superTypes.add(superElement); + } + collectSuperTypes(superElement, superTypes, superMcTypes, visited); + } + } + for (TypeMirror iface : type.getInterfaces()) { + if (iface.getKind() != TypeKind.DECLARED) { + continue; + } + TypeElement ifaceElement = (TypeElement) ((DeclaredType) iface).asElement(); + if (isMinecraftType(iface)) { + superMcTypes.add(ifaceElement); + } else { + superTypes.add(ifaceElement); + } + collectSuperTypes(ifaceElement, superTypes, superMcTypes, visited); + } + } + + private boolean isMinecraftType(TypeMirror type) { + if (type == null || type.getKind() != TypeKind.DECLARED) { + return false; + } + Element element = ((DeclaredType) type).asElement(); + if (!(element instanceof TypeElement typeElement)) { + return false; + } + String pkg = ElementNameUtils.getPackageName(typeElement); + return pkg != null && pkg.startsWith("net.minecraft."); + } + + private boolean isObfuscated(ExecutableElement method, TypeElement owner, Set superMcTypes) { + if (method.getAnnotation(Override.class) == null) { + return false; + } + for (TypeElement mcType : superMcTypes) { + for (Element element : mcType.getEnclosedElements()) { + if (element.getKind() != ElementKind.METHOD) { + continue; + } + if (elementUtils.overrides(method, (ExecutableElement) element, owner)) { + return true; + } + } + } + return false; + } + + private void addSuperMethods( + TypeElement owner, + Set superTypes, + Set superMcTypes, + List instanceMethods, + List members + ) { + if (instanceMethods.isEmpty() || superTypes.isEmpty()) { + return; + } + Set methodNames = new HashSet<>(); + for (ExecutableElement method : instanceMethods) { + methodNames.add(method.getSimpleName().toString()); + } + if (methodNames.isEmpty()) { + return; + } + + List superMethods = new ArrayList<>(); + for (TypeElement superType : superTypes) { + for (Element element : superType.getEnclosedElements()) { + if (element.getKind() != ElementKind.METHOD) { + continue; + } + if (!element.getModifiers().contains(Modifier.PUBLIC) + || element.getModifiers().contains(Modifier.STATIC)) { + continue; + } + ExecutableElement method = (ExecutableElement) element; + if (!methodNames.contains(method.getSimpleName().toString())) { + continue; + } + + boolean overridden = false; + for (ExecutableElement existing : instanceMethods) { + if (existing.getSimpleName().contentEquals(method.getSimpleName()) + && elementUtils.overrides(existing, method, owner)) { + overridden = true; + break; + } + } + if (overridden) { + continue; + } + for (ExecutableElement existing : superMethods) { + if (existing.getSimpleName().contentEquals(method.getSimpleName()) + && elementUtils.overrides(existing, method, owner)) { + overridden = true; + break; + } + } + if (overridden) { + continue; + } + if (element.getAnnotation(DocletIgnore.class) != null) { + continue; + } + if (isObfuscated(method, superType, superMcTypes)) { + continue; + } + superMethods.add(method); + } + } + + for (ExecutableElement method : superMethods) { + members.add(buildMethod(method)); + } + } + + private Map> collectMixinInterfaces(DocletEnvironment environment) { + Map> mixinInterfaces = new HashMap<>(); + for (Element element : environment.getIncludedElements()) { + if (!(element instanceof TypeElement type)) { + continue; + } + AnnotationMirror mixin = findAnnotation(type, "Mixin"); + if (mixin == null) { + continue; + } + List interfaces = type.getInterfaces(); + if (interfaces.isEmpty()) { + continue; + } + + Object targetsObj = getAnnotationValue(mixin, "value"); + if (!(targetsObj instanceof List targets) || targets.isEmpty()) { + continue; + } + + List mixinIfaces = new ArrayList<>(); + for (TypeMirror iface : interfaces) { + if (iface.getKind() != TypeKind.DECLARED) { + continue; + } + TypeElement ifaceElement = (TypeElement) ((DeclaredType) iface).asElement(); + if (ifaceElement.getAnnotation(DocletIgnore.class) != null) { + continue; + } + mixinIfaces.add(iface); + } + if (mixinIfaces.isEmpty()) { + continue; + } + + for (Object targetObj : targets) { + if (!(targetObj instanceof AnnotationValue av)) { + continue; + } + Object value = av.getValue(); + if (!(value instanceof TypeMirror mirror) || mirror.getKind() != TypeKind.DECLARED) { + continue; + } + TypeElement targetType = (TypeElement) ((DeclaredType) mirror).asElement(); + String qualifiedName = ElementNameUtils.getQualifiedName(targetType); + mixinInterfaces.computeIfAbsent(qualifiedName, key -> new ArrayList<>()) + .addAll(mixinIfaces); + } + } + return mixinInterfaces; + } + + private void addDeclaredType(Element element) { + DocletDeclareType declare = element.getAnnotation(DocletDeclareType.class); + if (declare != null) { + declaredTypes.add(new DeclaredTypeDoc(declare.name(), declare.type())); + } + } + + private MemberDoc buildField(Element element) { + DocComment comment = docCommentParser.parse(element); + List modifiers = new ArrayList<>(); + for (Modifier modifier : element.getModifiers()) { + modifiers.add(modifier.toString()); + } + + DocletReplaceReturn replaceReturn = element.getAnnotation(DocletReplaceReturn.class); + String replaceReturnValue = replaceReturn == null ? null : replaceReturn.value(); + TypeRef typeRef = typeResolver.resolve(element.asType()); + if (isNullable(element)) { + typeRef = typeRef.withNullable(true); + } + + return new MemberDoc( + MemberKind.FIELD, + element.getSimpleName().toString(), + ElementNameUtils.memberId(element), + List.of(), + List.of(), + typeRef, + null, + replaceReturnValue, + null, + modifiers, + comment + ); + } + + private MemberDoc buildConstructor(ExecutableElement element) { + return buildExecutable(element, MemberKind.CONSTRUCTOR); + } + + private MemberDoc buildMethod(ExecutableElement element) { + return buildExecutable(element, MemberKind.METHOD); + } + + private MemberDoc buildExecutable(ExecutableElement element, MemberKind kind) { + DocComment comment = docCommentParser.parse(element); + Map paramDocs = new HashMap<>(); + for (DocTag tag : comment.tags()) { + if (tag.kind() == DocTagKind.PARAM && tag.name() != null) { + paramDocs.put(tag.name(), tag.text()); + } + } + + List params = new ArrayList<>(); + List rawParams = element.getParameters(); + VariableElement varArgParam = element.isVarArgs() && !rawParams.isEmpty() + ? rawParams.get(rawParams.size() - 1) + : null; + for (VariableElement param : rawParams) { + boolean isVarArgs = param.equals(varArgParam); + TypeRef paramType = typeResolver.resolve(param.asType()); + if (isNullable(param)) { + paramType = paramType.withNullable(true); + } + params.add(new ParamDoc( + param.getSimpleName().toString(), + paramType, + isVarArgs, + paramDocs.getOrDefault(param.getSimpleName().toString(), "") + )); + } + + List typeParams = new ArrayList<>(); + for (TypeParameterElement param : element.getTypeParameters()) { + typeParams.add(typeResolver.resolve(param.asType())); + } + + List modifiers = new ArrayList<>(); + for (Modifier modifier : element.getModifiers()) { + modifiers.add(modifier.toString()); + } + + DocletReplaceParams replaceParams = element.getAnnotation(DocletReplaceParams.class); + DocletReplaceReturn replaceReturn = element.getAnnotation(DocletReplaceReturn.class); + DocletReplaceTypeParams replaceTypeParams = element.getAnnotation(DocletReplaceTypeParams.class); + + String replaceParamsValue = replaceParams == null ? null : replaceParams.value(); + String replaceReturnValue = replaceReturn == null ? null : replaceReturn.value(); + String replaceTypeParamsValue = replaceTypeParams == null ? null : replaceTypeParams.value(); + + String name = kind == MemberKind.CONSTRUCTOR + ? ElementNameUtils.getDisplayClassName((TypeElement) element.getEnclosingElement()) + : element.getSimpleName().toString(); + + TypeRef returnType = typeResolver.resolve( + kind == MemberKind.CONSTRUCTOR ? element.getEnclosingElement().asType() : element.getReturnType() + ); + if (kind == MemberKind.METHOD && isNullable(element)) { + returnType = returnType.withNullable(true); + } + + return new MemberDoc( + kind, + name, + ElementNameUtils.memberId(element), + params, + typeParams, + returnType, + replaceParamsValue, + replaceReturnValue, + replaceTypeParamsValue, + modifiers, + comment + ); + } + + private AnnotationMirror findAnnotation(TypeElement type, String name) { + for (AnnotationMirror mirror : type.getAnnotationMirrors()) { + String simpleName = mirror.getAnnotationType().asElement().getSimpleName().toString(); + if (simpleName.equals(name)) { + return mirror; + } + } + return null; + } + + private Object getAnnotationValue(AnnotationMirror annotation, String key) { + for (Map.Entry el : annotation.getElementValues().entrySet()) { + if (el.getKey().getSimpleName().toString().equals(key)) { + return el.getValue().getValue(); + } + } + return null; + } + + private boolean isNullable(Element element) { + return element.getAnnotationMirrors().stream() + .anyMatch(a -> a.getAnnotationType().asElement().getSimpleName().contentEquals("Nullable")); + } +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/LinkResolver.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/LinkResolver.java new file mode 100644 index 000000000..c2c57236f --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/LinkResolver.java @@ -0,0 +1,9 @@ +package com.jsmacrosce.doclet.core; + +import com.jsmacrosce.doclet.core.model.LinkRef; + +import javax.lang.model.element.Element; + +public interface LinkResolver { + LinkRef resolve(Element element); +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/Renderer.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/Renderer.java new file mode 100644 index 000000000..e913b30e2 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/Renderer.java @@ -0,0 +1,7 @@ +package com.jsmacrosce.doclet.core; + +import com.jsmacrosce.doclet.core.model.DocletModel; + +public interface Renderer { + String render(DocletModel model); +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/TargetLanguage.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/TargetLanguage.java new file mode 100644 index 000000000..917947fa2 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/TargetLanguage.java @@ -0,0 +1,8 @@ +package com.jsmacrosce.doclet.core; + +public enum TargetLanguage { + TYPESCRIPT, + PYTHON, + MARKDOWN, + HTML +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/TypeResolver.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/TypeResolver.java new file mode 100644 index 000000000..348e1955f --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/TypeResolver.java @@ -0,0 +1,14 @@ +package com.jsmacrosce.doclet.core; + +import com.jsmacrosce.doclet.core.model.TypeRef; + +import javax.lang.model.type.TypeMirror; + +public interface TypeResolver { + TypeRef resolve(TypeMirror type); + String format(TypeRef type, TargetLanguage target); + + default String format(TypeRef type, TargetLanguage target, boolean paramType) { + return format(type, target); + } +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/mddoclet/Main.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/mddoclet/Main.java new file mode 100644 index 000000000..dde83c2ba --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/mddoclet/Main.java @@ -0,0 +1,78 @@ +package com.jsmacrosce.doclet.core.mddoclet; + +import com.sun.source.util.DocTrees; +import jdk.javadoc.doclet.Doclet; +import jdk.javadoc.doclet.DocletEnvironment; +import jdk.javadoc.doclet.Reporter; +import com.jsmacrosce.doclet.core.BasicDocCommentParser; +import com.jsmacrosce.doclet.core.BasicTypeResolver; +import com.jsmacrosce.doclet.core.DocletModelBuilder; +import com.jsmacrosce.doclet.core.render.MarkdownWriter; +import com.jsmacrosce.doclet.mddoclet.options.Links; +import com.jsmacrosce.doclet.mddoclet.options.McVersion; +import com.jsmacrosce.doclet.options.IgnoredItem; +import com.jsmacrosce.doclet.options.OutputDirectory; +import com.jsmacrosce.doclet.options.Version; + +import javax.lang.model.SourceVersion; +import javax.tools.Diagnostic; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Locale; +import java.util.Set; + +public class Main implements Doclet { + private Reporter reporter; + + @Override + public void init(Locale locale, Reporter reporter) { + this.reporter = reporter; + } + + @Override + public String getName() { + return "VitePressDoc Generator (Core)"; + } + + @Override + public Set getSupportedOptions() { + return Set.of( + new Version(), + new McVersion(), + new OutputDirectory(), + new Links(), + new IgnoredItem("-doctitle", 1), + new IgnoredItem("-notimestamp", 0), + new IgnoredItem("-windowtitle", 1) + ); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.RELEASE_16; + } + + @Override + public boolean run(DocletEnvironment environment) { + DocTrees trees = environment.getDocTrees(); + BasicTypeResolver typeResolver = new BasicTypeResolver(); + DocletModelBuilder builder = new DocletModelBuilder(typeResolver, new BasicDocCommentParser(trees)); + var model = builder.build(environment); + + File outDir = new File(OutputDirectory.outputDir.toPath().resolve("content").toString(), Version.version); + if (!outDir.exists() && !outDir.mkdirs()) { + reporter.print(Diagnostic.Kind.ERROR, "Failed to create version dir\n"); + return false; + } + + MarkdownWriter writer = new MarkdownWriter(typeResolver); + try { + writer.write(model, outDir, Version.version, McVersion.mcVersion); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + } +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/ClassDoc.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/ClassDoc.java new file mode 100644 index 000000000..768e8674f --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/ClassDoc.java @@ -0,0 +1,22 @@ +package com.jsmacrosce.doclet.core.model; + +import java.util.List; + +public record ClassDoc( + String name, + String qualifiedName, + String packageName, + ClassKind kind, + String group, + String alias, + String category, + boolean eventCancellable, + String eventFilterer, + List typeParams, + List extendsTypes, + List implementsTypes, + List modifiers, + DocComment docComment, + List members +) { +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/ClassKind.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/ClassKind.java new file mode 100644 index 000000000..fe231d7a5 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/ClassKind.java @@ -0,0 +1,8 @@ +package com.jsmacrosce.doclet.core.model; + +public enum ClassKind { + CLASS, + INTERFACE, + ENUM, + ANNOTATION +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DeclaredTypeDoc.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DeclaredTypeDoc.java new file mode 100644 index 000000000..d46ed7e57 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DeclaredTypeDoc.java @@ -0,0 +1,4 @@ +package com.jsmacrosce.doclet.core.model; + +public record DeclaredTypeDoc(String name, String type) { +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocComment.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocComment.java new file mode 100644 index 000000000..6f5ccac2d --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocComment.java @@ -0,0 +1,6 @@ +package com.jsmacrosce.doclet.core.model; + +import java.util.List; + +public record DocComment(String summary, String description, List tags) { +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocTag.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocTag.java new file mode 100644 index 000000000..af163c373 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocTag.java @@ -0,0 +1,4 @@ +package com.jsmacrosce.doclet.core.model; + +public record DocTag(DocTagKind kind, String name, String text) { +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocTagKind.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocTagKind.java new file mode 100644 index 000000000..f345fa964 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocTagKind.java @@ -0,0 +1,11 @@ +package com.jsmacrosce.doclet.core.model; + +public enum DocTagKind { + SINCE, + DEPRECATED, + SEE, + PARAM, + TEMPLATE, + RETURN, + OTHER +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocletModel.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocletModel.java new file mode 100644 index 000000000..333dc1b4d --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/DocletModel.java @@ -0,0 +1,6 @@ +package com.jsmacrosce.doclet.core.model; + +import java.util.List; + +public record DocletModel(List packages, List declaredTypes) { +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/LinkRef.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/LinkRef.java new file mode 100644 index 000000000..eb83e26c1 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/LinkRef.java @@ -0,0 +1,4 @@ +package com.jsmacrosce.doclet.core.model; + +public record LinkRef(String url, boolean external) { +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/MemberDoc.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/MemberDoc.java new file mode 100644 index 000000000..ee526b403 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/MemberDoc.java @@ -0,0 +1,18 @@ +package com.jsmacrosce.doclet.core.model; + +import java.util.List; + +public record MemberDoc( + MemberKind kind, + String name, + String anchorId, + List params, + List typeParams, + TypeRef returnType, + String replaceParams, + String replaceReturn, + String replaceTypeParams, + List modifiers, + DocComment docComment +) { +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/MemberKind.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/MemberKind.java new file mode 100644 index 000000000..a53d5ff60 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/MemberKind.java @@ -0,0 +1,7 @@ +package com.jsmacrosce.doclet.core.model; + +public enum MemberKind { + FIELD, + METHOD, + CONSTRUCTOR +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/PackageDoc.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/PackageDoc.java new file mode 100644 index 000000000..a3754ecf6 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/PackageDoc.java @@ -0,0 +1,6 @@ +package com.jsmacrosce.doclet.core.model; + +import java.util.List; + +public record PackageDoc(String name, List classes) { +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/ParamDoc.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/ParamDoc.java new file mode 100644 index 000000000..9c967dc27 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/ParamDoc.java @@ -0,0 +1,4 @@ +package com.jsmacrosce.doclet.core.model; + +public record ParamDoc(String name, TypeRef type, boolean varArgs, String description) { +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/TypeKind.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/TypeKind.java new file mode 100644 index 000000000..02def2299 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/TypeKind.java @@ -0,0 +1,13 @@ +package com.jsmacrosce.doclet.core.model; + +public enum TypeKind { + PRIMITIVE, + DECLARED, + ARRAY, + TYPEVAR, + WILDCARD, + INTERSECTION, + UNION, + VOID, + UNKNOWN +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/TypeRef.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/TypeRef.java new file mode 100644 index 000000000..14742c020 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/model/TypeRef.java @@ -0,0 +1,21 @@ +package com.jsmacrosce.doclet.core.model; + +import java.util.List; + +public record TypeRef( + TypeKind kind, + String name, + String qualifiedName, + List typeArgs, + boolean array, + boolean varArgs, + TypeRef bounds, + boolean nullable +) { + public TypeRef withNullable(boolean nullable) { + if (this.nullable == nullable) { + return this; + } + return new TypeRef(kind, name, qualifiedName, typeArgs, array, varArgs, bounds, nullable); + } +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/pydoclet/Main.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/pydoclet/Main.java new file mode 100644 index 000000000..bbff12853 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/pydoclet/Main.java @@ -0,0 +1,96 @@ +package com.jsmacrosce.doclet.core.pydoclet; + +import com.sun.source.util.DocTrees; +import jdk.javadoc.doclet.Doclet; +import jdk.javadoc.doclet.DocletEnvironment; +import jdk.javadoc.doclet.Reporter; +import com.jsmacrosce.doclet.core.BasicDocCommentParser; +import com.jsmacrosce.doclet.core.BasicTypeResolver; +import com.jsmacrosce.doclet.core.DocletModelBuilder; +import com.jsmacrosce.doclet.core.render.PythonWriter; +import com.jsmacrosce.doclet.options.IgnoredItem; +import com.jsmacrosce.doclet.options.OutputDirectory; +import com.jsmacrosce.doclet.options.Version; + +import javax.lang.model.SourceVersion; +import javax.tools.Diagnostic; +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.Set; + +public class Main implements Doclet { + private Reporter reporter; + + @Override + public void init(Locale locale, Reporter reporter) { + this.reporter = reporter; + } + + @Override + public String getName() { + return "Python Generator (Core)"; + } + + @Override + public Set getSupportedOptions() { + return Set.of( + new Version(), + new OutputDirectory(), + new IgnoredItem("-doctitle", 1), + new IgnoredItem("-notimestamp", 0), + new IgnoredItem("-windowtitle", 1) + ); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.RELEASE_16; + } + + @Override + public boolean run(DocletEnvironment environment) { + DocTrees trees = environment.getDocTrees(); + BasicTypeResolver typeResolver = new BasicTypeResolver(); + typeResolver.setPythonAliasEnabled(false); + DocletModelBuilder builder = new DocletModelBuilder(typeResolver, new BasicDocCommentParser(trees)); + var model = builder.build(environment); + + File outDir = OutputDirectory.outputDir; + if (outDir == null) { + reporter.print(Diagnostic.Kind.ERROR, "Output directory not set\n"); + return false; + } + if (outDir.exists() && !deleteRecursively(outDir)) { + reporter.print(Diagnostic.Kind.ERROR, "Failed to remove old python output\n"); + return false; + } + if (!outDir.exists() && !outDir.mkdirs()) { + reporter.print(Diagnostic.Kind.ERROR, "Failed to create output directory\n"); + return false; + } + + PythonWriter writer = new PythonWriter(); + try { + writer.write(model, outDir, Version.version); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + } + + private boolean deleteRecursively(File file) { + if (file.isDirectory()) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + if (!deleteRecursively(child)) { + return false; + } + } + } + } + return file.delete(); + } +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/render/MarkdownWriter.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/render/MarkdownWriter.java new file mode 100644 index 000000000..a920dddf1 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/render/MarkdownWriter.java @@ -0,0 +1,819 @@ +package com.jsmacrosce.doclet.core.render; + +import com.jsmacrosce.FileHandler; +import com.jsmacrosce.doclet.core.TargetLanguage; +import com.jsmacrosce.doclet.core.TypeResolver; +import com.jsmacrosce.doclet.core.model.ClassDoc; +import com.jsmacrosce.doclet.core.model.DocComment; +import com.jsmacrosce.doclet.core.model.DocTag; +import com.jsmacrosce.doclet.core.model.DocTagKind; +import com.jsmacrosce.doclet.core.model.DocletModel; +import com.jsmacrosce.doclet.core.model.MemberDoc; +import com.jsmacrosce.doclet.core.model.MemberKind; +import com.jsmacrosce.doclet.core.model.PackageDoc; +import com.jsmacrosce.doclet.core.model.ParamDoc; +import com.jsmacrosce.doclet.core.model.TypeKind; +import com.jsmacrosce.doclet.core.model.TypeRef; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.regex.Pattern; + +public class MarkdownWriter { + private static final Pattern HTML_LINK = + Pattern.compile("(.*?)"); + private static final Pattern LINK_TAG = Pattern.compile("\\{@link\\s+([^}]+)}"); + private static final Map JAVA_NUMBER_TYPES = Map.of( + "java.lang.Integer", "int", + "java.lang.Float", "float", + "java.lang.Long", "long", + "java.lang.Short", "short", + "java.lang.Character", "char", + "java.lang.Byte", "byte", + "java.lang.Double", "double", + "java.lang.Number", "number" + ); + private static final String DEFAULT_CATEGORY = "Uncategorized"; + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + private final TypeResolver typeResolver; + private final Map classByQualifiedName = new HashMap<>(); + private final Map> classByName = new HashMap<>(); + private final Map> classByAlias = new HashMap<>(); + private String version; + + public MarkdownWriter(TypeResolver typeResolver) { + this.typeResolver = typeResolver; + } + + public void write(DocletModel model, File outDir, String version, String mcVersion) throws IOException { + this.version = version; + indexClasses(model); + Map> classCategories = groupByCategory(model, "Class"); + Map> eventCategories = groupByCategory(model, "Event"); + Map> libraryCategories = groupByCategory(model, "Library"); + SidebarData sidebarData = new SidebarData( + version, + mapToSidebarCategories(classCategories, version), + mapToSidebarCategories(eventCategories, version), + mapToSidebarCategories(libraryCategories, version) + ); + + for (PackageDoc pkg : model.packages()) { + for (ClassDoc clz : pkg.classes()) { + File out = new File(outDir, classPath(clz) + ".md"); + File parent = out.getParentFile(); + if (!parent.exists() && !parent.mkdirs()) { + throw new IOException("Failed to create package dir " + parent); + } + new FileHandler(out).write(renderClass(clz)); + } + } + + writeGroupIndexes(model, outDir, version, mcVersion, classCategories, eventCategories, libraryCategories); + writeSidebarData(outDir, sidebarData); + } + + private String classPath(ClassDoc clz) { + String pkgPath = clz.packageName().replace('.', '/'); + String namePath = clz.name().replace('$', '.'); + String basePath = pkgPath.isEmpty() ? namePath : pkgPath + "/" + namePath; + String groupPrefix = groupPathPrefix(clz); + return groupPrefix.isEmpty() ? basePath : groupPrefix + "/" + basePath; + } + + private String groupPathPrefix(ClassDoc clz) { + return switch (clz.group()) { + case "Event" -> "events"; + case "Class" -> "classes"; + case "Library" -> "libraries"; + default -> ""; + }; + } + + private void writeGroupIndexes( + DocletModel model, + File outDir, + String version, + String mcVersion, + Map> classCategories, + Map> eventCategories, + Map> libraryCategories + ) throws IOException { + Map> grouped = new java.util.HashMap<>(); + for (PackageDoc pkg : model.packages()) { + for (ClassDoc clz : pkg.classes()) { + grouped.computeIfAbsent(clz.group(), key -> new ArrayList<>()).add(clz); + } + } + grouped.values().forEach(list -> + list.sort(Comparator.comparing(ClassDoc::qualifiedName, String.CASE_INSENSITIVE_ORDER)) + ); + + new FileHandler(new File(outDir, "index.md")) + .write(renderOverview(grouped, version, mcVersion)); + new FileHandler(new File(outDir, "libraries.md")) + .write(renderGroupPage("Libraries", grouped.getOrDefault("Library", List.of()), true, libraryCategories)); + new FileHandler(new File(outDir, "events.md")) + .write(renderGroupPage("Events", grouped.getOrDefault("Event", List.of()), true, eventCategories)); + new FileHandler(new File(outDir, "classes.md")) + .write(renderGroupPage("Classes", grouped.getOrDefault("Class", List.of()), false, classCategories)); + } + + private String renderOverview(Map> grouped, String version, String mcVersion) { + StringBuilder builder = new StringBuilder(); + builder.append("---\noutline: false\n---\n\n"); + builder.append("# JsMacros API Reference\n\n"); + builder.append("Version: `").append(version).append("` \n"); + builder.append("Minecraft: `").append(mcVersion).append("`\n\n"); + builder.append("- [Libraries](./libraries.md) (").append(grouped.getOrDefault("Library", List.of()).size()).append(")\n"); + builder.append("- [Events](./events.md) (").append(grouped.getOrDefault("Event", List.of()).size()).append(")\n"); + builder.append("- [Classes](./classes.md) (").append(grouped.getOrDefault("Class", List.of()).size()).append(")\n\n"); + builder.append("Use the sidebar to browse packages and classes.\n"); + return builder.toString(); + } + + private String renderGroupPage(String title, List classes, boolean preferAlias, Map> categories) { + StringBuilder builder = new StringBuilder(); + builder.append("---\noutline: false\n---\n\n"); + builder.append("# ").append(title).append("\n\n"); + if ((categories == null || categories.isEmpty()) && classes.isEmpty()) { + builder.append("No entries found.\n"); + return builder.toString(); + } + if (categories != null && !categories.isEmpty()) { + for (Map.Entry> entry : categories.entrySet()) { + builder.append("### ").append(entry.getKey()).append("\n\n"); + renderGroupEntries(entry.getValue(), preferAlias, builder); + builder.append("\n"); + } + return builder.toString(); + } + renderGroupEntries(classes, preferAlias, builder); + return builder.toString(); + } + + private void renderGroupEntries(List entries, boolean preferAlias, StringBuilder builder) { + if (entries == null || entries.isEmpty()) { + builder.append("No entries found.\n"); + return; + } + for (ClassDoc clz : entries) { + String linkText = preferAlias && hasAlias(clz) + ? clz.alias() + : clz.qualifiedName(); + builder.append("- [") + .append(linkText) + .append("](./") + .append(classPath(clz)) + .append(".md)"); + if (preferAlias && hasAlias(clz) && !linkText.equals(clz.qualifiedName())) { + builder.append(" (`").append(clz.qualifiedName()).append("`)"); + } + builder.append("\n"); + } + } + + private boolean hasAlias(ClassDoc clz) { + return clz.alias() != null && !clz.alias().isBlank(); + } + + private Map> groupByCategory(DocletModel model, String targetGroup) { + Map> categories = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + for (PackageDoc pkg : model.packages()) { + for (ClassDoc clz : pkg.classes()) { + if (!targetGroup.equals(clz.group())) { + continue; + } + String category = clz.category(); + if (category == null || category.isBlank()) { + category = DEFAULT_CATEGORY; + } + categories.computeIfAbsent(category, key -> new ArrayList<>()).add(clz); + } + } + for (List list : categories.values()) { + list.sort(Comparator.comparing(this::sidebarSortKey, String.CASE_INSENSITIVE_ORDER)); + } + return categories; + } + + private String sidebarSortKey(ClassDoc clz) { + return hasAlias(clz) ? clz.alias() : clz.name(); + } + + private List mapToSidebarCategories(Map> categories, String version) { + List sections = new ArrayList<>(); + for (Map.Entry> entry : categories.entrySet()) { + List items = new ArrayList<>(); + for (ClassDoc clz : entry.getValue()) { + String link = "/" + version + "/" + classPath(clz); + items.add(new SidebarItem(displayLabel(clz), link)); + } + sections.add(new SidebarCategory(entry.getKey(), items)); + } + return sections; + } + + private String displayLabel(ClassDoc clz) { + if (hasAlias(clz)) { + return clz.alias(); + } + return clz.name(); + } + + private void writeSidebarData(File outDir, SidebarData data) throws IOException { + new FileHandler(new File(outDir, "sidebar-data.json")).write(GSON.toJson(data)); + } + + private record SidebarItem(String text, String link) {} + private record SidebarCategory(String name, List items) {} + private record SidebarData(String version, List classes, List events, List libraries) {} + + private String renderClass(ClassDoc clz) { + StringBuilder builder = new StringBuilder(); + builder.append("---\noutline: deep\n---\n\n"); + builder.append("# ").append(displayTitle(clz)).append("\n\n"); + builder.append(clz.qualifiedName()).append("\n\n"); + String desc = formatDescription(clz.docComment(), clz); + builder.append(desc.isEmpty() ? "TODO: No description supplied" : desc); + if ("Library".equals(clz.group())) { + String accessName = clz.alias() == null || clz.alias().isEmpty() ? clz.name() : clz.alias(); + builder.append("\nAccessible in scripts via the global `").append(accessName).append("` variable."); + } + builder.append("\n\n"); + + renderMemberSection(builder, clz, MemberKind.CONSTRUCTOR, "Constructors"); + renderMemberSection(builder, clz, MemberKind.FIELD, "Fields"); + renderMemberSection(builder, clz, MemberKind.METHOD, "Methods"); + return builder.toString(); + } + + private String displayTitle(ClassDoc clz) { + if ("Event".equals(clz.group()) && hasAlias(clz)) { + return clz.alias(); + } + return clz.name(); + } + + private void renderMemberSection(StringBuilder builder, ClassDoc clz, MemberKind kind, String title) { + List members = clz.members().stream() + .filter(member -> member.kind() == kind) + .toList(); + if (members.isEmpty()) { + return; + } + builder.append("## ").append(title).append("\n\n"); + for (MemberDoc member : members) { + if (member.anchorId() != null && !member.anchorId().isBlank()) { + builder.append("\n"); + } + builder.append("### ").append(renderMemberTitle(member)).append("\n\n"); + String signature = renderSignature(member); + builder.append("**Signature:** ").append(renderSignatureValue(signature)).append("\n\n"); + String desc = formatDescription(member.docComment(), clz); + if (!desc.isEmpty()) { + builder.append(desc).append("\n\n"); + } + String since = getTagText(member.docComment(), DocTagKind.SINCE); + if (!since.isEmpty()) { + builder.append("**Since:** ").append(formatDocText(since, clz)).append("\n\n"); + } + if (hasDeprecatedTag(member.docComment())) { + String deprecated = getTagText(member.docComment(), DocTagKind.DEPRECATED); + builder.append("**Deprecated:** ").append(formatDocText(deprecated, clz)).append("\n\n"); + } + appendParamDocs(builder, member, clz); + if (member.kind() == MemberKind.METHOD) { + String ret = getTagText(member.docComment(), DocTagKind.RETURN); + if (!ret.isEmpty()) { + builder.append("**Returns:** ").append(formatDocText(ret, clz)).append("\n\n"); + } + } + appendSeeDocs(builder, member.docComment(), clz); + } + } + + private String renderMemberTitle(MemberDoc member) { + if (member.kind() == MemberKind.CONSTRUCTOR) { + return "new " + member.name() + "(" + renderParamNames(member) + ")"; + } else if (member.kind() == MemberKind.FIELD) { + return member.name(); + } + return member.name() + "(" + renderParamNames(member) + ")"; + } + + private String renderParamNames(MemberDoc member) { + StringBuilder builder = new StringBuilder(); + for (ParamDoc param : member.params()) { + builder.append(param.name()).append(", "); + } + if (!member.params().isEmpty()) { + builder.setLength(builder.length() - 2); + } + return builder.toString(); + } + + private String renderSignature(MemberDoc member) { + if (member.kind() == MemberKind.FIELD) { + return member.name() + ": " + renderType(member); + } + StringBuilder builder = new StringBuilder(); + if (member.kind() == MemberKind.CONSTRUCTOR) { + builder.append("new "); + } + builder.append(member.name()).append("("); + if (member.replaceParams() != null && !member.replaceParams().isBlank()) { + builder.append(member.replaceParams()); + } else { + for (ParamDoc param : member.params()) { + builder.append(renderParam(param)).append(", "); + } + if (!member.params().isEmpty()) { + builder.setLength(builder.length() - 2); + } + } + builder.append(")"); + if (member.kind() != MemberKind.CONSTRUCTOR) { + builder.append(": ").append(renderType(member)); + } + return builder.toString(); + } + + private String renderParam(ParamDoc param) { + return typeResolver.format(param.type(), TargetLanguage.MARKDOWN) + " " + param.name(); + } + + private String renderType(MemberDoc member) { + if (member.replaceReturn() != null && !member.replaceReturn().isBlank()) { + return member.replaceReturn(); + } + return typeResolver.format(member.returnType(), TargetLanguage.MARKDOWN); + } + + private String getTagText(DocComment comment, DocTagKind kind) { + for (DocTag tag : comment.tags()) { + if (tag.kind() == kind) { + return tag.text(); + } + } + return ""; + } + + private String formatDescription(DocComment comment, ClassDoc context) { + if (comment == null) { + return ""; + } + String text = comment.description(); + if (text == null || text.isBlank()) { + text = comment.summary(); + } + return text == null ? "" : formatDocText(text, context); + } + + private boolean hasDeprecatedTag(DocComment comment) { + if (comment == null) { + return false; + } + return comment.tags().stream().anyMatch(tag -> tag.kind() == DocTagKind.DEPRECATED); + } + + private void appendParamDocs(StringBuilder builder, MemberDoc member, ClassDoc context) { + List params = member.params(); + boolean hasDocs = params.stream().anyMatch(param -> param.description() != null && !param.description().isBlank()); + if (!hasDocs) { + return; + } + builder.append("**Parameters:**\n"); + for (ParamDoc param : params) { + String desc = param.description() == null ? "" : formatDocText(param.description(), context); + if (desc.isBlank()) { + continue; + } + builder.append("- `").append(param.name()).append("`: ").append(desc).append("\n"); + } + builder.append("\n"); + } + + private void appendSeeDocs(StringBuilder builder, DocComment comment, ClassDoc context) { + if (comment == null) { + return; + } + List sees = new ArrayList<>(); + for (DocTag tag : comment.tags()) { + if (tag.kind() == DocTagKind.SEE && tag.text() != null && !tag.text().isBlank()) { + sees.add(formatDocText(tag.text(), context)); + } + } + if (sees.isEmpty()) { + return; + } + builder.append("**See:**\n"); + for (String see : sees) { + builder.append("- ").append(see).append("\n"); + } + builder.append("\n"); + } + + private String formatDocText(String text, ClassDoc context) { + if (text == null) { + return ""; + } + String formatted = text.trim(); + if (formatted.isEmpty()) { + return ""; + } + formatted = formatted.replaceAll("\n

", "\n") + .replaceAll("", "```"); + formatted = HTML_LINK.matcher(formatted).replaceAll("[$2]($1)"); + formatted = formatted.replace("<", "<").replace(">", ">"); + formatted = formatted.replaceAll("(?<=[.,:;>]) ?\n", " \n"); + formatted = convertLinkTags(formatted, context); + String trimmed = formatted.trim(); + if (looksLikeSignature(trimmed)) { + formatted = convertSignature(trimmed); + } + return formatted.trim(); + } + + private String convertLinkTags(String text, ClassDoc context) { + java.util.regex.Matcher matcher = LINK_TAG.matcher(text); + StringBuffer buffer = new StringBuffer(); + while (matcher.find()) { + String sig = matcher.group(1).trim(); + String mapped = mapSimpleLinkSignature(sig); + String replacement = mapped != null ? mapped : resolveLink(sig, context); + matcher.appendReplacement(buffer, java.util.regex.Matcher.quoteReplacement(replacement)); + } + matcher.appendTail(buffer); + return buffer.toString(); + } + + private boolean looksLikeSignature(String text) { + if (text.startsWith("#")) { + return true; + } + return text.matches("^xyz\\.wagyourtail\\.[^#]+\\w$") + || text.matches("^\\w+\\.(?:\\w+\\.)+[\\w$_]+$"); + } + + private String convertSignature(String sig) { + if (sig.matches("^xyz\\.wagyourtail\\.[^#]+\\w$")) { + return sig.replaceFirst("^.+\\.(?=[^.]+$)", ""); + } + if (sig.matches("^\\w+\\.(?:\\w+\\.)+[\\w$_]+$")) { + return "Packages." + sig; + } + if (sig.startsWith("#")) { + return sig.substring(1); + } + return sig + .replaceFirst("^(?:xyz\\.wagyourtail\\.jsmacros\\.(?:client\\.api|core)\\.library\\.impl\\.)?F([A-Z]\\w+)#", "$1.") + .replaceFirst("#", "."); + } + + private String mapSimpleLinkSignature(String sig) { + if (JAVA_NUMBER_TYPES.containsKey(sig)) { + return JAVA_NUMBER_TYPES.get(sig); + } + return switch (sig) { + case "java.lang.String" -> "string"; + case "java.lang.Boolean" -> "boolean"; + default -> null; + }; + } + + private void indexClasses(DocletModel model) { + classByQualifiedName.clear(); + classByName.clear(); + classByAlias.clear(); + for (PackageDoc pkg : model.packages()) { + for (ClassDoc clz : pkg.classes()) { + classByQualifiedName.put(clz.qualifiedName(), clz); + addClassNameIndex(classByName, clz.name(), clz); + String simpleName = simpleName(clz.name()); + if (!simpleName.equals(clz.name())) { + addClassNameIndex(classByName, simpleName, clz); + } + if (hasAlias(clz)) { + addClassNameIndex(classByAlias, clz.alias(), clz); + } + } + } + } + + private void addClassNameIndex(Map> index, String key, ClassDoc clz) { + index.computeIfAbsent(key, name -> new ArrayList<>()).add(clz); + } + + private String resolveLink(String signature, ClassDoc context) { + LinkSignature parsed = parseSignature(signature); + if (parsed == null) { + return linkLabel(signature); + } + ClassDoc targetClass = resolveClass(parsed.className(), context); + if (targetClass == null) { + return linkLabel(signature); + } + String anchor = resolveMemberAnchor(targetClass, parsed); + String url = buildLinkUrl(targetClass, anchor, context); + return "[" + linkLabel(signature) + "](" + url + ")"; + } + + private String buildLinkUrl(ClassDoc targetClass, String anchor, ClassDoc context) { + String url; + if (context != null && targetClass.qualifiedName().equals(context.qualifiedName()) && anchor != null) { + url = "#" + anchor; + } else { + url = "/" + version + "/" + classPath(targetClass); + if (anchor != null) { + url = url + "#" + anchor; + } + } + return url; + } + + private ClassDoc resolveClass(String name, ClassDoc context) { + if (name == null || name.isBlank()) { + return context; + } + String cleaned = name.startsWith("Packages.") ? name.substring("Packages.".length()) : name; + int genericIndex = cleaned.indexOf('<'); + if (genericIndex != -1) { + cleaned = cleaned.substring(0, genericIndex).trim(); + } + ClassDoc direct = classByQualifiedName.get(cleaned); + if (direct != null) { + return direct; + } + List matches = new ArrayList<>(); + List nameMatches = classByName.get(cleaned); + if (nameMatches != null) { + matches.addAll(nameMatches); + } + List aliasMatches = classByAlias.get(cleaned); + if (aliasMatches != null) { + matches.addAll(aliasMatches); + } + if (matches.isEmpty()) { + return null; + } + if (matches.size() == 1 || context == null) { + return matches.get(0); + } + for (ClassDoc match : matches) { + if (match.packageName().equals(context.packageName())) { + return match; + } + } + return matches.get(0); + } + + private LinkSignature parseSignature(String signature) { + if (signature == null) { + return null; + } + String trimmed = signature.trim(); + if (trimmed.isEmpty()) { + return null; + } + String classPart = null; + String memberPart = null; + int hashIndex = trimmed.indexOf('#'); + if (hashIndex == 0) { + memberPart = trimmed.substring(1); + } else if (hashIndex > 0) { + classPart = trimmed.substring(0, hashIndex); + memberPart = trimmed.substring(hashIndex + 1); + } else { + classPart = trimmed; + } + String memberName = null; + List params = null; + if (memberPart != null && !memberPart.isBlank()) { + int parenIndex = memberPart.indexOf('('); + if (parenIndex != -1 && memberPart.endsWith(")")) { + memberName = memberPart.substring(0, parenIndex); + String paramBody = memberPart.substring(parenIndex + 1, memberPart.length() - 1); + params = splitParams(paramBody); + } else { + memberName = memberPart; + } + } + return new LinkSignature(classPart, memberName, params); + } + + private List splitParams(String paramBody) { + List params = new ArrayList<>(); + if (paramBody == null || paramBody.isBlank()) { + return params; + } + int depth = 0; + StringBuilder current = new StringBuilder(); + for (int i = 0; i < paramBody.length(); i++) { + char ch = paramBody.charAt(i); + if (ch == '<') { + depth++; + } else if (ch == '>' && depth > 0) { + depth--; + } + if (ch == ',' && depth == 0) { + params.add(current.toString().trim()); + current.setLength(0); + } else { + current.append(ch); + } + } + if (!current.isEmpty()) { + params.add(current.toString().trim()); + } + return params; + } + + private String resolveMemberAnchor(ClassDoc clz, LinkSignature signature) { + if (signature.memberName() == null) { + return null; + } + List members = new ArrayList<>(); + for (MemberDoc member : clz.members()) { + if (member.name().equals(signature.memberName())) { + members.add(member); + } + } + if (members.isEmpty() && signature.memberName().equals(clz.name())) { + for (MemberDoc member : clz.members()) { + if (member.kind() == MemberKind.CONSTRUCTOR) { + members.add(member); + } + } + } + if (members.isEmpty()) { + return null; + } + List params = signature.paramTypes(); + if (params == null) { + return members.size() == 1 ? members.get(0).anchorId() : null; + } + for (MemberDoc member : members) { + if (paramsMatch(member, params)) { + return member.anchorId(); + } + } + return null; + } + + private boolean paramsMatch(MemberDoc member, List params) { + if (member.params().size() != params.size()) { + return false; + } + for (int i = 0; i < params.size(); i++) { + String expected = normalizeParamType(params.get(i)); + ParamDoc param = member.params().get(i); + String actual = normalizeParamType(memberParamTypeName(param)); + if (!expected.equals(actual)) { + return false; + } + } + return true; + } + + private String memberParamTypeName(ParamDoc param) { + return memberParamTypeName(param.type(), param.varArgs()); + } + + private String memberParamTypeName(TypeRef type, boolean varArgs) { + String base = type.kind() == TypeKind.ARRAY + ? memberParamTypeName(type.typeArgs().get(0), false) + "[]" + : type.name(); + if (varArgs && type.kind() != TypeKind.ARRAY) { + base = base + "[]"; + } + return base; + } + + private String normalizeParamType(String type) { + if (type == null) { + return ""; + } + String normalized = type.trim(); + if (normalized.isEmpty()) { + return ""; + } + if (normalized.startsWith("?")) { + return "?"; + } + int arrayDepth = 0; + while (normalized.endsWith("[]")) { + normalized = normalized.substring(0, normalized.length() - 2).trim(); + arrayDepth++; + } + if (normalized.endsWith("...")) { + normalized = normalized.substring(0, normalized.length() - 3).trim(); + arrayDepth++; + } + int genericIndex = normalized.indexOf('<'); + if (genericIndex != -1) { + normalized = normalized.substring(0, genericIndex).trim(); + } + normalized = stripPackageName(normalized); + StringBuilder builder = new StringBuilder(normalized); + for (int i = 0; i < arrayDepth; i++) { + builder.append("[]"); + } + return builder.toString(); + } + + private String stripPackageName(String name) { + if (name == null || name.isBlank()) { + return ""; + } + if (!name.contains(".")) { + return name; + } + String[] parts = name.split("\\."); + int firstTypeIndex = -1; + for (int i = 0; i < parts.length; i++) { + String part = parts[i]; + if (!part.isEmpty() && Character.isUpperCase(part.charAt(0))) { + firstTypeIndex = i; + break; + } + } + if (firstTypeIndex == -1) { + return parts[parts.length - 1]; + } + StringBuilder builder = new StringBuilder(); + for (int i = firstTypeIndex; i < parts.length; i++) { + if (!builder.isEmpty()) { + builder.append("."); + } + builder.append(parts[i]); + } + return builder.toString(); + } + + private String linkLabel(String signature) { + if (signature == null) { + return ""; + } + String cleaned = signature.trim(); + if (cleaned.startsWith("Packages.")) { + cleaned = cleaned.substring("Packages.".length()); + } + int hashIndex = cleaned.indexOf('#'); + if (hashIndex == 0) { + return cleaned.substring(1); + } + if (hashIndex > 0) { + String classPart = cleaned.substring(0, hashIndex); + String memberPart = cleaned.substring(hashIndex + 1); + String classLabel = stripPackageName(classPart); + if (classLabel.isBlank()) { + return memberPart; + } + return classLabel + "." + memberPart; + } + return stripPackageName(cleaned); + } + + private String simpleName(String name) { + int idx = name.lastIndexOf('.'); + return idx == -1 ? name : name.substring(idx + 1); + } + + private String renderSignatureValue(String signature) { + if (signature == null) { + return ""; + } + return renderCodeSpan(signature); + } + + private String renderCodeSpan(String text) { + if (text == null) { + return ""; + } + int maxTicks = 0; + int current = 0; + for (int i = 0; i < text.length(); i++) { + if (text.charAt(i) == '`') { + current++; + if (current > maxTicks) { + maxTicks = current; + } + } else { + current = 0; + } + } + String fence = "`".repeat(maxTicks + 1); + return fence + text + fence; + } + + private record LinkSignature(String className, String memberName, List paramTypes) {} +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/render/PythonWriter.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/render/PythonWriter.java new file mode 100644 index 000000000..f6896db97 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/render/PythonWriter.java @@ -0,0 +1,603 @@ +package com.jsmacrosce.doclet.core.render; + +import com.jsmacrosce.FileHandler; +import com.jsmacrosce.doclet.core.model.ClassDoc; +import com.jsmacrosce.doclet.core.model.DocComment; +import com.jsmacrosce.doclet.core.model.DocletModel; +import com.jsmacrosce.doclet.core.model.MemberDoc; +import com.jsmacrosce.doclet.core.model.MemberKind; +import com.jsmacrosce.doclet.core.model.PackageDoc; +import com.jsmacrosce.doclet.core.model.ParamDoc; +import com.jsmacrosce.doclet.core.model.TypeRef; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +public class PythonWriter { + private static final Set PYTHON_KEYWORDS = new LinkedHashSet<>(Arrays.asList( + "False", "await", "else", "import", "pass", "None", "break", "except", + "in", "raise", "True", "class", "finally", "is", "return", "and", + "continue", "for", "lambda", "try", "as", "def", "from", "nonlocal", + "while", "assert", "del", "global", "not", "with", "async", "elif", + "if", "or", "yield" + )); + + public PythonWriter() {} + + public void write(DocletModel model, File outDir, String version) throws IOException { + Map classNameByQualified = new LinkedHashMap<>(); + for (PackageDoc pkg : model.packages()) { + for (ClassDoc clz : pkg.classes()) { + classNameByQualified.put(clz.qualifiedName(), pythonClassName(clz)); + } + } + + for (PackageDoc pkg : model.packages()) { + for (ClassDoc clz : pkg.classes()) { + String fileName = pythonClassName(clz); + File out = new File(outDir, fileName + ".py"); + new FileHandler(out).write(renderClass(clz, classNameByQualified)); + } + } + + Map> grouped = groupClasses(model); + List groupOrder = List.of("libraries", "events", "helpers", "mixins", "rest"); + List groupModules = new ArrayList<>(); + for (String group : groupOrder) { + List classes = grouped.get(group); + if (classes == null || classes.isEmpty()) { + continue; + } + groupModules.add(group); + new FileHandler(new File(outDir, group + ".py")) + .write(renderGroupModule(group, classes)); + } + + StringBuilder init = new StringBuilder(); + for (String module : groupModules) { + init.append("from .").append(module).append(" import *\n"); + } + new FileHandler(new File(outDir, "__init__.py")).write(init.toString()); + + if (version != null) { + new FileHandler(new File(outDir, "setup.py")) + .write(renderSetupPy(version)); + } + } + + private String pythonClassName(ClassDoc clz) { + return clz.name().replace('.', '_'); + } + + private String renderClass(ClassDoc clz, Map classNameByQualified) { + PythonTypeContext ctx = new PythonTypeContext(classNameByQualified, pythonClassName(clz)); + StringBuilder body = new StringBuilder(); + + body.append(renderClassLine(clz, ctx)); + appendDocstring(body, 1, clz.docComment(), List.of(), false); + + for (MemberDoc member : clz.members()) { + if (member.kind() == MemberKind.FIELD) { + body.append(" ") + .append(getVarName(member.name())) + .append(": ") + .append(ctx.formatType(member.returnType(), false)) + .append("\n"); + } + } + + for (MemberDoc member : clz.members()) { + if (member.kind() == MemberKind.CONSTRUCTOR) { + body.append(renderConstructor(member, ctx)); + } else if (member.kind() == MemberKind.METHOD) { + body.append(renderMethod(member, ctx)); + } + } + + body.append(" pass\n\n"); + + StringBuilder builder = new StringBuilder(); + builder.append(ctx.renderImports()); + builder.append(body); + return builder.toString(); + } + + private String renderConstructor(MemberDoc member, PythonTypeContext ctx) { + StringBuilder builder = new StringBuilder(); + ctx.setOverloadUsed(true); + builder.append(" @overload\n"); + builder.append(" def __init__(self"); + appendParams(builder, member.params(), ctx); + builder.append(") -> None:\n"); + appendDocstring(builder, 2, member.docComment(), member.params(), false); + builder.append(" pass\n\n"); + return builder.toString(); + } + + private String renderMethod(MemberDoc member, PythonTypeContext ctx) { + StringBuilder builder = new StringBuilder(); + ctx.setOverloadUsed(true); + builder.append(" @overload\n"); + builder.append(" def ").append(getVarName(member.name())).append("(self"); + appendParams(builder, member.params(), ctx); + builder.append(") -> ").append(ctx.formatType(member.returnType(), false)).append(":\n"); + appendDocstring(builder, 2, member.docComment(), member.params(), true); + builder.append(" pass\n\n"); + return builder.toString(); + } + + private void appendParams(StringBuilder builder, List params, PythonTypeContext ctx) { + for (ParamDoc param : params) { + builder.append(", ").append(getVarName(param.name())).append(": ") + .append(ctx.formatType(param.type(), false)); + } + } + + private void appendDocstring( + StringBuilder builder, + int indent, + DocComment comment, + List params, + boolean includeReturn + ) { + String desc = formatDescription(comment); + String since = getTagText(comment, "SINCE"); + Map tagDocs = new LinkedHashMap<>(); + if (comment != null) { + comment.tags().stream() + .filter(tag -> tag.kind().name().equals("PARAM") && tag.name() != null) + .forEach(tag -> tagDocs.put(tag.name(), tag.text())); + } + Map paramDocs = new LinkedHashMap<>(); + if (params != null) { + for (ParamDoc param : params) { + if (tagDocs.containsKey(param.name())) { + paramDocs.put(param.name(), tagDocs.get(param.name())); + } + } + } + String ret = includeReturn ? getTagText(comment, "RETURN") : ""; + + if (desc.isEmpty() && since.isEmpty() && paramDocs.isEmpty() && ret.isEmpty()) { + return; + } + + String pad = " ".repeat(indent); + builder.append(pad).append("\"\"\""); + if (!desc.isEmpty()) { + builder.append(escape(desc)); + } + if (!since.isEmpty()) { + if (!desc.isEmpty()) { + builder.append("\n"); + } + builder.append("Since: ").append(escape(since)); + } + if (!paramDocs.isEmpty()) { + builder.append("\n\n").append(pad).append("Args:\n"); + for (Map.Entry entry : paramDocs.entrySet()) { + builder.append(pad).append(" ") + .append(getVarName(entry.getKey())) + .append(": ") + .append(escape(entry.getValue())) + .append("\n"); + } + builder.setLength(builder.length() - 1); + } + if (!ret.isEmpty()) { + builder.append("\n\n").append(pad).append("Returns:\n"); + builder.append(pad).append(" ").append(escape(ret)); + } + builder.append("\n").append(pad).append("\"\"\"\n"); + } + + private String renderClassLine(ClassDoc clz, PythonTypeContext ctx) { + StringBuilder builder = new StringBuilder("\nclass "); + builder.append(pythonClassName(clz)); + + List bases = new ArrayList<>(); + for (TypeRef iface : clz.implementsTypes()) { + String name = ctx.formatType(iface, true); + if (!name.isBlank()) { + bases.add(name); + } + } + if (!clz.typeParams().isEmpty()) { + ctx.setGenericUsed(true); + StringBuilder typeParams = new StringBuilder("Generic["); + for (TypeRef param : clz.typeParams()) { + String name = ctx.formatType(param, true); + typeParams.append(name).append(", "); + } + typeParams.setLength(typeParams.length() - 2); + typeParams.append("]"); + bases.add(typeParams.toString()); + } + for (TypeRef extend : clz.extendsTypes()) { + String name = ctx.formatType(extend, true); + if (!name.isBlank()) { + bases.add(name); + } + } + + if (!bases.isEmpty()) { + builder.append("("); + for (String base : bases) { + builder.append(base).append(", "); + } + builder.setLength(builder.length() - 2); + builder.append(")"); + } + builder.append(":\n"); + return builder.toString(); + } + + private String renderGroupModule(String group, List classes) { + StringBuilder builder = new StringBuilder(); + builder.append("from typing import TypeVar\n\n"); + builder.append("from .EventContainer import EventContainer\n"); + builder.append("from .BaseEvent import BaseEvent\n"); + + for (ClassDoc clz : classes) { + String name = pythonClassName(clz); + builder.append("from .").append(name).append(" import ").append(name).append("\n"); + } + + builder.append("\nFile = TypeVar(\"java.io.File\")\n\n"); + if ("libraries".equals(group)) { + builder.append("\n\n"); + for (ClassDoc clz : classes) { + String name = pythonClassName(clz); + String alias = clz.alias() == null || clz.alias().isEmpty() ? name : clz.alias(); + builder.append(alias).append(" = ").append(name).append("()\n"); + } + builder.append("context = EventContainer()\n"); + builder.append("file = File()\n"); + builder.append("event = BaseEvent()\n"); + } + + return builder.toString(); + } + + private Map> groupClasses(DocletModel model) { + Map> grouped = new LinkedHashMap<>(); + for (PackageDoc pkg : model.packages()) { + for (ClassDoc clz : pkg.classes()) { + String name = clz.name(); + String key; + if ("Library".equalsIgnoreCase(clz.group())) { + key = "libraries"; + } else if ("Event".equalsIgnoreCase(clz.group())) { + key = "events"; + } else if (name.contains("Helper")) { + key = "helpers"; + } else if (name.contains("Mixin")) { + key = "mixins"; + } else { + key = "rest"; + } + grouped.computeIfAbsent(key, value -> new ArrayList<>()).add(clz); + } + } + return grouped; + } + + private String renderSetupPy(String version) { + String cleaned = version; + if (cleaned.contains("-")) { + cleaned = cleaned.split("-", 2)[0]; + } + StringBuilder sb = new StringBuilder(); + sb.append(""" + from setuptools import setup, find_packages + from os import path + import os + import time + + this_directory = path.abspath(path.dirname(__file__)) + with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f: + long_description = f.read() + + + VERSION = '"""); + sb.append(cleaned); + sb.append(""" + ' + if "-" in VERSION: VERSION = VERSION.split("-")[0] + VERSION += "." + str(time.time()).split(".")[0][3:] + DESCRIPTION = 'A package to let your IDE know what JsMacros can do' + + def package_files(directory): + paths = [] + for (path, directories, filenames) in os.walk(directory): + for filename in filenames: + paths.append(os.path.join('..', path, filename)) + return paths + + extra_files = package_files('JsMacrosAC') + + # Setting up + setup( + name="JsMacrosAC", + version=VERSION, + author="Hasenzahn1", + author_email="", + description=DESCRIPTION, + long_description_content_type="text/markdown", + long_description=long_description, + packages=["JsMacrosAC"], + package_data = {"": extra_files}, + install_requires=[], + keywords=['python', 'JsMacros', 'Autocomplete', 'Doc'], + classifiers=[ + "Intended Audience :: Developers", + "Programming Language :: Python :: 3", + "Operating System :: Unix", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + ] + )"""); + return sb.toString(); + } + + private String formatDescription(DocComment comment) { + if (comment == null) { + return ""; + } + String text = comment.description(); + return text == null ? "" : text.trim(); + } + + private String getTagText(DocComment comment, String kind) { + if (comment == null) { + return ""; + } + return comment.tags().stream() + .filter(tag -> tag.kind().name().equals(kind)) + .map(tag -> tag.text()) + .findFirst() + .orElse(""); + } + + private String escape(String text) { + return text.replace("\"\"\"", "''"); + } + + private String getVarName(String name) { + return PYTHON_KEYWORDS.contains(name) ? name + "_" : name; + } + + private static class PythonTypeContext { + private static final Map TYPE_ALIASES = Map.ofEntries( + Map.entry("java.lang.Object", "object"), + Map.entry("java.lang.String", "str"), + Map.entry("java.lang.Integer", "int"), + Map.entry("java.lang.Boolean", "bool"), + Map.entry("java.lang.Double", "float"), + Map.entry("java.lang.Float", "float"), + Map.entry("java.lang.Long", "float"), + Map.entry("java.lang.Short", "float"), + Map.entry("java.lang.Byte", "float"), + Map.entry("java.lang.Character", "str"), + Map.entry("java.lang.annotation.Annotation", ""), + Map.entry("java.lang.Enum", "") + ); + private static final Set UNWANTED_CLASS = Set.of( + "java.lang.Object", + "java.lang.annotation.Annotation", + "java.lang.Enum", + "java.util.Collection" + ); + private static final Map WITH_ARG = Map.of( + "java.util.Set", "Set", + "java.util.List", "List", + "java.util.Map", "Mapping", + "java.util.Collection", "List" + ); + private static final List EXTERNAL_PREFIXES = List.of( + "net.", "com.", "io.", "org.", "java.", "javax.", "jdk." + ); + + private final Map classNameByQualified; + private final String currentClassName; + private final Set internalImports = new TreeSet<>(); + private final Map externalTypeVars = new TreeMap<>(); + private final Set typeVars = new TreeSet<>(); + private boolean overloadUsed; + private boolean importList; + private boolean importTypeVar; + private boolean importAny; + private boolean importMapping; + private boolean importSet; + private boolean importGeneric; + + private PythonTypeContext(Map classNameByQualified, String currentClassName) { + this.classNameByQualified = classNameByQualified; + this.currentClassName = currentClassName; + } + + String formatType(TypeRef type, boolean classContext) { + if (type == null) { + importAny = true; + return "Any"; + } + return switch (type.kind()) { + case PRIMITIVE -> switch (type.name()) { + case "boolean" -> "bool"; + case "int" -> "int"; + case "char" -> "str"; + case "byte", "short", "long", "float", "double" -> "float"; + default -> "int"; + }; + case VOID -> "None"; + case ARRAY -> { + importList = true; + String component = formatType(type.typeArgs().get(0), false); + yield "List[" + component + "]"; + } + case TYPEVAR -> { + importTypeVar = true; + typeVars.add(type.name()); + yield type.name(); + } + case WILDCARD -> { + importAny = true; + yield "Any"; + } + case DECLARED -> formatDeclared(type, classContext); + default -> "Any"; + }; + } + + private String formatDeclared(TypeRef type, boolean classContext) { + String qualified = type.qualifiedName(); + if (classContext && UNWANTED_CLASS.contains(qualified)) { + return ""; + } + if (TYPE_ALIASES.containsKey(qualified)) { + return TYPE_ALIASES.get(qualified); + } + if (WITH_ARG.containsKey(qualified)) { + String base = WITH_ARG.get(qualified); + if ("List".equals(base)) { + importList = true; + } else if ("Mapping".equals(base)) { + importMapping = true; + } else if ("Set".equals(base)) { + importSet = true; + } + if (type.typeArgs().isEmpty()) { + importAny = true; + return base + "[Any]"; + } + StringBuilder builder = new StringBuilder(base); + builder.append("["); + for (TypeRef arg : type.typeArgs()) { + builder.append(formatType(arg, false)).append(", "); + } + builder.setLength(builder.length() - 2); + builder.append("]"); + return builder.toString(); + } + + String className = type.name().replace('.', '_'); + if (className.equals(currentClassName)) { + return "\"" + className + "\""; + } + if (classNameByQualified.containsKey(qualified)) { + String importName = classNameByQualified.get(qualified); + if (!importName.equals(currentClassName)) { + internalImports.add(importName); + } + if (!type.typeArgs().isEmpty()) { + StringBuilder builder = new StringBuilder(importName); + builder.append("["); + for (TypeRef arg : type.typeArgs()) { + builder.append(formatType(arg, false)).append(", "); + } + builder.setLength(builder.length() - 2); + builder.append("]"); + return builder.toString(); + } + return importName; + } + + if (isExternalType(qualified)) { + importTypeVar = true; + String typeVarName = sanitizeTypeVarName(qualified); + externalTypeVars.put(className, typeVarName); + return className; + } + + if (!type.typeArgs().isEmpty()) { + StringBuilder builder = new StringBuilder(className); + builder.append("["); + for (TypeRef arg : type.typeArgs()) { + builder.append(formatType(arg, false)).append(", "); + } + builder.setLength(builder.length() - 2); + builder.append("]"); + return builder.toString(); + } + return className; + } + + private boolean isExternalType(String qualifiedName) { + for (String prefix : EXTERNAL_PREFIXES) { + if (qualifiedName.startsWith(prefix)) { + return true; + } + } + return false; + } + + private String sanitizeTypeVarName(String qualifiedName) { + return qualifiedName.replace("<", "_") + .replace(">", "_") + .replace("?", "") + .replace(".", "_"); + } + + String renderImports() { + StringBuilder builder = new StringBuilder(); + if (overloadUsed) { + builder.append("from typing import overload\n"); + } + if (importList) { + builder.append("from typing import List\n"); + } + if (importTypeVar) { + builder.append("from typing import TypeVar\n"); + } + if (importAny) { + builder.append("from typing import Any\n"); + } + if (importMapping) { + builder.append("from typing import Mapping\n"); + } + if (importSet) { + builder.append("from typing import Set\n"); + } + if (importGeneric) { + builder.append("from typing import Generic\n"); + } + for (String imp : internalImports) { + builder.append("from .").append(imp).append(" import ").append(imp).append("\n"); + } + builder.append("\n"); + + for (String typeVar : typeVars) { + builder.append(typeVar).append(" = TypeVar(\"").append(typeVar).append("\")\n"); + } + for (Map.Entry entry : externalTypeVars.entrySet()) { + String className = entry.getKey(); + String typeVarName = entry.getValue(); + if ("T".equals(typeVarName) || "U".equals(typeVarName) || "R".equals(typeVarName)) { + builder.append(typeVarName).append(" = TypeVar(\"").append(typeVarName).append("\")\n"); + } else { + builder.append(typeVarName).append(" = TypeVar(\"").append(typeVarName).append("\")\n"); + builder.append(className).append(" = ").append(typeVarName).append("\n\n"); + } + } + + return builder.toString(); + } + + void setOverloadUsed(boolean overloadUsed) { + this.overloadUsed = overloadUsed; + } + + void setGenericUsed(boolean genericUsed) { + this.importGeneric = genericUsed; + } + } +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/render/TsRenderer.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/render/TsRenderer.java new file mode 100644 index 000000000..c3756d2ea --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/render/TsRenderer.java @@ -0,0 +1,920 @@ +package com.jsmacrosce.doclet.core.render; + +import com.jsmacrosce.doclet.core.BasicTypeResolver; +import com.jsmacrosce.doclet.core.Renderer; +import com.jsmacrosce.doclet.core.TargetLanguage; +import com.jsmacrosce.doclet.core.TypeResolver; +import com.jsmacrosce.doclet.core.model.ClassDoc; +import com.jsmacrosce.doclet.core.model.ClassKind; +import com.jsmacrosce.doclet.core.model.DeclaredTypeDoc; +import com.jsmacrosce.doclet.core.model.DocComment; +import com.jsmacrosce.doclet.core.model.DocTag; +import com.jsmacrosce.doclet.core.model.DocTagKind; +import com.jsmacrosce.doclet.core.model.DocletModel; +import com.jsmacrosce.doclet.core.model.MemberDoc; +import com.jsmacrosce.doclet.core.model.MemberKind; +import com.jsmacrosce.doclet.core.model.PackageDoc; +import com.jsmacrosce.doclet.core.model.ParamDoc; +import com.jsmacrosce.doclet.core.model.TypeKind; +import com.jsmacrosce.doclet.core.model.TypeRef; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.regex.Pattern; + + +public class TsRenderer implements Renderer { + private static final Pattern HTML_LINK = + Pattern.compile("]*?href=\"([^\"]*)\"[^>]*?>(.*?)", Pattern.DOTALL); + private static final Pattern LINK_TAG = + Pattern.compile("\\{@link\\s+([^}]+)}"); + private static final Set TS_RESERVED_WORDS = Set.of( + "break", "case", "catch", "class", "const", "continue", "debugger", "default", + "delete", "do", "else", "enum", "export", "extends", "false", "finally", "for", + "function", "if", "import", "in", "instanceof", "new", "null", "return", "super", + "switch", "this", "throw", "true", "try", "typeof", "var", "void", "while", "with" + ); + private static final Map JAVA_NUMBER_TYPES = Map.of( + "java.lang.Integer", "int", + "java.lang.Float", "float", + "java.lang.Long", "long", + "java.lang.Short", "short", + "java.lang.Character", "char", + "java.lang.Byte", "byte", + "java.lang.Double", "double", + "java.lang.Number", "number" + ); + private final TypeResolver typeResolver; + + public TsRenderer(TypeResolver typeResolver) { + this.typeResolver = typeResolver; + } + + @Override + public String render(DocletModel model) { + Map tsAliases = buildTypeScriptAliases(model); + applyTypeScriptAliases(tsAliases); + + List events = collectByGroup(model, "Event"); + List libraries = collectByGroup(model, "Library"); + + StringBuilder out = new StringBuilder(); + appendGlobalDeclarations(out); + appendEvents(out, events); + appendEventFilterers(out, events); + appendEventTypeMap(out, events); + appendLibraries(out, libraries); + + out.append("\n\ndeclare ").append(renderPackages(model)).append("\n"); + appendAliasTypes(out, model); + appendEnumTypes(out, model.declaredTypes()); + + return out.toString(); + } + + private void appendGlobalDeclarations(StringBuilder out) { + out.append("/**\n"); + out.append(" * The global context\n"); + out.append(" * If you're trying to access the context in {@link JsMacros.on},\n"); + out.append(" * use the second param of callback\n"); + out.append(" */\n"); + out.append("declare const context: EventContainer;\n"); + out.append("/**\n"); + out.append(" * Assert and convert event type:\n"); + out.append(" * ```js\n"); + out.append(" * JsMacros.assertEvent(event, 'Service')\n"); + out.append(" * ```\n"); + out.append(" * If the type doesn't convert, that means the event type doesn't have any properties\n"); + out.append(" */\n"); + out.append("declare const event: Events.BaseEvent;\n"); + out.append("declare const file: Packages.java.io.File;\n\n"); + } + + private void appendEvents(StringBuilder out, List events) { + out.append("declare namespace Events {\n\n"); + indent(out, 1).append("interface BaseEvent extends JavaObject {\n\n"); + indent(out, 2).append("getEventName(): string;\n\n"); + indent(out, 1).append("}\n\n"); + indent(out, 1).append("interface Cancellable {\n\n"); + indent(out, 2).append("cancel(): void;\n\n"); + indent(out, 1).append("}\n"); + + for (ClassDoc event : events) { + out.append("\n"); + renderEventInterface(out, event, 1); + } + out.append("\n}\n"); + } + + private void appendEventFilterers(StringBuilder out, List events) { + out.append("\ninterface EventFilterers {\n"); + for (ClassDoc event : events) { + if (event.eventFilterer() == null || event.eventFilterer().isBlank()) { + continue; + } + indent(out, 1).append(event.alias()).append(": ").append(event.eventFilterer()).append(";\n"); + } + out.append("}\n"); + } + + private void appendEventTypeMap(StringBuilder out, List events) { + out.append("\ninterface Events {\n"); + for (ClassDoc event : events) { + indent(out, 1).append(event.alias()).append(": Events.").append(event.alias()).append(";\n"); + } + out.append("}\n"); + } + + private void appendLibraries(StringBuilder out, List libraries) { + for (ClassDoc library : libraries) { + out.append("\n"); + renderLibraryNamespace(out, library, 0); + } + } + + private void renderLibraryNamespace(StringBuilder out, ClassDoc library, int indent) { + DocComment libraryComment = sanitizeLibraryComment(library.docComment()); + appendDocComment(out, libraryComment, List.of(), false, null, library, indent); + indent(out, indent).append("declare namespace ").append(library.alias()).append(" {\n"); + for (MemberDoc member : library.members()) { + if (member.kind() != MemberKind.METHOD || hasModifier(member, "static")) { + continue; + } + appendDocComment(out, member.docComment(), member.params(), true, member, library, indent + 1); + indent(out, indent + 1).append("function ").append(member.name()); + appendTypeParams(out, member.typeParams(), member.replaceTypeParams(), false); + out.append("("); + appendParams(out, member.params()); + out.append(")"); + out.append(": ").append(formatReturn(member, library)); + out.append(";\n"); + } + indent(out, indent).append("}\n"); + } + + private void renderEventInterface(StringBuilder out, ClassDoc event, int indent) { + appendDocComment(out, event.docComment(), List.of(), false, null, event, indent); + indent(out, indent).append("interface ").append(event.alias()).append(" extends BaseEvent"); + if (event.eventCancellable()) { + out.append(", Cancellable"); + } + out.append(" {\n"); + for (MemberDoc member : event.members()) { + if (member.kind() == MemberKind.FIELD && !hasModifier(member, "static")) { + renderField(out, member, indent + 1, false, event); + } else if (member.kind() == MemberKind.METHOD && !hasModifier(member, "static")) { + renderMethod(out, member, indent + 1, false, event); + } + } + indent(out, indent).append("}\n"); + } + + private String renderPackages(DocletModel model) { + PackageNode root = buildTree(model); + PackageNode current = root; + String name = root.name; + while (current.classes.isEmpty() && current.children.size() == 1) { + PackageNode child = current.children.values().iterator().next(); + if (isReservedWord(child.name)) { + break; + } + name = name + "." + child.name; + current = child; + } + StringBuilder out = new StringBuilder(); + out.append("namespace ").append(name).append(" {\n"); + renderPackageNode(out, current, 1); + out.append("}"); + return out.toString(); + } + + private PackageNode buildTree(DocletModel model) { + PackageNode root = new PackageNode("Packages"); + for (PackageDoc pkg : model.packages()) { + for (ClassDoc clz : pkg.classes()) { + root.addClass(pkg.name(), clz); + } + } + return root; + } + + private void renderPackageNode(StringBuilder out, PackageNode node, int indent) { + for (PackageNode child : node.children.values()) { + PackageNode current = child; + String mergedName = child.name; + while (current.classes.isEmpty() && current.children.size() == 1) { + PackageNode onlyChild = current.children.values().iterator().next(); + if (isReservedWord(onlyChild.name)) { + break; + } + mergedName = mergedName + "." + onlyChild.name; + current = onlyChild; + } + String namespaceName = escapePackageName(mergedName); + indent(out, indent).append("export namespace ").append(namespaceName).append(" {\n"); + renderPackageNode(out, current, indent + 1); + indent(out, indent).append("}\n"); + if (isReservedWord(child.name)) { + indent(out, indent).append("export { ").append(namespaceName).append(" as ") + .append(child.name).append(" };\n"); + } + } + for (ClassDoc clz : node.classes) { + renderClass(out, clz, indent); + } + } + + private void renderClass(StringBuilder out, ClassDoc clz, int indent) { + if (clz.kind() == ClassKind.INTERFACE) { + appendDocComment(out, clz.docComment(), List.of(), false, null, clz, indent); + indent(out, indent).append("export abstract class ").append(tsSafeName(clz.name())) + .append(" extends java.lang.Interface {\n"); + appendClassHeader(out, clz, indent + 1); + renderStaticMembers(out, clz, indent + 1, clz); + indent(out, indent).append("}\n"); + + indent(out, indent).append("export interface ").append(tsSafeName(clz.name())); + appendTypeParams(out, clz.typeParams(), null, false); + appendImplements(out, clz); + out.append(" {\n"); + renderInstanceMembers(out, clz, indent + 1, clz); + indent(out, indent).append("}\n"); + return; + } + + // Don't generate interface for Library classes (they're rendered as namespaces) + if (!clz.implementsTypes().isEmpty() && !"Library".equals(clz.group())) { + appendDocComment(out, clz.docComment(), List.of(), false, null, clz, indent); + indent(out, indent).append("export interface ").append(tsSafeName(clz.name())); + appendTypeParams(out, clz.typeParams(), null, false); + appendImplements(out, clz); + out.append(" {}\n"); + } else { + appendDocComment(out, clz.docComment(), List.of(), false, null, clz, indent); + } + + boolean hasConstructor = clz.members().stream().anyMatch(member -> member.kind() == MemberKind.CONSTRUCTOR); + indent(out, indent).append("export ").append(hasConstructor ? "class " : "abstract class ") + .append(tsSafeName(clz.name())); + appendTypeParams(out, clz.typeParams(), null, false); + appendExtends(out, clz); + out.append(" {\n"); + appendClassHeader(out, clz, indent + 1); + renderStaticMembers(out, clz, indent + 1, clz); + renderConstructors(out, clz, indent + 1); + renderInstanceMembers(out, clz, indent + 1, clz); + indent(out, indent).append("}\n"); + } + + private void renderField(StringBuilder out, MemberDoc member, int indent, boolean includeStatic, ClassDoc owner) { + appendDocComment(out, member.docComment(), List.of(), false, member, owner, indent); + indent(out, indent); + if (includeStatic && hasModifier(member, "static")) { + out.append("static "); + } + if (hasModifier(member, "final")) { + out.append("readonly "); + } + out.append(member.name()).append(": ").append(formatReturn(member, owner)).append(";\n"); + } + + private void renderMethod(StringBuilder out, MemberDoc member, int indent, boolean includeStatic, ClassDoc owner) { + appendDocComment(out, member.docComment(), member.params(), true, member, owner, indent); + indent(out, indent); + if (includeStatic && hasModifier(member, "static")) { + out.append("static "); + } + out.append(member.name()); + appendTypeParams(out, member.typeParams(), member.replaceTypeParams(), false); + out.append("("); + if (member.replaceParams() != null && !member.replaceParams().isBlank()) { + String replaced = member.replaceParams(); + // Check if replaceParams contains complete declaration(s) with overloads + if (replaced.contains(");")) { + // It's a complete declaration with overloads, output as-is + out.append(replaced); + if (!replaced.endsWith("\n")) { + out.append("\n"); + } + return; + } + // Otherwise it's just parameter replacement + out.append(replaced); + } else { + appendParams(out, member.params()); + } + out.append(")"); + out.append(": ").append(formatReturn(member, owner)); + out.append(";\n"); + } + + private void renderConstructor(StringBuilder out, MemberDoc member, int indent, ClassDoc owner) { + appendDocComment(out, member.docComment(), member.params(), false, member, owner, indent); + indent(out, indent).append("constructor"); + appendTypeParams(out, member.typeParams(), member.replaceTypeParams(), false); + out.append("("); + if (member.replaceParams() != null && !member.replaceParams().isBlank()) { + out.append(member.replaceParams()); + } else { + appendParams(out, member.params()); + } + out.append(");\n"); + } + + private void renderStaticMembers(StringBuilder out, ClassDoc clz, int indent, ClassDoc owner) { + for (MemberDoc member : clz.members()) { + if (!hasModifier(member, "static")) { + continue; + } + if (member.kind() == MemberKind.FIELD) { + renderField(out, member, indent, true, owner); + } else if (member.kind() == MemberKind.METHOD) { + renderMethod(out, member, indent, true, owner); + } + } + } + + private void renderConstructors(StringBuilder out, ClassDoc clz, int indent) { + for (MemberDoc member : clz.members()) { + if (member.kind() == MemberKind.CONSTRUCTOR) { + renderConstructor(out, member, indent, clz); + } + } + } + + private void renderInstanceMembers(StringBuilder out, ClassDoc clz, int indent, ClassDoc owner) { + for (MemberDoc member : clz.members()) { + if (hasModifier(member, "static")) { + continue; + } + if (member.kind() == MemberKind.FIELD) { + renderField(out, member, indent, false, owner); + } else if (member.kind() == MemberKind.METHOD) { + renderMethod(out, member, indent, false, owner); + } + } + } + + private void appendParams(StringBuilder out, List params) { + boolean first = true; + for (ParamDoc param : params) { + if (!first) { + out.append(", "); + } + first = false; + if (param.varArgs()) { + out.append("..."); + } + String name = escapeParamName(param.name()); + out.append(name).append(": "); + if (param.varArgs()) { + String baseType = formatType(param.type(), true, false); + if (baseType.endsWith("[]")) { + baseType = baseType.substring(0, baseType.length() - "[]".length()); + } + if (param.type().nullable()) { + baseType = baseType + " | null"; + } + out.append("JavaVarArgs<").append(baseType).append(">"); + } else { + out.append(formatType(param.type(), true, true)); + } + } + } + + private void appendTypeParams( + StringBuilder out, + List typeParams, + String replaceTypeParams, + boolean defaultToAny + ) { + if (replaceTypeParams != null && !replaceTypeParams.isBlank()) { + out.append("<").append(replaceTypeParams).append(">"); + return; + } + if (typeParams == null || typeParams.isEmpty()) { + return; + } + out.append("<"); + boolean first = true; + for (TypeRef param : typeParams) { + if (!first) { + out.append(", "); + } + first = false; + out.append(formatTypeParam(param, defaultToAny)); + } + out.append(">"); + } + + private String formatTypeParam(TypeRef param, boolean defaultToAny) { + StringBuilder out = new StringBuilder(param.name()); + String ext = param.bounds() == null ? "any" : formatType(param.bounds(), false, false); + if (!ext.endsWith("any")) { + out.append(" extends ").append(ext); + if (defaultToAny) { + out.append(" = any"); + } + } else if (ext.startsWith("/* net.minecraft.")) { + out.append(" = ").append(ext); + } else if (defaultToAny) { + out.append(" = any"); + } + return out.toString(); + } + + private String formatReturn(MemberDoc member, ClassDoc owner) { + if (member.replaceReturn() != null && !member.replaceReturn().isBlank()) { + return member.replaceReturn(); + } + if (shouldReturnThis(member, owner)) { + return "this"; + } + return formatType(member.returnType(), false, true); + } + + private String formatType(TypeRef type, boolean paramType, boolean includeNull) { + String formatted = typeResolver.format(type, TargetLanguage.TYPESCRIPT, paramType); + if (includeNull && type.nullable()) { + return formatted + " | null"; + } + return formatted; + } + + private void appendAliasTypes(StringBuilder out, DocletModel model) { + List wagClasses = new ArrayList<>(); + for (PackageDoc pkg : model.packages()) { + if (pkg.name().startsWith("com.jsmacrosce")) { + wagClasses.addAll(pkg.classes()); + } + } + wagClasses.sort(Comparator.comparing(ClassDoc::name, String.CASE_INSENSITIVE_ORDER)); + Set seen = new HashSet<>(); + Set aliases = new TreeSet<>(); + for (ClassDoc clz : wagClasses) { + if (!seen.add(clz.name())) { + continue; + } + String aliasName = buildAliasName(clz, true); + String aliasValue = formatClassType(clz); + aliases.add("type " + aliasName + " = " + aliasValue + ";"); + } + for (String alias : aliases) { + out.append("\n").append(alias); + } + } + + private String buildAliasName(ClassDoc clz, boolean defaultToAny) { + StringBuilder out = new StringBuilder(clz.name().replace(".", "$")); + if (clz.typeParams() != null && !clz.typeParams().isEmpty()) { + out.append("<"); + boolean first = true; + for (TypeRef param : clz.typeParams()) { + if (!first) { + out.append(", "); + } + first = false; + out.append(formatTypeParam(param, defaultToAny)); + } + out.append(">"); + } + return out.toString(); + } + + private String formatClassType(ClassDoc clz) { + TypeRef classType = new TypeRef( + TypeKind.DECLARED, + clz.name(), + clz.qualifiedName(), + clz.typeParams(), + false, + false, + null, + false + ); + return typeResolver.format(classType, TargetLanguage.TYPESCRIPT, false); + } + + private void appendEnumTypes(StringBuilder out, List declaredTypes) { + out.append( + """ + + // Enum types + type Bit = 1 | 0; + type Trit = 2 | Bit; + type Dit = 3 | Trit; + type Pentit = 4 | Dit; + type Hexit = 5 | Pentit; + type Septit = 6 | Hexit; + type Octit = 7 | Septit; + + type Side = Hexit; + type HotbarSlot = Octit | 8; + type HotbarSwapSlot = HotbarSlot | OffhandSlot; + type ClickSlotButton = HotbarSwapSlot | 9 | 10; + type OffhandSlot = 40; + + """ + ); + + for (DeclaredTypeDoc decl : declaredTypes) { + out.append("type ").append(decl.name()).append(" = ").append(decl.type()); + if (!decl.type().contains("\n")) { + out.append(";"); + } + out.append("\n"); + } + } + + private List collectByGroup(DocletModel model, String group) { + List result = new ArrayList<>(); + for (PackageDoc pkg : model.packages()) { + for (ClassDoc clz : pkg.classes()) { + if (group.equals(clz.group())) { + result.add(clz); + } + } + } + result.sort(Comparator.comparing(ClassDoc::alias, String.CASE_INSENSITIVE_ORDER)); + return result; + } + + private Map buildTypeScriptAliases(DocletModel model) { + Map aliases = new HashMap<>(); + aliases.put("com.jsmacrosce.jsmacros.core.event.BaseEvent", "Events.BaseEvent"); + for (PackageDoc pkg : model.packages()) { + for (ClassDoc clz : pkg.classes()) { + if ("Event".equals(clz.group()) && clz.alias() != null) { + aliases.put(clz.qualifiedName(), "Events." + clz.alias()); + } else if ("Library".equals(clz.group()) && clz.alias() != null) { + aliases.put(clz.qualifiedName(), "typeof " + clz.alias()); + } + } + } + return aliases; + } + + private void applyTypeScriptAliases(Map aliases) { + if (typeResolver instanceof BasicTypeResolver basicTypeResolver) { + basicTypeResolver.setTypeScriptAliases(aliases); + } + } + + private StringBuilder indent(StringBuilder out, int indent) { + out.append(" ".repeat(Math.max(0, indent))); + return out; + } + + private boolean hasModifier(MemberDoc member, String modifier) { + return member.modifiers().contains(modifier); + } + + private String tsSafeName(String name) { + return name.replace('.', '$'); + } + + private String escapeParamName(String name) { + if (isReservedWord(name)) { + return "_" + name; + } + return name; + } + + private String escapePackageName(String name) { + if (isReservedWord(name)) { + return "_" + name; + } + return name; + } + + private boolean isReservedWord(String name) { + return TS_RESERVED_WORDS.contains(name); + } + + private void appendClassHeader(StringBuilder out, ClassDoc clz, int indent) { + indent(out, indent).append("static readonly class: JavaClass<") + .append(buildClassHeaderType(clz)).append(">;\n"); + indent(out, indent).append("/** @deprecated */ static prototype: undefined;\n"); + } + + private String buildClassHeaderType(ClassDoc clz) { + StringBuilder builder = new StringBuilder(tsSafeName(clz.name())); + int params = clz.typeParams().size(); + if (params > 0) { + builder.append("<"); + builder.append("any, ".repeat(params)); + builder.setLength(builder.length() - 2); + builder.append(">"); + } + return builder.toString(); + } + + private void appendExtends(StringBuilder out, ClassDoc clz) { + String extendsType; + if (clz.extendsTypes().isEmpty()) { + extendsType = "java.lang.Object"; + } else { + extendsType = formatHeritageType(clz.extendsTypes().get(0), true); + } + out.append(" extends ").append(extendsType); + } + + private void appendImplements(StringBuilder out, ClassDoc clz) { + if (clz.implementsTypes().isEmpty()) { + return; + } + out.append(" extends "); + boolean first = true; + for (TypeRef type : clz.implementsTypes()) { + if (!first) { + out.append(", "); + } + first = false; + out.append(formatHeritageType(type, false)); + } + } + + private String formatHeritageType(TypeRef type, boolean isExtends) { + String formatted = typeResolver.format(type, TargetLanguage.TYPESCRIPT, false); + if (isExtends) { + if (formatted.equals("any") || formatted.equals("JavaObject") || formatted.equals("Object") + || formatted.equals("void")) { + return "java.lang.Object"; + } + if (formatted.startsWith("/* net.minecraft.") && formatted.endsWith("any")) { + return formatted.substring(0, formatted.length() - "any".length()) + "java.lang.Object"; + } + return formatted; + } + if (formatted.startsWith("/* net.minecraft.") && formatted.endsWith("any")) { + return formatted.substring(0, formatted.length() - "any".length()) + "JavaObject"; + } + return formatted; + } + + private boolean shouldReturnThis(MemberDoc member, ClassDoc owner) { + if (owner == null || member.docComment() == null || member.kind() != MemberKind.METHOD) { + return false; + } + String returnText = getTagText(member.docComment(), DocTagKind.RETURN); + if (returnText.isBlank()) { + return false; + } + String trimmed = returnText.trim(); + if (!trimmed.equals("self") && !trimmed.startsWith("self ")) { + return false; + } + TypeRef returnType = member.returnType(); + return returnType != null && owner.qualifiedName().equals(returnType.qualifiedName()); + } + + private void appendDocComment( + StringBuilder out, + DocComment comment, + List params, + boolean includeReturn, + MemberDoc member, + ClassDoc owner, + int indent + ) { + if (comment == null) { + return; + } + String desc = formatDocText(comment.description().isBlank() ? comment.summary() : comment.description()); + List lines = new ArrayList<>(); + if (!desc.isBlank()) { + lines.add(desc); + } + + Map paramDocs = new HashMap<>(); + for (DocTag tag : comment.tags()) { + if (tag.kind() == DocTagKind.PARAM && tag.name() != null) { + paramDocs.put(tag.name(), formatDocText(tag.text())); + } + } + for (ParamDoc param : params) { + String text = paramDocs.get(param.name()); + if (text != null && !text.isBlank()) { + lines.add("@param " + escapeParamName(param.name()) + " " + text); + } + } + + if (includeReturn) { + String returnText = formatDocText(getTagText(comment, DocTagKind.RETURN)); + if (!returnText.isBlank()) { + if (returnText.startsWith("{")) { + returnText = "{*} " + returnText; + } + lines.add("@return " + returnText); + } else if (shouldReturnThis(member, owner)) { + lines.add("@return self"); + } + } + + String since = formatDocText(getTagText(comment, DocTagKind.SINCE)); + if (!since.isBlank()) { + lines.add("@since " + since); + } + String deprecated = formatDocText(getTagText(comment, DocTagKind.DEPRECATED)); + if (hasDeprecatedTag(comment)) { + lines.add(deprecated.isBlank() ? "@deprecated" : "@deprecated " + deprecated); + } + for (String see : getTagTexts(comment, DocTagKind.SEE)) { + String formatted = formatDocText(see); + if (!formatted.isBlank()) { + lines.add("@see " + formatted); + } + } + for (DocTag tag : comment.tags()) { + if (tag.kind() == DocTagKind.TEMPLATE && tag.name() != null) { + String text = formatDocText(tag.text()); + if (!text.isBlank()) { + lines.add("@template " + tag.name() + " " + text); + } + } + } + for (DocTag tag : comment.tags()) { + if (tag.kind() == DocTagKind.OTHER && tag.text() != null) { + String text = formatDocText(tag.text()); + if (!text.isBlank()) { + lines.add(text); + } + } + } + + if (lines.isEmpty()) { + return; + } + indent(out, indent).append("/**\n"); + for (String line : lines) { + // Split on newlines to handle multi-line comments + String[] subLines = line.split("\n"); + for (String subLine : subLines) { + indent(out, indent).append(" * ").append(subLine).append("\n"); + } + } + indent(out, indent).append(" */\n"); + } + + private boolean hasDeprecatedTag(DocComment comment) { + if (comment == null) { + return false; + } + return comment.tags().stream().anyMatch(tag -> tag.kind() == DocTagKind.DEPRECATED); + } + + private String getTagText(DocComment comment, DocTagKind kind) { + if (comment == null) { + return ""; + } + for (DocTag tag : comment.tags()) { + if (tag.kind() == kind) { + return tag.text(); + } + } + return ""; + } + + private List getTagTexts(DocComment comment, DocTagKind kind) { + if (comment == null) { + return List.of(); + } + List values = new ArrayList<>(); + for (DocTag tag : comment.tags()) { + if (tag.kind() == kind) { + values.add(tag.text()); + } + } + return values; + } + + private String formatDocText(String text) { + if (text == null) { + return ""; + } + String formatted = text.trim(); + if (formatted.isEmpty()) { + return ""; + } + formatted = formatted.replaceAll("\n

", "\n") + .replaceAll("", "```"); + // Convert HTML links to Markdown, cleaning up newlines in link text + formatted = convertHtmlLinks(formatted); + formatted = formatted.replace("<", "<").replace(">", ">"); + formatted = convertLinkTags(formatted); + String trimmed = formatted.trim(); + if (looksLikeSignature(trimmed)) { + formatted = convertSignature(trimmed); + } + return formatted.trim(); + } + + private String convertHtmlLinks(String text) { + java.util.regex.Matcher matcher = HTML_LINK.matcher(text); + StringBuffer buffer = new StringBuffer(); + while (matcher.find()) { + String url = matcher.group(1); + String linkText = matcher.group(2); + String replacement = "[" + linkText + "](" + url + ")"; + matcher.appendReplacement(buffer, java.util.regex.Matcher.quoteReplacement(replacement)); + } + matcher.appendTail(buffer); + return buffer.toString(); + } + + private String convertLinkTags(String text) { + java.util.regex.Matcher matcher = LINK_TAG.matcher(text); + StringBuffer buffer = new StringBuffer(); + while (matcher.find()) { + String sig = matcher.group(1).trim(); + String mapped = mapSimpleLinkSignature(sig); + String replacement = mapped != null ? mapped : "{@link " + convertSignature(sig) + "}"; + matcher.appendReplacement(buffer, java.util.regex.Matcher.quoteReplacement(replacement)); + } + matcher.appendTail(buffer); + return buffer.toString(); + } + + private boolean looksLikeSignature(String text) { + if (text.startsWith("#")) { + return true; + } + return text.matches("^xyz\\.wagyourtail\\.[^#]+\\w$") + || text.matches("^\\w+\\.(?:\\w+\\.)+[\\w$_]+$"); + } + + private String convertSignature(String sig) { + if (sig.matches("^xyz\\.wagyourtail\\.[^#]+\\w$")) { + return sig.replaceFirst("^.+\\.(?=[^.]+$)", ""); + } + if (sig.matches("^\\w+\\.(?:\\w+\\.)+[\\w$_]+$")) { + return "Packages." + sig; + } + if (sig.startsWith("#")) { + return sig.substring(1); + } + return sig + .replaceFirst("^(?:xyz\\.wagyourtail\\.jsmacros\\.(?:client\\.api|core)\\.library\\.impl\\.)?F([A-Z]\\w+)#", "$1.") + .replaceFirst("#", "."); + } + + private String mapSimpleLinkSignature(String sig) { + if (JAVA_NUMBER_TYPES.containsKey(sig)) { + return JAVA_NUMBER_TYPES.get(sig); + } + return switch (sig) { + case "java.lang.String" -> "string"; + case "java.lang.Boolean" -> "boolean"; + default -> null; + }; + } + + private DocComment sanitizeLibraryComment(DocComment comment) { + if (comment == null) { + return null; + } + String summary = stripLibraryBoilerplate(comment.summary()); + String description = stripLibraryBoilerplate(comment.description()); + if (summary.equals(comment.summary()) && description.equals(comment.description())) { + return comment; + } + return new DocComment(summary, description, comment.tags()); + } + + private String stripLibraryBoilerplate(String text) { + if (text == null || text.isBlank()) { + return text == null ? "" : text; + } + return text.replaceAll("(?m)^\\s*An instance of this class is passed to scripts as the `\\w+` variable\\.?\\s*$", "") + .trim(); + } + + private static class PackageNode { + private final String name; + private final Map children = new TreeMap<>(); + private final List classes = new ArrayList<>(); + + private PackageNode(String name) { + this.name = name; + } + + private void addClass(String packageName, ClassDoc clz) { + if (packageName == null || packageName.isEmpty()) { + classes.add(clz); + return; + } + String[] parts = packageName.split("\\."); + PackageNode current = this; + for (String part : parts) { + current = current.children.computeIfAbsent(part, PackageNode::new); + } + current.classes.add(clz); + } + } +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/tsdoclet/Main.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/tsdoclet/Main.java new file mode 100644 index 000000000..f66b7bff3 --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/tsdoclet/Main.java @@ -0,0 +1,82 @@ +package com.jsmacrosce.doclet.core.tsdoclet; + +import com.sun.source.util.DocTrees; +import jdk.javadoc.doclet.Doclet; +import jdk.javadoc.doclet.DocletEnvironment; +import jdk.javadoc.doclet.Reporter; +import com.jsmacrosce.FileHandler; +import com.jsmacrosce.doclet.core.BasicDocCommentParser; +import com.jsmacrosce.doclet.core.BasicTypeResolver; +import com.jsmacrosce.doclet.core.DocletModelBuilder; +import com.jsmacrosce.doclet.core.render.TsRenderer; +import com.jsmacrosce.doclet.options.IgnoredItem; +import com.jsmacrosce.doclet.options.OutputDirectory; +import com.jsmacrosce.doclet.options.Version; + +import javax.lang.model.SourceVersion; +import javax.tools.Diagnostic; +import java.io.File; +import java.io.IOException; +import java.util.*; + +public class Main implements Doclet { + public static Reporter reporter; + public static DocTrees treeUtils; + + @Override + public void init(Locale locale, Reporter reporter) { + Main.reporter = reporter; + } + + @Override + public String getName() { + return "TypeScript Generator"; + } + + @SuppressWarnings("SpellCheckingInspection") + @Override + public Set getSupportedOptions() { + return Set.of( + new Version(), + new OutputDirectory(), + new IgnoredItem("-doctitle", 1), + new IgnoredItem("-notimestamp", 0), + new IgnoredItem("-windowtitle", 1) + ); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.RELEASE_16; + } + + @Override + public boolean run(DocletEnvironment environment) { + treeUtils = environment.getDocTrees(); + + File outDir = OutputDirectory.outputDir; + if (outDir == null) { + reporter.print(Diagnostic.Kind.ERROR, "Output directory not set\n"); + return false; + } + if (!outDir.exists() && !outDir.mkdirs()) { + reporter.print(Diagnostic.Kind.ERROR, "Failed to create version dir\n"); + return false; + } + + FileHandler outputTS = new FileHandler(new File(outDir, "JsMacros-" + Version.version + ".d.ts")); + BasicTypeResolver typeResolver = new BasicTypeResolver(); + DocletModelBuilder builder = new DocletModelBuilder(typeResolver, new BasicDocCommentParser(treeUtils)); + var model = builder.build(environment); + TsRenderer renderer = new TsRenderer(typeResolver); + + try { + outputTS.write(renderer.render(model)); + } catch (IOException e) { + reporter.print(Diagnostic.Kind.ERROR, "Failed to write TypeScript output: " + e.getMessage()); + return false; + } + return true; + } + +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/core/util/ElementNameUtils.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/util/ElementNameUtils.java new file mode 100644 index 000000000..6208c1e3d --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/util/ElementNameUtils.java @@ -0,0 +1,81 @@ +package com.jsmacrosce.doclet.core.util; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; + +public final class ElementNameUtils { + private ElementNameUtils() { + } + + public static String getPackageName(TypeElement type) { + Element current = type; + while (current.getKind() != ElementKind.PACKAGE) { + current = current.getEnclosingElement(); + } + return ((PackageElement) current).getQualifiedName().toString(); + } + + public static String getDisplayClassName(TypeElement type) { + StringBuilder name = new StringBuilder(type.getSimpleName()); + Element current = type.getEnclosingElement(); + while (current.getKind() == ElementKind.INTERFACE || current.getKind() == ElementKind.CLASS) { + name.insert(0, current.getSimpleName() + "."); + current = current.getEnclosingElement(); + } + return name.toString(); + } + + public static String getQualifiedName(TypeElement type) { + String pkg = getPackageName(type); + String name = getDisplayClassName(type); + return pkg.isEmpty() ? name : pkg + "." + name; + } + + public static String memberId(Element member) { + StringBuilder s = new StringBuilder(); + switch (member.getKind()) { + case ENUM_CONSTANT, FIELD -> s.append(member.getSimpleName()); + case CONSTRUCTOR, METHOD -> { + if (member.getKind() == ElementKind.METHOD) { + s.append(member.getSimpleName()); + } else { + s.append("constructor"); + } + for (VariableElement parameter : ((ExecutableElement) member).getParameters()) { + s.append("-").append(getTypeMirrorName(parameter.asType())); + } + s.append("-"); + } + default -> throw new UnsupportedOperationException(String.valueOf(member.getKind())); + } + return s.toString(); + } + + private static String getTypeMirrorName(TypeMirror type) { + return switch (type.getKind()) { + case BOOLEAN -> "boolean"; + case BYTE -> "byte"; + case SHORT -> "short"; + case INT -> "int"; + case LONG -> "long"; + case CHAR -> "char"; + case FLOAT -> "float"; + case DOUBLE -> "double"; + case VOID, NONE -> "void"; + case NULL -> "null"; + case ARRAY -> getTypeMirrorName(((ArrayType) type).getComponentType()) + "[]"; + case DECLARED -> getDisplayClassName((TypeElement) ((DeclaredType) type).asElement()); + case TYPEVAR -> ((TypeVariable) type).asElement().getSimpleName().toString(); + case WILDCARD -> "?"; + default -> type.toString(); + }; + } +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/webdoclet/Main.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/webdoclet/Main.java similarity index 83% rename from buildSrc/src/main/java/com/jsmacrosce/doclet/webdoclet/Main.java rename to buildSrc/src/main/java/com/jsmacrosce/doclet/core/webdoclet/Main.java index b1998376f..6efb43c82 100644 --- a/buildSrc/src/main/java/com/jsmacrosce/doclet/webdoclet/Main.java +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/webdoclet/Main.java @@ -1,19 +1,23 @@ -package com.jsmacrosce.doclet.webdoclet; +package com.jsmacrosce.doclet.core.webdoclet; import com.sun.source.util.DocTrees; import jdk.javadoc.doclet.Doclet; import jdk.javadoc.doclet.DocletEnvironment; import jdk.javadoc.doclet.Reporter; import com.jsmacrosce.FileHandler; +import com.jsmacrosce.doclet.core.webdoclet.parsers.ClassParser; import com.jsmacrosce.doclet.options.IgnoredItem; import com.jsmacrosce.doclet.options.OutputDirectory; import com.jsmacrosce.doclet.options.Version; import com.jsmacrosce.doclet.webdoclet.options.Links; import com.jsmacrosce.doclet.webdoclet.options.McVersion; -import com.jsmacrosce.doclet.webdoclet.parsers.ClassParser; import javax.lang.model.SourceVersion; -import javax.lang.model.element.*; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.Diagnostic; @@ -40,7 +44,7 @@ public void init(Locale locale, Reporter reporter) { @Override public String getName() { - return "WebDoc Generator"; + return "WebDoc Generator (Core)"; } @Override @@ -70,22 +74,26 @@ public boolean run(DocletEnvironment environment) { elementUtils = environment.getElementUtils(); File outDir = new File(OutputDirectory.outputDir, Version.version); - try { if (!outDir.exists() && !outDir.mkdirs()) { reporter.print(Diagnostic.Kind.ERROR, "Failed to create version dir\n"); return false; } - //create package-list StringBuilder pkgList = new StringBuilder(); - elements.stream().filter(e -> e.getKind() == ElementKind.PACKAGE).map(e -> (PackageElement) e).forEach(e -> { - if (Links.externalPackages.containsKey(e.getQualifiedName().toString())) { - return; + for (Element element : elements) { + if (element.getKind() != javax.lang.model.element.ElementKind.PACKAGE) { + continue; } - pkgList.append(e.getQualifiedName()).append("\n"); - }); - pkgList.setLength(pkgList.length() - 1); + String name = ((javax.lang.model.element.PackageElement) element).getQualifiedName().toString(); + if (Links.externalPackages.containsKey(name)) { + continue; + } + pkgList.append(name).append("\n"); + } + if (pkgList.length() > 0) { + pkgList.setLength(pkgList.length() - 1); + } new FileHandler(new File(outDir, "package-list")).write(pkgList.toString()); elements.stream().filter(e -> e instanceof TypeElement).map(e -> (TypeElement) e).forEach(e -> { diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/webdoclet/parsers/ClassParser.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/webdoclet/parsers/ClassParser.java similarity index 98% rename from buildSrc/src/main/java/com/jsmacrosce/doclet/webdoclet/parsers/ClassParser.java rename to buildSrc/src/main/java/com/jsmacrosce/doclet/core/webdoclet/parsers/ClassParser.java index bce1bb4f9..ea21e372c 100644 --- a/buildSrc/src/main/java/com/jsmacrosce/doclet/webdoclet/parsers/ClassParser.java +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/core/webdoclet/parsers/ClassParser.java @@ -1,10 +1,10 @@ -package com.jsmacrosce.doclet.webdoclet.parsers; +package com.jsmacrosce.doclet.core.webdoclet.parsers; import com.sun.source.doctree.*; import com.sun.source.util.DocTreePath; import com.jsmacrosce.Pair; import com.jsmacrosce.XMLBuilder; -import com.jsmacrosce.doclet.webdoclet.Main; +import com.jsmacrosce.doclet.core.webdoclet.Main; import com.jsmacrosce.doclet.webdoclet.options.Links; import javax.lang.model.element.*; @@ -108,7 +108,7 @@ public String genXML() { new XMLBuilder("body").append( new XMLBuilder("header").append( new XMLBuilder("a").addStringOption("href", getUpDir(1)).append( - "<----- Return to main JsMacrosCE docs page." + "<----- Return to main JsMacros docs page." ) )), parseClass() @@ -117,6 +117,7 @@ public String genXML() { private XMLBuilder parseClass() { XMLBuilder builder = new XMLBuilder("main").setClass("classDoc"); + // subclasses start XMLBuilder subClasses; builder.append(subClasses = new XMLBuilder("div").setId("subClasses")); for (Element subClass : Main.elements.stream().filter(e -> { @@ -127,8 +128,13 @@ private XMLBuilder parseClass() { }).collect(Collectors.toList())) { subClasses.append(parseType(subClass.asType()), " "); } - XMLBuilder cname; - builder.append(cname = new XMLBuilder("h2", true, true).setClass("classTitle").append((getPackage(type)), ".", getClassName(type))); + // subclasses end + + // class name + types start + XMLBuilder cname = new XMLBuilder("h2", true, true) + .setClass("classTitle") + .append((getPackage(type)), ".", getClassName(type)); + builder.append(cname); List params = type.getTypeParameters(); if (params != null && !params.isEmpty()) { @@ -139,6 +145,7 @@ private XMLBuilder parseClass() { cname.pop(); cname.append(">"); } + // class name + types end builder.append(createFlags(type, false)); TypeMirror sup = type.getSuperclass(); diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/mddoclet/options/Links.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/mddoclet/options/Links.java new file mode 100644 index 000000000..3926bee9e --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/mddoclet/options/Links.java @@ -0,0 +1,54 @@ +package com.jsmacrosce.doclet.mddoclet.options; + +import jdk.javadoc.doclet.Doclet; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Links implements Doclet.Option { + public static Map externalPackages = new HashMap<>(); + + @Override + public int getArgumentCount() { + return 1; + } + + @Override + public String getDescription() { + return "link external javadoc"; + } + + @Override + public Kind getKind() { + return Kind.STANDARD; + } + + @Override + public List getNames() { + return List.of("-link"); + } + + @Override + public String getParameters() { + return ""; + } + + @Override + public boolean process(String option, List arguments) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(arguments.get(0) + "package-list").openStream()))) { + String line; + while ((line = reader.readLine()) != null) { + externalPackages.put(line, arguments.get(0) + "index.html?" + line.replaceAll("\\.", "/") + "/"); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/mddoclet/options/McVersion.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/mddoclet/options/McVersion.java new file mode 100644 index 000000000..781a3400a --- /dev/null +++ b/buildSrc/src/main/java/com/jsmacrosce/doclet/mddoclet/options/McVersion.java @@ -0,0 +1,41 @@ +package com.jsmacrosce.doclet.mddoclet.options; + +import jdk.javadoc.doclet.Doclet; + +import java.util.List; + +public class McVersion implements Doclet.Option { + public static String mcVersion; + + @Override + public int getArgumentCount() { + return 1; + } + + @Override + public String getDescription() { + return "Minecraft Version Number"; + } + + @Override + public Kind getKind() { + return Kind.STANDARD; + } + + @Override + public List getNames() { + return List.of("-mcv", "--mcversion"); + } + + @Override + public String getParameters() { + return ""; + } + + @Override + public boolean process(String option, List arguments) { + mcVersion = arguments.get(0); + return true; + } + +} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/pydoclet/Main.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/pydoclet/Main.java deleted file mode 100644 index 4b5fe4101..000000000 --- a/buildSrc/src/main/java/com/jsmacrosce/doclet/pydoclet/Main.java +++ /dev/null @@ -1,236 +0,0 @@ -package com.jsmacrosce.doclet.pydoclet; - -import com.sun.source.util.DocTrees; -import jdk.javadoc.doclet.Doclet; -import jdk.javadoc.doclet.DocletEnvironment; -import jdk.javadoc.doclet.Reporter; -import com.jsmacrosce.FileHandler; -import com.jsmacrosce.doclet.options.IgnoredItem; -import com.jsmacrosce.doclet.options.OutputDirectory; -import com.jsmacrosce.doclet.options.Version; -import com.jsmacrosce.doclet.pydoclet.parsers.ClassParser; - -import javax.lang.model.SourceVersion; -import javax.lang.model.element.*; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; -import javax.tools.Diagnostic; -import java.io.File; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -public class Main implements Doclet { - public static Reporter reporter; - public static DocTrees treeUtils; - public static Elements elementUtils; - public static Types typeUtils; - public static Set elements; - public static Map internalClasses; - - @Override - public void init(Locale locale, Reporter reporter) { - Main.reporter = reporter; - } - - @Override - public String getName() { - return "Python generator"; - } - - @Override - public Set getSupportedOptions() { - return Set.of( - new Version(), - new OutputDirectory(), - new IgnoredItem("-doctitle", 1), - new IgnoredItem("-notimestamp", 0), - new IgnoredItem("-windowtitle", 1) - ); - } - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.RELEASE_16; - } - - @Override - public boolean run(DocletEnvironment environment) { - typeUtils = environment.getTypeUtils(); - treeUtils = environment.getDocTrees(); - elements = environment.getIncludedElements(); - elementUtils = environment.getElementUtils(); - internalClasses = new HashMap<>(); - HashMap> classes = new HashMap<>(); - - //reporter.print(Diagnostic.Kind.NOTE, elements + ""); - - File outDir = new File(OutputDirectory.outputDir, ""); - - try { - //Remove Folder - if (outDir.exists() && !outDir.delete()) { - reporter.print(Diagnostic.Kind.ERROR, "Failed to remove old py output\n"); - return false; - } - - //Create Out Folder - if (!outDir.exists() && !outDir.mkdirs()) { - reporter.print(Diagnostic.Kind.ERROR, "Failed to create version dir\n"); - return false; - } - - //Create ClassParser - elements.stream().filter(e -> e instanceof TypeElement).map(e -> (TypeElement) e).forEach(e -> { - // filter elements, if e is TypeElement, then it can be - internalClasses.put(e, new ClassParser(e)); - - AnnotationMirror mirror = e.getAnnotationMirrors().stream().filter(a -> a.getAnnotationType().asElement().getSimpleName().toString().equals("Library")).findFirst().orElse(null); - //Library - if (mirror != null) { - //Library - if (!classes.containsKey("libraries")) { - classes.put("libraries", new HashMap<>()); - } - classes.get("libraries").put(ClassParser.getClassName(e), getAnnotationValue("value", mirror) + ""); - } else if (e.getAnnotationMirrors().stream().filter(a -> a.getAnnotationType().asElement().getSimpleName().toString().equals("Event")).findFirst().orElse(null) != null) { - //Event - if (!classes.containsKey("events")) { - classes.put("events", new HashMap<>()); - } - classes.get("events").put(ClassParser.getClassName(e), getAnnotationValue("value", e.getAnnotationMirrors().stream().filter(a -> a.getAnnotationType().asElement().getSimpleName().toString().equals("Event")).findFirst().orElse(null)) + ""); - } else if (ClassParser.getClassName(e).contains("Helper")) { - if (!classes.containsKey("helpers")) { - classes.put("helpers", new HashMap<>()); - } - classes.get("helpers").put(ClassParser.getClassName(e), ClassParser.getClassName(e)); - } else if (ClassParser.getClassName(e).contains("Mixin")) { - if (!classes.containsKey("mixins")) { - classes.put("mixins", new HashMap<>()); - } - classes.get("mixins").put(ClassParser.getClassName(e), ClassParser.getClassName(e)); - } else { - if (!classes.containsKey("rest")) { - classes.put("rest", new HashMap<>()); - } - classes.get("rest").put(ClassParser.getClassName(e), ClassParser.getClassName(e)); - } - - }); - - //Create Sum Up Files - reporter.print(Diagnostic.Kind.NOTE, classes + ""); - for (Map.Entry> entry : classes.entrySet()) { - StringBuilder sb = new StringBuilder(); - - sb.append("from typing import TypeVar\n\n"); - sb.append("from .EventContainer import EventContainer\n"); - sb.append("from .BaseEvent import BaseEvent\n"); - - for (Map.Entry args : entry.getValue().entrySet()) { - sb.append("from .").append(args.getKey()).append(" import ").append(args.getKey()).append("\n"); - } - - sb.append("\nFile = TypeVar(\"java.io.File\")\n\n"); // TypeVar should be () - - if (entry.getKey().equalsIgnoreCase("libraries")) { - sb.append("\n\n"); - for (Map.Entry args : entry.getValue().entrySet()) { - sb.append(args.getValue()).append(" = ").append(args.getKey()).append("()\n"); - } - - sb.append("context = EventContainer()\n"); - sb.append("file = File()\n"); - sb.append("event = BaseEvent()\n"); - } - new FileHandler(new File(outDir, entry.getKey() + ".py")).write(sb.toString()); - } - - //Create Classes - for (ClassParser value : internalClasses.values()) { - File out = new File(outDir, ClassParser.getClassName(value.type) + ".py"); - File parent = out.getParentFile(); - if (!parent.exists() && !parent.mkdirs()) { - reporter.print(Diagnostic.Kind.ERROR, "Failed to create package dir " + parent + "\n"); - return false; - } - new FileHandler(out).write(value.parseClass()); - } - - //Create __init__.py - StringBuilder sb = new StringBuilder(); - for (String file : classes.keySet()) { - sb.append("from .").append(file).append(" import *\n"); - } - new FileHandler(new File(outDir, "__init__.py")).write(sb.toString()); - - sb.delete(0, sb.length()); - sb.append(""" - from setuptools import setup, find_packages - from os import path - import os - import time - - this_directory = path.abspath(path.dirname(__file__)) - with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f: - long_description = f.read() - - - VERSION = '"""); - sb.append(Version.version); - sb.append(""" - ' - if "-" in VERSION: VERSION = VERSION.split("-")[0] - VERSION += "." + str(time.time()).split(".")[0][3:] - DESCRIPTION = 'A package to let your IDE know what JsMacrosCE can do' - - def package_files(directory): - paths = [] - for (path, directories, filenames) in os.walk(directory): - for filename in filenames: - paths.append(os.path.join('..', path, filename)) - return paths - - extra_files = package_files('JsMacrosAC') - - # Setting up - setup( - name="JsMacrosAC", - version=VERSION, - author="Hasenzahn1", - author_email="", - description=DESCRIPTION, - long_description_content_type="text/markdown", - long_description=long_description, - packages=["JsMacrosAC"], - package_data = {"": extra_files}, - install_requires=[], - keywords=['python', 'JsMacrosCE', 'JsMacros', 'Autocomplete', 'Doc'], - classifiers=[ - "Intended Audience :: Developers", - "Programming Language :: Python :: 3", - "Operating System :: Unix", - "Operating System :: MacOS :: MacOS X", - "Operating System :: Microsoft :: Windows", - ] - )"""); - new FileHandler(new File(outDir.getParent(), "setup.py")).write(sb.toString()); - - } catch (Exception e) { - e.printStackTrace(); - return false; - } - return true; - } - - public static Object getAnnotationValue(String key, AnnotationMirror annotation) { - for (Map.Entry el : annotation.getElementValues().entrySet()) { - if (el.getKey().getSimpleName().toString().equals(key)) { - return el.getValue().getValue(); - } - } - return null; - } - -} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/pydoclet/parsers/ClassParser.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/pydoclet/parsers/ClassParser.java deleted file mode 100644 index d797eb512..000000000 --- a/buildSrc/src/main/java/com/jsmacrosce/doclet/pydoclet/parsers/ClassParser.java +++ /dev/null @@ -1,493 +0,0 @@ -package com.jsmacrosce.doclet.pydoclet.parsers; - -import com.sun.source.doctree.*; -import com.sun.source.util.DocTreePath; -import com.jsmacrosce.doclet.pydoclet.Main; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import java.util.*; - -public class ClassParser { - public final TypeElement type; - private final List imports = new LinkedList<>(); - private boolean importOverload = false, importList = false, importTypeVar = false, importAny = false, importMapping = false, importSet = false, importGeneric = false; - HashMap> typeVars = new HashMap<>(); - private final HashMap types = new HashMap<>(), - withArg = new HashMap<>(), - unwantedClass = new HashMap<>(); - private final ArrayList keywords = new ArrayList<>(Arrays.asList("False", "await", "else", "import", "pass", "", "None", "break", "except", "in", "raise", "", "True", "class", "finally", "is", "return", "", "and", "continue", "for", "lambda", "try", "", "as", "def", "from", "nonlocal", "while", "", "assert", "del", "global", "not", "with", "", "async", "elif", "if", "or", "yield")); - - public ClassParser(TypeElement type) { - this.type = type; - - types.put("java.lang.Object", "object"); - types.put("java.lang.String", "str"); - types.put("java.lang.Integer", "int"); - types.put("java.lang.Boolean", "bool"); - types.put("java.lang.Double", "float"); - types.put("java.lang.annotation.Annotation", ""); - types.put("java.lang.Enum", ""); - types.put("java.util.Iterator", "iter"); - - withArg.put("java.util.Set", "Set"); - withArg.put("java.util.List", "List"); - withArg.put("java.util.Map", "Mapping"); - withArg.put("java.util.Collection", "List"); - - unwantedClass.put("java.lang.Object", ""); - unwantedClass.put("java.lang.annotation.Annotation", ""); - unwantedClass.put("java.lang.Enum", ""); - unwantedClass.put("java.util.Collection", ""); - } - - public String parseClass() { - StringBuilder sb = new StringBuilder(); - - //ClassLine e.g class Test(AbstractTest, ): - sb.append(getClassLine()); - - //Fields - sb.append(getFields()).append("\n"); - - //Methods / Constructor - sb.append(getMethods()); - - //safety pass - sb.append(getTabs(1)).append("pass\n\n"); - - //imports + abstract types - sb.insert(0, getImports()).append("\n"); - - return sb.toString(); - } - - private String getMethods() { - StringBuilder sb = new StringBuilder(); - - type.getEnclosedElements().stream().filter(e -> e.getKind() == ElementKind.METHOD || e.getKind() == ElementKind.CONSTRUCTOR).forEach(el -> { - if (!el.getModifiers().contains(Modifier.PUBLIC)) { - return; - } - ExecutableElement method = (ExecutableElement) el; - importOverload = true; - sb.append(getTabs(1)).append("@overload\n"); - sb.append(getTabs(1)).append("def "); - if (el.getKind() == ElementKind.CONSTRUCTOR) { - sb.append("__init__"); - } else { - sb.append(getVarName(method.getSimpleName().toString())); - } - - sb.append("(self"); - - method.getParameters().forEach(parameter -> sb.append(", ").append(getVarName(parameter.getSimpleName().toString())).append(": ").append(getTypeMirrorName(parameter.asType(), false))); - sb.append(") -> "); - if (method.getReceiverType() != null) { - String return_type = getTypeMirrorName(method.getReturnType(), false); - - sb.append(return_type); - }; - sb.append(":\n"); - - sb.append(getMethodDoc(method)); - sb.append(getTabs(2)).append("pass\n\n"); - }); - - return sb.toString(); - } - - private String getSince(Element element) { - DocCommentTree tree = Main.treeUtils.getDocCommentTree(element); - SinceTree since = tree == null ? null : (SinceTree) tree.getBlockTags().stream().filter(e -> e.getKind().equals(DocTree.Kind.SINCE)).findFirst().orElse(null); - if (since != null) { - return createDescription(element, since.getBody()); - } else { - return ""; - } - } - - private String getClassDoc(Element element) { - StringBuilder sb = new StringBuilder(); - DocCommentTree tree = Main.treeUtils.getDocCommentTree(element); - if (tree != null) { - sb.append(getTabs(1)).append("\"\"\"").append(createDescription(element, tree.getFullBody()).strip()); - String since = getSince(element); - if (since.length() > 0) { - if (sb.length() > 4) { - sb.append("\\n"); - } - sb.append("\n"); - sb.append(getTabs(1)).append("Since: ").append(since).append("\n"); - } else { - sb.append("\n"); - } - sb.append(getTabs(1)).append("\"\"\"\n"); - } - - return sb.toString(); - } - - private String getMethodDoc(ExecutableElement element) { - StringBuilder sb = new StringBuilder(); - DocCommentTree tree = Main.treeUtils.getDocCommentTree(element); - if (tree != null) { - sb.append(getTabs(2)).append("\"\"\"").append(createDescription(element, tree.getFullBody()).strip()); - String since = getSince(element); - if (since.length() > 0) { - if (sb.length() > 5) { - sb.append("\\n"); - } - sb.append("\n"); - sb.append(getTabs(2)).append("Since: ").append(since).append("\n"); - } else { - sb.append("\n"); - } - - Map paramMap = getParamDescriptions(element); - if (paramMap.size() > 0) { - sb.append("\n").append(getTabs(2)).append("Args:\n"); - for (Map.Entry entry : paramMap.entrySet()) { - sb.append(getTabs(3)).append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); - } - } - - String returnString = getReturnDescription(element); - if (returnString.length() > 0) { - sb.append("\n").append(getTabs(2)).append("Returns:\n"); - sb.append(getTabs(3)).append(returnString).append("\n"); - } - - sb.append(getTabs(2)).append("\"\"\"\n"); - } - - return sb.toString(); - } - - public Map getParamDescriptions(ExecutableElement element) { - Map paramMap = new HashMap<>(); - DocCommentTree comment = Main.treeUtils.getDocCommentTree(element); - if (comment == null) { - return paramMap; - } - comment.getBlockTags().stream().filter(e -> e.getKind() == DocTree.Kind.PARAM).forEach(e -> paramMap.put(((ParamTree) e).getName().getName().toString(), createDescription(element, ((ParamTree) e).getDescription()))); - return paramMap; - } - - private String getReturnDescription(ExecutableElement element) { - DocCommentTree dct = Main.treeUtils.getDocCommentTree(element); - if (dct == null) { - return ""; - } - ReturnTree t = (ReturnTree) dct.getBlockTags().stream().filter(e -> e.getKind() == DocTree.Kind.RETURN).findFirst().orElse(null); - if (t == null) { - return ""; - } - return createDescription(element, t.getDescription()); - } - - private String getVarName(String simpleName) { - return keywords.contains(simpleName) ? simpleName + "_" : simpleName; - } - - private String createDescription(Element element, List inlineDoc) { - StringBuilder sb = new StringBuilder(); - - for (DocTree docTree : inlineDoc) { - switch (docTree.getKind()) { - case TEXT -> sb.append(docTree.toString().strip()).append(" "); //.replace("\n", "") - case CODE -> sb.append("'").append(((LiteralTree) docTree).getBody()).append("' "); - case LINK, LINK_PLAIN -> { - Element ele = Main.treeUtils.getElement(new DocTreePath(new DocTreePath(Main.treeUtils.getPath(element), Main.treeUtils.getDocCommentTree(element)), ((LinkTree) docTree).getReference())); - - if (ele != null) { - - if (List.of(ElementKind.INTERFACE, ElementKind.CLASS, ElementKind.ANNOTATION_TYPE, ElementKind.ENUM).contains(ele.getKind())) { - sb.append(getClassName((TypeElement) ele)); - } else { - sb.append(getClassName((TypeElement) ele.getEnclosingElement())).append("#").append(ele); - } - - } else { - sb.append(((LinkTree) docTree).getReference().getSignature().replace("\n", "")); - } - sb.append(" "); - } - case START_ELEMENT -> { - if (Objects.equals(docTree.toString(), "

  • ")) { - sb.append("\n - "); - } - if (Objects.equals(docTree.toString(), "

    ")) { - sb.append("\n"); - } - } - } - } - - return sb.toString().replace("\n ", "\n"); - } - - private String getImports() { - StringBuilder sb = new StringBuilder(); - - List imp = new LinkedList<>(); - - imports.forEach(t -> { - if (!types.containsKey(getClearedNameFromTypeMirror(t))) { - if (!withArg.containsKey(getClearedNameFromTypeMirror(t))) { - if ((t + "").startsWith("com.jsmacrosce")) { - if (Main.typeUtils.asElement(t) != null) { - if (!getClassName((TypeElement) Main.typeUtils.asElement(t)).equals(getClassName(type))) { - String path = getClassName((TypeElement) Main.typeUtils.asElement(t)); //getPackage((TypeElement) Main.typeUtils.asElement(t)) + "." + - if (!imp.contains(path)) { - imp.add(path); - } - } - } - } else if ((t + "").startsWith("net") || (t + "").startsWith("com") || (t + "").startsWith("io") || (t + "").startsWith("java.util") || - (t + "").startsWith("java.lang.Runnable") || (t + "").startsWith("java.lang.Thread") || (t + "").startsWith("java.lang.Throwable") || - (t + "").startsWith("java.util.function") || (t + "").startsWith("java.lang.ref") || (t + "").startsWith("java.io") || (t + "").startsWith("org") || (t + "").startsWith("java.lang.Iterable") || - (t + "").startsWith("java.lang.StackTraceElement")) { - if (!importTypeVar) { - importTypeVar = true; - } - if (t.getKind() == TypeKind.ARRAY) { - t = ((ArrayType) t).getComponentType(); - } - typeVars.put( - getClassName((TypeElement) Main.typeUtils.asElement(t)), - new AbstractMap.SimpleEntry<>(t + "", false) - ); - }; - } - } - }); - - if (importOverload) { - sb.append("from typing import overload\n"); - } - if (importList) { - sb.append("from typing import List\n"); - } - if (importTypeVar) { - sb.append("from typing import TypeVar\n"); - } - if (importAny) { - sb.append("from typing import Any\n"); - } - if (importMapping) { - sb.append("from typing import Mapping\n"); - } - if (importSet) { - sb.append("from typing import Set\n"); - } - if (importGeneric) { - sb.append("from typing import Generic\n"); - } - - imp.forEach(s -> sb.append("from .").append(s).append(" import ").append(s).append("\n")); - - sb.append("\n"); - String type_name; - for(Map.Entry> entry : typeVars.entrySet()){ - type_name = entry.getValue().getKey().replace("<", "_").replace(">", "_").replace("?", "").replace(".", "_"); - if(Objects.equals(type_name.toString(), "T") || Objects.equals(type_name.toString(), "U") || Objects.equals(type_name.toString(), "R")){ - sb.append(entry.getKey()).append(" = TypeVar(\"").append(entry.getKey()).append("\")\n"); - } else { - sb.append(type_name).append(" = TypeVar(\"").append(type_name).append("\")\n"); - sb.append(entry.getKey()).append(" = ").append(type_name).append("\n\n"); - }; - } - - return sb.toString(); - } - - private String getClearedNameFromTypeMirror(TypeMirror type) { - StringBuilder s = new StringBuilder(type + ""); - if (s.indexOf("<") != -1) { - s.delete(s.indexOf("<"), s.length()); - } - if (s.indexOf(" ") != -1) { - s.delete(0, s.indexOf(" ") + 1); - } - return s.toString(); - } - - private String getFields() { - StringBuilder sb = new StringBuilder(); - - type.getEnclosedElements().stream().filter(e -> e.getKind().equals(ElementKind.FIELD) || e.getKind().equals(ElementKind.ENUM_CONSTANT)).forEach(el -> { - if (!el.getModifiers().contains(Modifier.PUBLIC)) { - return; - } - addImport(el.asType()); - sb.append(getTabs(1)); - sb.append(getVarName(el.getSimpleName().toString())); - sb.append(": "); - sb.append(getTypeMirrorName(el.asType(), false)); - sb.append("\n"); - }); - - return sb.toString(); - } - - private String getTabs(int amount) { - return new String(new char[amount]).replace("\0", "\t"); - } - - private String getClassLine(){ - StringBuilder sb = new StringBuilder("\nclass "); // for PEP8 - sb.append(getClassName(type)); - - List implement = type.getInterfaces(); - TypeMirror extend = type.getSuperclass(); - - if (!(implement.size() == 0 && extend.getKind().equals(TypeKind.NONE))) { - sb.append("("); - implement.forEach(i -> { - sb.append(getTypeMirrorName(i, true)).append(", "); - addImport(i); - }); - if (type.getTypeParameters().size() > 0) { - importGeneric = true; - addImport(type.getTypeParameters().get(0).asType()); - sb.append("Generic["); - sb.append(getTypeMirrorName(type.getTypeParameters().get(0).asType(), true)); - for (int i = 1; i < type.getTypeParameters().size(); i++) { - sb.append(", ").append(getTypeMirrorName(type.getTypeParameters().get(i).asType(), true)); - addImport(type.getTypeParameters().get(0).asType()); - } - sb.append("], "); - } - if (!extend.getKind().equals(TypeKind.NONE)) { - sb.append(getTypeMirrorName(extend, true)); - addImport(extend); - } - if (sb.lastIndexOf(", ") == sb.length() - 2) { - sb.delete(sb.length() - 2, sb.length()); - } - sb.append(")"); - if (sb.lastIndexOf("()") != -1) { - sb.delete(sb.length() - 2, sb.length()); - } - } - - sb.append(":\n"); - - sb.append(getClassDoc(type)); - - return sb.toString(); - } - - private void addImport(TypeMirror type) { - if (type != null) { - if (!imports.contains(type)) { - imports.add(type); - } - if (type.getKind().equals(TypeKind.ARRAY)) { - addImport(((ArrayType) type).getComponentType()); - } - } - - } - - private String getTypeMirrorName(TypeMirror type, boolean cls) { - imports.add(type); - switch (type.getKind()) { - case BOOLEAN -> { - return "bool"; - } - case BYTE, SHORT, LONG, FLOAT, DOUBLE -> { - return "float"; - } - case INT -> { - return "int"; - } - case CHAR -> { - return "str"; - } - case VOID, NONE, NULL -> { - return "None"; - } - case ARRAY -> { - //List[NAME] - importList = true; - return "List[" + getTypeMirrorName(((ArrayType) type).getComponentType(), false) + "]"; - } - case DECLARED -> { - return parseDeclared(type, cls); - } - case TYPEVAR -> { - typeVars.put( - ((TypeVariable) type).asElement().getSimpleName().toString(), - new AbstractMap.SimpleEntry<>(((TypeVariable) type).asElement().getSimpleName().toString(), true) - ); - importTypeVar = true; - return ((TypeVariable) type).asElement().getSimpleName().toString(); - } - case WILDCARD -> { - importAny = true; - return "Any"; - } - default -> throw new UnsupportedOperationException(String.valueOf(type.getKind())); - } - } - - private String parseDeclared(TypeMirror type, boolean cls) { - if (cls) { - if (unwantedClass.containsKey(getClearedNameFromTypeMirror(type))) { - return unwantedClass.get(getClearedNameFromTypeMirror(type)); - } - } - if (types.containsKey(getClearedNameFromTypeMirror(type))) { - - if (types.get(getClearedNameFromTypeMirror(type)).contains("List")) { - importList = true; - } - return types.get(getClearedNameFromTypeMirror(type)); - } - - if (getClearedNameFromTypeMirror(this.type.asType()).equals(getClearedNameFromTypeMirror(type))) { - return "\"" + getClassName((TypeElement) Main.typeUtils.asElement(type)) + "\""; - } - - if (withArg.containsKey(getClearedNameFromTypeMirror(type))) { - if (withArg.get(getClearedNameFromTypeMirror(type)).contains("List")) { - importList = true; - } else if (withArg.get(getClearedNameFromTypeMirror(type)).contains("Mapping")) { - importMapping = true; - } else if (withArg.get(getClearedNameFromTypeMirror(type)).contains("Set")) { - importSet = true; - } - - if (((DeclaredType) type).getTypeArguments().size() > 0) { - //Main.reporter.print(Diagnostic.Kind.NOTE, this.type + ", " + type + ": " + ((DeclaredType) type).getTypeArguments()); - StringBuilder sb = new StringBuilder(withArg.get(getClearedNameFromTypeMirror(type)) + "[" + getTypeMirrorName(((DeclaredType) type).getTypeArguments().get(0), false)); - for (int i = 1; i < ((DeclaredType) type).getTypeArguments().size(); i++) { - sb.append(", ").append(getTypeMirrorName(((DeclaredType) type).getTypeArguments().get(i), false)); - } - sb.append("]"); - //System.out.println(sb.toString()); - return sb.toString(); - } else { - System.out.println("ERROR: " + type); - return withArg.get(getClearedNameFromTypeMirror(type)) + "[]"; - } - } - return getClassName((TypeElement) Main.typeUtils.asElement(type)); - } - - /** - * @return class name with _ for inner class - */ - public static String getClassName(TypeElement type) { - StringBuilder s = new StringBuilder(type.getSimpleName()); - Element t2 = type.getEnclosingElement(); - while (t2.getKind() == ElementKind.INTERFACE || t2.getKind() == ElementKind.CLASS) { - s.insert(0, t2.getSimpleName() + "_"); - t2 = t2.getEnclosingElement(); - } - return s.toString(); - } - -} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/Main.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/Main.java deleted file mode 100644 index ab0176523..000000000 --- a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/Main.java +++ /dev/null @@ -1,268 +0,0 @@ -package com.jsmacrosce.doclet.tsdoclet; - -import com.sun.source.util.DocTrees; -import jdk.javadoc.doclet.Doclet; -import jdk.javadoc.doclet.DocletEnvironment; -import jdk.javadoc.doclet.Reporter; -import com.jsmacrosce.FileHandler; -import com.jsmacrosce.StringHelpers; -import com.jsmacrosce.doclet.options.IgnoredItem; -import com.jsmacrosce.doclet.options.OutputDirectory; -import com.jsmacrosce.doclet.options.Version; -import com.jsmacrosce.doclet.tsdoclet.parsers.AbstractParser; -import com.jsmacrosce.doclet.tsdoclet.parsers.ClassParser; -import com.jsmacrosce.doclet.tsdoclet.parsers.EventParser; -import com.jsmacrosce.doclet.tsdoclet.parsers.LibraryParser; - -import javax.lang.model.SourceVersion; -import javax.lang.model.element.*; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Elements; -import javax.tools.Diagnostic; -import java.io.File; -import java.io.IOException; -import java.util.*; - -import static com.jsmacrosce.doclet.tsdoclet.parsers.AbstractParser.shouldIgnore; -import static com.jsmacrosce.doclet.tsdoclet.parsers.ClassParser.mixinInterfaceMap; - -public class Main implements Doclet { - public static Reporter reporter; - public static FileHandler outputTS; - public static final PackageTree classes = new PackageTree("Packages"); - public static DocTrees treeUtils; - public static Elements elementUtils; - public static final Map enumTypes = new TreeMap<>(); - private final Map filterableEvents = new TreeMap<>(); - - public static final List includedClassPath = List.of( - "com.jsmacrosce.jsmacros.client.api.helpers.", - "com.jsmacrosce.jsmacros.client.api.classes.inventory." - ); - - @Override - public void init(Locale locale, Reporter reporter) { - Main.reporter = reporter; - } - - @Override - public String getName() { - return "TypeScript Generator"; - } - - @SuppressWarnings("SpellCheckingInspection") - @Override - public Set getSupportedOptions() { - return Set.of( - new Version(), - new OutputDirectory(), - new IgnoredItem("-doctitle", 1), - new IgnoredItem("-notimestamp", 0), - new IgnoredItem("-windowtitle", 1) - ); - } - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.RELEASE_16; - } - - @Override - public boolean run(DocletEnvironment environment) { - Set elements = environment.getIncludedElements(); - treeUtils = environment.getDocTrees(); - elementUtils = environment.getElementUtils(); - - AbstractParser.initObjectElement(); - - Set libraryClasses = new TreeSet<>((a, b) -> String.CASE_INSENSITIVE_ORDER.compare(a.name, b.name)); - Set eventClasses = new TreeSet<>((a, b) -> String.CASE_INSENSITIVE_ORDER.compare(a.getName(), b.getName())); - - outputTS = new FileHandler(new File(OutputDirectory.outputDir, "JsMacrosCE-" + Version.version + ".d.ts")); - - if (!OutputDirectory.outputDir.exists() && !OutputDirectory.outputDir.mkdirs()) { - reporter.print(Diagnostic.Kind.ERROR, "Failed to create version dir\n"); - return false; - } - - if (outputTS.getFile().exists() && !outputTS.getFile().delete()) { - reporter.print(Diagnostic.Kind.ERROR, "Failed to remove old ts output\n"); - return false; - } - - for (Element v : elements) if (v instanceof TypeElement e) { - for (AnnotationMirror annotationMirror : e.getAnnotationMirrors()) { - String annotationName = annotationMirror.getAnnotationType().asElement().getSimpleName().toString(); - switch (annotationName) { - case "Library" -> - libraryClasses.add(new LibraryParser(e, getAnnotationValue(annotationMirror).toString())); - case "Event" -> { - Boolean cancellableValue = (Boolean) getAnnotationValue(annotationMirror, "cancellable"); - boolean cancellable = Boolean.TRUE.equals(cancellableValue); - String name = getAnnotationValue(annotationMirror).toString(); - eventClasses.add(new EventParser(e, name, cancellable)); - DeclaredType filterer = (DeclaredType) getAnnotationValue(annotationMirror, "filterer"); - if (filterer != null) { - String filtererName = filterer.asElement().getSimpleName().toString(); - if (!filtererName.equals("EventFilterer")) { - classes.addClass(filterer.asElement()); - filterableEvents.put(name, filtererName); - } - } - } - case "Mixin" -> { - List interfaces = e.getInterfaces().stream() - .filter(t -> t.getKind() == TypeKind.DECLARED) - .map(t -> (TypeElement) ((DeclaredType) t).asElement()) - .filter(i -> !shouldIgnore(i)) - .toList(); - if (interfaces.isEmpty()) continue; - - @SuppressWarnings("unchecked") - List targets = (List) getAnnotationValue(annotationMirror); - if (targets == null || targets.isEmpty()) continue; - - for (AnnotationValue target : targets) { - TypeMirror type = (TypeMirror) target.getValue(); - if (type.getKind() != TypeKind.DECLARED) continue; - - TypeElement el = (TypeElement) ((DeclaredType) type).asElement(); - mixinInterfaceMap.computeIfAbsent(el, k -> new HashSet<>()).addAll(interfaces); - } - } - } - } - String qualifiedName = e.getQualifiedName().toString(); - if (includedClassPath.stream().anyMatch(qualifiedName::startsWith)) { - classes.addClass(e); - } - if (e.getSimpleName().contentEquals("EventContainer")) { - classes.addClass(e); - System.out.println(e); - } - } - - try { - // `\n\` to prevent java compiler from trimming the string - outputTS.append( - """ - \n\ - /** - * The global context \n\ - * If you're trying to access the context in {@link JsMacros.on}, \n\ - * use the second param of callback - */ - declare const context: EventContainer; - /** - * Assert and convert event type: - * ```js - * JsMacros.assertEvent(event, 'Service') - * ``` - * If the type doesn't convert, that means the event type doesn't have any properties - */ - declare const event: Events.BaseEvent; - declare const file: Packages.java.io.File; - - declare namespace Events { - - interface BaseEvent extends JavaObject { - - getEventName(): string; - - } - - interface Cancellable { - - cancel(): void; - - }""" - ); - for (EventParser event : eventClasses) { - outputTS.append("\n\n" + StringHelpers.tabIn(event.genTSInterface())); - } - - outputTS.append("\n\n}\n\ninterface EventFilterers {\n"); - for (String name : filterableEvents.keySet()) { - outputTS.append("\n ").append(name) - .append(": ").append(filterableEvents.get(name)).append(";"); - } - - // for type-safe event listener - outputTS.append("\n\n}\n\ninterface Events {\n"); - for (EventParser event : eventClasses) { - outputTS.append("\n ").append(event.getName()) - .append(": Events.").append(event.getName()).append(";"); - } - outputTS.append("\n\n}"); - - for (LibraryParser lib : libraryClasses) { - outputTS.append("\n\n").append(lib.genTSInterface()); - } - - outputTS.append("\n\ndeclare ").append(classes.genTSTree()).append("\n"); - - // short alias of jsmacros types, for jsdoc / type casting / type annotation and more - // also used by some DocletReplace annotations - Set duplicateCheck = new HashSet<>(); - Set sorter = new TreeSet<>(); - for (ClassParser clz : classes.getWagClasses()) { - if (!duplicateCheck.add(clz.getClassName(false))) continue; - clz.isPackage = false; // to trick it transfer full type - sorter.add("\ntype " + clz.getClassName(true, true) + " = " + - clz.getQualifiedType() + ";"); - clz.isPackage = true; - } - outputTS.append(String.join("", sorter)); - - // append number enums here because they are very unlikely to change - //noinspection SpellCheckingInspection - outputTS.append( - """ - \n - // Enum types - type Bit = 1 | 0; - type Trit = 2 | Bit; - type Dit = 3 | Trit; - type Pentit = 4 | Dit; - type Hexit = 5 | Pentit; - type Septit = 6 | Hexit; - type Octit = 7 | Septit; - - type Side = Hexit; - type HotbarSlot = Octit | 8; - type HotbarSwapSlot = HotbarSlot | OffhandSlot; - type ClickSlotButton = HotbarSwapSlot | 9 | 10; - type OffhandSlot = 40; - - """ - ); - - for (Map.Entry ent : enumTypes.entrySet()) { - outputTS.append("type ").append(ent.getKey()).append(" = ").append(ent.getValue()); - if (!ent.getValue().contains("\n")) outputTS.append(";\n"); - } - - } catch (IOException e) { - e.printStackTrace(); - return false; - } - - return true; - } - - public static Object getAnnotationValue(AnnotationMirror annotation) { - return getAnnotationValue(annotation, "value"); - } - - public static Object getAnnotationValue(AnnotationMirror annotation, String key) { - for (Map.Entry el : annotation.getElementValues().entrySet()) { - if (el.getKey().getSimpleName().contentEquals(key)) { - return el.getValue().getValue(); - } - } - return null; - } - -} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/PackageTree.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/PackageTree.java deleted file mode 100644 index 3761f6ad1..000000000 --- a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/PackageTree.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.jsmacrosce.doclet.tsdoclet; - -import com.jsmacrosce.StringHelpers; -import com.jsmacrosce.doclet.tsdoclet.parsers.AbstractParser; -import com.jsmacrosce.doclet.tsdoclet.parsers.ClassParser; - -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; -import java.util.*; -import java.util.stream.Stream; - -public class PackageTree { - public final static Set predefinedClasses = Set.of( - "java.lang.Class", "java.lang.Object", "java.lang.Iterable", - "java.lang.Throwable", "java.lang.StackTraceElement", - "java.util.Collection", "java.util.List", "java.util.Map", "java.util.Set", - "java.io.Serializable", "java.io.File", "java.net.URL", "java.net.URI" - ); - // List of reserved keywords #2536 - // https://github.com/microsoft/TypeScript/issues/2536 - public final static Set tsReservedWords = Set.of( - "break", "case", "catch", "class", "const", "continue", "debugger", "default", - "delete", "do", "else", "enum", "export", "extends", "false", "finally", "for", - "function", "if", "import", "in", "instanceof", "new", "null", "return", "super", - "switch", "this", "throw", "true", "try", "typeof", "var", "void", "while", "with" - ); - private String pkgName; - private final Map children = new TreeMap<>(); - private final Set classes = new LinkedHashSet<>(); - private final Map compiledClasses = new TreeMap<>((a, b) -> String.CASE_INSENSITIVE_ORDER.compare(a.className, b.className)); - - public boolean dirty = true; - - public PackageTree(String pkgName) { - this.pkgName = pkgName; - } - - public void addClass(Element clazz) { - if (AbstractParser.shouldIgnore(clazz)) return; - Stack enclosing = new Stack<>(); - Element enclose = clazz; - - while (enclose != null && enclose.getKind() != ElementKind.PACKAGE) enclose = enclose.getEnclosingElement(); - - if (enclose != null) { - String[] pkg = ((PackageElement)enclose).getQualifiedName().toString().split("\\."); - for (int i = pkg.length - 1; i >= 0; --i) { - if (!pkg[i].isEmpty()) enclosing.push(pkg[i]); - } - String path = String.join(".", pkg); - if (predefinedClasses.contains(path + "." + clazz.getSimpleName())) { - return; - } - if (path.startsWith("org.joml")) return; - } - addClassInternal(enclosing, clazz); - } - - private boolean addClassInternal(Stack enclosing, Element clazz) { - if (enclosing.empty()) { - this.dirty = classes.add(new ClassParser((TypeElement) clazz)) || this.dirty; - } else { - this.dirty = children.computeIfAbsent(enclosing.pop(), PackageTree::new) - .addClassInternal(enclosing, clazz) || this.dirty; - } - return this.dirty; - } - - private void prepareTSTree() { - while (this.dirty) { - this.dirty = false; - for (ClassParser aClass : Set.copyOf(classes)) { - compiledClasses.computeIfAbsent(aClass, ClassParser::genTSInterface); - } - for (PackageTree value : Set.copyOf(children.values())) { - value.prepareTSTree(); - } - } - } - - public String genTSTree() { - prepareTSTree(); - return genTSTreeIntern().replaceAll("\\bPackages\\.", ""); - } - - private String genTSTreeIntern() { - if (classes.isEmpty() && children.size() == 1) { - PackageTree onlyChild = children.values().iterator().next(); - if (!tsReservedWords.contains(onlyChild.pkgName)) { - onlyChild.pkgName = pkgName + "." + onlyChild.pkgName; - return onlyChild.genTSTreeIntern(); - } - } - - StringBuilder exports = new StringBuilder(); - // string builder for elements that needs export - StringBuilder se = new StringBuilder("namespace "); - if (tsReservedWords.contains(pkgName)) { - System.out.println("Escaped typescript reserved word: " + pkgName + " -> _" + pkgName); - se.append("_"); - } - se.append(pkgName).append(" {"); - // string builder for elements that doesn't need export - StringBuilder sn = new StringBuilder(se); - - for (Map.Entry ent : compiledClasses.entrySet()) { - exports.append(ent.getKey().getClassName(false)).append(",\n"); - se.append("\n\n").append(StringHelpers.tabIn(ent.getValue())); - } - for (PackageTree value : children.values()) { - if (tsReservedWords.contains(value.pkgName)) { - exports.append("_").append(value.pkgName).append(" as ").append(value.pkgName).append(",\n"); - se.append("\n\n").append(StringHelpers.tabIn(value.genTSTreeIntern())); - } else sn.append("\n\n").append(StringHelpers.tabIn(value.genTSTreeIntern())); - } - - if (!exports.isEmpty()) { - exports.setLength(exports.length() - ",\n".length()); - se.append("\n\n export {"); - if (exports.length() < 64) { - se.append(" ").append(exports.toString().replaceAll("\n", " ")).append(" }"); - } else { - se.append("\n") - .append(StringHelpers.tabIn(exports.toString(), 2)) - .append("\n }"); - } - se.append("\n\n}"); - } else se.setLength(0); - - if (!sn.toString().endsWith(" {")) { - if (se.isEmpty()) se = sn; - else se.append("\n").append(sn); - se.append("\n\n}"); - } - - return se.toString(); - } - - public List getWagClasses() { - return children.get("com").children.get("jsmacrosce").streamAllClasses().toList(); - } - - private Stream streamAllClasses() { - return Stream.concat(classes.stream(), children.values().stream().flatMap(PackageTree::streamAllClasses)); - } - -} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/AbstractParser.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/AbstractParser.java deleted file mode 100644 index 0c5a32bdd..000000000 --- a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/AbstractParser.java +++ /dev/null @@ -1,592 +0,0 @@ -package com.jsmacrosce.doclet.tsdoclet.parsers; - -import com.sun.source.doctree.*; -import org.jetbrains.annotations.NotNull; -import com.jsmacrosce.StringHelpers; -import com.jsmacrosce.doclet.*; -import com.jsmacrosce.doclet.tsdoclet.Main; -import com.jsmacrosce.doclet.tsdoclet.PackageTree; - -import javax.lang.model.element.*; -import javax.lang.model.type.*; -import java.util.*; -import java.util.stream.Collectors; - -import static com.jsmacrosce.doclet.tsdoclet.PackageTree.tsReservedWords; - -public abstract class AbstractParser { - static final public Set javaAliases = Set.of( - "java.lang.Array", - "java.lang.Class", - "java.util.Collection", - "java.util.List", - "java.util.Map", - "java.util.Set" - ); - static final public Map javaNumberType = Map.of( - "java.lang.Integer", "int", - "java.lang.Float", "float", - "java.lang.Long", "long", - "java.lang.Short", "short", - "java.lang.Character", "char", - "java.lang.Byte", "byte", - "java.lang.Double", "double", - "java.lang.Number", "number" - ); - static final public Map functionalInterfaces = Map.of( - "java.util.function.Consumer", "MethodWrapper<$0>", - "java.util.function.BiConsumer", "MethodWrapper<$0, $1>", - "java.util.function.Function", "MethodWrapper<$0, any, $1>", - "java.util.function.BiFunction", "MethodWrapper<$0, $1, $2>", - "java.util.function.Predicate", "MethodWrapper<$0, any, boolean>", - "java.util.function.BiPredicate", "MethodWrapper<$0, $1, boolean>", - "java.util.function.Supplier", "MethodWrapper", - "java.util.Comparator", "MethodWrapper<$0, $0, int>", - "java.lang.Runnable", "MethodWrapper" - ); - - private static final Set loggedTypes = new HashSet<>(); - private final String path; - protected final TypeElement type; - public boolean isPackage = true; - private transient boolean returnsSelf = false; - - public static TypeElement objectElement; - public static Set objectMethods; - public static Set objectMethodNames; - - public static void initObjectElement() { - objectElement = Main.elementUtils.getTypeElement("java.lang.Object"); - objectMethods = objectElement.getEnclosedElements().stream() - .filter(e -> e.getKind() == ElementKind.METHOD && checkModifier(e, false)) - .map(e -> (ExecutableElement) e) - .collect(Collectors.toUnmodifiableSet()); - objectMethodNames = objectMethods.stream() - .map(ExecutableElement::getSimpleName) - .collect(Collectors.toUnmodifiableSet()); - } - - public AbstractParser(TypeElement type) { - this.type = type; - Element elem = type.getEnclosingElement(); - while (!(elem instanceof PackageElement)) elem = elem.getEnclosingElement(); - this.path = ((PackageElement) elem).getQualifiedName().toString(); - } - - public String genFields(Set fields) { - final StringBuilder s = new StringBuilder(); - for (Element field : fields) { - if (checkModifier(field, false) && !shouldIgnore(field)) { - s.append(genField(field)).append("\n"); - } - } - return s.toString(); - } - - public String genStaticFields(Set fields) { - final StringBuilder s = new StringBuilder(); - for (Element field : fields) { - if (checkModifier(field, true) && !shouldIgnore(field)) { - s.append(genField(field)).append("\n"); - } - } - return s.toString(); - } - - public String genMethods(Set methods) { - final StringBuilder s = new StringBuilder(); - for (Element method : methods) { - if (checkModifier(method, false) && !shouldIgnore(method)) { - s.append(genMethod((ExecutableElement) method)).append("\n"); - } - } - return s.toString(); - } - - public String genStaticMethods(Set methods) { - final StringBuilder s = new StringBuilder(); - for (Element method : methods) { - if (checkModifier(method, true) && !shouldIgnore(method)) { - s.append(genMethod((ExecutableElement) method)).append("\n"); - } - } - return s.toString(); - } - - public String genConstructors(Set methods) { - final StringBuilder s = new StringBuilder(); - for (Element method : methods) { - if (!method.getModifiers().contains(Modifier.PUBLIC)) continue; - if (shouldIgnore(method)) continue; - s.append(genConstructor((ExecutableElement) method)).append("\n"); - } - return s.toString(); - } - - public String genField(Element field) { - StringBuilder s = new StringBuilder(); - s.append(genComment(field)); - - // modifiers - Set mods = field.getModifiers(); - if (mods.contains(Modifier.STATIC)) s.append("static "); - if (mods.contains(Modifier.FINAL)) s.append("readonly "); - - // name - s.append(field.getSimpleName()).append(": "); - - // type - DocletReplaceReturn replace = field.getAnnotation(DocletReplaceReturn.class); - if (replace != null) { - s.append(replace.value()); - } else { - s.append(transformType(field)); - if (isNullable(field)) s.append(" | null"); - } - - s.append(";"); - - return s.toString(); - } - - public String genMethod(ExecutableElement method) { - return genExecutable(method, false); - } - - public String genConstructor(ExecutableElement constructor) { - return genExecutable(constructor, true); - } - - public String genExecutable(ExecutableElement e, boolean isConstructor) { - final StringBuilder s = new StringBuilder(); - s.append(genComment(e)); - if (!isConstructor && e.getModifiers().contains(Modifier.STATIC)) s.append("static "); - - // name - s.append(isConstructor ? "constructor " : e.getSimpleName()); - - // type params - DocletReplaceTypeParams replace = e.getAnnotation(DocletReplaceTypeParams.class); - if (replace != null) { - if (!replace.value().isEmpty()) s.append("<").append(replace.value()).append(">"); - } else { - List typeParams = (isConstructor ? type : e).getTypeParameters(); - if (!typeParams.isEmpty()) { - s.append("<"); - for (TypeParameterElement param : typeParams) { - s.append(transformType(param)); - String ext = transformType(((TypeVariable) param.asType()).getUpperBound()); - if (!ext.equals("any")) { - s.append(" extends ").append(ext); - } - s.append(", "); - } - s.setLength(s.length() - ", ".length()); - s.append(">"); - } - } - - // params - s.append("("); - DocletReplaceParams replace2 = e.getAnnotation(DocletReplaceParams.class); - if (replace2 != null) { - s.append(replace2.value()); - } else { - List params = e.getParameters(); - if (!params.isEmpty()) { - VariableElement restParam = e.isVarArgs() ? params.get(params.size() - 1) : null; - for (VariableElement param : params) { - String name = param.getSimpleName().toString(); - if (restParam == param) { - s.append("..."); - if (tsReservedWords.contains(name)) s.append("_"); - s.append(name).append(": ").append("JavaVarArgs<").append(transformType(param, true)); - int sl2 = s.length() - "[]".length(); - if (s.substring(sl2).equals("[]")) s.setLength(sl2); - else System.out.println("varargs type is not array?? " + type.getSimpleName() + "." + e.getSimpleName()); - if (isNullable(param)) s.append(" | null"); - s.append(">"); - } else { - if (tsReservedWords.contains(name)) s.append("_"); - s.append(name).append(": ").append(transformType(param, true)); - if (isNullable(param)) s.append(" | null"); - } - s.append(", "); - } - s.setLength(s.length() - ", ".length()); - } - } - s.append(")"); - - // return type - if (!isConstructor) { - s.append(": "); - DocletReplaceReturn replace3 = e.getAnnotation(DocletReplaceReturn.class); - if (replace3 != null) { - transformType(e.getReturnType()); // to add type to the Packages - s.append(replace3.value()); - } else if (returnsSelf && type.asType().equals(e.getReturnType())) { - s.append("this"); - } else { - s.append(transformType(e.getReturnType())); - if (isNullable(e)) s.append(" | null"); - } - } - - s.append(";"); - - return s.toString(); - } - - public String transformType(Element elem) { - return transformType(elem.asType(), false, false); - } - - public String transformType(Element elem, boolean isParamType) { - return transformType(elem.asType(), isParamType, false); - } - - @SuppressWarnings("unused") - public String transformType(Element elem, boolean isParamType, boolean isExtends) { - return transformType(elem.asType(), isParamType, isExtends); - } - - public String transformType(TypeMirror type) { - return transformType(type, false, false); - } - - @SuppressWarnings("unused") - public String transformType(TypeMirror type, boolean isParamType) { - return transformType(type, isParamType, false); - } - - public String transformType(TypeMirror type, boolean isParamType, boolean isExtends) { - switch (type.getKind()) { - case BOOLEAN -> { - return "boolean"; - } - case BYTE -> { - return isParamType ? "byte" : "number"; - } - case SHORT -> { - return isParamType ? "short" : "number"; - } - case INT -> { - return isParamType ? "int" : "number"; - } - case LONG -> { - return isParamType ? "long" : "number"; - } - case FLOAT -> { - return isParamType ? "float" : "number"; - } - case DOUBLE -> { - return isParamType ? "double" : "number"; - } - case CHAR -> { - return isParamType ? "char" : "number"; - } - case VOID, NONE -> { - return "void"; - } - case DECLARED -> { - final Element typeElement = ((DeclaredType) type).asElement(); - StringBuilder rawType = new StringBuilder(typeElement.getSimpleName().toString()); - Element enclosing = typeElement.getEnclosingElement(); - // full class name - while (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { - rawType.insert(0, enclosing.getSimpleName().toString() + "$"); - enclosing = enclosing.getEnclosingElement(); - } - - String classpath = ((QualifiedNameable) enclosing).getQualifiedName().toString(); - // check Event and Library type (probably none Library) - if (classpath.startsWith("com.jsmacrosce.")) { - Optional special = typeElement.getAnnotationMirrors().stream() - .map(a -> switch (a.getAnnotationType().asElement().getSimpleName().toString()) { - case "Event" -> "Events." + Main.getAnnotationValue(a); - case "Library" -> "typeof " + Main.getAnnotationValue(a); - default -> null; - }) - .filter(Objects::nonNull) - .findFirst(); - if (special.isPresent()) return special.get(); - } - - // detect types defined in Graal.d.ts - boolean aliased = false; - if (!isExtends && javaAliases.contains(classpath + "." + rawType)) { - aliased = true; - rawType.insert(0, "Java"); - if (isParamType && rawType.toString().equals("JavaClass")) rawType.append("Arg"); - } else rawType.insert(0, classpath + "."); - - // type params - List params = ((DeclaredType) type).getTypeArguments(); - if (isParamType && functionalInterfaces.containsKey(rawType.toString())) { - // convert to MethodWrapper - String res = functionalInterfaces.get(rawType.toString()); - if (!params.isEmpty()) { - int size = params.size(); - for (int i = 0; i < size; i++) { - res = res.replace("$" + i, transformType(params.get(i), true, false)); - } - } - return res; - } - - if (!params.isEmpty()) { - rawType.append("<"); - for (TypeMirror param : params) { - rawType.append(transformType(param, isParamType, isExtends)).append(", "); - } - rawType.setLength(rawType.length() - 2); - rawType.append(">"); - } - - String res = rawType.toString(); - - // comment out minecraft types because it's obfuscated - // + including minecraft types will make the file large asf - // + don't even know how to get obfuscated names in doclet environment - if (res.startsWith("net.minecraft.")) { - return "/* " + res.replaceAll("/\\* ", "").replaceAll(" \\*/(?: any)?", "") + " */ any"; - } - - // check BaseEvent - if (res.equals("com.jsmacrosce.jsmacros.core.event.BaseEvent")) { - return "Events.BaseEvent"; - } - - // register this type to the package tree for further type generation - Main.classes.addClass(((DeclaredType) type).asElement()); - - // primitive/aliased check - if (!isExtends && res.startsWith("java.lang")) { - if (javaNumberType.containsKey(res)) { - return isParamType ? javaNumberType.get(res) : "number"; - } - - switch (res) { - case "java.lang.Boolean" -> { return "boolean"; } - case "java.lang.String" -> { return "string"; } - case "java.lang.Object" -> { return "any"; } - } - } else { - if (aliased) return res; - } - - // insert root name to be able to actually reference this type - // if it's redundant, the regex in PackageTree#genTSTree() will take care of it - if (!isPackage || !res.startsWith(this.path + ".")) return "Packages." + res; - // at this point, res must be starts with this.path, because of the condition above - - String withoutTypeParams = res.contains("<") ? res.substring(0, res.indexOf("<")) : res; - - // if res isn't in the same package as this.type - if (withoutTypeParams.substring(this.path.length() + 1).contains(".")) return "Packages." + res; - // if res is defined in Graal.d.ts, don't trim the path (as the next line did) - // because otherwise this won't be able to reference it - if (PackageTree.predefinedClasses.contains(withoutTypeParams)) return res; - // trim the path - return res.substring(this.path.length() + 1); - } - case TYPEVAR -> { - return ((TypeVariable) type).asElement().getSimpleName().toString(); - } - case ARRAY -> { - String component = transformType(((ArrayType) type).getComponentType(), isParamType, isExtends); - return isParamType ? component + "[]" : "JavaArray<" + component + ">"; - } - case WILDCARD -> { - TypeMirror bound = ((WildcardType) type).getExtendsBound(); - if (bound == null) bound = ((WildcardType) type).getSuperBound(); - return bound == null ? "any" : transformType(bound, isParamType, isExtends); - } - case INTERSECTION -> { - StringBuilder s = new StringBuilder("("); - for (TypeMirror t : ((IntersectionType) type).getBounds()) { - s.append(transformType(t, isParamType, isExtends)).append(" & "); - } - s.setLength(s.length() - " & ".length()); - s.append(")"); - return s.toString(); - } - case UNION -> { - StringBuilder s = new StringBuilder("("); - for (TypeMirror t : ((UnionType) type).getAlternatives()) { - s.append(transformType(t, isParamType, isExtends)).append(" | "); - } - s.setLength(s.length() - " | ".length()); - s.append(")"); - return s.toString(); - } - } - throw new UnsupportedOperationException(String.valueOf(type.getKind())); - } - - public String genComment(Element element) { - checkEnumType(element); - returnsSelf = false; - - DocCommentTree tree = Main.treeUtils.getDocCommentTree(element); - boolean isDeprecated = Main.elementUtils.isDeprecated(element); - if (tree == null) return isDeprecated ? "/** @deprecated */\n" : ""; - - StringBuilder b = new StringBuilder(); - b.append(genCommentDesc(tree.getFullBody()).replaceAll("(?<=[.,:;>]) ?\n", " \n")); - - for (DocTree blockTag : tree.getBlockTags()) { - switch (blockTag.getKind()) { - case SEE -> { - for (DocTree see : ((SeeTree) blockTag).getReference()) { - b.append("\n@see "); - if (see.getKind() == DocTree.Kind.REFERENCE) { - b.append(convertSignature(((ReferenceTree) see).getSignature())); - } else { - b.append(see); - } - } - } - case PARAM -> { - ParamTree param = (ParamTree) blockTag; - List description = param.getDescription(); - if (!description.isEmpty()) { - b.append(param.isTypeParameter() ? "\n@template " : "\n@param ") - .append(param.getName().getName()).append(" ") - .append(genCommentDesc(description)); - } - } - case RETURN -> { - List description = ((ReturnTree) blockTag).getDescription(); - if (!description.isEmpty()) { - String desc = genCommentDesc(description); - if (desc.startsWith("self") && (desc.length() == "self".length() || desc.charAt("self".length()) == ' ')) returnsSelf = true; - b.append("\n@return "); - // to prevent vscode from parsing the description as type - // typescript already provided the type, so assign it as any is fine - if (desc.startsWith("{")) b.append("{*} "); - b.append(desc); - } - } - case SINCE -> b.append("\n@since ").append(genCommentDesc(((SinceTree) blockTag).getBody())); - case DEPRECATED -> b.append("\n@deprecated ").append(genCommentDesc(((DeprecatedTree) blockTag).getBody())); - default -> b.append("\n").append(blockTag); - } - } - - String fin = b.toString().trim() - .replaceAll("\n

    ", "\n") - .replaceAll("", "```") - // is there any better way to parse html tag? - .replaceAll("((?:\n|.)*?)", "[$2]($1)") - .replaceAll("<", "<") - .replaceAll(">", ">"); - if (fin.isBlank()) return isDeprecated ? "/** @deprecated */\n" : ""; - - if (isDeprecated && !b.toString().contains("@deprecated")) { - fin += "\n@deprecated"; - } - - if (fin.startsWith("@since") && !fin.contains("\n")) return "/** " + fin + " */\n"; - - return ("\n/**\n" + - StringHelpers.addToLineStarts(fin, " * ") + - "\n */\n").replaceAll("\n \\* +\n", "\n *\n"); - } - - private String genCommentDesc(List desc) { - final StringBuilder s = new StringBuilder(); - for (DocTree docTree : desc) { - switch (docTree.getKind()) { - case LINK, LINK_PLAIN -> { - String sig = ((LinkTree) docTree).getReference().getSignature(); - if (javaNumberType.containsKey(sig)) s.append(javaNumberType.get(sig)); - else if (sig.equals("java.lang.String")) s.append("string"); - else if (sig.equals("java.lang.Boolean")) s.append("boolean"); - else { - String str = convertSignature(sig); - int i = str.indexOf("<"); - if (i == -1) i = str.indexOf("("); - s.append("{@link "); - if (i == -1) { - s.append(str).append("}"); - } else { - s.append(str, 0, i).append("}").append(str.substring(i)); - } - } - } - case CODE -> s.append("`").append(((LiteralTree) docTree).getBody()).append("`"); - default -> s.append(docTree); - } - } - return s.toString(); - } - - private String convertSignature(String sig) { - if (sig.matches("^com\\.jsmacrosce\\.[^#]+\\w$")) return sig.replaceFirst("^.+\\.(?=[^.]+$)", ""); - if (sig.matches("^\\w+\\.(?:\\w+\\.)+[\\w$_]+$")) return "Packages." + sig; -// sig = sig.replaceFirst("(?<=\\S)(?=[<(])", " "); - return sig.startsWith("#") - ? sig.substring(1) - : sig.replaceFirst("^(?:com\\.jsmacrosce\\.jsmacros\\.(?:client\\.api|core)\\.library\\.impl\\.)?F([A-Z]\\w+)#", "$1.").replaceFirst("#", "."); - } - - public abstract String genTSInterface(); - - public String getQualifiedType() { - return isPackage ? this.path + "." + transformType(type) : transformType(type); - } - - public static void checkEnumType(Element element) { - DocletDeclareType enumType = element.getAnnotation(DocletDeclareType.class); - if (enumType == null) return; - - if (Main.enumTypes.containsKey(enumType.name()) - && !loggedTypes.contains(enumType.name()) - && !Objects.equals(Main.enumTypes.get(enumType.name()), enumType.type()) - ) { - System.out.println("Duplicate enum type name: " + enumType.name()); - loggedTypes.add(enumType.name()); - } - Main.enumTypes.put(enumType.name(), enumType.type()); - } - - public static boolean checkModifier(@NotNull Element e, boolean shouldBeStatic) { - Set mods = e.getModifiers(); - return mods.contains(Modifier.PUBLIC) && mods.contains(Modifier.STATIC) == shouldBeStatic; - } - - public static boolean shouldIgnore(@NotNull Element e) { - return e.getAnnotation(DocletIgnore.class) != null; - } - - @SuppressWarnings("BooleanMethodIsAlwaysInverted") - protected boolean isObjectMethod(Element m) { - if (!objectMethodNames.contains(m.getSimpleName()) - || m.getKind() != ElementKind.METHOD - || Main.treeUtils.getDocCommentTree(m) != null) return false; - for (ExecutableElement om : objectMethods) { - if (Main.elementUtils.overrides((ExecutableElement) m, om, type)) return true; - } - return false; - } - - public boolean isNullable(Element e) { - return e.getAnnotationMirrors().stream() - .anyMatch(a -> a.getAnnotationType().asElement().getSimpleName().contentEquals("Nullable")); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof AbstractParser that)) return false; - return type.equals(that.type); - } - - @Override - public int hashCode() { - return Objects.hash(type); - } - -} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/ClassParser.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/ClassParser.java deleted file mode 100644 index 835fbe199..000000000 --- a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/ClassParser.java +++ /dev/null @@ -1,324 +0,0 @@ -package com.jsmacrosce.doclet.tsdoclet.parsers; - -import com.jsmacrosce.StringHelpers; -import com.jsmacrosce.doclet.tsdoclet.Main; - -import javax.lang.model.element.*; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVariable; -import java.util.*; - -public class ClassParser extends AbstractParser { - private static final Set objectAliases = Set.of("void", "any", "JavaObject", "Object"); - public static final Map> mixinInterfaceMap = new LinkedHashMap<>(); - public final String className; - private final Set superMcClasses = new LinkedHashSet<>(); - private boolean doesDirectExtendMc = false; - private Set mixinInterfaces; - - public ClassParser(TypeElement type) { - super(type); - StringBuilder s = new StringBuilder(type.getSimpleName()); - - Element enclosing = type.getEnclosingElement(); - while (enclosing.getKind() == ElementKind.INTERFACE || enclosing.getKind() == ElementKind.CLASS) { - s.insert(0, enclosing.getSimpleName() + "$"); - enclosing = enclosing.getEnclosingElement(); - } - - className = s.toString(); - } - - public String getClassName(boolean typeParams) { - return getClassName(typeParams, false); - } - - public String getClassName(boolean typeParams, boolean defaultToAny) { - if (!typeParams) return className; - StringBuilder s = new StringBuilder(className); - - List params = this.type.getTypeParameters(); - if (params != null && !params.isEmpty()) { - s.append("<"); - for (TypeParameterElement param : params) { - s.append(transformType(param)); - String ext = transformType(((TypeVariable) param.asType()).getUpperBound()); - if (!ext.endsWith("any")) { - s.append(" extends ").append(ext); - if (defaultToAny) s.append(" = any"); - } else if (ext.startsWith("/* net.minecraft.")) { - s.append(" = ").append(ext); - } else if (defaultToAny) s.append(" = any"); - s.append(", "); - } - s.setLength(s.length() - ", ".length()); - s.append(">"); - } - - return s.toString(); - } - - private String getClassHeader() { - StringBuilder s = new StringBuilder("static readonly class: JavaClass<"); - s.append(getClassName(false)); - - int params = type.getTypeParameters().size(); - if (params > 0) { - s.append("<").append( - ", any".repeat(params).substring(", ".length()) - ).append(">"); - } - - s.append(">;\n/** @deprecated */ static prototype: undefined;\n"); - return s.toString(); - } - - private String buildExtends() { - StringBuilder s = new StringBuilder(" extends "); - - String sup = transformType(type.getSuperclass(), false, true); - if (objectAliases.contains(sup)) { - s.append("java.lang.Object"); - } else if (sup.startsWith("/* net.minecraft.")) { - s.append(sup, 0, sup.length() - "any".length()).append("java.lang.Object"); - } else { - s.append(sup); - } - - return s.toString(); - } - - private String buildImplements() { - Set interfaces = new HashSet<>(type.getInterfaces()); - if (doesDirectExtendMc) for (TypeElement e : mixinInterfaces) { - interfaces.add(e.asType()); - System.out.println("Added mixin interface " + e.getSimpleName() + " on class " + type.getSimpleName()); - } - if (interfaces.isEmpty()) return ""; - - Set strings = new TreeSet<>(); - for (TypeMirror ifa : interfaces) { - strings.add(transformType(ifa, false, true)); - } - - StringBuilder s = new StringBuilder(" extends "); - for (String sup : strings) { - if (sup.startsWith("/* net.minecraft.")) { - s.append(sup, 0, sup.length() - "any".length()).append("JavaObject"); - } else { - s.append(sup); - } - s.append(", "); - } - s.setLength(s.length() - ", ".length()); - - return s.toString(); - } - - private void getSuperClasses(Set set, TypeElement c) { - if (!c.getKind().isInterface()) { - TypeMirror t = c.getSuperclass(); - if (t instanceof DeclaredType) { - TypeElement e = (TypeElement) ((DeclaredType) t).asElement(); - if (isMinecraftClass(t)) { - superMcClasses.add(e); - if (doesDirectExtendMc) { - Set ifs = mixinInterfaceMap.get(e); - if (ifs != null) { - set.addAll(ifs); - mixinInterfaces.addAll(ifs); - } - } - } else { - set.add(e); - } - getSuperClasses(set, e); - } - } - - for (TypeMirror t : c.getInterfaces()) { - TypeElement e = (TypeElement) ((DeclaredType) t).asElement(); - if (isMinecraftClass(t)) { - superMcClasses.add(e); - } else { - set.add(e); - } - getSuperClasses(set, e); - } - } - - private boolean isObfuscated(Element m) { - return isObfuscated(m, type); - } - - private boolean isObfuscated(Element m, TypeElement type) { - // probably doesn't cover edge cases because this annotation is optional - if (m.getAnnotation(Override.class) == null) return false; - if (m.getKind() != ElementKind.METHOD) return false; - for (TypeElement clz : superMcClasses) { - for (Element e : clz.getEnclosedElements()) { - if (e.getKind() != ElementKind.METHOD) continue; - if (overrides(m, e, type)) return true; - } - } - return false; - } - - private boolean isMinecraftClass(TypeMirror type) { - if (type.getKind() != TypeKind.DECLARED) return false; - Element e = ((DeclaredType) type).asElement(); - do { - e = e.getEnclosingElement(); - } while (e.getKind() == ElementKind.CLASS || e.getKind() == ElementKind.INTERFACE); - - return ((PackageElement) e).getQualifiedName().toString().startsWith("net.minecraft."); - } - - private boolean overrides(Element overrider, Element overridden) { - return overrides(overrider, overridden, type); - } - - private boolean overrides(Element overrider, Element overridden, TypeElement type) { - return Main.elementUtils.overrides( - (ExecutableElement) overrider, - (ExecutableElement) overridden, - type - ); - } - - @Override - public String genTSInterface() { - superMcClasses.clear(); - Set superClasses = new LinkedHashSet<>(); - Set fields = new LinkedHashSet<>(); - Set methods = new LinkedHashSet<>(); - Set constructors = new LinkedHashSet<>(); - - if (isMinecraftClass(type.getSuperclass())) { - doesDirectExtendMc = true; - mixinInterfaces = new LinkedHashSet<>(); - } - getSuperClasses(superClasses, type); - - for (Element el : type.getEnclosedElements()) { - if (el.getModifiers().contains(Modifier.PUBLIC)) { - switch (el.getKind()) { - case METHOD -> { - if (!isObfuscated(el) && !isObjectMethod(el)) methods.add(el); - } - case FIELD, ENUM_CONSTANT -> fields.add(el); - case CONSTRUCTOR -> constructors.add(el); - } - } - } - - Set methodNames = new LinkedHashSet<>(); - for (Element m : methods) { - if (!m.getModifiers().contains(Modifier.STATIC)) { - methodNames.add(m.getSimpleName()); - } - } - - // add super methods with same name to this class because js extending works a bit different - if (!methodNames.isEmpty()) { - Set superMethods = new LinkedHashSet<>(); - for (TypeElement clz : superClasses) { - outer: - for (Element e : clz.getEnclosedElements()) { - if (e.getKind() != ElementKind.METHOD) continue; - if (e.getModifiers().contains(Modifier.STATIC)) continue; - Name name = e.getSimpleName(); - if (!methodNames.contains(name)) continue; - - // if this class's method overrides the method, continue outer - for (Element m : methods) { - if (!m.getSimpleName().equals(name)) continue; - if (overrides(m, e)) continue outer; - } - - // if the method already added to the set, continue outer - for (Element m : superMethods) { - if (!m.getSimpleName().equals(name)) continue; - if (overrides(m, e)) continue outer; - } - - if (!isObfuscated(e, clz)) superMethods.add(e); - } - } - if (!superMethods.isEmpty()) { - // try to insert methods by name - Set merged = new LinkedHashSet<>(); - Set superMethodNames = new LinkedHashSet<>(); - Name next = null; - for (Element m : superMethods) superMethodNames.add(m.getSimpleName()); - for (Element m : methods) { - if (next != null) { - if (m.getSimpleName().equals(next)) { - merged.add(m); - continue; - } - - for (Element sm : superMethods) { - if (sm.getSimpleName().equals(next)) merged.add(sm); - } - superMethodNames.remove(next); - next = null; - } - - Name name = m.getSimpleName(); - if (superMethodNames.contains(name)) next = name; - merged.add(m); - } - - if (next != null) { - for (Element sm : superMethods) { - if (sm.getSimpleName().equals(next)) merged.add(sm); - } - } - methods = merged; - } - } - - StringBuilder s = new StringBuilder(genComment(type)); - if (!s.isEmpty() && s.charAt(0) == '\n') s.deleteCharAt(0); - - String className = getClassName(true); - String temp; - if (type.getKind().isInterface()) { - s.append("abstract class ").append(className).append(" extends java.lang.Interface {\n") - .append(StringHelpers.tabIn(getClassHeader())); - if (!(temp = genStaticFields(fields)).isEmpty()) s.append("\n").append(StringHelpers.tabIn(temp)); - if (!(temp = genStaticMethods(methods)).isEmpty()) s.append("\n").append(StringHelpers.tabIn(temp)).append("\n"); - s.append("}\ninterface ").append(className).append(buildImplements()).append(" {\n"); - int len = s.length(); - if (!(temp = genFields(fields)).isEmpty()) s.append(StringHelpers.tabIn(temp)); - if (!(temp = genMethods(methods)).isEmpty()) s.append("\n").append(StringHelpers.tabIn(temp)).append("\n"); - if (len == s.length()) s.setLength(len - "\n".length()); - s.append("}"); - } else { - //noinspection SpellCheckingInspection - String constrs = genConstructors(constructors); - String implementS = buildImplements(); - if (!implementS.isEmpty()) s.append("interface ").append(className).append(implementS).append(" {}\n"); - if (constrs.isBlank()) s.append("abstract "); - s.append("class ").append(className).append(buildExtends()).append(" {\n") - .append(StringHelpers.tabIn(getClassHeader())); - if (!(temp = genStaticFields(fields)).isEmpty()) s.append("\n").append(StringHelpers.tabIn(temp)); - int len = s.length(); - if (!(temp = genStaticMethods(methods)).isEmpty()) s.append("\n").append(StringHelpers.tabIn(temp)); - if (!constrs.isBlank()) s.append("\n").append(StringHelpers.tabIn(constrs)); - if (!(temp = genFields(fields)).isEmpty()) { - s.append("\n").append(StringHelpers.tabIn(temp)); - len = s.length(); - } - if (!(temp = genMethods(methods)).isEmpty()) s.append("\n").append(StringHelpers.tabIn(temp)); - if (len != s.length()) s.append("\n"); - s.append("}"); - } - - return s.toString().replaceAll("\n\n\n+", "\n\n"); - } - -} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/EventParser.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/EventParser.java deleted file mode 100644 index 56b478770..000000000 --- a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/EventParser.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.jsmacrosce.doclet.tsdoclet.parsers; - -import com.jsmacrosce.StringHelpers; - -import javax.lang.model.element.Element; -import javax.lang.model.element.Name; -import javax.lang.model.element.TypeElement; -import java.util.*; - -public class EventParser extends AbstractParser { - protected final String name; - protected final boolean cancellable; - - public EventParser(TypeElement type, String name, boolean cancellable) { - super(type); - this.name = name; - this.isPackage = false; - this.cancellable = cancellable; - } - - public String getName() { - return name; - } - - @Override - public String genTSInterface() { - Set fields = new LinkedHashSet<>(); - Set methods = new LinkedHashSet<>(); - - for (Element el : type.getEnclosedElements()) { - if (checkModifier(el, false)) { - switch (el.getKind()) { - case FIELD, ENUM_CONSTANT -> fields.add(el); - case METHOD -> methods.add(el); - } - } - } - - Map> methodMap = new LinkedHashMap<>(); - for (Element m : methods) { - methodMap.computeIfAbsent(m.getSimpleName(), k -> new HashSet<>()).add(m); - } - - // remove unnecessary object method overrides - // mainly toString(): string; - outer: - for (Map.Entry> ent : methodMap.entrySet()) { - if (!objectMethodNames.contains(ent.getKey())) continue; - for (Element m : ent.getValue()) if (!isObjectMethod(m)) continue outer; - methods.removeAll(ent.getValue()); - } - - StringBuilder s = new StringBuilder("interface ").append(name).append(" extends BaseEvent"); - if (cancellable) s.append(", Cancellable"); - s.append(" {\n").append(StringHelpers.tabIn(genFields(fields))); - String m = genMethods(methods); - if (!m.isEmpty()) s.append("\n").append(StringHelpers.tabIn(m)).append("\n"); - s.append("}"); - - return s.toString().replaceAll("\\{[\n ]+\\}", "{}").replaceAll("\n\n\n+", "\n\n"); - } - -} diff --git a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/LibraryParser.java b/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/LibraryParser.java deleted file mode 100644 index d4726bae1..000000000 --- a/buildSrc/src/main/java/com/jsmacrosce/doclet/tsdoclet/parsers/LibraryParser.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.jsmacrosce.doclet.tsdoclet.parsers; - -import com.jsmacrosce.StringHelpers; - -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.TypeElement; -import java.util.LinkedHashSet; -import java.util.Set; - -public class LibraryParser extends AbstractParser { - public final String name; - - public LibraryParser(TypeElement type, String name) { - super(type); - this.name = name; - this.isPackage = false; - } - - @Override - public String genComment(Element comment) { - return super.genComment(comment) + "function "; - } - - @Override - public String genTSInterface() { - String comment = super.genComment(type).trim() - .replaceAll("\n \\* An instance of this class is passed to scripts as the `\\w+` variable\\.", ""); - StringBuilder s = new StringBuilder(comment); - if (!s.isEmpty()) s.append("\n"); - - Set methods = new LinkedHashSet<>(); - - for (Element el : type.getEnclosedElements()) { - if (checkModifier(el, false) && el.getKind() == ElementKind.METHOD) { - methods.add(el); - } - } - - s.append("declare namespace ").append(name).append(" {\n") - .append(StringHelpers.tabIn(genMethods(methods))) - .append("\n}"); - - return s.toString(); - } - -} diff --git a/buildSrc/src/main/kotlin/multiloader-loader.gradle.kts b/buildSrc/src/main/kotlin/multiloader-loader.gradle.kts index 388d8c269..6e3a2cfdd 100644 --- a/buildSrc/src/main/kotlin/multiloader-loader.gradle.kts +++ b/buildSrc/src/main/kotlin/multiloader-loader.gradle.kts @@ -28,27 +28,32 @@ val ensureStonecutterGenerate = tasks.register("ensureStonecutterGenerate") { dependsOn("stonecutterGenerate") } +// Add common's Stonecutter-generated sources to the source set +sourceSets { + main { + java { + srcDir(commonStonecutterJava) + } + resources { + srcDir(commonStonecutterResources) + } + } +} + tasks.named("compileJava") { dependsOn(ensureStonecutterGenerate) - // Add common's Stonecutter-generated sources - source(commonStonecutterJava) } tasks.named("processResources") { dependsOn(ensureStonecutterGenerate) - // Include common's Stonecutter-generated resources - from(commonStonecutterResources) } tasks.named("javadoc") { dependsOn(ensureStonecutterGenerate) - source(commonStonecutterJava) } tasks.named("sourcesJar") { dependsOn(ensureStonecutterGenerate) - from(commonStonecutterJava) - from(commonStonecutterResources) } // Exclude access wideners folder from the jar (each loader handles this separately) diff --git a/common/src/main/java/com/jsmacrosce/doclet/DocletCategory.java b/common/src/main/java/com/jsmacrosce/doclet/DocletCategory.java new file mode 100644 index 000000000..5614a3af7 --- /dev/null +++ b/common/src/main/java/com/jsmacrosce/doclet/DocletCategory.java @@ -0,0 +1,17 @@ +package com.jsmacrosce.doclet; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface DocletCategory { + /** + * Category used for grouping doclet-generated pages. + */ + String value(); +} diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/CustomImage.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/CustomImage.java index 625495ce3..ac2075f9a 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/CustomImage.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/CustomImage.java @@ -5,6 +5,7 @@ import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import javax.imageio.ImageIO; @@ -22,6 +23,7 @@ * @since 1.8.4 */ @SuppressWarnings("unused") +@DocletCategory("Rendering/Graphics") public class CustomImage { public static final Map IMAGES = new HashMap<>(); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/AnvilInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/AnvilInventory.java index 08bf24e7e..7280295de 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/AnvilInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/AnvilInventory.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.classes.inventory; import net.minecraft.client.gui.screens.inventory.AnvilScreen; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; import com.jsmacrosce.jsmacros.client.mixin.access.MixinAnvilScreen; @@ -8,6 +9,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class AnvilInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/BeaconInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/BeaconInventory.java index 64173f976..665d3fd77 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/BeaconInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/BeaconInventory.java @@ -8,6 +8,7 @@ import net.minecraft.world.effect.MobEffects; import net.minecraft.world.level.block.entity.BeaconBlockEntity; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.doclet.DocletReplaceReturn; @@ -16,6 +17,7 @@ /** * @since 1.5.1 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class BeaconInventory extends Inventory { protected BeaconInventory(BeaconScreen inventory) { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/BrewingStandInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/BrewingStandInventory.java index fdc7e1dcc..3f6040476 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/BrewingStandInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/BrewingStandInventory.java @@ -6,6 +6,7 @@ import net.minecraft.world.item.alchemy.PotionBrewing; import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.level.block.entity.BrewingStandBlockEntity; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; import java.util.Arrays; @@ -17,6 +18,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class BrewingStandInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CartographyInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CartographyInventory.java index f4daae78b..cf0d56cd9 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CartographyInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CartographyInventory.java @@ -2,11 +2,13 @@ import net.minecraft.client.gui.screens.inventory.CartographyTableScreen; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; +import com.jsmacrosce.doclet.DocletCategory; /** * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class CartographyInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CommandBuilder.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CommandBuilder.java index 39e10b8cb..a57c086a2 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CommandBuilder.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CommandBuilder.java @@ -17,6 +17,7 @@ import net.minecraft.commands.arguments.item.ItemPredicateArgument; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.CommandContextHelper; import com.jsmacrosce.jsmacros.client.api.helper.SuggestionsBuilderHelper; @@ -40,6 +41,7 @@ /** * @since 1.4.2 */ +@DocletCategory("Commands") @SuppressWarnings("unused") public abstract class CommandBuilder implements Registrable { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CommandManager.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CommandManager.java index d1c53acc2..aed18f9d8 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CommandManager.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CommandManager.java @@ -11,6 +11,7 @@ import net.minecraft.client.multiplayer.ClientSuggestionProvider; import net.minecraft.commands.CommandSource; import net.minecraft.commands.SharedSuggestionProvider; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.helper.CommandNodeHelper; import com.jsmacrosce.jsmacros.core.MethodWrapper; @@ -21,6 +22,7 @@ /** * @since 1.7.0 */ +@DocletCategory("Commands") public abstract class CommandManager { public static CommandManager instance; private static final Minecraft mc = Minecraft.getInstance(); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/ContainerInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/ContainerInventory.java index 8684d3709..6b2439759 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/ContainerInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/ContainerInventory.java @@ -1,11 +1,13 @@ package com.jsmacrosce.jsmacros.client.api.classes.inventory; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import com.jsmacrosce.doclet.DocletCategory; /** * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class ContainerInventory> extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CraftingInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CraftingInventory.java index 8f47db320..3966ec5a6 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CraftingInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CraftingInventory.java @@ -1,12 +1,14 @@ package com.jsmacrosce.jsmacros.client.api.classes.inventory; import net.minecraft.client.gui.screens.inventory.CraftingScreen; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; /** * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") public class CraftingInventory extends RecipeInventory { protected CraftingInventory(CraftingScreen inventory) { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CreativeInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CreativeInventory.java index 59a644413..f6aea69a0 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CreativeInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/CreativeInventory.java @@ -9,6 +9,7 @@ import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTabs; import net.minecraft.world.item.ItemStack; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.RegistryHelper; import com.jsmacrosce.jsmacros.client.api.helper.TextHelper; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; @@ -22,6 +23,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class CreativeInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/EnchantInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/EnchantInventory.java index 56f9bd926..7611b9d61 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/EnchantInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/EnchantInventory.java @@ -5,6 +5,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.world.inventory.EnchantmentMenu; import net.minecraft.world.item.enchantment.Enchantment; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.helper.TextHelper; import com.jsmacrosce.jsmacros.client.api.helper.inventory.EnchantmentHelper; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; @@ -12,6 +13,7 @@ /** * @since 1.3.1 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class EnchantInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/FurnaceInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/FurnaceInventory.java index 3bf8315e2..393cf053e 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/FurnaceInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/FurnaceInventory.java @@ -6,6 +6,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.inventory.ContainerData; import net.minecraft.world.item.Item; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; import com.jsmacrosce.jsmacros.client.mixin.access.MixinAbstractFurnaceScreenHandler; @@ -15,6 +16,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class FurnaceInventory extends RecipeInventory> { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/GrindStoneInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/GrindStoneInventory.java index f0da5f31a..514a697d5 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/GrindStoneInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/GrindStoneInventory.java @@ -8,12 +8,14 @@ import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.ItemEnchantments; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; /** * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class GrindStoneInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/HorseInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/HorseInventory.java index 9fdae991a..b54b00e64 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/HorseInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/HorseInventory.java @@ -4,6 +4,7 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; import net.minecraft.world.entity.animal.horse.AbstractHorse; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.access.IHorseScreen; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.specialized.passive.AbstractHorseEntityHelper; @@ -16,6 +17,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class HorseInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/Inventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/Inventory.java index 2f3ec9334..a0656a1f0 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/Inventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/Inventory.java @@ -16,10 +16,7 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; -import com.jsmacrosce.doclet.DocletDeclareType; -import com.jsmacrosce.doclet.DocletReplaceParams; -import com.jsmacrosce.doclet.DocletReplaceReturn; -import com.jsmacrosce.doclet.DocletReplaceTypeParams; +import com.jsmacrosce.doclet.*; import com.jsmacrosce.jsmacros.api.math.Pos2D; import com.jsmacrosce.jsmacros.client.JsMacros; import com.jsmacrosce.jsmacros.client.JsMacrosClient; @@ -39,6 +36,7 @@ * @author Wagyourtail * @since 1.0.8 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class Inventory> { protected T inventory; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/LoomInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/LoomInventory.java index 4b43bc2ef..dd0949e8d 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/LoomInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/LoomInventory.java @@ -9,6 +9,7 @@ import net.minecraft.tags.TagKey; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BannerPattern; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.access.ILoomScreen; import java.util.List; @@ -19,6 +20,7 @@ /** * @since 1.5.1 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class LoomInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/PlayerInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/PlayerInventory.java index 9a026b99f..261671488 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/PlayerInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/PlayerInventory.java @@ -2,12 +2,14 @@ import net.minecraft.client.gui.screens.inventory.InventoryScreen; import net.minecraft.world.inventory.InventoryMenu; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; /** * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") public class PlayerInventory extends RecipeInventory { protected PlayerInventory(InventoryScreen inventory) { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/RecipeInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/RecipeInventory.java index 5c18ba9b5..e98bf547d 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/RecipeInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/RecipeInventory.java @@ -8,6 +8,7 @@ import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.api.classes.render.IScreen; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; @@ -21,6 +22,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public abstract class RecipeInventory> extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/SmithingInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/SmithingInventory.java index 4f1ee4b70..00f20c01c 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/SmithingInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/SmithingInventory.java @@ -1,12 +1,14 @@ package com.jsmacrosce.jsmacros.client.api.classes.inventory; import net.minecraft.client.gui.screens.inventory.SmithingScreen; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; /** * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class SmithingInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/StoneCutterInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/StoneCutterInventory.java index 635e32a0a..74781000f 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/StoneCutterInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/StoneCutterInventory.java @@ -3,6 +3,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.inventory.StonecutterScreen; import net.minecraft.world.item.crafting.display.SlotDisplayContext; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; import java.util.List; @@ -12,6 +13,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class StoneCutterInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/VillagerInventory.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/VillagerInventory.java index e4c036350..aca75be08 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/VillagerInventory.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/inventory/VillagerInventory.java @@ -2,6 +2,7 @@ import net.minecraft.client.gui.screens.inventory.MerchantScreen; import net.minecraft.world.item.trading.MerchantOffer; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.access.IMerchantScreen; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.TradeOfferHelper; @@ -11,6 +12,7 @@ /** * @since 1.3.1 */ +@DocletCategory("Inventory") @SuppressWarnings("unused") public class VillagerInventory extends Inventory { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/Draw2D.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/Draw2D.java index dd427757a..d30007489 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/Draw2D.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/Draw2D.java @@ -5,6 +5,7 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Renderable; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletIgnore; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.jsmacros.client.JsMacrosClient; @@ -25,6 +26,7 @@ * @see IDraw2D * @since 1.0.5 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("deprecation") public class Draw2D implements IDraw2D, Registrable { protected final Set elements = new LinkedHashSet<>(); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/Draw3D.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/Draw3D.java index c0ea640c9..8603ba743 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/Draw3D.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/Draw3D.java @@ -5,6 +5,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.world.phys.Vec3; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletIgnore; import com.jsmacrosce.jsmacros.api.math.Pos2D; import com.jsmacrosce.jsmacros.api.math.Pos3D; @@ -24,6 +25,7 @@ * @author Wagyourtail * @since 1.0.6 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class Draw3D implements Registrable { private final List> elements = new ArrayList<>(); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/IDraw2D.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/IDraw2D.java index dab0d3512..312a83660 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/IDraw2D.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/IDraw2D.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.classes.render; import net.minecraft.client.gui.GuiGraphics; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletIgnore; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.jsmacros.client.api.classes.render.components.*; @@ -16,6 +17,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Rendering/Graphics") public interface IDraw2D { /** diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/IScreen.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/IScreen.java index 374b81719..d7b973617 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/IScreen.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/IScreen.java @@ -2,6 +2,7 @@ import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.api.math.Pos2D; import com.jsmacrosce.jsmacros.api.math.Vec2D; import com.jsmacrosce.jsmacros.client.api.helper.TextHelper; @@ -16,6 +17,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Screen and UI Elements") public interface IScreen extends IDraw2D { /** diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/ScriptScreen.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/ScriptScreen.java index 0ff1737d3..8214b4cf6 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/ScriptScreen.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/ScriptScreen.java @@ -6,6 +6,7 @@ import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.network.chat.Component; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.api.math.Pos3D; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.access.IScreenInternal; @@ -20,6 +21,7 @@ * @see IScreen * @since 1.0.5 */ +@DocletCategory("Screen and UI Elements") public class ScriptScreen extends BaseScreen { public boolean drawTitle; /** diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Draw2DElement.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Draw2DElement.java index bce67ca80..22d6afa10 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Draw2DElement.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Draw2DElement.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable; import org.joml.Matrix3x2fStack; import org.joml.Quaternionf; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.render.Draw2D; import com.jsmacrosce.jsmacros.client.api.classes.render.IDraw2D; @@ -14,6 +15,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class Draw2DElement implements RenderElement, Alignable { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Image.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Image.java index 67e078762..e2f8215c2 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Image.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Image.java @@ -9,6 +9,7 @@ import net.minecraft.util.Mth; import org.jetbrains.annotations.Nullable; import org.joml.Matrix3x2fStack; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.CustomImage; import com.jsmacrosce.jsmacros.client.api.classes.RegistryHelper; import com.jsmacrosce.jsmacros.client.api.classes.render.IDraw2D; @@ -18,6 +19,7 @@ * @author Wagyourtail * @since 1.2.3 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class Image implements RenderElement, Alignable { @@ -379,6 +381,7 @@ public Image moveTo(int x, int y) { * @author Etheradon * @since 1.8.4 */ + @DocletCategory("Rendering/Graphics") public static final class Builder extends RenderElementBuilder implements Alignable { private String identifier; private int x = 0; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Item.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Item.java index 9aad8e705..b86e91bab 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Item.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Item.java @@ -8,6 +8,7 @@ import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; import org.joml.Matrix3x2fStack; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletIgnore; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.jsmacros.client.api.classes.RegistryHelper; @@ -18,6 +19,7 @@ * @author Wagyourtail * @since 1.0.5 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class Item implements RenderElement, Alignable { @@ -360,6 +362,7 @@ public Item moveTo(int x, int y) { * @author Etheradon * @since 1.8.4 */ + @DocletCategory("Rendering/Graphics") public static final class Builder extends RenderElementBuilder implements Alignable { private int x = 0; private int y = 0; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Line.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Line.java index 959d3a0b6..c48a3c691 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Line.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Line.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; import org.joml.Matrix3x2fStack; import org.joml.Quaternionf; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.render.IDraw2D; import com.jsmacrosce.jsmacros.client.util.ColorUtil; @@ -13,6 +14,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class Line implements RenderElement, Alignable { @@ -352,6 +354,7 @@ public int getScaledTop() { * @author Etheradon * @since 1.8.4 */ + @DocletCategory("Rendering/Graphics") public static class Builder extends RenderElementBuilder implements Alignable { private int x1 = 0; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Rect.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Rect.java index 07fbfc5b9..b90e48578 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Rect.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Rect.java @@ -5,6 +5,7 @@ import net.minecraft.util.Mth; import org.jetbrains.annotations.Nullable; import org.joml.Matrix3x2fStack; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.render.IDraw2D; import com.jsmacrosce.jsmacros.client.util.ColorUtil; @@ -12,6 +13,7 @@ * @author Wagyourtail * @since 1.0.5 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class Rect implements RenderElement, Alignable { @@ -368,6 +370,7 @@ public Rect moveTo(int x, int y) { * @author Etheradon * @since 1.8.4 */ + @DocletCategory("Rendering/Graphics") public static final class Builder extends RenderElementBuilder implements Alignable { private int x1 = 0; private int y1 = 0; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/RenderElement.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/RenderElement.java index a2c66e7dd..ab9388052 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/RenderElement.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/RenderElement.java @@ -6,11 +6,13 @@ import net.minecraft.client.gui.components.Renderable; import org.joml.Matrix3x2fStack; import org.joml.Quaternionf; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletIgnore; /** * @author Wagyourtail */ +@DocletCategory("Rendering/Graphics") public interface RenderElement extends Renderable { Minecraft mc = Minecraft.getInstance(); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/RenderElementBuilder.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/RenderElementBuilder.java index 76546514b..f0d7bc990 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/RenderElementBuilder.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/RenderElementBuilder.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.classes.render.components; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.render.IDraw2D; /** @@ -7,6 +8,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Rendering/Graphics") public abstract class RenderElementBuilder { protected final IDraw2D parent; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Text.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Text.java index b22e8583f..56f36b86e 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Text.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components/Text.java @@ -10,6 +10,7 @@ import org.joml.Matrix3x2fStack; import org.joml.Matrix4f; import org.lwjgl.system.MemoryStack; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletIgnore; import com.jsmacrosce.jsmacros.client.api.classes.TextBuilder; import com.jsmacrosce.jsmacros.client.api.classes.render.IDraw2D; @@ -22,6 +23,7 @@ * @author Wagyourtail * @since 1.0.5 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class Text implements RenderElement, Alignable { @@ -373,6 +375,7 @@ public Text moveTo(int x, int y) { * @author Etheradon * @since 1.8.4 */ + @DocletCategory("Rendering/Graphics") public static class Builder extends RenderElementBuilder implements Alignable { private int x = 0; private int y = 0; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Box.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Box.java index 6bfc3bbba..833f58c2e 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Box.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Box.java @@ -6,6 +6,7 @@ import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.ShapeRenderer; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletIgnore; import com.jsmacrosce.jsmacros.api.math.Pos3D; import com.jsmacrosce.jsmacros.api.math.Vec3D; @@ -19,6 +20,7 @@ /** * @author Wagyourtail */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class Box implements RenderElement3D { private static final Field lineDepthTestFunction; @@ -255,6 +257,7 @@ public void render(PoseStack matrixStack, MultiBufferSource consumers, float tic * @author Etheradon * @since 1.8.4 */ + @DocletCategory("Rendering/Graphics") public static class Builder { private final Draw3D parent; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/EntityTraceLine.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/EntityTraceLine.java index 27e5da545..524749cc3 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/EntityTraceLine.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/EntityTraceLine.java @@ -5,6 +5,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.render.Draw3D; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.EntityHelper; @@ -14,6 +15,7 @@ * @author aMelonRind * @since 1.9.0 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class EntityTraceLine extends TraceLine { public static boolean dirty = false; @@ -66,6 +68,7 @@ public void render(PoseStack matrixStack, MultiBufferSource consumers, float tic super.render(matrixStack, consumers, tickDelta); } + @DocletCategory("Rendering/Graphics") public static class Builder { private final Draw3D parent; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Line3D.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Line3D.java index 2b7ba68a4..1ef3ba22a 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Line3D.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Line3D.java @@ -5,6 +5,7 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.RenderType; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletIgnore; import com.jsmacrosce.jsmacros.api.math.Pos3D; import com.jsmacrosce.jsmacros.api.math.Vec3D; @@ -18,6 +19,7 @@ /** * @author Wagyourtail */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class Line3D implements RenderElement3D { private static final Field lineDepthTestFunction; @@ -144,6 +146,7 @@ public void render(PoseStack matrixStack, MultiBufferSource consumers, float tic * @author Etheradon * @since 1.8.4 */ + @DocletCategory("Rendering/Graphics") public static class Builder { private final Draw3D parent; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/RenderElement3D.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/RenderElement3D.java index 89b08e54e..2936ff26f 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/RenderElement3D.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/RenderElement3D.java @@ -3,8 +3,10 @@ import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.renderer.MultiBufferSource; import org.jetbrains.annotations.NotNull; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletIgnore; +@DocletCategory("Rendering/Graphics") public interface RenderElement3D> extends Comparable> { @DocletIgnore diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Surface.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Surface.java index 4080a0752..848fc7686 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Surface.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/Surface.java @@ -12,6 +12,7 @@ import org.joml.Matrix3x2fStack; import org.joml.Quaternionf; import org.joml.Vector3f; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletIgnore; import com.jsmacrosce.jsmacros.api.math.Pos2D; import com.jsmacrosce.jsmacros.api.math.Pos3D; @@ -29,6 +30,7 @@ * @author Wagyourtail * @since 1.6.5 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class Surface extends Draw2D implements RenderElement, RenderElement3D { public boolean rotateToPlayer; @@ -420,6 +422,7 @@ public void render(GuiGraphics drawContext, int mouseX, int mouseY, float delta) * @author Etheradon * @since 1.8.4 */ + @DocletCategory("Rendering/Graphics") public static class Builder { private final Draw3D parent; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/TraceLine.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/TraceLine.java index 3303fd0f2..7f00f4ccf 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/TraceLine.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/render/components3d/TraceLine.java @@ -5,6 +5,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.world.phys.Vec3; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.api.math.Pos3D; import com.jsmacrosce.jsmacros.client.api.classes.render.Draw3D; import com.jsmacrosce.jsmacros.client.api.helper.world.BlockPosHelper; @@ -15,6 +16,7 @@ * @author aMelonRind * @since 1.9.0 */ +@DocletCategory("Rendering/Graphics") @SuppressWarnings("unused") public class TraceLine implements RenderElement3D { private final Line3D render; @@ -106,6 +108,7 @@ public void render(PoseStack matrixStack, MultiBufferSource consumers, float tic render.render(matrixStack, consumers, tickDelta); } + @DocletCategory("Rendering/Graphics") public static class Builder { private final Draw3D parent; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/ClassWrapperFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/ClassWrapperFilter.java index 300661471..95932997d 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/ClassWrapperFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/ClassWrapperFilter.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.IFilter; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.compare.BooleanCompareFilter; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.compare.CharCompareFilter; @@ -17,6 +18,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public abstract class ClassWrapperFilter extends BasicFilter { protected final String methodName; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/GroupFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/GroupFilter.java index d52dda8bd..685ee408c 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/GroupFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/GroupFilter.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter; import com.google.common.collect.ImmutableList; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.IFilter; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.compare.NumberCompareFilter; @@ -11,6 +12,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public abstract class GroupFilter implements IFilter { protected List> filters; @@ -43,6 +45,7 @@ public List> getFilters() { return ImmutableList.copyOf(filters); } + @DocletCategory("Filters/Predicates") public static class AllMatchFilter extends GroupFilter { public AllMatchFilter() { @@ -56,6 +59,7 @@ public Boolean apply(T t) { } + @DocletCategory("Filters/Predicates") public static class AnyMatchFilter extends GroupFilter { public AnyMatchFilter() { @@ -69,6 +73,7 @@ public Boolean apply(T t) { } + @DocletCategory("Filters/Predicates") public static class NoneMatchFilter extends GroupFilter { public NoneMatchFilter() { @@ -82,6 +87,7 @@ public Boolean apply(T t) { } + @DocletCategory("Filters/Predicates") public static class CountMatchFilter extends GroupFilter { private final IFilter filter; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/IAdvancedFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/IAdvancedFilter.java index 3bb825055..07d150ac5 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/IAdvancedFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/IAdvancedFilter.java @@ -1,9 +1,12 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api; +import com.jsmacrosce.doclet.DocletCategory; + /** * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public interface IAdvancedFilter extends IFilter { IAdvancedFilter and(IFilter filter); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/ICompare.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/ICompare.java index cbcff4388..7a884e7ce 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/ICompare.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/ICompare.java @@ -1,6 +1,9 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api; +import com.jsmacrosce.doclet.DocletCategory; + @FunctionalInterface +@DocletCategory("Filters/Predicates") public interface ICompare { boolean compare(T obj1, T obj2); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/IFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/IFilter.java index 02696d5f5..1b593ed6e 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/IFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/api/IFilter.java @@ -1,11 +1,14 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api; +import com.jsmacrosce.doclet.DocletCategory; + import java.util.function.Function; /** * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public interface IFilter extends Function { @Override diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/BooleanCompareFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/BooleanCompareFilter.java index 3caf00a1c..72f9f024d 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/BooleanCompareFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/BooleanCompareFilter.java @@ -1,11 +1,13 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.compare; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.IFilter; /** * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public class BooleanCompareFilter implements IFilter { private final boolean compareTo; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/CharCompareFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/CharCompareFilter.java index 3f0a6d95e..c31cb2515 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/CharCompareFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/CharCompareFilter.java @@ -1,7 +1,9 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.compare; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.IFilter; +@DocletCategory("Filters/Predicates") public class CharCompareFilter implements IFilter { private final char compareTo; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/NumberCompareFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/NumberCompareFilter.java index 765da7d02..22290a8ea 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/NumberCompareFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/NumberCompareFilter.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.compare; import com.google.common.math.DoubleMath; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.IFilter; import java.util.Locale; @@ -9,6 +10,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public class NumberCompareFilter implements IFilter { private final static double EPSILON = 0.000001d; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/StringCompareFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/StringCompareFilter.java index d00b60a31..385285b94 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/StringCompareFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/compare/StringCompareFilter.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.compare; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.ICompare; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.IFilter; @@ -7,6 +8,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public class StringCompareFilter implements IFilter { private final String compareTo; @@ -23,6 +25,7 @@ public Boolean apply(String val) { return filter.compare(val, compareTo); } + @DocletCategory("Filters/Predicates") public enum FilterMethod { CONTAINS(String::contains), EQUALS(String::equals), diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/BlockFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/BlockFilter.java index f4dc541c4..dff8369c2 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/BlockFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/BlockFilter.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.impl; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.ClassWrapperFilter; import com.jsmacrosce.jsmacros.client.api.helper.world.BlockHelper; @@ -10,6 +11,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public class BlockFilter extends ClassWrapperFilter { private static final Map METHOD_LOOKUP = getPublicNoParameterMethods(BlockHelper.class); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/BlockStateFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/BlockStateFilter.java index 94382b2d9..6ade40506 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/BlockStateFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/BlockStateFilter.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.impl; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.ClassWrapperFilter; import com.jsmacrosce.jsmacros.client.api.helper.world.BlockStateHelper; @@ -10,6 +11,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public class BlockStateFilter extends ClassWrapperFilter { private static final Map METHOD_LOOKUP = getPublicNoParameterMethods(BlockStateHelper.class); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/StringifyFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/StringifyFilter.java index 095ff888b..98a271acc 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/StringifyFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/impl/StringifyFilter.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.impl; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.BasicFilter; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.ICompare; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.compare.StringCompareFilter; @@ -12,6 +13,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public class StringifyFilter extends BasicFilter { private final Set filterObjects; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/AndFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/AndFilter.java index ea3dc6f6a..0c8f99323 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/AndFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/AndFilter.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.logical; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.BasicFilter; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.IFilter; @@ -7,6 +8,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public class AndFilter extends BasicFilter { private final IFilter filterOne; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/NotFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/NotFilter.java index 8f0957f58..bfb8607af 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/NotFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/NotFilter.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.logical; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.BasicFilter; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.IFilter; @@ -7,6 +8,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public class NotFilter extends BasicFilter { private final IFilter filter; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/OrFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/OrFilter.java index 5bfd46824..451292053 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/OrFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/OrFilter.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.logical; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.BasicFilter; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.IFilter; @@ -7,6 +8,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public class OrFilter extends BasicFilter { private final IFilter filterOne; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/XorFilter.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/XorFilter.java index ef098b009..4b3b19a29 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/XorFilter.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/classes/worldscanner/filter/logical/XorFilter.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.logical; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.BasicFilter; import com.jsmacrosce.jsmacros.client.api.classes.worldscanner.filter.api.IFilter; @@ -7,6 +8,7 @@ * @author Etheradon * @since 1.6.5 */ +@DocletCategory("Filters/Predicates") public class XorFilter extends BasicFilter { private final IFilter filterOne; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererBlockUpdate.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererBlockUpdate.java index 624ad4785..090469af9 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererBlockUpdate.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererBlockUpdate.java @@ -2,6 +2,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.api.classes.RegistryHelper; @@ -18,6 +19,7 @@ * @author aMelonRind * @since 1.9.1 */ +@DocletCategory("Event Filterers") @SuppressWarnings("unused") public class FiltererBlockUpdate implements EventFilterer { @Nullable diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererRecvPacket.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererRecvPacket.java index f07e65e87..85e77e7b3 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererRecvPacket.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererRecvPacket.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.filterer; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.api.event.impl.EventRecvPacket; @@ -11,6 +12,7 @@ * @author aMelonRind * @since 1.9.1 */ +@DocletCategory("Event Filterers") @SuppressWarnings("unused") public class FiltererRecvPacket implements EventFilterer { @Nullable diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererSendPacket.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererSendPacket.java index 29c0e0893..6ea407f70 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererSendPacket.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/filterer/FiltererSendPacket.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.filterer; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.api.event.impl.EventSendPacket; @@ -11,6 +12,7 @@ * @author aMelonRind * @since 1.9.1 */ +@DocletCategory("Event Filterers") @SuppressWarnings("unused") public class FiltererSendPacket implements EventFilterer { @Nullable diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventKey.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventKey.java index 48d2eb52d..7562beea9 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventKey.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventKey.java @@ -5,6 +5,7 @@ import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletDeclareType; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; @@ -22,6 +23,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Inputs/Interactions") @Event(value = "Key", oldName = "KEY", cancellable = true) public class EventKey extends BaseEvent { static final Minecraft mc = Minecraft.getInstance(); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventLaunchGame.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventLaunchGame.java index 83139ecac..db6373afc 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventLaunchGame.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventLaunchGame.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -8,6 +9,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("System/Lifecycle") @Event(value = "LaunchGame") public class EventLaunchGame extends BaseEvent { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventMouseScroll.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventMouseScroll.java index 514fc7387..08a7d4364 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventMouseScroll.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventMouseScroll.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -8,6 +9,7 @@ * @author aMelonRind * @since 1.9.0 */ +@DocletCategory("Inputs/Interactions") @Event(value = "MouseScroll", cancellable = true) public class EventMouseScroll extends BaseEvent { public final double deltaX; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventQuitGame.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventQuitGame.java index 838fdbffa..bab0a4fea 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventQuitGame.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventQuitGame.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -8,6 +9,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("System/Lifecycle") @Event(value = "QuitGame") public class EventQuitGame extends BaseEvent { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventRecvMessage.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventRecvMessage.java index 494b86f28..c12cd1b2f 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventRecvMessage.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventRecvMessage.java @@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MessageSignature; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.TextHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -13,6 +14,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Network/Chat") @Event(value = "RecvMessage", oldName = "RECV_MESSAGE", cancellable = true) public class EventRecvMessage extends BaseEvent { @Nullable diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventRecvPacket.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventRecvPacket.java index df37bce6a..a7409c9db 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventRecvPacket.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventRecvPacket.java @@ -3,6 +3,7 @@ import net.minecraft.network.protocol.Packet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.event.filterer.FiltererRecvPacket; @@ -14,6 +15,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Network/Chat") @Event(value = "RecvPacket", cancellable = true, filterer = FiltererRecvPacket.class) @SuppressWarnings("unused") public class EventRecvPacket extends BaseEvent { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventResourcePackLoaded.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventResourcePackLoaded.java index d12dc44fd..7e95676e7 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventResourcePackLoaded.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventResourcePackLoaded.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl; import net.minecraft.client.Minecraft; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -15,6 +16,7 @@ * * @since 1.5.1 */ +@DocletCategory("System/Lifecycle") @Event("ResourcePackLoaded") public class EventResourcePackLoaded extends BaseEvent { public final boolean isGameStart; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventSendMessage.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventSendMessage.java index 22912fae3..d1bf266c8 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventSendMessage.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventSendMessage.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -9,6 +10,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Network/Chat") @Event(value = "SendMessage", oldName = "SEND_MESSAGE", cancellable = true) public class EventSendMessage extends BaseEvent { @Nullable diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventSendPacket.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventSendPacket.java index 20b42aa10..c24f47ef4 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventSendPacket.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventSendPacket.java @@ -3,6 +3,7 @@ import net.minecraft.network.protocol.Packet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.event.filterer.FiltererSendPacket; @@ -15,6 +16,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Network/Chat") @Event(value = "SendPacket", cancellable = true, filterer = FiltererSendPacket.class) @SuppressWarnings("unused") public class EventSendPacket extends BaseEvent { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventTitle.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventTitle.java index faabdc03c..eeb1cb06b 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventTitle.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/EventTitle.java @@ -2,6 +2,7 @@ import net.minecraft.network.chat.Component; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletDeclareType; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; @@ -13,6 +14,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Render/UI") @Event(value = "Title", oldName = "TITLE", cancellable = true) public class EventTitle extends BaseEvent { @DocletReplaceReturn("TitleType") diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventClickSlot.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventClickSlot.java index dbda83a46..70bf24586 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventClickSlot.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventClickSlot.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.inventory; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.classes.inventory.Inventory; @@ -13,11 +14,12 @@ * @author Wagyourtail * @since 1.6.4 */ +@DocletCategory("Inventory") @Event(value = "ClickSlot", cancellable = true) public class EventClickSlot extends BaseEvent { protected final AbstractContainerScreen screen; /** - * https://wiki.vg/Protocol#Click_Window + * https://minecraft.wiki/w/Java_Edition_protocol/Packets#Click_Container */ public final int mode; @DocletReplaceReturn("ClickSlotButton") diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventContainerUpdate.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventContainerUpdate.java index 86a9bc55c..c74e2320f 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventContainerUpdate.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventContainerUpdate.java @@ -2,12 +2,14 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.classes.inventory.Inventory; import com.jsmacrosce.jsmacros.client.api.classes.render.IScreen; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; +@DocletCategory("Inventory") @Event(value = "ContainerUpdate") public class EventContainerUpdate extends BaseEvent { public final Inventory inventory; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventDropSlot.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventDropSlot.java index b7bdce530..31a74a31c 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventDropSlot.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventDropSlot.java @@ -3,6 +3,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.InventoryScreen; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.classes.inventory.Inventory; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -14,6 +15,7 @@ * @author Wagyourtail * @since 1.6.4 */ +@DocletCategory("Inventory") @Event(value = "DropSlot", cancellable = true) public class EventDropSlot extends BaseEvent { protected static final Minecraft mc = Minecraft.getInstance(); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventItemDamage.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventItemDamage.java index 1ff8801b8..9da05d5f3 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventItemDamage.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventItemDamage.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.inventory; import net.minecraft.world.item.ItemStack; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -10,6 +11,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Inventory") @Event(value = "ItemDamage", oldName = "ITEM_DAMAGE") public class EventItemDamage extends BaseEvent { public final ItemStackHelper item; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventItemPickup.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventItemPickup.java index 2bdf39e5e..aba46ec3c 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventItemPickup.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventItemPickup.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.inventory; import net.minecraft.world.item.ItemStack; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -10,6 +11,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Inventory") @Event(value = "ItemPickup", oldName = "ITEM_PICKUP") public class EventItemPickup extends BaseEvent { public final ItemStackHelper item; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventOpenContainer.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventOpenContainer.java index 9122dcefa..a54f239cc 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventOpenContainer.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventOpenContainer.java @@ -2,6 +2,7 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.classes.inventory.Inventory; import com.jsmacrosce.jsmacros.client.api.classes.render.IScreen; @@ -12,6 +13,7 @@ * @author Wagyourtail * @since 1.6.5 */ +@DocletCategory("Inventory") @Event(value = "OpenContainer", cancellable = true) public class EventOpenContainer extends BaseEvent { public final Inventory inventory; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventSlotUpdate.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventSlotUpdate.java index 44d3a9713..3aa6474c8 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventSlotUpdate.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/inventory/EventSlotUpdate.java @@ -2,6 +2,7 @@ import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.world.item.ItemStack; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletDeclareType; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; @@ -13,6 +14,7 @@ /** * @since 1.9.0 */ +@DocletCategory("Inventory") @Event(value = "SlotUpdate") public class EventSlotUpdate extends BaseEvent { protected final AbstractContainerScreen screen; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAirChange.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAirChange.java index bfe844020..a7aadb9b8 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAirChange.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAirChange.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -8,6 +9,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Player/Stats") @Event(value = "AirChange", oldName = "AIR_CHANGE") public class EventAirChange extends BaseEvent { public final int air; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventArmorChange.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventArmorChange.java index 4bc89f6b5..c3c70e5e7 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventArmorChange.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventArmorChange.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; import net.minecraft.world.item.ItemStack; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletDeclareType; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; @@ -12,6 +13,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Player/Stats") @Event(value = "ArmorChange", oldName = "ARMOR_CHANGE") public class EventArmorChange extends BaseEvent { @DocletReplaceReturn("ArmorSlot") diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAttackBlock.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAttackBlock.java index 709855475..a1166c324 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAttackBlock.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAttackBlock.java @@ -1,11 +1,13 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.BlockDataHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; +@DocletCategory("Inputs/Interactions") @Event("AttackBlock") public class EventAttackBlock extends BaseEvent { public final BlockDataHelper block; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAttackEntity.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAttackEntity.java index 487a4fa61..075c19271 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAttackEntity.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventAttackEntity.java @@ -1,11 +1,13 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; import net.minecraft.world.entity.Entity; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.EntityHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; +@DocletCategory("Inputs/Interactions") @Event("AttackEntity") public class EventAttackEntity extends BaseEvent { public final EntityHelper entity; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventDamage.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventDamage.java index 7c4036e21..fe992e6e2 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventDamage.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventDamage.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; import net.minecraft.world.damagesource.DamageSource; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.EntityHelper; @@ -11,6 +12,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Player/Stats") @Event(value = "Damage", oldName = "DAMAGE") public class EventDamage extends BaseEvent { /** diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventDeath.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventDeath.java index 3ad9431a3..a584c359b 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventDeath.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventDeath.java @@ -3,6 +3,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.entity.player.Inventory; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; import com.jsmacrosce.jsmacros.client.api.helper.world.BlockPosHelper; @@ -16,6 +17,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Player/Stats") @Event(value = "Death", oldName = "DEATH") public class EventDeath extends BaseEvent { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventEXPChange.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventEXPChange.java index 8e95103e1..07f45dec1 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventEXPChange.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventEXPChange.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -8,6 +9,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Player/Stats") @Event(value = "EXPChange", oldName = "EXP_CHANGE") public class EventEXPChange extends BaseEvent { public final float progress; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventFallFlying.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventFallFlying.java index e4142e578..9db58c15a 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventFallFlying.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventFallFlying.java @@ -1,9 +1,11 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; +@DocletCategory("Player/Stats") @Event("FallFlying") public class EventFallFlying extends BaseEvent { public final boolean state; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHeal.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHeal.java index 4f9e80120..5fe313ca4 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHeal.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHeal.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; import net.minecraft.world.damagesource.DamageSource; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletDeclareType; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; @@ -11,6 +12,7 @@ * @author FlareStormGaming * @since 1.6.5 */ +@DocletCategory("Player/Stats") @Event("Heal") public class EventHeal extends BaseEvent { @DocletReplaceReturn("HealSource") diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHealthChange.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHealthChange.java index 730b8a7b8..e0a9e4c23 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHealthChange.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHealthChange.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -8,6 +9,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Player/Stats") @Event(value = "HealthChange") public class EventHealthChange extends BaseEvent { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHeldItemChange.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHeldItemChange.java index a2787111d..13db10f35 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHeldItemChange.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHeldItemChange.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; import net.minecraft.world.item.ItemStack; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.inventory.ItemStackHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -10,6 +11,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Inventory") @Event(value = "HeldItemChange", oldName = "HELD_ITEM") public class EventHeldItemChange extends BaseEvent { public final boolean offHand; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHungerChange.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHungerChange.java index 490ee716d..ce63502e6 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHungerChange.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventHungerChange.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -8,6 +9,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Player/Stats") @Event(value = "HungerChange", oldName = "HUNGER_CHANGE") public class EventHungerChange extends BaseEvent { public final int foodLevel; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventInteractBlock.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventInteractBlock.java index 4f681fafe..5246bf857 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventInteractBlock.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventInteractBlock.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.BlockDataHelper; @@ -10,6 +11,7 @@ * @author Wagyourtail * @since 1.8.0 */ +@DocletCategory("Inputs/Interactions") @Event("InteractBlock") public class EventInteractBlock extends BaseEvent { public final boolean offhand; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventInteractEntity.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventInteractEntity.java index d281a5066..2c924e0fd 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventInteractEntity.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventInteractEntity.java @@ -1,11 +1,13 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; import net.minecraft.world.entity.Entity; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.EntityHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; +@DocletCategory("Inputs/Interactions") @Event("InteractEntity") public class EventInteractEntity extends BaseEvent { public final boolean offhand; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventOpenScreen.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventOpenScreen.java index 1c5e95b17..734c15b57 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventOpenScreen.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventOpenScreen.java @@ -2,6 +2,7 @@ import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.classes.render.IScreen; @@ -12,6 +13,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Render/UI") @Event(value = "OpenScreen", oldName = "OPEN_SCREEN") public class EventOpenScreen extends BaseEvent { @Nullable diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventRiding.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventRiding.java index 6633574ae..6e8ccb08d 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventRiding.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventRiding.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; import net.minecraft.world.entity.Entity; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.EntityHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -9,6 +10,7 @@ /** * @since 1.5.0 */ +@DocletCategory("Player/Stats") @Event("Riding") public class EventRiding extends BaseEvent { public final boolean state; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventSignEdit.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventSignEdit.java index 3ed88e0a9..d961c3480 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventSignEdit.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventSignEdit.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.api.math.Pos3D; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -12,6 +13,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Inputs/Interactions") @Event(value = "SignEdit", oldName = "SIGN_EDIT", cancellable = true) public class EventSignEdit extends BaseEvent { public final Pos3D pos; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventStatusEffectUpdate.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventStatusEffectUpdate.java index 39cade401..29ae0e47c 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventStatusEffectUpdate.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/player/EventStatusEffectUpdate.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.player; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.StatusEffectHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -9,6 +10,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Player/Stats") @Event(value = "StatusEffectUpdate") public class EventStatusEffectUpdate extends BaseEvent { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventBlockUpdate.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventBlockUpdate.java index 758172d8b..22fdc0d3f 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventBlockUpdate.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventBlockUpdate.java @@ -3,6 +3,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletDeclareType; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; @@ -15,6 +16,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("World") @Event(value = "BlockUpdate", oldName = "BLOCK_UPDATE", filterer = FiltererBlockUpdate.class) public class EventBlockUpdate extends BaseEvent { public final BlockDataHelper block; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventBossbar.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventBossbar.java index a9f69e8f5..9ab239d8c 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventBossbar.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventBossbar.java @@ -2,6 +2,7 @@ import net.minecraft.client.gui.components.LerpingBossEvent; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletDeclareType; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; @@ -15,6 +16,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Render/UI") @Event(value = "Bossbar", oldName = "BOSSBAR_UPDATE") public class EventBossbar extends BaseEvent { @Nullable diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventChunkLoad.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventChunkLoad.java index bb696f699..1a6b637e3 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventChunkLoad.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventChunkLoad.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -8,6 +9,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("World") @Event(value = "ChunkLoad", oldName = "CHUNK_LOAD") public class EventChunkLoad extends BaseEvent { public final int x; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventChunkUnload.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventChunkUnload.java index 075301435..6b38c9021 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventChunkUnload.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventChunkUnload.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -8,6 +9,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("World") @Event(value = "ChunkUnload", oldName = "CHUNK_UNLOAD") public class EventChunkUnload extends BaseEvent { public final int x; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventDimensionChange.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventDimensionChange.java index a67f4cb5f..c3d204827 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventDimensionChange.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventDimensionChange.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -9,6 +10,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("World") @Event(value = "DimensionChange", oldName = "DIMENSION_CHANGE") public class EventDimensionChange extends BaseEvent { @DocletReplaceReturn("Dimension") diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventDisconnect.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventDisconnect.java index 2258bd133..21a2b2e6c 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventDisconnect.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventDisconnect.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; import net.minecraft.network.chat.Component; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.TextHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -10,6 +11,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Network/Chat") @Event(value = "Disconnect", oldName = "DISCONNECT") public class EventDisconnect extends BaseEvent { /** diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityDamaged.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityDamaged.java index ede67b4a6..c90322209 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityDamaged.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityDamaged.java @@ -1,11 +1,13 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; import net.minecraft.world.entity.Entity; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.EntityHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; +@DocletCategory("World") @Event("EntityDamaged") public class EventEntityDamaged extends BaseEvent { public final EntityHelper entity; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityHealed.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityHealed.java index fce57b035..3d005349d 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityHealed.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityHealed.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; import net.minecraft.world.entity.Entity; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.EntityHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -11,6 +12,7 @@ * @since 1.6.5 */ +@DocletCategory("World") @Event("EntityHealed") public class EventEntityHealed extends BaseEvent { public final EntityHelper entity; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityLoad.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityLoad.java index a45c3915f..954a9fae0 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityLoad.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityLoad.java @@ -1,11 +1,13 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; import net.minecraft.world.entity.Entity; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.EntityHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; +@DocletCategory("World") @Event("EntityLoad") public class EventEntityLoad extends BaseEvent { public final EntityHelper entity; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityUnload.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityUnload.java index 4a33b2ae1..caa9896af 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityUnload.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventEntityUnload.java @@ -1,12 +1,14 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; import net.minecraft.world.entity.Entity; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.EntityHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; +@DocletCategory("World") @Event("EntityUnload") public class EventEntityUnload extends BaseEvent { public final EntityHelper entity; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventJoinServer.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventJoinServer.java index 2d71adec3..ebcf53610 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventJoinServer.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventJoinServer.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; import net.minecraft.client.player.LocalPlayer; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.ClientPlayerEntityHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -10,6 +11,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Network/Chat") @Event(value = "JoinServer", oldName = "JOIN_SERVER") public class EventJoinServer extends BaseEvent { public final ClientPlayerEntityHelper player; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventNameChange.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventNameChange.java index 6705badae..b822a5a27 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventNameChange.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventNameChange.java @@ -3,6 +3,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.TextHelper; import com.jsmacrosce.jsmacros.client.api.helper.world.entity.EntityHelper; @@ -13,6 +14,7 @@ * @author aMelonRind * @since 1.9.1 */ +@DocletCategory("Network/Chat") @Event(value = "NameChange", cancellable = true) public class EventNameChange extends BaseEvent { public final EntityHelper entity; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventPlayerJoin.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventPlayerJoin.java index e5027c3da..d83938a71 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventPlayerJoin.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventPlayerJoin.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; import net.minecraft.client.multiplayer.PlayerInfo; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.PlayerListEntryHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -12,6 +13,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Network/Chat") @Event(value = "PlayerJoin", oldName = "PLAYER_JOIN") public class EventPlayerJoin extends BaseEvent { public final String UUID; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventPlayerLeave.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventPlayerLeave.java index b7dcf7684..5034ad610 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventPlayerLeave.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventPlayerLeave.java @@ -1,6 +1,7 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; import net.minecraft.client.multiplayer.PlayerInfo; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.helper.world.PlayerListEntryHelper; import com.jsmacrosce.jsmacros.core.event.BaseEvent; @@ -12,6 +13,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("Network/Chat") @Event(value = "PlayerLeave", oldName = "PLAYER_LEAVE") public class EventPlayerLeave extends BaseEvent { public final String UUID; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventSound.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventSound.java index 9a118c7da..58cc41d28 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventSound.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventSound.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.api.math.Pos3D; import com.jsmacrosce.jsmacros.client.JsMacrosClient; @@ -10,6 +11,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("World") @Event(value = "Sound", oldName = "SOUND", cancellable = true) public class EventSound extends BaseEvent { @DocletReplaceReturn("SoundId") diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventTick.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventTick.java index 3a2262101..84f2e285c 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventTick.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/event/impl/world/EventTick.java @@ -1,5 +1,6 @@ package com.jsmacrosce.jsmacros.client.api.event.impl.world; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.core.event.BaseEvent; import com.jsmacrosce.jsmacros.core.event.Event; @@ -8,6 +9,7 @@ * @author Wagyourtail * @since 1.2.7 */ +@DocletCategory("World") @Event(value = "Tick", oldName = "TICK") public class EventTick extends BaseEvent { public EventTick() { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/CommandContextHelper.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/CommandContextHelper.java index 647fc6c4c..b031e4382 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/CommandContextHelper.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/CommandContextHelper.java @@ -23,6 +23,7 @@ import net.minecraft.world.effect.MobEffect; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.level.block.state.pattern.BlockInWorld; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.classes.FakeServerCommandSource; import com.jsmacrosce.jsmacros.client.api.helper.inventory.EnchantmentHelper; @@ -39,6 +40,7 @@ /** * @since 1.4.2 */ +@DocletCategory("System/Lifecycle") @Event("CommandContext") @SuppressWarnings("unused") public class CommandContextHelper extends BaseEvent { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/CommandNodeHelper.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/CommandNodeHelper.java index 2f9936df6..fcf0ba359 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/CommandNodeHelper.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/CommandNodeHelper.java @@ -1,8 +1,10 @@ package com.jsmacrosce.jsmacros.client.api.helper; import com.mojang.brigadier.tree.CommandNode; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.core.helpers.BaseHelper; +@DocletCategory("Commands") public class CommandNodeHelper extends BaseHelper { public final CommandNode fabric; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/OptionsHelper.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/OptionsHelper.java index 1287c2ec6..abf7b0b43 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/OptionsHelper.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/OptionsHelper.java @@ -19,6 +19,7 @@ import net.minecraft.world.entity.player.PlayerModelPart; import org.apache.commons.lang3.ArrayUtils; import org.lwjgl.glfw.GLFW; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletDeclareType; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.doclet.DocletReplaceReturn; @@ -39,6 +40,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Configuration/Profiles") @SuppressWarnings("unused") public class OptionsHelper extends BaseHelper { @@ -390,6 +392,7 @@ private MixinSimpleOption getBase(OptionInstance option) { return (MixinSimpleOption) (Object) option; } + @DocletCategory("Configuration/Profiles") public class SkinOptionsHelper { public final OptionsHelper parent; @@ -567,6 +570,7 @@ public SkinOptionsHelper toggleMainHand(String hand) { } + @DocletCategory("Configuration/Profiles") public class VideoOptionsHelper { public final OptionsHelper parent; @@ -1125,6 +1129,7 @@ public VideoOptionsHelper enableAutosaveIndicator(boolean val) { } + @DocletCategory("Configuration/Profiles") public class MusicOptionsHelper { public final OptionsHelper parent; @@ -1406,6 +1411,7 @@ public MusicOptionsHelper showSubtitles(boolean val) { } + @DocletCategory("Configuration/Profiles") public class ControlOptionsHelper { public final OptionsHelper parent; @@ -1685,6 +1691,7 @@ public Map> getKeyBindsByCategory() { } + @DocletCategory("Configuration/Profiles") public class ChatOptionsHelper { public final OptionsHelper parent; @@ -2035,6 +2042,7 @@ public ChatOptionsHelper reduceDebugInfo(boolean val) { } + @DocletCategory("Configuration/Profiles") public class AccessibilityOptionsHelper { public final OptionsHelper parent; diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/CreativeItemStackHelper.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/CreativeItemStackHelper.java index 9ad647ffb..cf0f51358 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/CreativeItemStackHelper.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/CreativeItemStackHelper.java @@ -12,6 +12,7 @@ import net.minecraft.world.item.component.TooltipDisplay; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.ItemEnchantments; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.jsmacros.client.api.classes.TextBuilder; import com.jsmacrosce.jsmacros.client.api.helper.TextHelper; @@ -24,6 +25,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Items/Enchantments") @SuppressWarnings("unused") public class CreativeItemStackHelper extends ItemStackHelper { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/EnchantmentHelper.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/EnchantmentHelper.java index 866faff85..da5bd8a42 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/EnchantmentHelper.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/EnchantmentHelper.java @@ -8,6 +8,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.EnchantmentTags; import net.minecraft.world.item.enchantment.Enchantment; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.api.helper.TextHelper; @@ -20,6 +21,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Items/Enchantments") @SuppressWarnings("unused") public class EnchantmentHelper extends BaseHelper> { private static final Minecraft mc = Minecraft.getInstance(); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/FoodComponentHelper.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/FoodComponentHelper.java index e0a413864..609350297 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/FoodComponentHelper.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/FoodComponentHelper.java @@ -1,12 +1,14 @@ package com.jsmacrosce.jsmacros.client.api.helper.inventory; import net.minecraft.world.food.FoodProperties; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.core.helpers.BaseHelper; /** * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Items/Enchantments") @SuppressWarnings("unused") public class FoodComponentHelper extends BaseHelper { diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/ItemHelper.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/ItemHelper.java index eba50d4b9..f392cf3d6 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/ItemHelper.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/ItemHelper.java @@ -9,6 +9,7 @@ import net.minecraft.tags.DamageTypeTags; import net.minecraft.world.item.*; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.api.helper.TextHelper; import com.jsmacrosce.jsmacros.client.api.helper.world.BlockHelper; @@ -24,6 +25,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Items/Enchantments") @SuppressWarnings("unused") public class ItemHelper extends BaseHelper { private static final Minecraft mc = Minecraft.getInstance(); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/ItemStackHelper.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/ItemStackHelper.java index 33dfa4043..ec074325f 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/ItemStackHelper.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/ItemStackHelper.java @@ -22,6 +22,7 @@ import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.ItemEnchantments; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.doclet.DocletReplaceParams; import com.jsmacrosce.doclet.DocletReplaceReturn; import com.jsmacrosce.jsmacros.client.api.classes.RegistryHelper; @@ -42,6 +43,7 @@ /** * @author Wagyourtail */ +@DocletCategory("Items/Enchantments") @SuppressWarnings("unused") public class ItemStackHelper extends BaseHelper { private static final Style LORE_STYLE = Style.EMPTY.withColor(ChatFormatting.DARK_PURPLE).withItalic(true); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/RecipeHelper.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/RecipeHelper.java index ede46a0fd..786403cd4 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/RecipeHelper.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/inventory/RecipeHelper.java @@ -9,6 +9,7 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.display.RecipeDisplayEntry; import net.minecraft.world.item.crafting.display.SlotDisplayContext; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.core.helpers.BaseHelper; import java.util.ArrayList; @@ -19,6 +20,7 @@ * @author Wagyourtail * @since 1.3.1 */ +@DocletCategory("Items/Enchantments") @SuppressWarnings("unused") public class RecipeHelper extends BaseHelper { private static final Minecraft mc = Minecraft.getInstance(); diff --git a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/screen/ButtonWidgetHelper.java b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/screen/ButtonWidgetHelper.java index 37725a324..8c65d6752 100644 --- a/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/screen/ButtonWidgetHelper.java +++ b/common/src/main/java/com/jsmacrosce/jsmacros/client/api/helper/screen/ButtonWidgetHelper.java @@ -5,6 +5,7 @@ import net.minecraft.client.gui.components.WidgetSprites; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; +import com.jsmacrosce.doclet.DocletCategory; import com.jsmacrosce.jsmacros.client.JsMacrosClient; import com.jsmacrosce.jsmacros.client.api.classes.render.IScreen; import com.jsmacrosce.jsmacros.core.MethodWrapper; @@ -15,6 +16,7 @@ * @author Etheradon * @since 1.8.4 */ +@DocletCategory("Screen and UI Elements") public class ButtonWidgetHelper extends ClickableWidgetHelper, T> { public ButtonWidgetHelper(T btn) { @@ -29,6 +31,7 @@ public ButtonWidgetHelper(T btn, int zIndex) { * @author Etheradon * @since 1.8.4 */ + @DocletCategory("Screen and UI Elements") public static class ButtonBuilder extends AbstractWidgetBuilder> { @Nullable @@ -103,6 +106,7 @@ public ButtonWidgetHelper