Fix: IDEA-40926 (Make GSP aware of model returned from controller)

This commit is contained in:
Sergey Evdokimov
2010-09-09 18:24:44 +04:00
parent 39045413e1
commit 4bdc92737c
4 changed files with 56 additions and 41 deletions
@@ -135,22 +135,12 @@ public abstract class GrLiteralClassType extends PsiClassType {
return type == null ? CommonClassNames.JAVA_LANG_OBJECT : type.getInternalCanonicalText();
}
@Nullable
private static PsiType getLeastUpperBound(@Nullable PsiType result, @Nullable PsiType other, PsiManager manager) {
if (other == null) return result;
if (result == null) result = other;
if (result.isAssignableFrom(other)) return result;
if (other.isAssignableFrom(result)) result = other;
return TypesUtil.getLeastUpperBound(result, other, manager);
}
@NotNull
protected PsiType getLeastUpperBound(PsiType[] psiTypes) {
PsiType result = null;
final PsiManager manager = getPsiManager();
for (final PsiType other : psiTypes) {
result = getLeastUpperBound(result, other, manager);
result = TypesUtil.getLeastUpperBoundNullable(result, other, manager);
}
return result == null ? PsiType.getJavaLangObject(manager, getResolveScope()) : result;
}
@@ -398,6 +398,15 @@ public class TypesUtil {
return PsiType.getJavaLangObject(context.getManager(), context.getResolveScope());
}
@Nullable
public static PsiType getLeastUpperBoundNullable(@Nullable PsiType type1, @Nullable PsiType type2, PsiManager manager) {
if (type1 == null) return type2;
if (type2 == null) return type1;
if (type1.isAssignableFrom(type2)) return type1;
if (type2.isAssignableFrom(type1)) return type2;
return getLeastUpperBound(type1, type2, manager);
}
@Nullable
public static PsiType getLeastUpperBound(@NotNull PsiType type1, @NotNull PsiType type2, PsiManager manager) {
if (type1 instanceof GrTupleType && type2 instanceof GrTupleType) {
@@ -28,6 +28,7 @@ import com.intellij.psi.search.SearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
@@ -51,6 +52,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
@@ -964,4 +967,40 @@ public class PsiUtil {
}
}
public static List<GrReturnStatement> collectReturns(PsiElement element) {
class ArrayListConsumer extends ArrayList<GrReturnStatement> implements Consumer<GrReturnStatement> {
@Override
public void consume(GrReturnStatement grReturnStatement) {
add(grReturnStatement);
}
}
ArrayListConsumer res = new ArrayListConsumer();
collectReturns(element, res);
return res;
}
public static void collectReturns(PsiElement element, Consumer<GrReturnStatement> consumer) {
if (element instanceof GrReturnStatement) {
consumer.consume((GrReturnStatement) element);
} else {
PsiElement child = element.getFirstChild();
while(child != null) {
collectReturns(child, consumer);
child = child.getNextSibling();
}
}
}
@Nullable
public static GrStatement getLastStatement(@NotNull GrCodeBlock block) {
for (PsiElement element = block.getLastChild(); element != null; element = element.getPrevSibling()) {
if (element instanceof GrStatement) {
return (GrStatement)element;
}
}
return null;
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.ArrayList;
import java.util.List;
@@ -39,51 +40,27 @@ public class MethodTypeInferencer implements Computable<PsiType> {
@Nullable
public PsiType compute () {
List<GrReturnStatement> returns = new ArrayList<GrReturnStatement>();
collectReturns(myBlock, returns);
List<GrReturnStatement> returns = PsiUtil.collectReturns(myBlock);
PsiType result = null;
PsiManager manager = myBlock.getManager();
for (GrReturnStatement returnStatement : returns) {
GrExpression value = returnStatement.getReturnValue();
if (value != null) {
result = upperBound(result, value.getType(), manager);
result = TypesUtil.getLeastUpperBoundNullable(result, value.getType(), manager);
}
}
boolean isObject = returns.size() == 0;
GrStatement[] statements = myBlock.getStatements();
if (statements.length > 0) {
GrStatement last = statements[statements.length - 1];
if (last instanceof GrExpression) {
result = upperBound(((GrExpression) last).getType(), result, manager);
isObject = false;
}
GrStatement last = PsiUtil.getLastStatement(myBlock);
if (last instanceof GrExpression) {
result = TypesUtil.getLeastUpperBoundNullable(((GrExpression) last).getType(), result, manager);
isObject = false;
}
if (isObject) return TypesUtil.getJavaLangObject(myBlock);
return result;
}
private static PsiType upperBound(PsiType type1, PsiType type2, PsiManager manager) {
if (type1 == null) return type2;
if (type2 == null) return type1;
if (type1.isAssignableFrom(type2)) return type1;
if (type2.isAssignableFrom(type1)) return type2;
return TypesUtil.getLeastUpperBound(type1, type2, manager);
}
private static void collectReturns(PsiElement element, List<GrReturnStatement> returns) {
if (element instanceof GrReturnStatement) {
returns.add((GrReturnStatement) element);
} else {
PsiElement child = element.getFirstChild();
while(child != null) {
collectReturns(child, returns);
child = child.getNextSibling();
}
}
}
}