diff --git a/src/main/java/com/intellij/plugins/haxe/lang/psi/HaxeResolver.java b/src/main/java/com/intellij/plugins/haxe/lang/psi/HaxeResolver.java index 7099c02e0..db713e55f 100644 --- a/src/main/java/com/intellij/plugins/haxe/lang/psi/HaxeResolver.java +++ b/src/main/java/com/intellij/plugins/haxe/lang/psi/HaxeResolver.java @@ -186,6 +186,7 @@ private List doResolveInner(@NotNull HaxeReference referen List result = checkIsTypeParameter(reference); if (result == null) result = checkIsAlias(reference); + if (result == null) result = checkEnumMemberHints(reference); if (result == null) result = checkIsType(reference); if (result == null) result = checkIsFullyQualifiedStatement(reference); if (result == null) result = checkIsSuperExpression(reference); @@ -267,6 +268,60 @@ private List doResolveInner(@NotNull HaxeReference referen return result; } + // checks if we are attempting to assign an enum type, this makes sure we chose the enum value and not competing class names + private List checkEnumMemberHints(HaxeReference reference) { + HaxePsiField fieldFromReferenceExpression = null; + HaxeAssignExpression assignExpression = PsiTreeUtil.getParentOfType(reference, HaxeAssignExpression.class); + if (assignExpression != null) { + HaxeExpression left = assignExpression.getLeftExpression(); + if (left instanceof HaxeReferenceExpression referenceExpression) { + PsiElement resolve = referenceExpression.resolve(); + if (resolve instanceof HaxePsiField psiField) { + fieldFromReferenceExpression = psiField; + } + } + } + + HaxePsiField field = fieldFromReferenceExpression != null ? fieldFromReferenceExpression : PsiTreeUtil.getParentOfType(reference, HaxePsiField.class); + if (field != null) { + HaxeTypeTag tag = field.getTypeTag(); + if (tag != null && tag.getTypeOrAnonymous() != null) { + ResultHolder type = HaxeTypeResolver.getTypeFromTypeOrAnonymous(tag.getTypeOrAnonymous()); + if (type.getClassType() != null) { + SpecificTypeReference typeReference = type.getClassType().fullyResolveTypeDefAndUnwrapNullTypeReference(); + return findEnumMember(reference, typeReference); + } + } + } + + HaxeParameter parameter = PsiTreeUtil.getParentOfType(reference, HaxeParameter.class); + if (parameter != null) { + HaxeTypeTag tag = parameter.getTypeTag(); + if (tag != null && tag.getTypeOrAnonymous() != null) { + ResultHolder type = HaxeTypeResolver.getTypeFromTypeOrAnonymous(tag.getTypeOrAnonymous()); + if (type.getClassType() != null) { + SpecificTypeReference typeReference = type.getClassType().fullyResolveTypeDefAndUnwrapNullTypeReference(); + return findEnumMember(reference, typeReference); + } + } + } + return null; + } + + @Nullable + private static List findEnumMember(HaxeReference reference, SpecificTypeReference typeReference) { + if (typeReference.isEnumType()) { + if (typeReference instanceof SpecificHaxeClassReference classReference) { + HaxeClass haxeClass = classReference.getHaxeClass(); + if (haxeClass != null) { + HaxeNamedComponent name = haxeClass.findHaxeMemberByName(reference.getText(), null); + if (name != null) return List.of(name); + } + } + } + return null; + } + private List checkGlobalAlias(HaxeReference reference) { if (reference.textMatches("trace")) { if (!ApplicationManager.getApplication().isUnitTestMode()) { diff --git a/src/test/java/com/intellij/plugins/haxe/ide/HaxeSemanticAnnotatorTest.java b/src/test/java/com/intellij/plugins/haxe/ide/HaxeSemanticAnnotatorTest.java index 2f485b7c7..ad2d43614 100644 --- a/src/test/java/com/intellij/plugins/haxe/ide/HaxeSemanticAnnotatorTest.java +++ b/src/test/java/com/intellij/plugins/haxe/ide/HaxeSemanticAnnotatorTest.java @@ -842,4 +842,12 @@ public void testSwitchEumVariableCapture() throws Throwable { myFixture.enableInspections(HaxeUnresolvedSymbolInspection.class); doTestNoFixWithWarnings(); } + + // this might not be the right place for this test as its testing the resolver logic + // but to verify the resolved results we need to do type compare + @Test + public void testEnumTypeHints() throws Throwable { + myFixture.enableInspections(HaxeUnresolvedSymbolInspection.class); + doTestNoFixWithWarnings(); + } } diff --git a/src/test/resources/testData/annotation.semantic/EnumTypeHints.hx b/src/test/resources/testData/annotation.semantic/EnumTypeHints.hx new file mode 100644 index 000000000..b82b36fdf --- /dev/null +++ b/src/test/resources/testData/annotation.semantic/EnumTypeHints.hx @@ -0,0 +1,20 @@ +class LooksLikeClass {} + +enum EnumForHints { + LooksLikeClass; + NotClass; +} + +class TestAssignHints { + public function new() { + var fullyQualified:EnumForHints = EnumForHints.LooksLikeClass; + var hintFromType:EnumForHints = NotClass; + var competingClassName:EnumForHints = LooksLikeClass; + var className:Class = LooksLikeClass; + + // not found + var notFound:EnumForHints = NotFound; + // wrong type + var wrong:EnumForHints = TestAssignHints; + } +}