Skip to content

Commit

Permalink
adding logic that utilize expected type when resolving enumValues and…
Browse files Browse the repository at this point in the history
… Types
  • Loading branch information
m0rkeulv committed Jan 28, 2024
1 parent 26622b6 commit 8c2f421
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
55 changes: 55 additions & 0 deletions src/main/java/com/intellij/plugins/haxe/lang/psi/HaxeResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ private List<? extends PsiElement> doResolveInner(@NotNull HaxeReference referen
List<? extends PsiElement> 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);
Expand Down Expand Up @@ -267,6 +268,60 @@ private List<? extends PsiElement> 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<? extends PsiElement> 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<HaxeNamedComponent> 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<? extends PsiElement> checkGlobalAlias(HaxeReference reference) {
if (reference.textMatches("trace")) {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
20 changes: 20 additions & 0 deletions src/test/resources/testData/annotation.semantic/EnumTypeHints.hx
Original file line number Diff line number Diff line change
@@ -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<Dynamic> = LooksLikeClass;

// not found
var notFound:EnumForHints = <warning descr="Unresolved symbol">NotFound</warning>;
// wrong type
var <error descr="Incompatible type: Class<TestAssignHints> should be EnumForHints">wrong:EnumForHints = TestAssignHints</error>;
}
}

0 comments on commit 8c2f421

Please sign in to comment.