mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Unary expression resolve and type inference
This commit is contained in:
+8
-1
@@ -16,12 +16,19 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions;
|
||||
|
||||
import com.intellij.psi.PsiPolyVariantReference;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public interface GrSafeCastExpression extends GrExpression {
|
||||
public interface GrSafeCastExpression extends GrExpression, PsiPolyVariantReference {
|
||||
GrTypeElement getCastTypeElement();
|
||||
GrExpression getOperand();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
GroovyResolveResult[] multiResolve(final boolean incompleteCode);
|
||||
}
|
||||
+10
-3
@@ -16,16 +16,23 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiPolyVariantReference;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public interface GrUnaryExpression extends GrExpression {
|
||||
public String toString();
|
||||
|
||||
public interface GrUnaryExpression extends GrExpression, PsiPolyVariantReference {
|
||||
IElementType getOperationTokenType();
|
||||
PsiElement getOperationToken();
|
||||
|
||||
@Nullable GrExpression getOperand();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
GroovyResolveResult[] multiResolve(final boolean incompleteCode);
|
||||
}
|
||||
|
||||
+6
-1
@@ -54,13 +54,18 @@ public abstract class GrBinaryExpressionImpl extends GrExpressionImpl implements
|
||||
|
||||
@Nullable
|
||||
public IElementType getOperationTokenType() {
|
||||
final PsiElement child = findChildByType(TokenSets.BINARY_OP_SET);
|
||||
final PsiElement child = getOperationToken();
|
||||
if (child == null) return null;
|
||||
final ASTNode node = child.getNode();
|
||||
assert node != null;
|
||||
return node.getElementType();
|
||||
}
|
||||
|
||||
public PsiElement getOperationToken() {
|
||||
final PsiElement child = findChildByType(TokenSets.BINARY_OP_SET);
|
||||
return child;
|
||||
}
|
||||
|
||||
public void accept(GroovyElementVisitor visitor) {
|
||||
visitor.visitBinaryExpression(this);
|
||||
}
|
||||
|
||||
+11
-11
@@ -345,17 +345,17 @@ public class TypesUtil {
|
||||
@Nullable
|
||||
public static PsiType getTypeForIncOrDecExpression(GrUnaryExpression expr) {
|
||||
final GrExpression op = expr.getOperand();
|
||||
if (op != null) {
|
||||
final PsiType opType = op.getType();
|
||||
if (opType != null) {
|
||||
final PsiType overloaded = getOverloadedOperatorType(opType, expr.getOperationTokenType(), expr, PsiType.EMPTY_ARRAY);
|
||||
if (overloaded != null) {
|
||||
return overloaded;
|
||||
}
|
||||
if (isNumericType(opType)) {
|
||||
return opType;
|
||||
}
|
||||
}
|
||||
if (op == null) return null;
|
||||
|
||||
final PsiType opType = op.getType();
|
||||
if (opType == null) return null;
|
||||
|
||||
final PsiType overloaded = getOverloadedOperatorType(opType, expr.getOperationTokenType(), expr, PsiType.EMPTY_ARRAY);
|
||||
if (overloaded != null) {
|
||||
return overloaded;
|
||||
}
|
||||
if (isNumericType(opType)) {
|
||||
return opType;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
+1
-7
@@ -17,11 +17,9 @@
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrPostfixExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrPostfixExpression;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
@@ -36,10 +34,6 @@ public class GrPostfixExprImpl extends GrUnaryExpressionImpl implements GrPostfi
|
||||
return "Postfix expression";
|
||||
}
|
||||
|
||||
public PsiType getType() {
|
||||
return TypesUtil.getTypeForIncOrDecExpression(this);
|
||||
}
|
||||
|
||||
public void accept(GroovyElementVisitor visitor) {
|
||||
visitor.visitPostfixExpression(this);
|
||||
}
|
||||
|
||||
+119
-21
@@ -17,22 +17,70 @@
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.impl.source.resolve.ResolveCache;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public class GrUnaryExpressionImpl extends GrExpressionImpl implements GrUnaryExpression {
|
||||
private static final String PATTERN_FQ_NAME = "java.util.regex.Pattern";
|
||||
|
||||
private static final Function<GrUnaryExpressionImpl,PsiType> TYPE_CALCULATOR = new Function<GrUnaryExpressionImpl, PsiType>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType fun(GrUnaryExpressionImpl unary) {
|
||||
GrExpression operand = unary.getOperand();
|
||||
if (operand == null) return null;
|
||||
|
||||
PsiType opType = operand.getType();
|
||||
if (opType == null) return null;
|
||||
|
||||
IElementType opToken = unary.getOperationTokenType();
|
||||
if (opToken == GroovyTokenTypes.mINC || opToken == GroovyTokenTypes.mDEC) {
|
||||
return TypesUtil.getTypeForIncOrDecExpression(unary);
|
||||
}
|
||||
|
||||
if (opToken == GroovyTokenTypes.mBNOT && opType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
|
||||
return unary.getTypeByFQName(GroovyCommonClassNames.JAVA_UTIL_REGEX_PATTERN);
|
||||
}
|
||||
|
||||
return opType;
|
||||
}
|
||||
};
|
||||
|
||||
private static final ResolveCache.PolyVariantResolver<GrUnaryExpressionImpl> OUR_RESOLVER =
|
||||
new ResolveCache.PolyVariantResolver<GrUnaryExpressionImpl>() {
|
||||
@Override
|
||||
public GroovyResolveResult[] resolve(GrUnaryExpressionImpl unary, boolean incompleteCode) {
|
||||
final GrExpression operand = unary.getOperand();
|
||||
if (operand == null) return GroovyResolveResult.EMPTY_ARRAY;
|
||||
|
||||
final PsiType type = operand.getType();
|
||||
if (type == null) return GroovyResolveResult.EMPTY_ARRAY;
|
||||
|
||||
return TypesUtil.getOverloadedOperatorCandidates(type, unary.getOperationTokenType(), unary, PsiType.EMPTY_ARRAY);
|
||||
}
|
||||
};
|
||||
|
||||
public GrUnaryExpressionImpl(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
@@ -43,32 +91,22 @@ public class GrUnaryExpressionImpl extends GrExpressionImpl implements GrUnaryEx
|
||||
}
|
||||
|
||||
public PsiType getType() {
|
||||
IElementType opToken = getOperationTokenType();
|
||||
GrExpression operand = getOperand();
|
||||
if (operand == null) return null;
|
||||
if (opToken == GroovyTokenTypes.mINC || opToken == GroovyTokenTypes.mDEC) {
|
||||
return TypesUtil.getTypeForIncOrDecExpression(this);
|
||||
}
|
||||
PsiType opType = operand.getType();
|
||||
if (opType == null) return null;
|
||||
|
||||
if (opToken == GroovyTokenTypes.mBNOT) {
|
||||
if (opType.equalsToText("java.lang.String")) {
|
||||
return getTypeByFQName(PATTERN_FQ_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
return opType;
|
||||
return GroovyPsiManager.getInstance(getProject()).getType(this, TYPE_CALCULATOR);
|
||||
}
|
||||
|
||||
public IElementType getOperationTokenType() {
|
||||
PsiElement opElement = findChildByType(GroovyTokenTypes.UNARY_OP_SET);
|
||||
assert opElement != null;
|
||||
PsiElement opElement = getOperationToken();
|
||||
ASTNode node = opElement.getNode();
|
||||
assert node != null;
|
||||
return node.getElementType();
|
||||
}
|
||||
|
||||
public PsiElement getOperationToken() {
|
||||
PsiElement opElement = findChildByType(GroovyTokenTypes.UNARY_OP_SET);
|
||||
assert opElement != null;
|
||||
return opElement;
|
||||
}
|
||||
|
||||
public GrExpression getOperand() {
|
||||
return findChildByClass(GrExpression.class);
|
||||
}
|
||||
@@ -76,4 +114,64 @@ public class GrUnaryExpressionImpl extends GrExpressionImpl implements GrUnaryEx
|
||||
public void accept(GroovyElementVisitor visitor) {
|
||||
visitor.visitUnaryExpression(this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
|
||||
return (GroovyResolveResult[])getManager().getResolveCache().resolveWithCaching(this, OUR_RESOLVER, false, incompleteCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getElement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextRange getRangeInElement() {
|
||||
final PsiElement opToken = getOperationToken();
|
||||
final int offset = opToken.getStartOffsetInParent();
|
||||
return new TextRange(offset, offset + opToken.getTextLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement resolve() {
|
||||
return PsiImplUtil.extractUniqueElement(multiResolve(false));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
|
||||
throw new IncorrectOperationException("unary expression cannot be renamed to anything");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
|
||||
throw new IncorrectOperationException("unary expression cannot be bounded to anything");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReferenceTo(PsiElement element) {
|
||||
return getManager().areElementsEquivalent(resolve(), element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] getVariants() {
|
||||
return ArrayUtil.EMPTY_OBJECT_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSoft() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiReference getReference() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+1
@@ -29,6 +29,7 @@ public final class GroovyCommonClassNames {
|
||||
public static final String GROOVY_LANG_INT_RANGE = "groovy.lang.IntRange";
|
||||
public static final String GROOVY_LANG_OBJECT_RANGE = "groovy.lang.ObjectRange";
|
||||
public static final String GROOVY_LANG_DELEGATE = "groovy.lang.Delegate";
|
||||
public static final String JAVA_UTIL_REGEX_PATTERN = "java.util.regex.Pattern";
|
||||
|
||||
private GroovyCommonClassNames() {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user