Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Generate JSON docs with Gson #5738

Merged
merged 30 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0d21393
Start work on new json docs generation
Pikachu920 Jun 10, 2023
70f296f
Merge remote-tracking branch 'origin/master' into fix/json-docs
Pikachu920 Jun 11, 2023
bff5226
Add more to the JSON
Pikachu920 Jun 11, 2023
2c6841a
Add sections
Pikachu920 Aug 1, 2023
141cad5
Add ID generation to JSON docs
Pikachu920 Dec 19, 2023
724d3f0
Fix SkriptCommand errors
Pikachu920 Dec 19, 2023
e75278c
Add license header
Pikachu920 Dec 19, 2023
6dc3ee0
Merge branch 'dev/feature' into fix/json-docs
Pikachu920 Dec 19, 2023
9a540d9
Test duplicate checker
Pikachu920 Dec 19, 2023
b1fac55
Merge remote-tracking branch 'origin/fix/json-docs' into fix/json-docs
Pikachu920 Dec 19, 2023
1e141f4
Existing IDs actually start at 2
Pikachu920 Dec 19, 2023
856e81b
Address reviews
Pikachu920 Dec 19, 2023
2dfdfa3
Remove test class
Pikachu920 Dec 19, 2023
9b85439
Address reviews
Pikachu920 Dec 20, 2023
78b9c21
Merge branch 'dev/feature' into fix/json-docs
Pikachu920 Dec 21, 2023
0f72ebf
Address reviews
Pikachu920 Jan 2, 2024
fcfa58a
Try new way of generating IDs
Pikachu920 Sep 5, 2024
468dca7
Add license header
Pikachu920 Sep 5, 2024
2c1bad3
Merge branch 'dev/feature' into fix/json-docs
Pikachu920 Sep 5, 2024
73fa78d
Fix nullable import
Pikachu920 Sep 5, 2024
40f172c
Merge remote-tracking branch 'origin/dev/feature' into fix/json-docs
Pikachu920 Sep 5, 2024
80adf80
Add javadocs
Pikachu920 Sep 5, 2024
868d683
Remove license headers
Pikachu920 Sep 5, 2024
dc80514
Merge remote-tracking branch 'origin/fix/json-docs' into fix/json-docs
Pikachu920 Sep 5, 2024
36877c4
Address reviews
Pikachu920 Sep 6, 2024
9e33cf6
Address reviews
Pikachu920 Sep 6, 2024
704eb04
Address reviews
Pikachu920 Sep 9, 2024
33e3344
Address reviews
Pikachu920 Sep 9, 2024
ba63d20
Address reviews
Pikachu920 Sep 9, 2024
8866bf3
Merge branch 'dev/feature' into fix/json-docs
Pikachu920 Sep 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/main/java/ch/njol/skript/SkriptCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
import ch.njol.skript.aliases.Aliases;
import ch.njol.skript.command.CommandHelp;
import ch.njol.skript.doc.Documentation;
import ch.njol.skript.doc.DocumentationIdProvider;
import ch.njol.skript.doc.HTMLGenerator;
import ch.njol.skript.doc.JSONGenerator;
import ch.njol.skript.localization.ArgsMessage;
import ch.njol.skript.localization.Language;
import ch.njol.skript.localization.PluralizingArgsMessage;
Expand Down Expand Up @@ -403,9 +405,11 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
}
File outputDir = Documentation.getDocsOutputDirectory();
outputDir.mkdirs();
HTMLGenerator generator = new HTMLGenerator(templateDir, outputDir);
HTMLGenerator htmlGenerator = new HTMLGenerator(templateDir, outputDir);
JSONGenerator jsonGenerator = new JSONGenerator(templateDir, outputDir);
Skript.info(sender, "Generating docs...");
generator.generate(); // Try to generate docs... hopefully
htmlGenerator.generate(); // Try to generate docs... hopefully
jsonGenerator.generate();
Skript.info(sender, "Documentation generated!");
} else if (args[0].equalsIgnoreCase("test") && TestMode.DEV_MODE) {
File scriptFile;
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/ch/njol/skript/doc/DocumentationGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ch.njol.skript.doc;

import java.io.File;

/**
* Represents a class which generates a documentation format (like HTML or JSON)
*/
public abstract class DocumentationGenerator {

protected File templateDir;
protected File outputDir;

public DocumentationGenerator(File templateDir, File outputDir) {
this.templateDir = templateDir;
this.outputDir = outputDir;
}

/**
* Generates the documentation file
*/
public abstract void generate();

}
145 changes: 145 additions & 0 deletions src/main/java/ch/njol/skript/doc/DocumentationIdProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package ch.njol.skript.doc;

import ch.njol.skript.Skript;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.lang.Condition;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.Section;
import ch.njol.skript.lang.SkriptEventInfo;
import ch.njol.skript.lang.SyntaxElementInfo;
import ch.njol.skript.lang.function.Function;
import ch.njol.skript.lang.function.Functions;
import ch.njol.skript.registrations.Classes;
import org.skriptlang.skript.lang.structure.Structure;

import java.util.Iterator;
import java.util.Objects;
import java.util.function.Predicate;

public class DocumentationIdProvider {
Pikachu920 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Some syntax classes are registered more than once. This method applies a suffix
* to the id in order to differentiate them
* @param id the potentially conflicting ID
* @param collisionCount the number of conflicts this element has
* @return the unique ID for the element
*/
private static String addCollisionSuffix(String id, int collisionCount) {
if (collisionCount == 0) {
return id;
}
return id + "-" + (collisionCount + 1);
}

/**
* Calculates the number of collisions in an iterator
* @param potentialCollisions the iterator of potential collisions
* @param collisionCriteria a predicate which checks whether a potential collision is really a collision
* @param equalsCriteria a predicate which checks whether a potential collision equals the current element we are generating
* @return the number of collisions in potentialCollisions up until equalsCriteria was true
*/
private static <T> int calculateCollisionCount(Iterator<? extends T> potentialCollisions, Predicate<T> collisionCriteria,
Predicate<T> equalsCriteria) {
Comment on lines +43 to +44
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this indentation doing?

int collisionCount = 0;
while (potentialCollisions.hasNext()) {
T potentialCollision = potentialCollisions.next();
if (collisionCriteria.test(potentialCollision)) {
if (equalsCriteria.test(potentialCollision)) {
break;
}
collisionCount += 1;
}
}
return collisionCount;
}

/**
* Gets the documentation ID of a syntax element
* @param syntaxInfo the SyntaxElementInfo to get the ID of
* @return the ID of the syntax element
*/
public static <T> String getId(SyntaxElementInfo<? extends T> syntaxInfo) {
Class<?> syntaxClass = syntaxInfo.getElementClass();
Iterator<? extends SyntaxElementInfo<?>> syntaxElementIterator;
if (Effect.class.isAssignableFrom(syntaxClass)) {
syntaxElementIterator = Skript.getEffects().iterator();
} else if (Condition.class.isAssignableFrom(syntaxClass)) {
syntaxElementIterator = Skript.getConditions().iterator();
} else if (Expression.class.isAssignableFrom(syntaxClass)) {
syntaxElementIterator = Skript.getExpressions();
} else if (Section.class.isAssignableFrom(syntaxClass)) {
syntaxElementIterator = Skript.getSections().iterator();
} else if (Structure.class.isAssignableFrom(syntaxClass)) {
syntaxElementIterator = Skript.getStructures().iterator();
} else {
throw new IllegalStateException("Unsupported syntax type provided");
}
int collisionCount = calculateCollisionCount(syntaxElementIterator,
elementInfo -> elementInfo.getElementClass() == syntaxClass,
elementInfo -> elementInfo == syntaxInfo);
DocumentationId documentationIdAnnotation = syntaxClass.getAnnotation(DocumentationId.class);
if (documentationIdAnnotation == null) {
return addCollisionSuffix(syntaxClass.getSimpleName(), collisionCount);
}
return addCollisionSuffix(documentationIdAnnotation.value(), collisionCount);
}

/**
* Gets the documentation ID of a function
* @param function the function to get the ID of
* @return the documentation ID of the function
*/
public static String getId(Function<?> function) {
int collisionCount = calculateCollisionCount(Functions.getJavaFunctions().iterator(),
javaFunction -> function.getName().equals(javaFunction.getName()),
javaFunction -> javaFunction == function);
return addCollisionSuffix(function.getName(), collisionCount);
}

/**
* Gets either the explicitly declared documentation ID or code name of a classinfo
* @param classInfo the ClassInfo to get the ID of
* @return the ID of the ClassInfo
*/
private static String getClassInfoId(ClassInfo<?> classInfo) {
return Objects.requireNonNullElse(classInfo.getDocumentationID(), classInfo.getCodeName());
}

/**
* Gets the documentation ID of a ClassInfo
* @param classInfo the ClassInfo to get the ID of
* @return the ID of the ClassInfo
*/
public static String getId(ClassInfo<?> classInfo) {
String classInfoId = getClassInfoId(classInfo);
int collisionCount = calculateCollisionCount(Classes.getClassInfos().iterator(),
otherClassInfo -> classInfoId.equals(getClassInfoId(otherClassInfo)),
otherClassInfo -> classInfo == otherClassInfo);
return addCollisionSuffix(classInfoId, collisionCount);
}

/**
* Gets either the explicitly declared documentation ID or default ID of an event
* @param eventInfo the event to get the ID of
* @return the ID of the event
*/
private static String getEventId(SkriptEventInfo<?> eventInfo) {
return Objects.requireNonNullElse(eventInfo.getDocumentationID(), eventInfo.getId());
}

/**
* Gets the documentation ID of an event
* @param eventInfo the event to get the ID of
* @return the ID of the event
*/
public static String getId(SkriptEventInfo<?> eventInfo) {
String eventId = getEventId(eventInfo);
int collisionCount = calculateCollisionCount(Skript.getEvents().iterator(),
otherEventInfo -> eventId.equals(getEventId(otherEventInfo)),
otherEventInfo -> otherEventInfo == eventInfo);
return addCollisionSuffix(eventId, collisionCount);
}

}
Loading
Loading