|
39 | 39 |
|
40 | 40 | import static com.intellij.plugins.haxe.lang.lexer.HaxeTokenTypeSets.ONLY_COMMENTS; |
41 | 41 | import static com.intellij.plugins.haxe.lang.lexer.HaxeTokenTypes.KUNTYPED; |
| 42 | +import static com.intellij.plugins.haxe.lang.psi.HaxeResolver.buildExtractVarPath; |
42 | 43 | import static com.intellij.plugins.haxe.lang.psi.impl.HaxeReferenceImpl.getLiteralClassName; |
43 | 44 | import static com.intellij.plugins.haxe.lang.psi.impl.HaxeReferenceImpl.tryToFindTypeFromCallExpression; |
44 | 45 | import static com.intellij.plugins.haxe.lang.psi.impl.HaxeReferenceUtil.isStaticExtension; |
@@ -856,28 +857,88 @@ public void run() { |
856 | 857 | } |
857 | 858 |
|
858 | 859 |
|
859 | | - static ResultHolder handleEnumExtractedValue(@NotNull HaxeEnumExtractedValueReference extractedValue, @NotNull HaxeGenericResolver resolver) { |
860 | | - HaxeExtractorMatchExpression matchExpression = PsiTreeUtil.getParentOfType(extractedValue, HaxeExtractorMatchExpression.class, true, HaxeEnumArgumentExtractor.class); |
| 860 | + static ResultHolder handleExtractedValue(@NotNull HaxeEnumExtractedValueReference extractedValueRef, @NotNull HaxeGenericResolver resolver) { |
| 861 | + HaxeExtractorMatchExpression matchExpression = PsiTreeUtil.getParentOfType(extractedValueRef, HaxeExtractorMatchExpression.class, true, HaxeEnumArgumentExtractor.class); |
861 | 862 | if (matchExpression != null) { |
862 | 863 | HaxeSwitchCaseExpr match = matchExpression.getMatch(); |
863 | | - if (PsiTreeUtil.isAncestor(match, extractedValue, false)) { |
| 864 | + if (PsiTreeUtil.isAncestor(match, extractedValueRef, false)) { |
864 | 865 | return evaluate(matchExpression.getExtractorExpression(), resolver).result; |
865 | 866 | } |
866 | 867 | } |
867 | 868 |
|
868 | | - HaxeEnumArgumentExtractor extractor = PsiTreeUtil.getParentOfType(extractedValue, HaxeEnumArgumentExtractor.class, true, HaxeEnumArgumentExtractor.class); |
| 869 | + HaxeEnumArgumentExtractor extractor = PsiTreeUtil.getParentOfType(extractedValueRef, HaxeEnumArgumentExtractor.class, true, HaxeEnumArgumentExtractor.class); |
869 | 870 | if (extractor != null) { |
870 | 871 | HaxeEnumExtractorModel extractorModel = (HaxeEnumExtractorModel)extractor.getModel(); |
871 | | - return extractorModel.resolveExtractedValueType(extractedValue); |
| 872 | + return extractorModel.resolveExtractedValueType(extractedValueRef); |
872 | 873 | } |
873 | 874 |
|
874 | | - PsiElement resolve = extractedValue.resolve(); |
| 875 | + PsiElement resolve = extractedValueRef.resolve(); |
875 | 876 | if(resolve != null) { |
876 | | - return evaluate(resolve).result; |
| 877 | + |
| 878 | + ResultHolder result = evaluate(resolve).result; |
| 879 | + |
| 880 | + if (extractedValueRef.getParent() instanceof HaxeEnumExtractedValue extractedValue) { |
| 881 | + //TODO: mlo - We should probably try to redo how switch extractors are parsed in the BNF |
| 882 | + // to get more consistency between ExprArray and ArrayLiteral (we might not need both) |
| 883 | + if (extractedValue.getParent() instanceof HaxeEnumExtractArrayLiteral |
| 884 | + || extractedValue.getParent() instanceof HaxeSwitchCaseExprArray) { |
| 885 | + |
| 886 | + Stack<Object> objectPath = new Stack<>(); |
| 887 | + |
| 888 | + HaxeSwitchStatement switchStatement = PsiTreeUtil.getParentOfType(extractedValue, HaxeSwitchStatement.class); |
| 889 | + buildExtractVarPath(extractedValue, true, objectPath, switchStatement); |
| 890 | + |
| 891 | + Collections.reverse(objectPath); |
| 892 | + // workaround for switch on literal array (ex. switch (["mixed Types", 1, false]{...})) |
| 893 | + // as we are not going to look for generics in these situations to determine type. |
| 894 | + boolean isLiteralInSwitchExpression = isLiteralInSwitchExpression(resolve, extractedValueRef); |
| 895 | + int offset = isLiteralInSwitchExpression ? 1 : 0; |
| 896 | + |
| 897 | + ResultHolder typePointer = result; |
| 898 | + for (int i = offset; i < objectPath.size(); i++) { |
| 899 | + Object o = objectPath.get(i); |
| 900 | + if (typePointer == null || typePointer.isUnknown()) break; |
| 901 | + |
| 902 | + if (o instanceof Integer index) { |
| 903 | + typePointer = typeFromArray(typePointer, index); |
| 904 | + //TODO do we need support for objects here ? |
| 905 | +// } else if (o instanceof String name) { |
| 906 | + // typePointer = typeFromObjectName(typePointer,name); |
| 907 | + } |
| 908 | + } |
| 909 | + return typePointer != null ? typePointer : createUnknown(extractedValueRef); |
| 910 | + } |
| 911 | + } |
| 912 | + return result; |
877 | 913 | } |
878 | | - return createUnknown(extractedValue); |
| 914 | + return createUnknown(extractedValueRef); |
879 | 915 | } |
880 | 916 |
|
| 917 | + private static boolean isLiteralInSwitchExpression(PsiElement resolve, @NotNull HaxeEnumExtractedValueReference extractedValueRef) { |
| 918 | + HaxeLiteralExpression isLiteral = PsiTreeUtil.getParentOfType(resolve, HaxeLiteralExpression.class, false, HaxeSwitchStatement.class); |
| 919 | + HaxeArrayLiteral isInsideArrayLiteral = PsiTreeUtil.getParentOfType(resolve, HaxeArrayLiteral.class, false, HaxeSwitchStatement.class); |
| 920 | + HaxeSwitchStatement resolvedSwitchParent = PsiTreeUtil.getParentOfType(resolve, HaxeSwitchStatement.class); |
| 921 | + if(resolvedSwitchParent == null) return false; |
| 922 | + boolean isInSameSwitch = PsiTreeUtil.isAncestor(resolvedSwitchParent.getSwitchBlock(), extractedValueRef, false); |
| 923 | + return isInSameSwitch && (isLiteral != null || isInsideArrayLiteral != null); |
| 924 | + } |
| 925 | + |
| 926 | + private static ResultHolder typeFromArray(ResultHolder typePointer, Integer index) { |
| 927 | + |
| 928 | + SpecificHaxeClassReference classType = typePointer.getClassType(); |
| 929 | + if(classType != null){ |
| 930 | + if(classType.fullyResolveTypeDefAndUnwrapNullTypeReference() instanceof SpecificHaxeClassReference classReference) { |
| 931 | + if(classReference.isArray()) { |
| 932 | + @NotNull ResultHolder[] specifics = classReference.getSpecifics(); |
| 933 | + if(specifics.length == 1) return specifics[0]; |
| 934 | +// }else { |
| 935 | + // TODO considder checking array access in other types for expected return value |
| 936 | + // - verify if its supported first |
| 937 | + } |
| 938 | + } |
| 939 | + } |
| 940 | + return null; |
| 941 | + } |
881 | 942 |
|
882 | 943 |
|
883 | 944 | static ResultHolder handleForStatement( |
|
0 commit comments