From ff0b9878d493144e0b0f9ead066e61398bb8cb75 Mon Sep 17 00:00:00 2001
From: Ayham Al-Ali <20037329+AyhamAl-Ali@users.noreply.github.com>
Date: Wed, 10 May 2023 03:10:32 +0300
Subject: [PATCH 1/3] Add Accepted ChangeModes to docs
- Enhancements: Pre-Compile some regex patterns
- Enhancement: Removed some duplicated null checks
- Ignore Skript errors in getAcceptedChangeModes method
---
.../njol/skript/doc/AcceptedChangeModes.java | 40 +++++++++++++
.../ch/njol/skript/doc/HTMLGenerator.java | 57 +++++++++++++------
.../java/ch/njol/skript/lang/Expression.java | 41 ++++++-------
3 files changed, 102 insertions(+), 36 deletions(-)
create mode 100644 src/main/java/ch/njol/skript/doc/AcceptedChangeModes.java
diff --git a/src/main/java/ch/njol/skript/doc/AcceptedChangeModes.java b/src/main/java/ch/njol/skript/doc/AcceptedChangeModes.java
new file mode 100644
index 00000000000..44bf36aaa12
--- /dev/null
+++ b/src/main/java/ch/njol/skript/doc/AcceptedChangeModes.java
@@ -0,0 +1,40 @@
+/**
+ * This file is part of Skript.
+ *
+ * Skript is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Skript is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Skript. If not, see .
+ *
+ * Copyright Peter Güttinger, SkriptLang team and contributors
+ */
+package ch.njol.skript.doc;
+
+import ch.njol.skript.classes.Changer;
+
+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;
+
+/**
+ * Provides a list of accepted {@link ch.njol.skript.classes.Changer.ChangeMode}s to be used in documentation for annotated
+ * elements.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface AcceptedChangeModes {
+
+ public Changer.ChangeMode[] value();
+
+}
diff --git a/src/main/java/ch/njol/skript/doc/HTMLGenerator.java b/src/main/java/ch/njol/skript/doc/HTMLGenerator.java
index 0da3679904c..27f1d007dba 100644
--- a/src/main/java/ch/njol/skript/doc/HTMLGenerator.java
+++ b/src/main/java/ch/njol/skript/doc/HTMLGenerator.java
@@ -20,6 +20,7 @@
import ch.njol.skript.Skript;
import ch.njol.skript.SkriptAPIException;
+import ch.njol.skript.classes.Changer;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.lang.Condition;
import ch.njol.skript.lang.Effect;
@@ -31,6 +32,7 @@
import ch.njol.skript.lang.function.Functions;
import ch.njol.skript.lang.function.JavaFunction;
import ch.njol.skript.lang.function.Parameter;
+import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.skript.registrations.Classes;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
@@ -46,6 +48,7 @@
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
@@ -64,6 +67,8 @@ public class HTMLGenerator {
private static final String SKRIPT_VERSION = Skript.getVersion().toString().replaceAll("-(dev|alpha|beta)\\d*", ""); // Filter branches
private static final Pattern NEW_TAG_PATTERN = Pattern.compile(SKRIPT_VERSION + "(?!\\.)"); // (?!\\.) to avoid matching 2.6 in 2.6.1 etc.
private static final Pattern RETURN_TYPE_LINK_PATTERN = Pattern.compile("( ?href=\"(classes\\.html|)#|)\\$\\{element\\.return-type-linkcheck}");
+ private static final Pattern DOCS_PASSED_FOLDERS_PATTERN = Pattern.compile("css|js|assets");
+ private static final Pattern DOCS_ACCEPTED_FILES_PATTERN = Pattern.compile("(?i)(.*)\\.(html?|js|css|json)");
private final File template;
private final File output;
@@ -210,9 +215,9 @@ public int compare(@Nullable JavaFunction> o1, @Nullable JavaFunction> o2) {
*/
@SuppressWarnings("unchecked")
public void generate() {
- for (File f : template.listFiles()) {
- if (f.getName().matches("css|js|assets")) { // Copy CSS/JS/Assets folders
- String slashName = "/" + f.getName();
+ for (File file : template.listFiles()) {
+ if (DOCS_PASSED_FOLDERS_PATTERN.matcher(file.getName()).matches()) { // Copy CSS/JS/Assets folders
+ String slashName = "/" + file.getName();
File fileTo = new File(output + slashName);
fileTo.mkdirs();
for (File filesInside : new File(template + slashName).listFiles()) {
@@ -223,7 +228,7 @@ public void generate() {
writeFile(new File(fileTo + "/" + filesInside.getName()), readFile(filesInside));
}
- else if (!filesInside.getName().matches("(?i)(.*)\\.(html?|js|css|json)")) {
+ else if (!DOCS_ACCEPTED_FILES_PATTERN.matcher(filesInside.getName()).matches()) {
try {
Files.copy(filesInside, new File(fileTo + "/" + filesInside.getName()));
} catch (IOException e) {
@@ -233,23 +238,23 @@ else if (!filesInside.getName().matches("(?i)(.*)\\.(html?|js|css|json)")) {
}
}
continue;
- } else if (f.isDirectory()) // Ignore other directories
+ } else if (file.isDirectory()) // Ignore other directories
continue;
- if (f.getName().endsWith("template.html") || f.getName().endsWith(".md"))
+ if (file.getName().endsWith("template.html") || file.getName().endsWith(".md"))
continue; // Ignore skeleton and README
- Skript.info("Creating documentation for " + f.getName());
+ Skript.info("Creating documentation for " + file.getName());
- String content = readFile(f);
+ String content = readFile(file);
String page;
- if (f.getName().endsWith(".html"))
+ if (file.getName().endsWith(".html"))
page = skeleton.replace("${content}", content); // Content to inside skeleton
else // Not HTML, so don't even try to use template.html
page = content;
page = page.replace("${skript.version}", Skript.getVersion().toString()); // Skript version
page = page.replace("${skript.build.date}", new SimpleDateFormat("dd/MM/yyyy").format(new Date())); // Build date
- page = page.replace("${pagename}", f.getName().replace(".html", ""));
+ page = page.replace("${pagename}", file.getName().replace(".html", ""));
List replace = Lists.newArrayList();
int include = page.indexOf("${include"); // Single file includes
@@ -375,7 +380,7 @@ else if (!filesInside.getName().matches("(?i)(.*)\\.(html?|js|css|json)")) {
generate = page.indexOf("${generate", nextBracket);
}
- String name = f.getName();
+ String name = file.getName();
if (name.endsWith(".html")) { // Fix some stuff specially for HTML
page = page.replace("\t", " "); // Tab to 4 non-collapsible spaces
assert page != null;
@@ -493,12 +498,12 @@ private String generateAnnotated(String descTemp, SyntaxElementInfo> info, @Nu
}
desc = desc.replace("${element.events}", Joiner.on(", ").join(eventLinks));
}
- desc = desc.replace("${element.events-safe}", events == null ? "" : Joiner.on(", ").join((events != null ? events.value() : null)));
+ desc = desc.replace("${element.events-safe}", events == null ? "" : Joiner.on(", ").join(events.value()));
// RequiredPlugins
RequiredPlugins plugins = c.getAnnotation(RequiredPlugins.class);
desc = handleIf(desc, "${if required-plugins}", plugins != null);
- desc = desc.replace("${element.required-plugins}", plugins == null ? "" : Joiner.on(", ").join((plugins != null ? plugins.value() : null)));
+ desc = desc.replace("${element.required-plugins}", plugins == null ? "" : Joiner.on(", ").join(plugins.value()));
// Return Type
ClassInfo> returnType = info instanceof ExpressionInfo ? Classes.getSuperClassInfo(((ExpressionInfo,?>) info).getReturnType()) : null;
@@ -511,6 +516,24 @@ private String generateAnnotated(String descTemp, SyntaxElementInfo> info, @Nu
// desc = desc.replace("${element.by-addon}", addon);
desc = handleIf(desc, "${if by-addon}", false);
+ // Accepted Changers
+ if (info instanceof ExpressionInfo,?>) {
+ List acceptedChangeModes = new ArrayList<>(4); // 4 is common, SET/ADD/REMOVE/DELETE
+ AcceptedChangeModes annotation = c.getAnnotation(AcceptedChangeModes.class);
+ if (annotation != null) {
+ acceptedChangeModes = Arrays.stream(annotation.value()).toList();
+ } else {
+ try {
+ acceptedChangeModes = ((SimpleExpression>) info.getElementClass().newInstance()).getAcceptedChangeModes().keySet().stream().toList();
+ } catch (Exception ignored) {}
+ }
+
+ desc = handleIf(desc, "${if accepted-change-modes}", acceptedChangeModes.size() > 0);
+ desc = desc.replace("${element.accepted-change-modes}", acceptedChangeModes.size() == 0 ? "" :Joiner.on(", ").join(acceptedChangeModes.toArray()));
+ } else {
+ desc = handleIf(desc, "${if accepted-change-modes}", false);
+ }
+
// New Elements
desc = handleIf(desc, "${if new-element}", NEW_TAG_PATTERN.matcher((since != null ? since.value() : "")).find());
@@ -625,12 +648,12 @@ private String generateEvent(String descTemp, SkriptEventInfo> info, @Nullable
}
desc = desc.replace("${element.events}", Joiner.on(", ").join(eventLinks));
}
- desc = desc.replace("${element.events-safe}", events == null ? "" : Joiner.on(", ").join((events != null ? events.value() : null)));
+ desc = desc.replace("${element.events-safe}", events == null ? "" : Joiner.on(", ").join(events.value()));
// Required Plugins
String[] requiredPlugins = info.getRequiredPlugins();
desc = handleIf(desc, "${if required-plugins}", requiredPlugins != null);
- desc = desc.replace("${element.required-plugins}", Joiner.on(", ").join(requiredPlugins == null ? new String[0] : requiredPlugins));
+ desc = desc.replace("${element.required-plugins}", requiredPlugins == null ? "" : Joiner.on(", ").join(requiredPlugins));
// New Elements
desc = handleIf(desc, "${if new-element}", NEW_TAG_PATTERN.matcher(since).find());
@@ -729,12 +752,12 @@ private String generateClass(String descTemp, ClassInfo> info, @Nullable Strin
}
desc = desc.replace("${element.events}", Joiner.on(", ").join(eventLinks));
}
- desc = desc.replace("${element.events-safe}", events == null ? "" : Joiner.on(", ").join((events != null ? events.value() : null)));
+ desc = desc.replace("${element.events-safe}", events == null ? "" : Joiner.on(", ").join(events.value()));
// Required Plugins
String[] requiredPlugins = info.getRequiredPlugins();
desc = handleIf(desc, "${if required-plugins}", requiredPlugins != null);
- desc = desc.replace("${element.required-plugins}", Joiner.on(", ").join(requiredPlugins == null ? new String[0] : requiredPlugins));
+ desc = desc.replace("${element.required-plugins}", requiredPlugins == null ? "" : Joiner.on(", ").join(requiredPlugins));
// New Elements
desc = handleIf(desc, "${if new-element}", NEW_TAG_PATTERN.matcher(since).find());
diff --git a/src/main/java/ch/njol/skript/lang/Expression.java b/src/main/java/ch/njol/skript/lang/Expression.java
index 413c9103e10..e839d920564 100644
--- a/src/main/java/ch/njol/skript/lang/Expression.java
+++ b/src/main/java/ch/njol/skript/lang/Expression.java
@@ -18,26 +18,17 @@
*/
package ch.njol.skript.lang;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Spliterators;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-import org.bukkit.event.Event;
-import org.bukkit.inventory.ItemStack;
-import org.eclipse.jdt.annotation.Nullable;
-
import ch.njol.skript.Skript;
import ch.njol.skript.classes.Changer;
import ch.njol.skript.classes.Changer.ChangeMode;
import ch.njol.skript.classes.Changer.ChangerUtils;
-import org.skriptlang.skript.lang.converter.Converter;
import ch.njol.skript.conditions.CondIsSet;
import ch.njol.skript.lang.util.ConvertedExpression;
import ch.njol.skript.lang.util.SimpleExpression;
+import ch.njol.skript.log.BlockingLogHandler;
import ch.njol.skript.log.ErrorQuality;
+import ch.njol.skript.log.LogHandler;
+import ch.njol.skript.log.SkriptLogger;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.util.slot.Slot;
import ch.njol.util.Checker;
@@ -45,9 +36,11 @@
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import org.skriptlang.skript.lang.converter.Converter;
-import java.util.Arrays;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import java.util.Optional;
import java.util.Spliterators;
import java.util.stream.Stream;
@@ -291,15 +284,25 @@ default Optional getOptionalSingle(Event e) {
public Class>[] acceptChange(ChangeMode mode);
/**
- * Tests all accepted change modes, and if so what type it expects the delta
to be.
+ * Tests all accepted change modes, and if so what data type it expects the delta
to be.
+ * Keep in mind that this can't be very accurate if a change mode requires a specific condition to be met
+ * this will not be able to grab that most likely, therefore {@link ch.njol.skript.doc.AcceptedChangeModes} annotation
+ * exists to override the accepted change modes value in docs however, currently that annotation is missing the accepted data type.
+ *
+ * Skript errors that occur during testing {@link #acceptChange(ChangeMode)} method will be ignored.
* @return A Map contains ChangeMode as the key and accepted types of that mode as the value
*/
default Map[]> getAcceptedChangeModes() {
- HashMap[]> map = new HashMap<>();
- for (ChangeMode cm : ChangeMode.values()) {
- Class>[] ac = acceptChange(cm);
- if (ac != null)
- map.put(cm, ac);
+ LogHandler logHandler = SkriptLogger.startLogHandler(new BlockingLogHandler());
+ Map[]> map = new HashMap<>();
+ try {
+ for (ChangeMode cm : ChangeMode.values()) {
+ Class>[] ac = acceptChange(cm);
+ if (ac != null)
+ map.put(cm, ac);
+ }
+ } finally {
+ logHandler.stop();
}
return map;
}
From b37394f2a6af521c4170c0f8d1df7cb16d276958 Mon Sep 17 00:00:00 2001
From: Ayham Al-Ali <20037329+AyhamAl-Ali@users.noreply.github.com>
Date: Wed, 10 May 2023 03:11:26 +0300
Subject: [PATCH 2/3] Add TODO comment
---
src/main/java/ch/njol/skript/doc/HTMLGenerator.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/main/java/ch/njol/skript/doc/HTMLGenerator.java b/src/main/java/ch/njol/skript/doc/HTMLGenerator.java
index 27f1d007dba..eb454a9fbd2 100644
--- a/src/main/java/ch/njol/skript/doc/HTMLGenerator.java
+++ b/src/main/java/ch/njol/skript/doc/HTMLGenerator.java
@@ -517,6 +517,7 @@ private String generateAnnotated(String descTemp, SyntaxElementInfo> info, @Nu
desc = handleIf(desc, "${if by-addon}", false);
// Accepted Changers
+ // TODO grab the accepted data type as well (find a way to include that in annotation as well)
if (info instanceof ExpressionInfo,?>) {
List acceptedChangeModes = new ArrayList<>(4); // 4 is common, SET/ADD/REMOVE/DELETE
AcceptedChangeModes annotation = c.getAnnotation(AcceptedChangeModes.class);
From f86f82909168edd09910f106ca4988b9e3a277dd Mon Sep 17 00:00:00 2001
From: Ayham Al Ali <20037329+AyhamAl-Ali@users.noreply.github.com>
Date: Fri, 15 Mar 2024 18:29:14 +0300
Subject: [PATCH 3/3] Update src/main/java/ch/njol/skript/lang/Expression.java
Co-authored-by: Patrick Miller
---
src/main/java/ch/njol/skript/lang/Expression.java | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/main/java/ch/njol/skript/lang/Expression.java b/src/main/java/ch/njol/skript/lang/Expression.java
index e839d920564..f301016b7ce 100644
--- a/src/main/java/ch/njol/skript/lang/Expression.java
+++ b/src/main/java/ch/njol/skript/lang/Expression.java
@@ -295,14 +295,12 @@ default Optional getOptionalSingle(Event e) {
default Map[]> getAcceptedChangeModes() {
LogHandler logHandler = SkriptLogger.startLogHandler(new BlockingLogHandler());
Map[]> map = new HashMap<>();
- try {
+ try (LogHandler logHandler = new BlockingLogHandler()) {
for (ChangeMode cm : ChangeMode.values()) {
Class>[] ac = acceptChange(cm);
if (ac != null)
map.put(cm, ac);
}
- } finally {
- logHandler.stop();
}
return map;
}