Skip to content

Commit

Permalink
refactoring, removing unnecessary code duplication in expression eval…
Browse files Browse the repository at this point in the history
…uator
  • Loading branch information
m0rkeulv committed Feb 18, 2024
1 parent 2adffe6 commit 208a4d8
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,32 +48,11 @@ private static void handleForEachHints(@NotNull PsiElement element,
HaxeIteratorkey iteratorKey = keyValueIterator.getIteratorkey();
HaxeIteratorValue iteratorValue = keyValueIterator.getIteratorValue();

var keyValueIteratorType = HaxeTypeResolver.getPsiElementType(iterable, element, resolver);
var iteratorType = keyValueIteratorType.getClassType();
if (iteratorType.isTypeDef()) {
SpecificTypeReference type = iteratorType.fullyResolveTypeDefReference();
if (type instanceof SpecificHaxeClassReference classReference) {
iteratorType = classReference;
}
}
var iteratorTypeResolver = iteratorType.getGenericResolver();

HaxeMethodModel iteratorReturnType = (HaxeMethodModel)iteratorType.getHaxeClassModel().getMember("next", iteratorTypeResolver);
if (iteratorReturnType == null) return;

HaxeGenericResolver nextResolver = iteratorReturnType.getGenericResolver(null);
nextResolver.addAll(iteratorTypeResolver);

ResultHolder returnType = iteratorReturnType.getReturnType(nextResolver);
SpecificHaxeClassReference type = returnType.getClassType();
HaxeGenericResolver genericResolver = type.getGenericResolver();

ResultHolder keyType = type.getHaxeClassModel().getMember("key", null).getResultType(genericResolver);
ResultHolder valueType = type.getHaxeClassModel().getMember("value", null).getResultType(genericResolver);

ResultHolder keyType = HaxeExpressionEvaluator.findIteratorType(element, iteratorKey);
ResultHolder valueType = HaxeExpressionEvaluator.findIteratorType(element, iteratorValue);

createInlayHint(iteratorKey.getComponentName(), sink, keyType);
createInlayHint(iteratorValue.getComponentName(), sink, valueType);
if (keyType!= null) createInlayHint(iteratorKey.getComponentName(), sink, keyType);
if (valueType!= null) createInlayHint(iteratorValue.getComponentName(), sink, valueType);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ static public HaxeExpressionEvaluatorContext evaluate(PsiElement element, HaxeEx
return context;
}

private static ThreadLocal<HashSet<PsiElement>> resolvesInProcess = new ThreadLocal<>().withInitial(()->new HashSet<PsiElement>());
@Nullable
private static ResultHolder handleWithRecursionGuard(PsiElement element,
HaxeExpressionEvaluatorContext context,
HaxeGenericResolver resolver) {
if (element == null) return null;
HashSet<PsiElement> elements = resolvesInProcess.get();
try {
if (elements.contains(element)) return null;
elements.add(element);
return handle(element, context, resolver);
} finally {
elements.remove(element);
}
}

@NotNull
static private ResultHolder handle(final PsiElement element,
final HaxeExpressionEvaluatorContext context,
Expand Down Expand Up @@ -456,17 +472,30 @@ public void run() {
return holder;
}

if (element instanceof HaxeRestParameter restParameter) {
HaxeTypeTag tag = restParameter.getTypeTag();
ResultHolder type = HaxeTypeResolver.getTypeFromTypeTag(tag, restParameter);
return new ResultHolder(SpecificTypeReference.getStdClass(ARRAY, restParameter, new ResultHolder[]{type}));
}

if (element instanceof HaxeParameter parameter) {
HaxeTypeTag typeTag = parameter.getTypeTag();
if (typeTag!= null) {
if (typeTag != null) {
ResultHolder typeFromTypeTag = HaxeTypeResolver.getTypeFromTypeTag(typeTag, element);
if (typeFromTypeTag.isTypeParameter()) {
ResultHolder resolve = resolver.resolve(typeFromTypeTag);
if (!resolve.isUnknown()) return resolve;
}
return typeFromTypeTag;
}
if (parameter.getVarInit() == null) {

HaxeVarInit init = parameter.getVarInit();
if (init != null) {
ResultHolder holder = handle(init, context, resolver);
if (!holder.isUnknown()) {
return holder;
}
}else {
if (element.getParent().getParent() instanceof HaxeFunctionLiteral functionLiteral) {
ResultHolder holder = tryToFindTypeFromCallExpression(functionLiteral, parameter);
if (holder!= null && !holder.isUnknown()) {
Expand Down Expand Up @@ -661,13 +690,13 @@ else if (element instanceof HaxeLocalVarDeclaration varDeclaration) {
}
return handle(expression, context, resolver);
}
if (element instanceof HaxeRegularExpressionLiteral) {
if (element instanceof HaxeRegularExpressionLiteral) {
HaxeClass regexClass = HaxeResolveUtil.findClassByQName(getLiteralClassName(HaxeTokenTypes.REG_EXP), element);
if (regexClass != null) {
return SpecificHaxeClassReference.withoutGenerics(new HaxeClassReference(regexClass.getModel(),element)).createHolder();
}
}
if (element instanceof HaxeValueExpression valueExpression) {
if (element instanceof HaxeValueExpression valueExpression) {
if (valueExpression.getSwitchStatement() != null){
return handle(valueExpression.getSwitchStatement(), context, resolver);
}
Expand All @@ -684,10 +713,6 @@ else if (element instanceof HaxeLocalVarDeclaration varDeclaration) {
return handle(valueExpression.getExpression(), context, resolver);
}
}
//if (element instanceof HaxeParenthesizedExpressionReference parenthesizedReference) {
// ResultHolder handle = handle(parenthesizedReference.getExpression(), context, resolver);
// boolean unknown = handle.isUnknown();
//}

if (element instanceof HaxeReferenceExpression) {
PsiElement[] children = element.getChildren();
Expand Down Expand Up @@ -750,14 +775,10 @@ else if (element instanceof HaxeLocalVarDeclaration varDeclaration) {
PsiReference reference = element.getReference();
if (reference != null) {
PsiElement subelement = reference.resolve();

if (subelement instanceof HaxeReferenceExpression referenceExpression) {
PsiElement resolve = referenceExpression.resolve();
if (resolve != null) {
// small attempt at recursion guard
if (resolve != element) {
typeHolder = handle(resolve, context, resolver);
}
}
typeHolder = handleWithRecursionGuard(resolve, context, resolver);
}
if (subelement instanceof HaxeClass haxeClass) {

Expand Down Expand Up @@ -800,41 +821,6 @@ else if (subelement instanceof HaxeMethodDeclaration methodDeclaration) {
typeHolder = type.createHolder();
}

else if (subelement instanceof HaxeParameter parameter) {
if (subelement instanceof HaxeRestParameter restParameter) {
HaxeTypeTag tag = restParameter.getTypeTag();
ResultHolder type = HaxeTypeResolver.getTypeFromTypeTag(tag, restParameter);
typeHolder = new ResultHolder(SpecificTypeReference.getStdClass(ARRAY, subelement, new ResultHolder[]{type}));
}
else {
HaxeTypeTag tag = parameter.getTypeTag();
if (tag != null) {
typeHolder = HaxeTypeResolver.getTypeFromTypeTag(tag, parameter);
ResultHolder holder = HaxeTypeResolver.resolveParameterizedType(typeHolder, resolver);
if (!holder.isUnknown()) {
typeHolder = holder;
}
}else {
HaxeVarInit init = parameter.getVarInit();
if (init != null) {
ResultHolder holder = handle(init, context, resolver);
if (!holder.isUnknown()) {
typeHolder = holder;
}
}
}
}
}
else if (subelement instanceof HaxeLocalVarDeclaration varDeclaration) {
HaxeVarInit init = varDeclaration.getVarInit();
if (init != null) {
HaxeExpression initExpression = init.getExpression();
HaxeGenericResolver initResolver = HaxeGenericResolverUtil.generateResolverFromScopeParents(initExpression);
typeHolder = HaxeTypeResolver.getFieldOrMethodReturnType((AbstractHaxeNamedComponent)subelement, initResolver);
}else {
typeHolder = handle(subelement, context,resolver);
}
}
else if (subelement instanceof HaxeForStatement forStatement) {
// key-value iterator is not relevant here as it will be resolved to HaxeIteratorkey or HaxeIteratorValue
final HaxeComponentName name = forStatement.getComponentName();
Expand All @@ -859,34 +845,26 @@ else if (subelement instanceof HaxeIteratorkey || subelement instanceof HaxeIter
typeHolder = findIteratorType(element, subelement);
}


else if (subelement instanceof HaxeSwitchCaseCaptureVar caseCaptureVar) {
HaxeSwitchStatement switchStatement = PsiTreeUtil.getParentOfType(caseCaptureVar, HaxeSwitchStatement.class);
if (switchStatement.getExpression() != null) {
typeHolder = handle(switchStatement.getExpression(), context, resolver);
}
}

else if (subelement instanceof HaxeSwitchCaseExpr caseExpr) {
HaxeSwitchStatement switchStatement = PsiTreeUtil.getParentOfType(caseExpr, HaxeSwitchStatement.class);
if (switchStatement.getExpression() != null) {
typeHolder = handle(switchStatement.getExpression(), context, resolver);
}
}

else if (subelement instanceof HaxeEnumExtractedValue extractedValue) {
//we can handle HaxeEnumExtractedValue with "handle", probably no need to duplicate code here
typeHolder = handle(subelement, context, resolver);
}

else if (subelement instanceof HaxeLocalFunctionDeclaration functionDeclaration) {
typeHolder = functionDeclaration.getModel().getFunctionType(resolver).createHolder();
}

else if (subelement instanceof AbstractHaxeNamedComponent namedComponent) {
typeHolder = HaxeTypeResolver.getFieldOrMethodReturnType(namedComponent, resolver);
} else {
// unable to find type
typeHolder = SpecificTypeReference.getUnknown(element).createHolder();
else {
// attempt to resolve subelement using default handle logic
typeHolder = handleWithRecursionGuard(subelement, context, resolver);
if (typeHolder == null) {
typeHolder = SpecificTypeReference.getUnknown(element).createHolder();
}
}

}
Expand Down Expand Up @@ -1423,7 +1401,7 @@ else if (getter instanceof HaxeExternInterfaceDeclaration interfaceDeclaration)
}
return typeHolder;
}
if (element instanceof HaxeIsTypeExpression) {
if (element instanceof HaxeIsTypeExpression) {
return SpecificHaxeClassReference.primitive("Bool", element, null).createHolder();
}
//check if common parent before checking all accepted variants (note should not include HaxeAssignExpression, HaxeIteratorExpression etc)
Expand Down Expand Up @@ -1484,11 +1462,15 @@ else if (getter instanceof HaxeExternInterfaceDeclaration interfaceDeclaration)
}
}

if (element instanceof AbstractHaxeNamedComponent namedComponent) {
return HaxeTypeResolver.getFieldOrMethodReturnType(namedComponent, resolver);
}

if(log.isDebugEnabled()) log.debug("Unhandled " + element.getClass());
return SpecificHaxeClassReference.getUnknown(element).createHolder();
}

@Nullable
public static ResultHolder findIteratorType(PsiElement reference, PsiElement iteratorElement) {
HaxeForStatement forStatement = PsiTreeUtil.getParentOfType(iteratorElement, HaxeForStatement.class);
HaxeGenericResolver forResolver = HaxeGenericResolverUtil.generateResolverFromScopeParents(forStatement);
Expand All @@ -1505,7 +1487,20 @@ public static ResultHolder findIteratorType(PsiElement reference, PsiElement ite
}
var iteratorTypeResolver = iteratorType.getGenericResolver();

HaxeMethodModel iteratorReturnType = (HaxeMethodModel)iteratorType.getHaxeClassModel().getMember("next", iteratorTypeResolver);
HaxeClassModel classModel = iteratorType.getHaxeClassModel();
if (classModel == null) return null;
// NOTE if "String" we need to add iterator types manually as std string class does not have this method
if (iteratorType.isString()) {
if (iteratorElement instanceof HaxeIteratorkey ) {
return SpecificTypeReference.getInt(iteratorElement).createHolder();
}else if (iteratorElement instanceof HaxeIteratorValue){
return SpecificTypeReference.getString(iteratorElement).createHolder();
}
}

HaxeMethodModel iteratorReturnType = (HaxeMethodModel)classModel.getMember("next", iteratorTypeResolver);
if (iteratorReturnType == null) return null;

HaxeGenericResolver nextResolver = iteratorReturnType.getGenericResolver(null);
nextResolver.addAll(iteratorTypeResolver);

Expand Down

0 comments on commit 208a4d8

Please sign in to comment.