Skip to content

Commit

Permalink
Stack overflow fix and better resolving untyped parameters.
Browse files Browse the repository at this point in the history
  • Loading branch information
m0rkeulv committed Feb 21, 2024
1 parent 4d37da5 commit 9108c05
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 115 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Changelog
## 1.4.42
* Bugfix: function bindings was incorrectly treated as static extensions
* Bugfix: Function bindings was incorrectly treated as static extensions
* Bugfix: Stack overflow when resolving expression type
* Misc resolver tweaks to better resolve untyped parameters and performance

## 1.4.41
* Bugfix: fixed type resolve regression for iterators
## 1.4.40
Expand Down
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
org.gradle.jvmargs =-Xmx1g
# IntelliJ Platform Artifacts Repositories
# -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html

Expand All @@ -6,7 +7,7 @@ pluginName = Haxe Toolkit Support
pluginRepositoryUrl = https://github.com/HaxeFoundation/intellij-haxe

# SemVer format -> https://semver.org
pluginVersion = 1.4.41
pluginVersion = 1.4.42

# IntelliJ Platform Properties -> https://github.com/JetBrains/gradle-intellij-plugin#intellij-platform-properties
platformType = IU
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ private List<? extends PsiElement> doResolveInner(@NotNull HaxeReference referen
if (result == null) {
LogResolution(reference, "failed after exhausting all options.");
}
if (result == null) {
if (result == null || result.isEmpty()) {
// to avoid caching empty due to already being resolved we mark
// elements so we know if we want to cache as not found or just skip (null is not cached, empty list is cached)
if (incompleteCode || reference.getUserData(skipCacheKey) == Boolean.TRUE) {
Expand Down Expand Up @@ -608,7 +608,7 @@ private List<? extends PsiElement> checkIsSwitchVar(HaxeReference reference) {

// NOTE: this one has to come before `checkIfSwitchCaseDefaultValue`
// check if default name in match expression (ex `case TString(_ => captureVar)`)
if (result == null) result = checkIfDefaultValueInMatchExpression(reference, switchCaseExpr);
result = checkIfDefaultValueInMatchExpression(reference, switchCaseExpr);

// check if matches default name ( ex. `case _:`)
if (result == null) result = checkIfSwitchCaseDefaultValue(reference);
Expand Down Expand Up @@ -873,7 +873,6 @@ private List<? extends PsiElement> checkIsFullyQualifiedStatement(@NotNull HaxeR
if (parent != null) {

//TODO check for @:using on haxeType and add to using (this might not be the correct place, but its a reminder to add it somewhere in the resolver logic)
// TODO if using, include all members from file for resolving ( qualified path / package + memberName in using should resolve)

LogResolution(reference, "via parent/package import.");
return asList(resolveQualifiedReference(reference));
Expand Down Expand Up @@ -916,12 +915,10 @@ private List<? extends PsiElement> resolveChain(HaxeReference lefthandExpression
}

// Check 'using' classes.
HaxeClass leftClass = leftExpression.getHaxeClass();
if (leftClass != null) {
HaxeFileModel fileModel = HaxeFileModel.fromElement(reference.getContainingFile());

// Add the global usings to the top of the list (so they're checked last).
HaxeProjectModel projectModel = HaxeProjectModel.fromElement(leftClass);
HaxeProjectModel projectModel = HaxeProjectModel.fromElement(reference);
HaxeStdPackageModel stdPackageModel = (HaxeStdPackageModel)projectModel.getStdPackage();
final List<HaxeUsingModel> usingModels = new ArrayList<>(stdPackageModel.getGlobalUsings());

Expand All @@ -943,7 +940,12 @@ private List<? extends PsiElement> resolveChain(HaxeReference lefthandExpression
if (log.isTraceEnabled()) log.trace("Found method in 'using' import: " + foundMethod.getName());
return asList(foundMethod.getBasePsi());
}
}
// check other types ("using" can be used to find typedefsetc)
PsiElement element = usingModels.get(i).exposeByName(identifier);
if (element != null) {
if (log.isTraceEnabled()) log.trace("Found method in 'using' import: " + identifier);
return List.of(element);
}
}

if (log.isTraceEnabled()) log.trace(traceMsg(null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ public AbstractHaxeTypeDefImpl(@NotNull ASTNode node) {
super(node);
}

private HaxeResolveResult targetClass;

public HaxeResolveResult getTargetClass() {
return getTargetClass(new HaxeGenericSpecialization());
if (targetClass != null) return targetClass;
targetClass = getTargetClass(new HaxeGenericSpecialization());
return targetClass;
}

public SpecificHaxeClassReference getTargetClass(HaxeGenericResolver genericResolver) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import java.util.stream.Collectors;

import static com.intellij.openapi.util.text.StringUtil.defaultIfEmpty;
import static com.intellij.plugins.haxe.model.type.HaxeExpressionEvaluator.searchReferencesForType;
import static com.intellij.plugins.haxe.model.type.SpecificTypeReference.ARRAY;
import static com.intellij.plugins.haxe.model.type.SpecificTypeReference.CLASS;
import static com.intellij.plugins.haxe.util.HaxeDebugLogUtil.traceAs;
Expand Down Expand Up @@ -265,7 +266,7 @@ public PsiElement resolveToComponentName() {
final PsiElement result = resolveResults.length != 1 ||
!resolveResults[0].isValidResult() ? null : resolveResults[0].getElement();

if (result != null && result instanceof HaxeNamedComponent namedComponent) {
if (result instanceof HaxeNamedComponent namedComponent) {
return namedComponent.getComponentName();
}

Expand Down Expand Up @@ -816,15 +817,17 @@ else if (resolvedType.isFunctionType()) {
}
if (isType(resolve, HaxeParameter.class)) {
// check if type parameters has multiple constraints and try to unify
HaxeTypeTag tag = ((HaxeParameter)resolve).getTypeTag();
HaxeParameter parameter = (HaxeParameter)resolve;
HaxeTypeTag tag = parameter.getTypeTag();
String typeName = tag != null && tag.getTypeOrAnonymous() != null ? tag.getTypeOrAnonymous().getText() : null;
PsiElement parameterList = resolve.getParent();
if (parameterList != null && parameterList.getParent() instanceof HaxeFunctionLiteral literal) {
if (parameterList != null) {
if (parameterList.getParent() instanceof HaxeFunctionLiteral literal) {
// if parameter type is unknown (allowed in function literals) we can try to find it from assignment, ex. callExpression
ResultHolder holder = tryToFindTypeFromCallExpression(literal, resolve);
if (holder != null && !holder.isUnknown()) return holder.getType().asResolveResult();
}
if (parameterList != null && parameterList.getParent() instanceof HaxeMethodDeclaration method) {
else if (parameterList.getParent() instanceof HaxeMethodDeclaration method) {
HaxeGenericParam methodGenericParam = method.getGenericParam();
List<HaxeGenericListPart> methodPartList = methodGenericParam != null ? methodGenericParam.getGenericListPartList() : null;

Expand Down Expand Up @@ -891,8 +894,16 @@ else if (typeOrAnonymous.getAnonymousType() != null) {
}
}
}
else {

}
// try to search for usage to determine type
if (tag == null && parameter.getVarInit() == null) {
HaxeComponentName componentName = parameter.getComponentName();
HaxeExpressionEvaluatorContext context = new HaxeExpressionEvaluatorContext(parameterList);
HaxeMethod method = PsiTreeUtil.getParentOfType(parameter, HaxeMethod.class);
ResultHolder holder = searchReferencesForType(componentName, context, null, method == null ? null : method.getBody());
if (!holder.isUnknown()) {
return holder.getType().asResolveResult();
}
}
}
}
Expand Down
Loading

0 comments on commit 9108c05

Please sign in to comment.