Skip to content

2. Document format of a ProbeJS document

Prunoideae edited this page Mar 5, 2022 · 1 revision

0. Before starting

There're some examples in the docs folder located in here. Refer to these while reading the instructions may help you to understand how documents are formatted better. Documents there are guaranteed to be correct, as they will be shipped with ProbeJS every version.

1. Language?

The document is in a TypeScript declaration file like format, but this is not TypeScript at all - it's just a document. But still, they're guaranteed to produce no error in TS, so if you see something wrong in the editor, the document is probably not correct.

However, there're limitations, since it's only a small parser to process all the documents at behind:

  • // comments are not allowed, using this as comments will almost guarantee to break the documents.
  • Only names mentioned below are allowed in creating documents, and creating namespaces is not one of them.
  • Definition must be in one line when writing method/field definitions (not comments), if the line is changed, it will break.
  • No any other contents not mentioned in the class, things in a class definition can only be method, field or comment.
  • Generics of class definitions will break the document.

2. Class and Interface

Static document is about giving extra information to classes, to help people understand how to write code correctly and easily.

In the document, you can define only class and interface at the file-level, and you must not add declare before them, or they will not be recognized. Like the following is correct:

class SomeClass {

}

interface SomeInterface {

}

3. Methods and Fields

In a class, there're only method and field (with their comments). To declare such a property in the document, write:

class SomeClass {
     /**
     * Adds a function.
     */
    func(a: number, b: java.util.Map<String, K>): void;
    field1: 1;
    field2: java.util.List<string>;
}

Adding static keyword will mark the property as static, which means that they can only be referred in class. Adding readonly keyword to fields will mark the property as readonly, which means they can not be changed.

4. Annotations

4.1 @Target

A class will generate a dummy class named Document.{Class Name} when dumping by default, to make the class to override the auto-generated typing of a certain class, you will need to add a @Target annotation before the definition, in this example, let's override RecipeEventJS:

/**
 * Holds all the recipes collected from documents.
 */
@Target("dev.latvian.mods.kubejs.recipe.RecipeEventJS")
class RecipeEventJS {
    
}

Adding the Target annotation before the class definition will make the parser try to modify the typing of the given class. Full class name is required here to ensure the target is unchanged by how ProbeJS resolves the names. So in this case, a comment will be added into the RecipeEventJS class.

In addition, the document will override the method with same name, parameters and return type, and a field will always override the field with same name. For modifying how a function work, please refer to 5. Comments.

4.2 @Mod

Apart from the @Target annotation, @Mod annotation is available for giving classes a mod requirement to load. So documents of other mods will not generate when mods are not loaded:

@Mod("create")
@Mod("kubejs_create")
class CreateRecipes {

}

So this will only create the CreateRecipes document class when both Create and KubeJS-Create are loaded.

5. Comments

More than from adding description to objects, comments can also modify the original methods' signature, to change the return type (from stupid any or object), change the type of a parameter (from stupid any or object still) and to add/delete a parameter in the list (to completely override weird names like arg0...). This feature uses the @param notations in the comments, and they will be stripped off in generated typings.

For example, let's change Vec3d.equals(arg0: object) to Vec3d.equals(vecOther: Vec3d) :

@Target("net.minecraft.world.phys.Vec3")
class Vec3d {
    /**
     * Compares two Vec3d to test if they're equal.
     * @param {null} arg0
     * @param {net.minecraft.world.phys.Vec3} vecOther
     */
    equals(arg0: java.lang.Object): boolean
}

So, the commented did 2 things: removed the parameter arg0 by setting the type to null, and added the vecOther parameter.

Clone this wiki locally