Skip to content

Commit

Permalink
Fix #31
Browse files Browse the repository at this point in the history
Added some javadocs
Some code cleanup
Some internal changes
  • Loading branch information
TPGamesNL committed Jan 21, 2021
1 parent 4e65fa9 commit 1a5c7a6
Show file tree
Hide file tree
Showing 15 changed files with 263 additions and 171 deletions.
87 changes: 60 additions & 27 deletions src/main/java/com/btk5h/skriptmirror/Descriptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,30 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* A Descriptor is all the info that can be provided in a script about a method.
* This consists of:
* <ul>
* <li>An optional class the member (method, field or constructor) is defined in.</li>
* <li>The name of the member</li>
* <li>The parameter types of the member.</li>
* </ul>
*/
public final class Descriptor {

/**
* A regex string for a list of array symbols, e.g. {@code [][][]}.
*/
private static final String PACKAGE_ARRAY = SkriptMirrorUtil.PACKAGE + "(?:\\[])*";

/**
* A regex {@link Pattern} for a single array symbol, matches only {@code []}.
*/
private static final Pattern PACKAGE_ARRAY_SINGLE = Pattern.compile("\\[]");

/**
* A regex {@link Pattern} for a {@link Descriptor}.
*/
private static final Pattern DESCRIPTOR =
Pattern.compile("" +
"(?:\\[(" + SkriptMirrorUtil.PACKAGE + ")])?" +
Expand Down Expand Up @@ -61,63 +82,73 @@ public String toString() {
}

public String toString(boolean isStatic) {
return String.format("%s" + (isStatic ? "." : "#") + "%s",
javaClass == null ? "(unspecified)" : SkriptMirrorUtil.getDebugName(javaClass),
name);
return javaClass == null ? "(unspecified)" : SkriptMirrorUtil.getDebugName(javaClass)
+ (isStatic ? "." : "#")
+ name;
}

/**
* Returns a new descriptor with a new {@link #javaClass}.
* If this Descriptors {@link #javaClass} is not null, it will instead return itself.
*/
public Descriptor orDefaultClass(Class<?> cls) {
if (getJavaClass() != null) {
if (javaClass != null) {
return this;
}

return new Descriptor(cls, getName(), getParameterTypes());
return new Descriptor(cls, name, parameterTypes);
}

public static Descriptor parse(String desc, File script) throws ClassNotFoundException {
/**
* Parses the given {@link String} as a {@link Descriptor}. The script parameter is to get the imports.
*/
public static Descriptor parse(String desc, File script) throws ImportNotFoundException {
Matcher m = DESCRIPTOR.matcher(desc);

if (m.matches()) {
String cls = m.group(1);
String name = m.group(2);
String args = m.group(3);

Class<?> javaClass = null;
Class<?>[] parameterTypes = null;
Class<?> javaClass = cls == null ? null : lookupClass(script, cls);

if (cls != null) {
javaClass = lookupClass(script, cls);
}
String name = m.group(2);

if (args != null) {
parameterTypes = parseParams(args, script);
}
String args = m.group(3);
Class<?>[] parameterTypes = args == null ? null : parseParams(args, script);

return new Descriptor(javaClass, name, parameterTypes);
}

return null;
}

private static Class<?>[] parseParams(String args, File script) throws ClassNotFoundException {
/**
* Parses a list of imported names, returning a class array containing the classes in the given string.
*/
private static Class<?>[] parseParams(String args, File script) throws ImportNotFoundException {
String[] rawClasses = args.split(",");

Class<?>[] parsedClasses = new Class<?>[rawClasses.length];

for (int i = 0; i < rawClasses.length; i++) {
String userType = rawClasses[i].trim();

// Calculate array depth with regex
Matcher arrayDepthMatcher = PACKAGE_ARRAY_SINGLE.matcher(userType);
int arrayDepth = 0;
while (arrayDepthMatcher.find()) {
arrayDepth++;
}
userType = userType.substring(0, userType.length() - (2 * arrayDepth));

Class<?> cls = JavaUtil.PRIMITIVE_CLASS_NAMES.get(userType);
// Remove array's square brackets
userType = userType.substring(0, userType.length() - (2 * arrayDepth));

if (cls == null) {
Class<?> cls;
if (JavaUtil.PRIMITIVE_CLASS_NAMES.containsKey(userType)) {
cls = JavaUtil.PRIMITIVE_CLASS_NAMES.get(userType);
} else {
cls = lookupClass(script, userType);
}

// Convert class to array class with calculated depth
cls = JavaUtil.getArrayClass(cls, arrayDepth);

parsedClasses[i] = cls;
Expand All @@ -126,13 +157,15 @@ private static Class<?>[] parseParams(String args, File script) throws ClassNotF
return parsedClasses;
}

private static Class<?> lookupClass(File script, String userType) throws ClassNotFoundException {
/**
* Looks up a class from its imported name in the given file.
*/
private static Class<?> lookupClass(File script, String userType) throws ImportNotFoundException {
JavaType customImport = CustomImport.lookup(script, userType);
if (customImport == null)
throw new ImportNotFoundException(userType);

if (customImport != null) {
return customImport.getJavaClass();
} else {
return LibraryLoader.getClassLoader().loadClass(userType);
}
return customImport.getJavaClass();
}

}
20 changes: 20 additions & 0 deletions src/main/java/com/btk5h/skriptmirror/ImportNotFoundException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.btk5h.skriptmirror;

/**
* Exception thrown when the user tries to use a certain class, but that class is not imported.
* Currently only used in the {@link Descriptor} class.
*/
public class ImportNotFoundException extends Exception {

private final String userType;

public ImportNotFoundException(String userType) {
super("Import not found: " + userType);
this.userType = userType;
}

public String getUserType() {
return userType;
}

}
16 changes: 8 additions & 8 deletions src/main/java/com/btk5h/skriptmirror/ScriptLoaderState.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import org.bukkit.event.Event;

public class ScriptLoaderState {
private Config currentScript;
private String currentEventName;
private Class<? extends Event>[] currentEvents;
private Kleenean hasDelayBefore;
private final Config currentScript;
private final String currentEventName;
private final Class<? extends Event>[] currentEvents;
private final Kleenean hasDelayBefore;

private ScriptLoaderState(Config currentScript, String currentEventName, Class<? extends Event>[] currentEvents,
Kleenean hasDelayBefore) {
Expand All @@ -27,10 +27,10 @@ public void applyToCurrentState() {

public static ScriptLoaderState copyOfCurrentState() {
return new ScriptLoaderState(
ScriptLoader.currentScript,
ScriptLoader.getCurrentEventName(),
ScriptLoader.getCurrentEvents(),
ScriptLoader.hasDelayBefore
ScriptLoader.currentScript,
ScriptLoader.getCurrentEventName(),
ScriptLoader.getCurrentEvents(),
ScriptLoader.hasDelayBefore
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.concurrent.Executors;

public class CondExpressionStatement extends Condition {

static {
Skript.registerCondition(CondExpressionStatement.class, "[(1¦await)] %~javaobject%");
}
Expand Down Expand Up @@ -69,15 +70,13 @@ public String toString(Event e, boolean debug) {
return arg.toString(e, debug);
}

@SuppressWarnings("unchecked")
@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed,
SkriptParser.ParseResult parseResult) {
arg = SkriptUtil.defendExpression(exprs[0]);

if (!(arg instanceof ExprJavaCall)) {
if (!(arg instanceof ExprJavaCall))
return false;
}

isAsynchronous = (parseResult.mark & 1) == 1;
isCondition = SkriptLogger.getNode() instanceof SectionNode;
Expand All @@ -86,6 +85,7 @@ public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelaye
Skript.error("Asynchronous java calls may not be used as conditions.");
return false;
}

if (isAsynchronous)
ScriptLoader.hasDelayBefore = Kleenean.TRUE;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelaye

private Statement getParsedStatement() {
if (parsedStatement == null) {
ScriptLoaderState previousState = ScriptLoaderState.copyOfCurrentState();
scriptLoaderState.applyToCurrentState();
parsedStatement = Statement.parse(statement,
String.format("Could not parse condition/effect at runtime: %s", statement));
parsedStatement = Statement.parse(statement, "Could not parse condition/effect at runtime: "
+ statement);
previousState.applyToCurrentState();

if (parsedStatement == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ protected void execute(Event e) {
@Override
protected TriggerItem walk(Event e) {
if (isAsynchronous) {
// TODO how to implement async, Bukkit or just other Java (CondExpressionStatement#walk(Event))
Object localVariables = SkriptReflection.getLocals(e);
CompletableFuture.runAsync(() -> {
SkriptReflection.putLocals(localVariables, e);
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/com/btk5h/skriptmirror/skript/Types.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,7 @@ protected boolean canBeInstantiated() {
}
}));

Converters.registerConverter(ClassInfo.class, JavaType.class,
((Converter<ClassInfo, JavaType>) c -> new JavaType(c.getC())));
Converters.registerConverter(ClassInfo.class, JavaType.class, c -> new JavaType(c.getC()));

Classes.registerClass(new ClassInfo<>(Null.class, "null")
.parser(new Parser<Null>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ public String toString(Event e, boolean debug) {
return "parser mark";
}

@SuppressWarnings("unchecked")
@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed,
SkriptParser.ParseResult parseResult) {
Expand All @@ -52,6 +51,7 @@ public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelaye
)) {
Skript.error("The parser mark may only be used in custom syntax.",
ErrorQuality.SEMANTIC_ERROR);
return false;
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,18 @@ public String toString(Event e, boolean debug) {
return "parser mark";
}

@SuppressWarnings("unchecked")
@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed,
SkriptParser.ParseResult parseResult) {
if (!ScriptLoader.isCurrentEvent(
EffectTriggerEvent.class,
ExpressionGetEvent.class,
ExpressionChangeEvent.class,
ConditionCheckEvent.class
)) {
EffectTriggerEvent.class,
ExpressionGetEvent.class,
ExpressionChangeEvent.class,
ConditionCheckEvent.class
)) {
Skript.error("The parsed regular expression may only be used in custom syntax.",
ErrorQuality.SEMANTIC_ERROR);
ErrorQuality.SEMANTIC_ERROR);
return false;
}

index = Utils.parseInt(parseResult.regexes.get(0).group(0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,6 @@ public void onPreScriptLoad(PreScriptLoadEvent preScriptLoadEvent) {
}
}

// TODO docs for all changes

// TODO error for non-preloadable syntax when attempted to be used on preload
// TODO and have a concrete boolean for whether a custom syntax section is preloadable

// TODO usable in section (imports)

public static void handleEventNode(SectionNode sectionNode) {
String key = sectionNode.getKey();
assert key != null;
Expand Down
Loading

0 comments on commit 1a5c7a6

Please sign in to comment.