- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 413
Docs categories #8194
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
base: dev/feature
Are you sure you want to change the base?
Docs categories #8194
Changes from 27 commits
6723148
              4213806
              aa11019
              d4c7b51
              35655aa
              34bc926
              5616181
              6fe255e
              afd70a7
              1d926c8
              4b79f1f
              3369e17
              278377c
              2dd2203
              dce21d6
              87caead
              5b914e8
              5f7eded
              9ab6833
              6254455
              310880f
              ec002bd
              a211958
              35cf06b
              efe7536
              b33472e
              e43f09b
              03a7f86
              7023f3a
              9645e27
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package ch.njol.skript.doc; | ||
|  | ||
| import org.jetbrains.annotations.NotNull; | ||
|  | ||
| import java.util.Set; | ||
|  | ||
| /** | ||
| * Represents anything that can be categorized. | ||
| */ | ||
| @FunctionalInterface | ||
| public interface Categorizable { | ||
|  | ||
| /** | ||
| * Returns the documentation categories which this object belongs to. | ||
| * | ||
| * @return The categories of this object. | ||
| */ | ||
| @NotNull Set<Category> categories(); | ||
|  | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| package ch.njol.skript.doc; | ||
|  | ||
| import com.google.common.base.Preconditions; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import org.skriptlang.skript.addon.AddonModule; | ||
|  | ||
| import java.util.Set; | ||
|  | ||
| /** | ||
| * Represents a category a documented element can belong to. | ||
| */ | ||
| public interface Category { | ||
|  | ||
| Category ENTITIES = new CategoryImpl("Entities", "entity", "entities", "animal", "panda", "allay", | ||
| "zombie", "goat", "horse", "pig", "fish", "villager", "bee"); | ||
| Category BREEDING = new CategoryImpl("Breeding"); | ||
| Category PLAYERS = new CategoryImpl("Players", "player", "operator"); | ||
| Category DAMAGE_SOURCES = new CategoryImpl("Damage Sources", "damage source"); | ||
| Category BLOCKS = new CategoryImpl("Blocks", "block"); | ||
| Category STRINGS = new CategoryImpl("Strings", "string", "text"); | ||
| Category COMMANDS = new CategoryImpl("Commands", "command"); | ||
| Category ITEMS = new CategoryImpl("Items", "item", "enchantment", "lore", "tooltip", "banner"); | ||
| Category WORLDS = new CategoryImpl("Worlds", "world"); | ||
| Category SCRIPTS = new CategoryImpl("Scripts", "script"); | ||
| Category DISPLAYS = new CategoryImpl("Displays", "display"); | ||
| Category TIME = new CategoryImpl("Time", "time", "unix"); | ||
| Category UUIDS = new CategoryImpl("UUIDs", "uuid"); | ||
| Category DATES = new CategoryImpl("Dates", "date"); | ||
| Category LOCATIONS = new CategoryImpl("Locations", "location"); | ||
| Category MATH = new CategoryImpl("Math", "angle", "degree", "radian", | ||
| "arithmetic", "nan", "round", "rounds", "root", "quaternion", "permutations", | ||
| "combinations", "numbers", "infinity", "exponential"); | ||
| Category VECTORS = new CategoryImpl("Vectors", Category.MATH, "vector"); | ||
|  | ||
| /** | ||
| * @return The display name of this category. | ||
| */ | ||
| @NotNull String name(); | ||
|  | ||
| /** | ||
| * @return The parent category of this category. | ||
| */ | ||
| Category parent(); | ||
|  | ||
| /** | ||
| * Adds a module to this category. | ||
| * | ||
| * @param module The module to add. | ||
| */ | ||
| void addModule(@NotNull Class<? extends AddonModule> module); | ||
|  | ||
| /** | ||
| * @return The modules that are represented by this category. | ||
| */ | ||
| @NotNull Set<Class<? extends AddonModule>> modules(); | ||
|  | ||
| /** | ||
| * Creates a new category. | ||
| * | ||
| * @param name The name. | ||
| * @return The new category. | ||
| */ | ||
| static Category of(@NotNull String name) { | ||
| Preconditions.checkNotNull(name, "name cannot be null"); | ||
|  | ||
| return new CategoryImpl(name); | ||
| } | ||
|  | ||
| /** | ||
| * Creates a new category. | ||
| * | ||
| * @param name The name. | ||
| * @param category The category. | ||
| * @return The new category. | ||
| */ | ||
| static Category of(@NotNull String name, @NotNull Category category) { | ||
| Preconditions.checkNotNull(name, "name cannot be null"); | ||
| Preconditions.checkNotNull(category, "category cannot be null"); | ||
|  | ||
| return new CategoryImpl(name, category); | ||
| } | ||
|  | ||
| /** | ||
| * @return All registered categories. | ||
| */ | ||
| static Set<Category> values() { | ||
| return CategoryImpl.getInstances(); | ||
| } | ||
|  | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| package ch.njol.skript.doc; | ||
|  | ||
| import com.google.common.base.Preconditions; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import org.jetbrains.annotations.Unmodifiable; | ||
| import org.skriptlang.skript.addon.AddonModule; | ||
|  | ||
| import java.util.Arrays; | ||
| import java.util.HashSet; | ||
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
|  | ||
| final class CategoryImpl implements Category { | ||
|  | ||
| private static final Set<Category> instances = new HashSet<>(); | ||
| private final String name; | ||
| private final Category parent; | ||
| private final Set<String> keywords; | ||
| private final Set<Class<? extends AddonModule>> modules; | ||
|  | ||
| static Set<Category> getInstances() { | ||
| return instances; | ||
| } | ||
|  | ||
| CategoryImpl(String name, String... keywords) { | ||
| this(name, null, keywords); | ||
| } | ||
|  | ||
| CategoryImpl(String name, Category parent, String... keywords) { | ||
| instances.add(this); | ||
| this.name = name; | ||
| this.parent = parent; | ||
| this.keywords = Arrays.stream(keywords) | ||
| .map(String::toLowerCase) | ||
| .collect(Collectors.toUnmodifiableSet()); | ||
| this.modules = new HashSet<>(); | ||
| } | ||
|  | ||
| @Override | ||
| public @NotNull String name() { | ||
| return name; | ||
| } | ||
|  | ||
| @Override | ||
| public Category parent() { | ||
| return parent; | ||
| } | ||
|  | ||
| public @NotNull Set<String> keywords() { | ||
| return keywords; | ||
| } | ||
|  | ||
| @Override | ||
| public void addModule(@NotNull Class<? extends AddonModule> module) { | ||
| Preconditions.checkNotNull(module, "module cannot be null"); | ||
|  | ||
| modules.add(module); | ||
| } | ||
|  | ||
| @Override | ||
| public @Unmodifiable @NotNull Set<Class<? extends AddonModule>> modules() { | ||
| return Set.copyOf(modules); | ||
| } | ||
|  | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -21,12 +21,15 @@ | |
| import org.jetbrains.annotations.Contract; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import org.jetbrains.annotations.Nullable; | ||
| import org.skriptlang.skript.addon.AddonModule; | ||
| import org.skriptlang.skript.addon.SkriptAddon; | ||
| import org.skriptlang.skript.bukkit.registration.BukkitRegistryKeys; | ||
| import org.skriptlang.skript.bukkit.registration.BukkitSyntaxInfos; | ||
| import org.skriptlang.skript.lang.structure.Structure; | ||
| import org.skriptlang.skript.registration.DefaultSyntaxInfos; | ||
| import org.skriptlang.skript.registration.SyntaxInfo; | ||
| import org.skriptlang.skript.registration.SyntaxOrigin; | ||
| import org.skriptlang.skript.registration.SyntaxOrigin.ModuleOrigin; | ||
| import org.skriptlang.skript.registration.SyntaxRegistry; | ||
|  | ||
| import java.io.File; | ||
|  | @@ -163,6 +166,9 @@ private static JsonObject generatedAnnotatedElement(SyntaxInfo<?> syntaxInfo) { | |
| syntaxJsonObject.add("returns", getExpressionReturnTypes(expression)); | ||
| } | ||
|  | ||
| syntaxJsonObject.add("categories", getCategoriesArray(syntaxInfo.origin(), name.value(), | ||
| description == null ? null : List.of(description.value()), syntaxInfo.patterns())); | ||
|  | ||
| return syntaxJsonObject; | ||
| } | ||
|  | ||
|  | @@ -224,7 +230,7 @@ private static JsonObject generateEventElement(BukkitSyntaxInfos.Event<?> info) | |
| syntaxJsonObject.add("requirements", convertToJsonArray(info.requiredPlugins().toArray(new String[0]))); | ||
| syntaxJsonObject.add("examples", convertToJsonArray(info.examples().toArray(new String[0]))); | ||
| syntaxJsonObject.add("eventValues", getEventValues(info)); | ||
| syntaxJsonObject.add("keywords", convertToJsonArray(info.keywords().toArray(new String[0]))); | ||
| syntaxJsonObject.add("categories", getCategoriesArray(info.origin(), info.name(), info.description(), info.patterns())); | ||
|  | ||
| return syntaxJsonObject; | ||
| } | ||
|  | @@ -370,6 +376,9 @@ private static JsonObject generateClassInfoElement(ClassInfo<?> classInfo) { | |
| syntaxJsonObject.add("description", convertToJsonArray(classInfo.getDescription())); | ||
| syntaxJsonObject.add("requirements", convertToJsonArray(classInfo.getRequiredPlugins())); | ||
| syntaxJsonObject.add("examples", convertToJsonArray(classInfo.getExamples())); | ||
| syntaxJsonObject.add("categories", getCategoriesArray(null, | ||
| Objects.requireNonNullElse(classInfo.getDocName(), classInfo.getCodeName()), | ||
| List.of(classInfo.getDescription()), null)); | ||
|  | ||
| return syntaxJsonObject; | ||
| } | ||
|  | @@ -408,6 +417,7 @@ private static JsonObject generateFunctionElement(JavaFunction<?> function) { | |
|  | ||
| String functionSignature = function.getSignature().toString(false, false); | ||
| functionJsonObject.add("patterns", convertToJsonArray(functionSignature)); | ||
| functionJsonObject.add("categories", getCategoriesArray(null, function.getName(), List.of(function.getDescription()), null)); | ||
| return functionJsonObject; | ||
| } | ||
|  | ||
|  | @@ -459,6 +469,91 @@ private static JsonArray cleanPatterns(String... strings) { | |
| return convertToJsonArray(strings); | ||
| } | ||
|  | ||
| /** | ||
| * Returns the category name of an element given its origin, name, description and patterns. | ||
| * | ||
| * <p>Attempts to find a category by using pattern first. | ||
| * If this has no results, then it will use the name and description. | ||
| * </p> | ||
| * | ||
| * @param origin The origin of this element. | ||
| * @param name The name of this element. | ||
| * @param description The description of this element. | ||
| * @param patterns The patterns of this element. | ||
| * @return The category name, or null if none is found. | ||
| */ | ||
| private static @Nullable JsonArray getCategoriesArray( | ||
| @Nullable SyntaxOrigin origin, @NotNull String name, | ||
| @Nullable Collection<String> description, @Nullable Collection<String> patterns | ||
| ) { | ||
| JsonArray categories = new JsonArray(); | ||
| if (origin instanceof ModuleOrigin elementOrigin) { | ||
| Class<?> moduleClass = elementOrigin.module().getClass(); | ||
| for (Category category : Category.values()) { | ||
| if (category.modules().contains(moduleClass)) { | ||
| categories.add(getCategoryJson(category)); | ||
| } | ||
| } | ||
| return categories; | ||
| } | ||
|  | ||
| if (patterns == null) patterns = List.of(); | ||
| JsonArray first = getCategories(String.join("", patterns)); | ||
| if (!first.isEmpty()) { | ||
| return first; | ||
| } | ||
| if (description == null) description = List.of(); | ||
|  | ||
| JsonArray second = getCategories(name + String.join("", description) + String.join("", patterns)); | ||
| if (!second.isEmpty()) { | ||
| return second; | ||
| } | ||
| return null; | ||
| } | ||
|  | ||
| /** | ||
| * Attempts to find the categories based on the input. | ||
| * | ||
| * @param input The input. | ||
| * @return The categories, or null if no are found. | ||
|         
                  Efnilite marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| */ | ||
| private static @NotNull JsonArray getCategories(@NotNull String input) { | ||
| String lower = input.toLowerCase(); | ||
| JsonArray options = new JsonArray(); | ||
| for (Category category : Category.values()) { | ||
| if (!(category instanceof CategoryImpl impl)) { | ||
| break; | ||
| } | ||
|  | ||
| for (String keyword : impl.keywords()) { | ||
| if (lower.contains(keyword)) { | ||
| options.add(getCategoryJson(category)); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| 
      Comment on lines
    
      +648
     to 
      +654
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was randomly going through the wip updated docs page again and noticed "category" checked it out saw that timespan and beacon effect are classified as apart of the "Display" category. I decided to go check into this, this is caused by the usage guessing assignments with  Is this behavior planned to stay or do you plan to eventually move away from automatic assignments. 
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think excluding the description/examples, searching with  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Until every syntax has been categorized, selecting one based on the documentation is the best bet of approximating a category. The current estimation system is meant as a way to plug the gap. While this approximation might not be very accurate, the important part of this PR is the infrastructure for adding a Category to a module, and adding categories to  There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think they're fine as optional selections you can filter by for now, rather than the default organization | ||
|  | ||
| return options; | ||
| } | ||
|  | ||
| /** | ||
| * Transforms a category into a json object. | ||
| * @param category The category. | ||
| * @return The transformed category. | ||
| */ | ||
| private static JsonObject getCategoryJson(@NotNull Category category) { | ||
| JsonObject object = new JsonObject(); | ||
|  | ||
| object.addProperty("name", category.name()); | ||
| if (category.parent() != null) { | ||
| object.addProperty("parent", category.parent().name()); | ||
| } else { | ||
| object.add("parent", null); | ||
| } | ||
|  | ||
| return object; | ||
| } | ||
|  | ||
| /** | ||
| * Gets the json object representing the addon. | ||
| * | ||
|  | ||
Uh oh!
There was an error while loading. Please reload this page.