diff --git a/src/main/java/com/denizenscript/denizencore/exceptions/CommandExecutionException.java b/src/main/java/com/denizenscript/denizencore/exceptions/CommandExecutionException.java deleted file mode 100644 index c83d6c90..00000000 --- a/src/main/java/com/denizenscript/denizencore/exceptions/CommandExecutionException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.denizenscript.denizencore.exceptions; - -public class CommandExecutionException extends Exception { - - // TODO: Remove. - - private static final long serialVersionUID = 3159123423457792068L; - - public CommandExecutionException(String msg) { - super(msg); - } -} diff --git a/src/main/java/com/denizenscript/denizencore/exceptions/TagProcessingException.java b/src/main/java/com/denizenscript/denizencore/exceptions/TagProcessingException.java new file mode 100644 index 00000000..1c78a85e --- /dev/null +++ b/src/main/java/com/denizenscript/denizencore/exceptions/TagProcessingException.java @@ -0,0 +1,16 @@ +package com.denizenscript.denizencore.exceptions; + +public class TagProcessingException extends Exception { + + private static final long serialVersionUID = 3159108944857792068L; + public String message; + + public TagProcessingException(String msg) { + message = msg; + } + + @Override + public String getMessage() { + return message; + } +} diff --git a/src/main/java/com/denizenscript/denizencore/objects/core/ListTag.java b/src/main/java/com/denizenscript/denizencore/objects/core/ListTag.java index 4244cde7..b4e792fa 100644 --- a/src/main/java/com/denizenscript/denizencore/objects/core/ListTag.java +++ b/src/main/java/com/denizenscript/denizencore/objects/core/ListTag.java @@ -1,5 +1,6 @@ package com.denizenscript.denizencore.objects.core; +import com.denizenscript.denizencore.exceptions.TagProcessingException; import com.denizenscript.denizencore.objects.ArgumentHelper; import com.denizenscript.denizencore.objects.Fetchable; import com.denizenscript.denizencore.objects.ObjectFetcher; @@ -1632,6 +1633,14 @@ else if (input.size() > 1) { if (attribute.hasContext(1)) { tag = attribute.getRawContext(1); } + Attribute subAttribute; + try { + subAttribute = tag == null ? null : new Attribute(tag, attribute.getScriptEntry(), attribute.context); + } + catch (TagProcessingException ex) { + attribute.echoError("Tag processing failed: " + ex.getMessage()); + return null; + } // <--[tag] // @attribute )].count[<#>]> @@ -1651,7 +1660,7 @@ else if (input.size() > 1) { for (int i = 0; i < object.size(); i++) { ObjectTag obj = object.getObject(i); if (tag != null) { - obj = CoreUtilities.autoAttribTyped(obj, new Attribute(tag, attribute.getScriptEntry(), attribute.context)); + obj = CoreUtilities.autoAttribTyped(obj, new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context)); } String str = obj.toString(); if (ArgumentHelper.matchesDouble(str)) { @@ -1682,7 +1691,7 @@ else if (input.size() > 1) { for (ObjectTag obj : object.objectForms) { ObjectTag actualObj = obj; if (tag != null) { - obj = CoreUtilities.autoAttribTyped(obj, new Attribute(tag, attribute.getScriptEntry(), attribute.context)); + obj = CoreUtilities.autoAttribTyped(obj, new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context)); } String str = obj.toString(); if (ArgumentHelper.matchesDouble(str)) { @@ -1710,6 +1719,14 @@ else if (input.size() > 1) { if (attribute.hasContext(1)) { tag = attribute.getRawContext(1); } + Attribute subAttribute; + try { + subAttribute = tag == null ? null : new Attribute(tag, attribute.getScriptEntry(), attribute.context); + } + catch (TagProcessingException ex) { + attribute.echoError("Tag processing failed: " + ex.getMessage()); + return null; + } // <--[tag] // @attribute )].count[<#>]> @@ -1729,7 +1746,7 @@ else if (input.size() > 1) { for (int i = 0; i < object.size(); i++) { ObjectTag obj = object.getObject(i); if (tag != null) { - obj = CoreUtilities.autoAttribTyped(obj, new Attribute(tag, attribute.getScriptEntry(), attribute.context)); + obj = CoreUtilities.autoAttribTyped(obj, new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context)); } String str = obj.toString(); if (ArgumentHelper.matchesDouble(str)) { @@ -1760,7 +1777,7 @@ else if (input.size() > 1) { for (ObjectTag obj : object.objectForms) { ObjectTag actualObj = obj; if (tag != null) { - obj = CoreUtilities.autoAttribTyped(obj, new Attribute(tag, attribute.getScriptEntry(), attribute.context)); + obj = CoreUtilities.autoAttribTyped(obj, new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context)); } String str = obj.toString(); if (ArgumentHelper.matchesDouble(str)) { @@ -1840,10 +1857,18 @@ else if (value > 0) { ListTag newlist = new ListTag(object); final NaturalOrderComparator comparator = new NaturalOrderComparator(); final String tag = attribute.getRawContext(1); + Attribute subAttribute; + try { + subAttribute = new Attribute(tag, attribute.getScriptEntry(), attribute.context); + } + catch (TagProcessingException ex) { + attribute.echoError("Tag processing failed: " + ex.getMessage()); + return null; + } try { newlist.objectForms.sort((o1, o2) -> { - ObjectTag or1 = CoreUtilities.autoAttribTyped(o1, new Attribute(tag, attribute.getScriptEntry(), attribute.context)); - ObjectTag or2 = CoreUtilities.autoAttribTyped(o2, new Attribute(tag, attribute.getScriptEntry(), attribute.context)); + ObjectTag or1 = CoreUtilities.autoAttribTyped(o1, new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context)); + ObjectTag or2 = CoreUtilities.autoAttribTyped(o2, new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context)); return comparator.compare(or1, or2); }); return new ListTag(newlist.objectForms); @@ -1870,10 +1895,18 @@ else if (value > 0) { } ListTag newlist = new ListTag(object); final String tag = attribute.getRawContext(1); + Attribute subAttribute; + try { + subAttribute = new Attribute(tag, attribute.getScriptEntry(), attribute.context); + } + catch (TagProcessingException ex) { + attribute.echoError("Tag processing failed: " + ex.getMessage()); + return null; + } try { newlist.objectForms.sort((o1, o2) -> { - ObjectTag or1 = CoreUtilities.autoAttribTyped(o1, new Attribute(tag, attribute.getScriptEntry(), attribute.context)); - ObjectTag or2 = CoreUtilities.autoAttribTyped(o2, new Attribute(tag, attribute.getScriptEntry(), attribute.context)); + ObjectTag or1 = CoreUtilities.autoAttribTyped(o1, new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context)); + ObjectTag or2 = CoreUtilities.autoAttribTyped(o2, new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context)); try { double r1 = Double.parseDouble(or1.toString()); double r2 = Double.parseDouble(or2.toString()); @@ -1990,10 +2023,18 @@ else if (value > 0) { if (defaultValue) { tag = tag.substring(0, tag.length() - "||true".length()); } + Attribute subAttribute; + try { + subAttribute = new Attribute(tag, attribute.getScriptEntry(), attribute.context); + } + catch (TagProcessingException ex) { + attribute.echoError("Tag processing failed: " + ex.getMessage()); + return null; + } ListTag newlist = new ListTag(); try { for (ObjectTag obj : object.objectForms) { - Attribute tempAttrib = new Attribute(tag, attribute.getScriptEntry(), attribute.context); + Attribute tempAttrib = new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context); tempAttrib.setHadAlternative(true); ObjectTag objs = CoreUtilities.autoAttribTyped(obj, tempAttrib); if ((objs == null) ? defaultValue : CoreUtilities.equalsIgnoreCase(objs.toString(), "true")) { @@ -2039,9 +2080,17 @@ else if (marks == 0 && c == '|' && tag.charAt(i + 1) == '|') { } } } + Attribute subAttribute; + try { + subAttribute = new Attribute(tag, attribute.getScriptEntry(), attribute.context); + } + catch (TagProcessingException ex) { + attribute.echoError("Tag processing failed: " + ex.getMessage()); + return null; + } try { for (ObjectTag obj : object.objectForms) { - Attribute tempAttrib = new Attribute(tag, attribute.getScriptEntry(), attribute.context); + Attribute tempAttrib = new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context); tempAttrib.setHadAlternative(attribute.hasAlternative() || fallback); ObjectTag objs = CoreUtilities.autoAttribTyped(obj, tempAttrib); if (objs == null) { diff --git a/src/main/java/com/denizenscript/denizencore/objects/core/MapTag.java b/src/main/java/com/denizenscript/denizencore/objects/core/MapTag.java index 177fdd8c..67726587 100644 --- a/src/main/java/com/denizenscript/denizencore/objects/core/MapTag.java +++ b/src/main/java/com/denizenscript/denizencore/objects/core/MapTag.java @@ -1,5 +1,6 @@ package com.denizenscript.denizencore.objects.core; +import com.denizenscript.denizencore.exceptions.TagProcessingException; import com.denizenscript.denizencore.objects.*; import com.denizenscript.denizencore.tags.Attribute; import com.denizenscript.denizencore.tags.ObjectTagProcessor; @@ -276,13 +277,21 @@ public static void registerTags() { ArrayList> entryList = new ArrayList<>(object.map.entrySet()); final NaturalOrderComparator comparator = new NaturalOrderComparator(); final String tag = attribute.hasContext(1) ? attribute.getRawContext(1) : null; + Attribute subAttribute; + try { + subAttribute = tag == null ? null : new Attribute(tag, attribute.getScriptEntry(), attribute.context); + } + catch (TagProcessingException ex) { + attribute.echoError("Tag processing failed: " + ex.getMessage()); + return null; + } try { entryList.sort((e1, e2) -> { ObjectTag o1 = e1.getValue(); ObjectTag o2 = e2.getValue(); if (tag != null) { - o1 = CoreUtilities.autoAttribTyped(o1, new Attribute(tag, attribute.getScriptEntry(), attribute.context)); - o2 = CoreUtilities.autoAttribTyped(o2, new Attribute(tag, attribute.getScriptEntry(), attribute.context)); + o1 = CoreUtilities.autoAttribTyped(o1, new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context)); + o2 = CoreUtilities.autoAttribTyped(o2, new Attribute(subAttribute, attribute.getScriptEntry(), attribute.context)); } return comparator.compare(o1, o2); }); diff --git a/src/main/java/com/denizenscript/denizencore/scripts/ScriptBuilder.java b/src/main/java/com/denizenscript/denizencore/scripts/ScriptBuilder.java index e562a287..e48022ea 100644 --- a/src/main/java/com/denizenscript/denizencore/scripts/ScriptBuilder.java +++ b/src/main/java/com/denizenscript/denizencore/scripts/ScriptBuilder.java @@ -81,7 +81,7 @@ public static List buildScriptEntries(List contents, Script scriptCommands.add(newEntry); } catch (Exception e) { - Debug.echoError("Exception while building script '" + parent.getName() + "'..."); + Debug.echoError("Exception while building script '" + (parent == null ? "(null)" : parent.getName()) + "'..."); Debug.echoError(e); } } diff --git a/src/main/java/com/denizenscript/denizencore/tags/Attribute.java b/src/main/java/com/denizenscript/denizencore/tags/Attribute.java index 4b6534ec..67704f9a 100644 --- a/src/main/java/com/denizenscript/denizencore/tags/Attribute.java +++ b/src/main/java/com/denizenscript/denizencore/tags/Attribute.java @@ -1,5 +1,7 @@ package com.denizenscript.denizencore.tags; +import com.denizenscript.denizencore.exceptions.InvalidArgumentsException; +import com.denizenscript.denizencore.exceptions.TagProcessingException; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntry; @@ -47,11 +49,14 @@ private static boolean isNumber(char c) { return c >= '0' && c <= '9'; } - private static AttributeComponent[] separate_attributes(String attributes) { + private static AttributeComponent[] separate_attributes(String attributes) throws TagProcessingException { AttributeComponent[] matchesRes = attribsLookup.get(attributes); if (matchesRes != null) { return matchesRes; } + if (attributes.startsWith(".") || attributes.endsWith(".")) { + throw new TagProcessingException("The tag '" + attributes + "' is invalid due to a misplaced dot at the start or end of the tag."); + } ArrayList matches = new ArrayList<>(attributes.length() / 7); int x1 = 0, x2 = -1; int braced = 0; @@ -73,11 +78,17 @@ else if (chr == '.' && !(x > 0 && isNumber(attrInp[x + 1]) && isNumber(attrInp[x x2 = x; } if (x2 > -1) { + if (x2 <= x1) { + throw new TagProcessingException("The tag '" + attributes + "' is invalid, likely due to double dots '..' somewhere. Did you forget a sub-tag, or accidentally double-tap the dot key?"); + } matches.add(new AttributeComponent(attributes.substring(x1, x2))); x2 = -1; x1 = x + 1; } } + if (braced != 0) { + throw new TagProcessingException("The tag '" + attributes + "' is invalid due to misplaced [square brackets]. Did you forget to close some brackets?"); + } if (Debug.verbose) { Debug.log("attribute splitter: '" + attributes + "' becomes: " + matches); } @@ -128,7 +139,7 @@ public Attribute(Attribute ref, ScriptEntry scriptEntry, TagContext context) { } } - public Attribute(String attributes, ScriptEntry scriptEntry, TagContext context) { + public Attribute(String attributes, ScriptEntry scriptEntry, TagContext context) throws TagProcessingException { origin = attributes; this.scriptEntry = scriptEntry; this.context = context; diff --git a/src/main/java/com/denizenscript/denizencore/tags/ReplaceableTagEvent.java b/src/main/java/com/denizenscript/denizencore/tags/ReplaceableTagEvent.java index 3cb4409b..29321fa3 100644 --- a/src/main/java/com/denizenscript/denizencore/tags/ReplaceableTagEvent.java +++ b/src/main/java/com/denizenscript/denizencore/tags/ReplaceableTagEvent.java @@ -1,5 +1,6 @@ package com.denizenscript.denizencore.tags; +import com.denizenscript.denizencore.exceptions.TagProcessingException; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ScriptTag; @@ -70,7 +71,7 @@ public ReplaceableTagEvent(ReferenceData ref, String tag, TagContext context) { } } - public ReplaceableTagEvent(String tag, TagContext context) { + public ReplaceableTagEvent(String tag, TagContext context) throws TagProcessingException { this(refs.get(tag), tag, context); if (mainRef != null) { return; diff --git a/src/main/java/com/denizenscript/denizencore/tags/TagManager.java b/src/main/java/com/denizenscript/denizencore/tags/TagManager.java index 68e37b72..98760e51 100644 --- a/src/main/java/com/denizenscript/denizencore/tags/TagManager.java +++ b/src/main/java/com/denizenscript/denizencore/tags/TagManager.java @@ -1,5 +1,6 @@ package com.denizenscript.denizencore.tags; +import com.denizenscript.denizencore.exceptions.TagProcessingException; import com.denizenscript.denizencore.objects.*; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntry; @@ -156,8 +157,14 @@ public static void executeWithTimeLimit(final ReplaceableTagEvent event, int sec } public static String readSingleTag(String str, TagContext context) { - ReplaceableTagEvent event = new ReplaceableTagEvent(str, context); - return readSingleTagObject(context, event).toString(); + try { + ReplaceableTagEvent event = new ReplaceableTagEvent(str, context); + return readSingleTagObject(context, event).toString(); + } + catch (TagProcessingException ex) { + Debug.echoError("Tag processing failed: " + ex.getMessage()); + return null; + } } public static ObjectTag readSingleTagObject(ParseableTagPiece tag, TagContext context) { @@ -342,10 +349,19 @@ public static List genChain(String arg, TagContext context) { ParseableTagPiece midTag = new ParseableTagPiece(); midTag.content = tagToProc; midTag.isTag = true; - midTag.tagData = new ReplaceableTagEvent(tagToProc, context).mainRef; - pieces.add(midTag); - if (Debug.verbose) { - Debug.log("Tag: " + (preText == null ? "" : preText.content) + " ||| " + midTag.content); + try { + midTag.tagData = new ReplaceableTagEvent(tagToProc, context).mainRef; + pieces.add(midTag); + if (Debug.verbose) { + Debug.log("Tag: " + (preText == null ? "" : preText.content) + " ||| " + midTag.content); + } + } + catch (TagProcessingException ex) { + Debug.echoError("Tag processing failed: " + ex.getMessage()); + ParseableTagPiece errorNote = new ParseableTagPiece(); + errorNote.isError = true; + errorNote.content = "Tag processing failed: " + ex.getMessage(); + pieces.add(errorNote); } arg = arg.substring(positions[1] + 1); locateTag(arg, positions, 0);