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; }