diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrFuncDef.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrFuncDef.java index 6b3f985a3..e653e04fa 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrFuncDef.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrFuncDef.java @@ -98,7 +98,7 @@ public static FuncLink calculate(final ExprFuncRef node) { cands.addAll(methods); cands.addAll(exts); - var argTypes = AttrFuncDef.argumentTypesPre(node); + var argTypes = AttrFuncDef.argumentTypes(node); // Pass 1: exact matches java.util.ArrayList exactLinks = new java.util.ArrayList<>(); @@ -242,9 +242,11 @@ public static List argumentTypes(StmtCall node) { pIndex++; } if (hasInferredType) { - // if there are unknown parameter types, use an approximated function type for overloading resolution - WurstType resultType = WurstTypeInfer.instance(); - argType = new WurstTypeClosure(paramTypes, resultType); + WurstType bodyType = closure.getImplementation().attrTyp(); + if (bodyType == null || bodyType instanceof WurstTypeUnknown) { + bodyType = WurstTypeInfer.instance(); + } + argType = new WurstTypeClosure(paramTypes, bodyType); } else { // if there are no unknown types for the argument, then it should be safe to directly calculate the type argType = arg.attrTyp(); diff --git a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/EliminateGenerics.java b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/EliminateGenerics.java index af579b99a..130b2afa4 100644 --- a/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/EliminateGenerics.java +++ b/de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/EliminateGenerics.java @@ -342,7 +342,7 @@ private void adaptSubmethods(List oldSubMethods, ImMethod newM) { newM.getSubMethods().add(specializedSubMethod); } }); - } else { + }else { subClass.getSuperClasses().replaceAll(this::specializeType); ImClassType newClassTspecialized = specializeType(newClassT); if (subClass.isSubclassOf(newClassTspecialized.getClassDef())) { diff --git a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/BugTests.java b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/BugTests.java index 97633a923..46e03be35 100644 --- a/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/BugTests.java +++ b/de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/BugTests.java @@ -1679,6 +1679,137 @@ public void linkedListModule_perClassStatics_andTyping_ok() { ); } + @Test + public void testTooltipGenerator() { + test().withStdLib().lines( + "package Test", + "import AbilityObjEditing", + "import HashMap", + "", + "@configurable constant TITLE_COLOR = \"|cff3B97D3\"", + "@configurable constant TITLE_TTYPE = \"Target Type:\"", + "@configurable constant MAX_TITLES = 10", + "", + "@configurable function buildLearnTooltip(string name) returns string", + "\treturn \"|cffFFCC00Learn|r \" + name + \" - [|cffffcc00Level %d|r]\"", + "", + "@configurable function buildActiveTooltip(string name, int lvl) returns string", + "\treturn name + \" - Level \" + lvl.toString()", + "", + "@configurable function buildPassiveTooltip(string name, int lvl) returns string", + "\treturn name + \" - Level \" + lvl.toString()", + "", + "@configurable function buildDescription(string description) returns string", + "\treturn \"|cff919191\" + description + \"|r\"", + "\t", + "public class AbilityTooltipGenerator implements TooltipGenerator", + "\tprivate constant propMap = new IterableMap", + "\tprivate var description = \"\"", + "", + "\tprivate var levels = 1", + "\tprivate var hotkey = \"\"", + "\tprivate var name = \"\"", + "", + "\tconstruct(string description)", + "\t\tthis.description = description", + "", + "\tconstruct()", + "", + "\toverride function addProperty(string title, StringLevelClosure lc)", + "\t\tpropMap.put(title, lc)", + "", + "\toverride function applyToDef(AbilityDefinition def)", + "\t\tlevels = propMap.has(\"Levels\") ? fixValue(propMap.getAndRemove(\"Levels\").run(0)).toInt() : 1", + "\t\tname = propMap.has(\"Name\") ? propMap.getAndRemove(\"Name\").run(0) : \"unnamed\"", + "\t\thotkey = propMap.has(\"Hotkey\") ? propMap.getAndRemove(\"Hotkey\").run(0) : \"Q\"", + "\t\tdef..setTooltipLearn(generateTooltipLearn())", + "\t\t..setTooltipLearnExtended(generateTooltipExtended(-1, true))", + "\t\tfor i = 1 to levels", + "\t\t\tdef..setTooltipNormal(i, generateTooltipNormal(i))", + "\t\t\t..setTooltipNormalExtended(i, generateTooltipExtended(i, false))", + "", + "\tprivate function generateTooltipLearn() returns string", + "\t\treturn buildLearnTooltip(name)", + "", + "\tprivate function generateTooltipNormal(int lvl) returns string", + "\t\treturn buildActiveTooltip(name, lvl)", + "", + "\tprivate function generateTooltipExtended(int lvl, boolean learn) returns string", + "\t\tvar s = \"\"", + "", + "\t\tfor key in propMap", + "\t\t\tvar tmp = \"\"", + "\t\t\tvar isConstantValue = true", + "\t\t\tlet val = fixValue(propMap.get(key).run(1))", + "\t\t\tfor i = 2 to levels", + "\t\t\t\tlet tval = fixValue(propMap.get(key).run(i))", + "\t\t\t\tif val != tval", + "\t\t\t\t\tisConstantValue = false", + "\t\t\t\t\tbreak", + "", + "\t\t\tif isConstantValue", + "\t\t\t\ttmp += \"|cffFFCC00\" + val + \"|r \"", + "\t\t\telse", + "\t\t\t\tfor i = 1 to levels", + "\t\t\t\t\ttmp += fixValue(propMap.get(key).run(i)) + (i < levels ? \"/\" : \"\")", + "", + "\t\t\ts += TITLE_COLOR + key + \":|r \" + colorLevelValue(tmp, lvl, levels) + \"\\n\"", + "\t\ts += \"\\n\"", + "\t\ts += buildDescription(description)", + "\t\treturn s", + "", + "\tprivate static function fixValue(string value) returns string", + "\t\tif value == \"\"", + "\t\t\treturn \"\"", + "\t\tvar s = value", + "\t\tlet len = s.length()", + "\t\tlet lastChar = s.substring(len-1, len)", + "\t\tif lastChar == \".\"", + "\t\t\ts = s.substring(0, len-1)", + "\t\telse if len > 1 and s.substring(len-2, len) == \".0\"", + "\t\t\ts = s.substring(0, len-2)", + "\t\treturn s", + "", + "\tprivate static function colorLevelValue(string oldString, int lvl, int maxLevel) returns string", + "\t\tvar _newString = \"\"", + "\t\tvar charCount = 0", + "\t\tvar charPosCount = 0", + "\t\tint array charPos", + "\t\tlet oldLen = oldString.length()", + "\t\tfor char in oldString", + "\t\t\tif char == \"/\"", + "\t\t\t\tcharPos[charPosCount] = charCount", + "\t\t\t\tcharPosCount++", + "\t\t\tcharCount++", + "\t\tif lvl == -1", + "\t\t\t_newString = oldString", + "\t\telse if charPosCount <= 0", + "\t\t\t_newString = \"|cffFFCC00\" + oldString", + "\t\telse if maxLevel <= 1", + "\t\t\t_newString = \"|cffFFCC00\" + oldString", + "\t\telse if lvl == 1", + "\t\t\t_newString = \"|cffFFCC00\" + oldString.substring(0, charPos[0]) + \"|r\" + oldString.substring(charPos[0], oldLen)", + "\t\telse if lvl == maxLevel", + "\t\t\t_newString = oldString.substring(0, charPos[lvl-2] + 1) + \"|cffFFCC00\" + oldString.substring(charPos[lvl-2] + 1, oldLen) + \"|r\"", + "\t\telse", + "\t\t\t_newString = oldString.substring(0, charPos[lvl-2] + 1) + \"|cffFFCC00\" + oldString.substring(charPos[lvl-2] + 1, charPos[lvl-1]) + \"|r\" + oldString.substring(charPos[lvl-1], oldLen)", + "\t\treturn _newString", + "constant h = compiletime(gen())", + "", + "function gen() returns int", + " let myInt = 20", + " let tgen = new AbilityTooltipGenerator(\"Test1\")", + " new AbilityDefinitionItemHealAoe('1234')", + " ..registerTooltipGenerator(tgen)", + " ..tooltipStartListen()", + " ..addTooltipProperty(\"String\", _ -> \"a\")", + " ..tooltipStopListen(true)", + "", + " return 1", + "init", + " testSuccess()" + ); + } }