IDEA-57503 Criteria builder calls reported as syntax errors in static methods (Idea X)

This commit is contained in:
Maxim Medvedev
2010-09-23 14:27:04 +04:00
parent f6da0fffbe
commit 7aa7ab5e90
10 changed files with 78 additions and 25 deletions
@@ -178,6 +178,8 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
registerAccessFix(annotation, referenceExpression, ((PsiMember)resolved));
}
}
//todo uncomment when correct isStatic() is working
if (!resolveResult.isStaticsOK() && resolved instanceof PsiModifierListOwner) {
if (!((PsiModifierListOwner)resolved).hasModifierProperty(GrModifier.STATIC)) {
Annotation annotation = myHolder.createInfoAnnotation(referenceExpression,
@@ -37,6 +37,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
@@ -137,6 +138,7 @@ public class PsiImplUtil {
GrClosableBlock closure = PsiTreeUtil.getParentOfType(refExpr, GrClosableBlock.class);
while (closure != null) {
PsiElement parent = closure.getParent();
if (parent instanceof GrArgumentList) parent = parent.getParent();
if (parent instanceof GrMethodCall) {
GrExpression funExpr = ((GrMethodCall)parent).getInvokedExpression();
if (funExpr instanceof GrReferenceExpression) {
@@ -326,6 +328,7 @@ public class PsiImplUtil {
method.hasModifierProperty(PsiModifier.STATIC);
}
@Nullable
public static PsiMethod resolveMethod(GrMethodCall expression) {
final GrExpression methodExpr = expression.getInvokedExpression();
if (methodExpr instanceof GrReferenceExpression) {
@@ -42,6 +42,7 @@ import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
@@ -580,20 +581,20 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
}
if (qualifier instanceof GrReferenceExpression && "class".equals(((GrReferenceExpression)qualifier).getReferenceName())) {
processIfJavaLangClass(processor, qualifier.getType());
processIfJavaLangClass(processor, qualifier.getType(), qualifier);
} else if (qualifier instanceof GrThisReferenceExpression) {
processIfJavaLangClass(processor, qualifier.getType());
processIfJavaLangClass(processor, qualifier.getType(), qualifier);
}
}
}
private void processIfJavaLangClass(ResolverProcessor processor, PsiType type) {
private void processIfJavaLangClass(ResolverProcessor processor, PsiType type, GroovyPsiElement resolveContext) {
if (type instanceof PsiClassType) {
final PsiClass psiClass = ((PsiClassType)type).resolve();
if (psiClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(psiClass.getQualifiedName())) {
final PsiType[] params = ((PsiClassType)type).getParameters();
if (params.length == 1) {
processClassQualifierType(processor, params[0]);
processClassQualifierType(processor, params[0], resolveContext);
}
}
}
@@ -611,13 +612,13 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
if (substitutor != null) {
PsiType componentType = substitutor.substitute(listClass.getTypeParameters()[0]);
if (componentType != null) {
processClassQualifierType(processor, componentType);
processClassQualifierType(processor, componentType, qualifier);
}
}
}
}
} else if (qualifierType instanceof PsiArrayType) {
processClassQualifierType(processor, ((PsiArrayType) qualifierType).getComponentType());
processClassQualifierType(processor, ((PsiArrayType) qualifierType).getComponentType(), qualifier);
}
}
@@ -627,22 +628,22 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
if (qualifier instanceof GrReferenceExpression) {
PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
if (resolved instanceof PsiPackage) {
if (!resolved.processDeclarations(processor, ResolveState.initial(), null, this)) //noinspection UnnecessaryReturnStatement
if (!resolved.processDeclarations(processor, ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, qualifier), null, this)) //noinspection UnnecessaryReturnStatement
return;
}
else {
qualifierType = JavaPsiFacade.getInstance(getProject()).getElementFactory()
.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, getResolveScope());
processClassQualifierType(processor, qualifierType);
processClassQualifierType(processor, qualifierType, qualifier);
}
}
} else {
if (qualifierType instanceof PsiIntersectionType) {
for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
processClassQualifierType(processor, conjunct);
processClassQualifierType(processor, conjunct, qualifier);
}
} else {
processClassQualifierType(processor, qualifierType);
processClassQualifierType(processor, qualifierType, qualifier);
if (qualifier instanceof GrReferenceExpression) {
PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
if (resolved instanceof PsiClass) { //omitted .class
@@ -666,14 +667,14 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
}
}
private void processClassQualifierType(ResolverProcessor processor, PsiType qualifierType) {
private void processClassQualifierType(ResolverProcessor processor, PsiType qualifierType, GroovyPsiElement resolveContext) {
Project project = getProject();
if (qualifierType instanceof PsiClassType) {
PsiClassType.ClassResolveResult qualifierResult = ((PsiClassType) qualifierType).resolveGenerics();
PsiClass qualifierClass = qualifierResult.getElement();
if (qualifierClass != null) {
if (!qualifierClass.processDeclarations(processor,
ResolveState.initial().put(PsiSubstitutor.KEY, qualifierResult.getSubstitutor()), null, this))
if (!qualifierClass.processDeclarations(processor, ResolveState.initial().put(PsiSubstitutor.KEY, qualifierResult.getSubstitutor())
.put(ResolverProcessor.RESOLVE_CONTEXT, resolveContext), null, this))
return;
}
if (!ResolveUtil.processCategoryMembers(this, processor)) return;
@@ -682,7 +683,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
if (!arrayClass.processDeclarations(processor, ResolveState.initial(), null, this)) return;
} else if (qualifierType instanceof PsiIntersectionType) {
for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
processClassQualifierType(processor, conjunct);
processClassQualifierType(processor, conjunct, resolveContext);
}
return;
}
@@ -53,7 +53,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgument
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.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
@@ -68,7 +67,6 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals.GrLiteralImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.JavaIdentifier;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
@@ -384,6 +382,10 @@ public class PsiUtil {
}
public static boolean isStaticsOK(PsiModifierListOwner owner, PsiElement place) {
return isStaticsOK(owner, place, owner);
}
public static boolean isStaticsOK(PsiModifierListOwner owner, PsiElement place, PsiElement resolveContext) {
if (owner instanceof PsiMember) {
if (place instanceof GrReferenceExpression) {
GrExpression qualifier = ((GrReferenceExpression)place).getQualifierExpression();
@@ -459,9 +461,14 @@ public class PsiUtil {
if (((PsiMember)owner).getContainingClass() == null) return true;
if (owner instanceof GrVariable && !(owner instanceof GrField)) return true;
if (owner.hasModifierProperty(GrModifier.STATIC)) return true;
final GrMember placeOwner = PsiTreeUtil.getParentOfType(place, GrMember.class);
if (placeOwner == null) return true;
return !placeOwner.hasModifierProperty(GrModifier.STATIC);
PsiElement stopAt = resolveContext != null ? PsiTreeUtil.findCommonParent(place, resolveContext) : null;
while (place != null && place != stopAt && !(place instanceof GrMember)) {
if (place instanceof PsiFile) break;
place = place.getParent();
}
if (place == null || place instanceof PsiFile || place == stopAt) return true;
return !((GrMember)place).hasModifierProperty(GrModifier.STATIC);
}
}
}
@@ -109,7 +109,7 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint
if (resolveContext instanceof GrImportStatement) return true;
if (element instanceof PsiModifierListOwner) {
return PsiUtil.isStaticsOK((PsiModifierListOwner) element, myPlace);
return PsiUtil.isStaticsOK((PsiModifierListOwner) element, myPlace, resolveContext);
}
return true;
}
@@ -19,6 +19,7 @@ package org.jetbrains.plugins.groovy.lang.resolve;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -74,4 +75,10 @@ public abstract class GroovyResolveTestCase extends LightGroovyTestCase {
return configureByFile(filePath, null);
}
@Nullable
protected PsiElement resolve(String fileName) {
PsiReference ref = configureByFile(getTestName(true) + "/" + fileName);
return ref.resolve();
}
}
@@ -602,11 +602,6 @@ class Zoo {
assertInstanceOf resolved, GrVariable
}
private PsiElement resolve(String fileName) {
PsiReference ref = configureByFile("${getTestName(true)}/$fileName");
ref.resolve()
}
public void testCommandExpressionStatement1() {
PsiElement method = resolve("A.groovy")
assertInstanceOf method, GrMethod
@@ -581,4 +581,17 @@ set<caret>Foo(2)
PsiElement resolved = ref.resolve()
assertInstanceOf resolved, PsiField
}
public void testFieldAccessInStaticContext() {
def ref = configureByFile("fieldAccessInStaticContext/A.groovy")
def resolveResult = ref.advancedResolve()
assertTrue !resolveResult.staticsOK
}
public void testFieldAccessInClosureVsStaticContext() {
def ref = configureByFile("fieldAccessInClosureVsStaticContext/A.groovy")
def resolveResult = ref.advancedResolve()
assertTrue resolveResult.staticsOK
}
}
@@ -0,0 +1,18 @@
class MyDom {
static void main(String[] args) {
new Foo().foo({
print ba<ref>r
});
}
}
class Foo {
def bar = 2
def foo(Closure c) {
c.delegate = this
c.call()
}
}
@@ -0,0 +1,7 @@
class Foo {
def field = 2
static def foo() {
print fiel<ref>d
}
}