Skip to content

Commit 9deea57

Browse files
authored
Document via Descriptor and adjust Recipe Builder (#302)
* add method to generate based on descriptor * apply MethodOverride * adjust import sort order * extract noise from Documentation * shorten Predicate line * extract Exporter.signature code and rename * minor cleanup and simplification * apply override capability to builder * apply RecipeBuilderOverride * fix dissolver not overriding parent * replace duplicate list with name to signature map * add title and description to RBD * apply custom builder titles and descriptions * fix format being used oddly * fix Miniaturization duration method * fix dissolver using output * fix typo with roots predicates * fix fountain using duplicate lang keys * move descriptor helper and extract inner class * create ComparisonHelper and apply * log skipped classes as debug * remove getName from MethodAnnotation * rework how skipped classes are logged * move helper classes into specific folder * format doesnt get used there * fix minor typos * ensure slash in link generators * suppress invalid string buffer warnings * adjust description helper * extract and fix defaultValueConverter * default value for longs have L * improve javadoc localization key examples * update example docs
1 parent b0914ab commit 9deea57

File tree

72 files changed

+1441
-960
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1441
-960
lines changed

examples/postInit/roots.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,8 @@ mods.roots.pacifist.recipeBuilder()
208208

209209

210210
// Predicates:
211-
// Predicates are used in Transmution and RunicShearBlock. They either match all blockstates of a block, or all blockstates
212-
// that have the given properties that match the input blockstate.
211+
// Predicates are used in Transmutation and RunicShearBlock. They either match all blockstates of a block, or all
212+
// blockstates that have the given properties that match the input blockstate.
213213

214214
mods.roots.predicates.stateBuilder()
215215
.blockstate(blockstate('minecraft:red_flower'))

src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Admonition.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* The localization key for the admonition description, should be in the format of
1919
* <br>
2020
* <code>
21-
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.note{index of note in array}
21+
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.note{index}
2222
* </code>
2323
*
2424
* @return localization key for the admonition description

src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Example.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,15 @@
2727
public @interface Example {
2828

2929
/**
30-
* For recipe builders, this will be a string that is a valid one-line series of methods to create a Recipe Builder that will
30+
* For basic recipe builders, this will be a string that is a valid one-line series of methods to create a Recipe Builder that will
3131
* pass the {@link com.cleanroommc.groovyscript.helper.recipe.IRecipeBuilder#validate() IRecipeBuilder#validate()} check and be successfully registered.
32-
* <br>
33-
* For methods, this should be exclusive the parameters of the method. e.g. {@code "item('minecraft:clay')"}<br>
32+
* {@code ".do('thing').and('other')"}
33+
* <p>
34+
* For complex recipe builders, those that have one or more parameters, in the creation method,
35+
* the above is true after an initial segment for the creation. {@code "('init').do('thing').and('other')"}
36+
* <p>
37+
* For methods, this should be exclusive the parameters of the method. e.g. {@code "item('minecraft:clay')"}
38+
* <p>
3439
* Any comments for the wiki should be marked by
3540
* <code>
3641
* /*()*{@literal /}

src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/MethodDescription.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@
1111
* All fields are optional, and most have default values generated in {@link Example}.
1212
*
1313
* <ul>
14+
* <li>{@link #method()} either contains nothing if annotated on a method or contains a
15+
* string that targets the desired method in conjunction with {@link MethodOverride}.
16+
* To target a method, if only a single method has the given name, excluding
17+
* bridge, non-public, Object, or methods annotated with {@link com.cleanroommc.groovyscript.api.GroovyBlacklist},
18+
* the target may be the method name.
19+
* Otherwise, the target must be the name and full descriptor of the method.</li>
1420
* <li>{@link #description()} is a localization key that is autogenerated to be
1521
* <code>
16-
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.{@link Method#getName()}
22+
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}
1723
* </code>
1824
* </li>
1925
* <li>{@link #example()} is an array of {@link Example}s In situations where either a single {@link Example} with multiple lines or
@@ -28,16 +34,32 @@
2834
@Target(ElementType.METHOD)
2935
public @interface MethodDescription {
3036

37+
/**
38+
* If this {@link MethodDescription} annotation is attached to a method, this element is set to the name of the method they are attached to.
39+
* When annotated on a method directly, this should not be set, as it has no functionality.
40+
* <br>
41+
* If this is not annotated to a method, this should either be the method name
42+
* (if only a single method has the given name)
43+
* or needs to be the name and full descriptor of the method.
44+
* <br>
45+
* Methods that are bridge, non-public, Object, or methods annotated with {@link com.cleanroommc.groovyscript.api.GroovyBlacklist}
46+
* cannot be targeted.
47+
*
48+
* @return the target method, if not annotated to a method directly.
49+
* @see MethodOverride
50+
*/
51+
String method() default "";
52+
3153
/**
3254
* The localization key for a description of the compat.
3355
* <br>
3456
* Generates a description via minecraft's localization files via
3557
* <code>{@link net.minecraft.client.resources.I18n#format(String, Object...) I18n.format(description())}</code>
3658
* <br>
3759
* If this is empty, will fall back to generating a description based on
38-
* <code>groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.{@link Method#getName()}</code>.
60+
* <code>groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}</code>.
3961
* Then, if that does not have a lang key defined, it will attempt to use a global lang key based on the method name
40-
* <code>groovyscript.wiki.{@link Method#getName()}</code>
62+
* <code>groovyscript.wiki.{@link Method#getName() {methodName}}</code>
4163
* if that also does not have a lang key defined, will log a missing key in the {@code groovy.log} file.
4264
*
4365
* @return localization key for method description
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.cleanroommc.groovyscript.api.documentation.annotations;
2+
3+
import java.lang.annotation.Retention;
4+
import java.lang.annotation.RetentionPolicy;
5+
import java.lang.annotation.Target;
6+
7+
/**
8+
* Allows a {@link RegistryDescription} to override any
9+
* {@link MethodDescription} or {@link RecipeBuilderDescription} declarations.
10+
* <p>
11+
* Methods can be referred to by name if there is only one method with the given name
12+
* in the class, otherwise must be referred to by the method name + method signature.
13+
* <p>
14+
* While this can be used for any method, it is preferred to only use it for
15+
* methods that require it - namely, methods that are declared in a parent class
16+
* and not overridden in the focused class.
17+
*/
18+
@Retention(RetentionPolicy.RUNTIME)
19+
@Target({}) // No targets allowed
20+
public @interface MethodOverride {
21+
22+
/**
23+
* An override to other {@link MethodDescription} declarations, and only used for {@link MethodDescription} instances which
24+
* should have custom data for the class they are accessed from.
25+
*
26+
* @return array of method description annotations for the class
27+
* @see MethodDescription
28+
*/
29+
MethodDescription[] method() default {};
30+
31+
/**
32+
* An override to other {@link RecipeBuilderDescription} declarations, and only used for {@link RecipeBuilderDescription} instances which
33+
* should have custom data for the class they are accessed from.
34+
*
35+
* @return array of method description annotations for the class
36+
* @see RecipeBuilderDescription
37+
*/
38+
RecipeBuilderDescription[] recipeBuilder() default {};
39+
}

src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Property.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
* </li>
1717
* <li>
1818
* {@link ElementType#METHOD}: Marks the field targeted by {@link #property()} within the class the attached method returns with this {@link Property}.
19-
* Can only be attached via being inside {@link RecipeBuilderDescription#requirement()}.
19+
* Can be attached via being inside {@link RecipeBuilderOverride#requirement()}.
2020
* </li>
2121
* </ul>
2222
* <p>
2323
* Elements:
2424
* <ul>
2525
* <li>{@link #value()} is a localization key that is autogenerated to be
2626
* <code>
27-
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link Field#getName()}.value
27+
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Field#getName() {fieldName}}.value
2828
* </code>
2929
* and states what the property does.
3030
* </li>
@@ -53,7 +53,7 @@
5353
/**
5454
* The localization key for the name of the compat, will default to generating
5555
* <code>
56-
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.{@link Field#getName()}.value
56+
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Field#getName() {fieldName}}.value
5757
* </code>
5858
*
5959
* @return localization key for what the target field will accomplish
@@ -219,7 +219,7 @@
219219
* Wrapper to allow repeatable instances of {@link Property}.
220220
* If more than one {@link Property} is applied to anywhere other than a class, it will generate an error.
221221
* For a given Field. only a single {@link Property} should be attached,
222-
* and for a given Method, all {@link Property} annotations should be placed inside {@link RecipeBuilderDescription#requirement()}
222+
* and for a given Method, all {@link Property} annotations should be placed inside {@link RecipeBuilderOverride#requirement()}
223223
*
224224
* @see Property
225225
*/

src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderDescription.java

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,101 @@
44
import java.lang.annotation.Retention;
55
import java.lang.annotation.RetentionPolicy;
66
import java.lang.annotation.Target;
7-
import java.lang.reflect.Field;
7+
import java.lang.reflect.Method;
88

99
/**
1010
* Marks the given Method as the initializing method for a Recipe Builder, indicating it returns a Recipe Builder class.<br>
1111
* A Recipe Builder is a class which follows the Builder design pattern, where each step of the builder returns the builder class,
1212
* allowing chaining of methods to quickly and cleanly create complicated objects which may or may not require some values.
1313
*
1414
* <ul>
15-
* <li>{@link #example()} is an array of {@link Example}s In situations where either a single {@link Example} with multiple lines or
16-
* multiple {@link Example}s could be used, using multiple {@link Example}s is preferable.</li>
17-
* <li>{@link #requirement()} is a localization key that is autogenerated to be
15+
* <li>{@link #title()} is a localization key that is autogenerated to be
1816
* <code>
19-
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.{@link Field#getName()}
17+
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}.title
2018
* </code>
19+
* to name the Recipe Builder.
2120
* </li>
21+
* <li>{@link #description()} is a localization key that is autogenerated to be
22+
* <code>
23+
* groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}.description
24+
* </code>
25+
* to describe the method used to create the Recipe Builder.
26+
* </li>
27+
* <li>{@link #method()} either contains nothing if annotated on a method or contains a
28+
* string that targets the desired method in conjunction with {@link MethodOverride}.
29+
* To target a method, if only a single method has the given name, excluding
30+
* bridge, non-public, Object, or methods annotated with {@link com.cleanroommc.groovyscript.api.GroovyBlacklist},
31+
* the target may be the method name.
32+
* Otherwise, the target must be the name and full descriptor of the method.</li>
33+
* <li>{@link #clazz()} is the class being targeted by the recipe builder. By default this is the return value of the method.</li>
34+
* <li>{@link #example()} is an array of {@link Example}s In situations where either a single {@link Example} with multiple lines or
35+
* multiple {@link Example}s could be used, using multiple {@link Example}s is preferable.</li>
36+
* <li>{@link #override()} allows creating overrides for the {@link Property}, {@link RecipeBuilderMethodDescription}, and {@link RecipeBuilderRegistrationMethod}
37+
* annotated in the builder using {@link RecipeBuilderOverride}.</li>
2238
* <li>{@link #priority()} is an integer that influences the sorting of the {@link RecipeBuilderDescription} relative to other {@link RecipeBuilderDescription}s.</li>
2339
* </ul>
2440
*/
2541
@Retention(RetentionPolicy.RUNTIME)
2642
@Target(ElementType.METHOD)
2743
public @interface RecipeBuilderDescription {
2844

45+
/**
46+
* The localization key for the name of the builder, if different from Recipe Builder.
47+
* <br>
48+
* This should be used when there is more than one way to create a Recipe Builder
49+
* for the given class.
50+
* <br>
51+
* Generates the title via minecraft's localization files via
52+
* <code>{@link net.minecraft.client.resources.I18n#format(String, Object...) I18n.format(description())}</code>
53+
* <br>
54+
* If this is empty, will fall back to generating a description based on
55+
* <code>groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}.title</code>.
56+
* Then, if that does not have a lang key defined, it will use the global default for recipe builders of
57+
* <code>groovyscript.wiki.recipe_builder.title</code>.
58+
*
59+
* @return localization key for method title
60+
*/
61+
String title() default "";
62+
63+
/**
64+
* The localization key for a description of the compat.
65+
* <br>
66+
* This should always be used when the creation method accepts parameters.
67+
* In most cases this should be changed so that each parameter is an individual builder method,
68+
* but in some situations this is not possible, and so must be documented accordingly.
69+
* <br>
70+
* When a builder method with one or more parameters does not have a localization key set,
71+
* if it does not use a lang key, it will log a missing key in the {@code groovy.log} file.
72+
* <br>
73+
* Generates a description via minecraft's localization files via
74+
* <code>{@link net.minecraft.client.resources.I18n#format(String, Object...) I18n.format(description())}</code>
75+
* <br>
76+
* If this is empty, will fall back to generating a description based on
77+
* <code>groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}.description</code>.
78+
* Then, if that does not have a lang key defined, it will use the global default for recipe builders of
79+
* <code>groovyscript.wiki.recipe_builder.description</code>.
80+
*
81+
* @return localization key for method description
82+
*/
83+
String description() default "";
84+
85+
/**
86+
* If this {@link RecipeBuilderDescription} annotation is attached to a method, this element is set to the name of the method they are attached to.
87+
* When annotated on a method directly, this should not be set, as it has no functionality.
88+
*
89+
* @return the target method, if not annotated to a method directly.
90+
* @see MethodOverride
91+
*/
92+
String method() default "";
93+
94+
/**
95+
* The builder class. By default, this will use the return class of the target method.
96+
* If this is undesired, specify the real class here.
97+
*
98+
* @return the class used by the builder, if different from the return type of the target method
99+
*/
100+
Class<?> clazz() default void.class;
101+
29102
/**
30103
* An array of examples, which will then be formatted and generated for both the wiki and the text script files.
31104
*
@@ -40,9 +113,24 @@
40113
*
41114
* @return array of requirements unique to the recipe builder being accessed via this method
42115
* @see Property
116+
* @deprecated use {@link #override()} and {@link RecipeBuilderOverride#requirement()}
43117
*/
118+
@Deprecated
44119
Property[] requirement() default {};
45120

121+
/**
122+
* Allows overriding the {@link Property}, {@link RecipeBuilderMethodDescription}, and {@link RecipeBuilderRegistrationMethod} annotations
123+
* for the builder class.
124+
* This should only be used in situations where custom data that does not apply to the class normally
125+
* is used.
126+
*
127+
* @return overrides for the Recipe Builder annotations
128+
* @see Property
129+
* @see RecipeBuilderMethodDescription
130+
* @see RecipeBuilderRegistrationMethod
131+
*/
132+
RecipeBuilderOverride override() default @RecipeBuilderOverride;
133+
46134
/**
47135
* Priority of the method, relative to other Recipe Builder methods in the same class.
48136
* Priorities sort entries such that lowest is first, with ties being broken via alphabetical sorting of the method name.

0 commit comments

Comments
 (0)