[groovy] pass noncode flag via ResolveState instance

This commit is contained in:
Daniil Ovchinnikov
2016-10-14 21:28:55 +03:00
parent 85013de183
commit aaf00dd6f5
7 changed files with 59 additions and 88 deletions
@@ -56,7 +56,6 @@ public interface GrClosableBlock extends GrExpression, GrCodeBlock, GrParameters
boolean isVarArgs();
boolean processClosureDeclarations(@NotNull final PsiScopeProcessor placeProcessor,
@NotNull final PsiScopeProcessor nonCodeProcessor,
@NotNull final ResolveState _state,
@Nullable final PsiElement lastParent,
@NotNull final PsiElement place);
@@ -76,12 +76,11 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
@Override
public boolean processClosureDeclarations(@NotNull final PsiScopeProcessor plainProcessor,
@NotNull final PsiScopeProcessor nonCodeProcessor,
@NotNull final ResolveState state,
@Nullable final PsiElement lastParent,
@NotNull final PsiElement place) {
if (!processDeclarations(plainProcessor, state, lastParent, place)) return false;
if (!processOwnerAndDelegate(plainProcessor, nonCodeProcessor, state, place)) return false;
if (!processOwnerAndDelegate(plainProcessor, state, place)) return false;
return true;
}
@@ -102,19 +101,17 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
}
private boolean processOwnerAndDelegate(@NotNull PsiScopeProcessor processor,
@NotNull PsiScopeProcessor nonCodeProcessor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
Boolean result = processDelegatesTo(processor, nonCodeProcessor, state, place);
Boolean result = processDelegatesTo(processor, state, place);
if (result != null) return result.booleanValue();
if (!processOwner(processor, nonCodeProcessor, state, place)) return false;
if (!processOwner(processor, state, place)) return false;
return true;
}
@Nullable
private Boolean processDelegatesTo(@NotNull PsiScopeProcessor processor,
@NotNull PsiScopeProcessor nonCodeProcessor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
GrDelegatesToUtil.DelegatesToInfo info = GrDelegatesToUtil.getDelegatesToInfo(place, this);
@@ -124,18 +121,18 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
switch (info.getStrategy()) {
case Closure.OWNER_FIRST:
if (!processOwner(processor, nonCodeProcessor, state, place)) return false;
if (!processDelegate(processor, nonCodeProcessor, state, place, info.getTypeToDelegate())) return false;
if (!processOwner(processor, state, place)) return false;
if (!processDelegate(processor, state, place, info.getTypeToDelegate())) return false;
return true;
case Closure.DELEGATE_FIRST:
if (!processDelegate(processor, nonCodeProcessor, state, place, info.getTypeToDelegate())) return false;
if (!processOwner(processor, nonCodeProcessor, state, place)) return false;
if (!processDelegate(processor, state, place, info.getTypeToDelegate())) return false;
if (!processOwner(processor, state, place)) return false;
return true;
case Closure.OWNER_ONLY:
if (!processOwner(processor, nonCodeProcessor, state, place)) return false;
if (!processOwner(processor, state, place)) return false;
return true;
case Closure.DELEGATE_ONLY:
if (!processDelegate(processor, nonCodeProcessor, state, place, info.getTypeToDelegate())) return false;
if (!processDelegate(processor, state, place, info.getTypeToDelegate())) return false;
return true;
case Closure.TO_SELF:
return true;
@@ -145,14 +142,12 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
}
private boolean processDelegate(@NotNull PsiScopeProcessor processor,
@NotNull PsiScopeProcessor nonCodeProcessor,
@NotNull ResolveState state,
@NotNull PsiElement place,
@Nullable final PsiType classToDelegate) {
if (classToDelegate == null) return true;
return ResolveUtil.processAllDeclarationsSeparately(classToDelegate, processor, nonCodeProcessor,
state.put(ClassHint.RESOLVE_CONTEXT, this), place);
return ResolveUtil.processAllDeclarations(classToDelegate, processor, state.put(ClassHint.RESOLVE_CONTEXT, this), place);
}
private boolean processClosureClassMembers(@NotNull PsiScopeProcessor processor,
@@ -185,7 +180,6 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
}
private boolean processOwner(@NotNull PsiScopeProcessor processor,
@NotNull PsiScopeProcessor nonCodeProcessor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
final PsiElement parent = getParent();
@@ -193,7 +187,7 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
if (!ResolveUtil.processStaticImports(processor, getContainingFile(), state, place)) return false;
return ResolveUtil.doTreeWalkUp(parent, place, processor, nonCodeProcessor, state);
return ResolveUtil.treeWalkUp(parent, place, processor, state);
}
private boolean isItAlreadyDeclared(@Nullable PsiElement place) {
@@ -29,6 +29,7 @@ import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhan
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil
import org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil
import org.jetbrains.plugins.groovy.lang.resolve.processNonCodeMembers
import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint
fun resolveReferenceExpression(place: GrReferenceExpression, processor: PsiScopeProcessor): Boolean {
@@ -131,7 +132,9 @@ fun doProcessQualifierType(place: PsiElement, qualifierType: PsiType, processor:
}
}
if (!ResolveUtil.processCategoryMembers(place, processor, state)) return false
if (!ResolveUtil.processNonCodeMembers(qualifierType, processor, place, state)) return false
if (state.processNonCodeMembers()) {
if (!ResolveUtil.processCategoryMembers(place, processor, state)) return false
if (!ResolveUtil.processNonCodeMembers(qualifierType, processor, place, state)) return false
}
return true
}
@@ -16,7 +16,6 @@
package org.jetbrains.plugins.groovy.lang.resolve;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
@@ -62,7 +61,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyMethodResult;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
@@ -80,11 +78,12 @@ import org.jetbrains.plugins.groovy.lang.resolve.processors.*;
import java.util.*;
import static org.jetbrains.plugins.groovy.lang.resolve.ResolveUtilKt.initialState;
/**
* @author ven
*/
public class ResolveUtil {
private static final Logger LOG = Logger.getInstance(ResolveUtil.class);
public static final PsiScopeProcessor.Event DECLARATION_SCOPE_PASSED = new PsiScopeProcessor.Event() {};
public static final Key<String> DOCUMENTATION_DELEGATE_FQN = Key.create("groovy.documentation.delegate.fqn");
@@ -96,47 +95,22 @@ public class ResolveUtil {
*
* @param place - place to start tree walk up
* @param processor
* @param processNonCodeMethods - this parameter tells us if we need non code members
* @param processNonCodeMembers - this parameter tells us if we need non code members
* @return
*/
public static boolean treeWalkUp(@NotNull final PsiElement place,
@NotNull final PsiScopeProcessor processor,
boolean processNonCodeMethods) {
return treeWalkUp(place, place, processor, processNonCodeMethods, ResolveState.initial());
public static boolean treeWalkUp(@NotNull PsiElement place, @NotNull PsiScopeProcessor processor, boolean processNonCodeMembers) {
return ResolveUtilKt.treeWalkUp(place, processor, initialState(processNonCodeMembers));
}
/**
*
* @param place - place to start tree walk up
* @param processor
* @param processNonCodeMethods - this parameter tells us if we need non code members
* @param state
* @return
*/
public static boolean treeWalkUp(@NotNull final PsiElement place,
@NotNull final PsiElement originalPlace,
@NotNull final PsiScopeProcessor processor,
boolean processNonCodeMethods,
@NotNull final ResolveState state) {
try {
return doTreeWalkUp(place, originalPlace, processor, processNonCodeMethods ? processor : null, state);
}
catch (StackOverflowError e) {
LOG.error("StackOverflow", e, place.getContainingFile().getText());
throw e;
}
}
public static boolean doTreeWalkUp(@NotNull final PsiElement place,
@NotNull final PsiElement originalPlace,
@NotNull final PsiScopeProcessor processor,
@Nullable final PsiScopeProcessor nonCodeProcessor,
@NotNull final ResolveState state) {
final GrClosableBlock maxScope = nonCodeProcessor != null ? PsiTreeUtil.getParentOfType(place, GrClosableBlock.class, true, PsiFile.class) : null;
final GrClosableBlock maxScope = ResolveUtilKt.processNonCodeMembers(state) ? PsiTreeUtil.getParentOfType(place, GrClosableBlock.class, true, PsiFile.class) : null;
return PsiTreeUtil.treeWalkUp(place, maxScope, (scope, lastParent) -> {
ProgressManager.checkCanceled();
if (!doProcessDeclarations(originalPlace, lastParent, scope, substituteProcessor(processor, scope), nonCodeProcessor, state)) {
if (!doProcessDeclarations(originalPlace, lastParent, scope, substituteProcessor(processor, scope), state)) {
return false;
}
issueLevelChangeEvents(processor, scope);
@@ -147,26 +121,26 @@ public class ResolveUtil {
static boolean doProcessDeclarations(@NotNull PsiElement place,
@Nullable PsiElement lastParent,
@NotNull PsiElement scope,
@NotNull PsiScopeProcessor plainProcessor,
@Nullable PsiScopeProcessor nonCodeProcessor,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state) {
if (scope instanceof GrClosableBlock && nonCodeProcessor != null) {
if (!((GrClosableBlock)scope).processClosureDeclarations(plainProcessor, nonCodeProcessor, state, lastParent, place)) return false;
boolean processNonCodeMembers = ResolveUtilKt.processNonCodeMembers(state);
if (scope instanceof GrClosableBlock && processNonCodeMembers) {
if (!((GrClosableBlock)scope).processClosureDeclarations(processor, state, lastParent, place)) return false;
}
else {
if (scope instanceof PsiClass) {
if (!processClassDeclarations((PsiClass)scope, plainProcessor, state, lastParent, place)) return false;
if (!processClassDeclarations((PsiClass)scope, processor, state, lastParent, place)) return false;
} else {
if (!scope.processDeclarations(plainProcessor, state, lastParent, place)) return false;
if (!scope.processDeclarations(processor, state, lastParent, place)) return false;
}
if (scope instanceof GrTypeDefinition || scope instanceof GrClosableBlock) {
if (!processStaticImports(plainProcessor, place.getContainingFile(), state, place)) return false;
if (!processStaticImports(processor, place.getContainingFile(), state, place)) return false;
}
}
if (nonCodeProcessor != null) {
if (!processScopeNonCodeMembers(place, lastParent, nonCodeProcessor, scope, state)) return false;
if (processNonCodeMembers) {
if (!processScopeNonCodeMembers(place, lastParent, processor, scope, state)) return false;
}
return true;
}
@@ -278,17 +252,16 @@ public class ResolveUtil {
public static boolean processAllDeclarations(@NotNull PsiType type,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
boolean processNonCodeMembers,
@NotNull PsiElement place) {
return processAllDeclarationsSeparately(type, processor, processor, state, place);
return processAllDeclarations(type, processor, initialState(processNonCodeMembers), place);
}
public static boolean processAllDeclarationsSeparately(@NotNull PsiType type,
@NotNull PsiScopeProcessor processor,
@NotNull PsiScopeProcessor nonCodeProcessor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
type = TypesUtil.boxPrimitiveType(type,place.getManager(),place.getResolveScope());
public static boolean processAllDeclarations(@NotNull PsiType type,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
type = TypesUtil.boxPrimitiveType(type, place.getManager(), place.getResolveScope());
if (type instanceof PsiClassType) {
final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
final PsiClass psiClass = resolveResult.getElement();
@@ -298,8 +271,10 @@ public class ResolveUtil {
if (!processClassDeclarations(psiClass, processor, state, null, place)) return false;
}
}
if (!processCategoryMembers(place, nonCodeProcessor, state)) return false;
if (!processNonCodeMembers(type, nonCodeProcessor, place, state)) return false;
if (ResolveUtilKt.processNonCodeMembers(state)) {
if (!processCategoryMembers(place, processor, state)) return false;
if (!processNonCodeMembers(type, processor, place, state)) return false;
}
return true;
}
@@ -15,9 +15,22 @@
*/
package org.jetbrains.plugins.groovy.lang.resolve
import com.intellij.openapi.util.Key
import com.intellij.psi.PsiElement
import com.intellij.psi.ResolveState
import com.intellij.psi.scope.PsiScopeProcessor
import org.jetbrains.plugins.groovy.lang.resolve.processors.DynamicMembersHint
@JvmField val NON_CODE = Key.create<Boolean?>("groovy.process.non.code.members")
fun initialState(processNonCodeMembers: Boolean) = ResolveState.initial().put(NON_CODE, processNonCodeMembers)
fun ResolveState.processNonCodeMembers(): Boolean = get(NON_CODE).let { it == null || it }
fun treeWalkUp(place: PsiElement, processor: PsiScopeProcessor, state: ResolveState): Boolean {
return ResolveUtil.treeWalkUp(place, place, processor, state)
}
fun shouldProcessDynamicMethods(processor: PsiScopeProcessor): Boolean {
return processor.getHint(DynamicMembersHint.KEY)?.shouldProcessMethods() ?: false
}
@@ -21,7 +21,6 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightElement;
import com.intellij.psi.scope.BaseScopeProcessor;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
@@ -1396,12 +1395,7 @@ public class ExpressionGenerator extends Generator {
final PsiType[] conjuncts = ((PsiIntersectionType)type).getConjuncts();
for (PsiType conjunct : conjuncts) {
final GenerationUtil.CheckProcessElement processor = new GenerationUtil.CheckProcessElement(method);
ResolveUtil.processAllDeclarationsSeparately(conjunct, processor, new BaseScopeProcessor() {
@Override
public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
return false;
}
}, ResolveState.initial(), context);
ResolveUtil.processAllDeclarations(conjunct, processor, false, context);
if (processor.isFound()) return conjunct;
}
}
@@ -21,7 +21,6 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.scope.BaseScopeProcessor;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.containers.HashMap;
@@ -517,24 +516,18 @@ public class GenerationUtil {
if (declared == null) return false;
final CheckProcessElement checker = new CheckProcessElement(member);
final BaseScopeProcessor processor = new BaseScopeProcessor() {
@Override
public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
return false;
}
};
if (ResolveUtil.resolvesToClass(qualifier)) {
PsiType type = ResolveUtil.unwrapClassType(declared);
if (type != null) {
ResolveUtil.processAllDeclarationsSeparately(type, checker, processor, ResolveState.initial(), qualifier);
ResolveUtil.processAllDeclarations(type, checker, false, qualifier);
if (checker.isFound()) {
return false;
}
}
}
ResolveUtil.processAllDeclarationsSeparately(declared, checker, processor, ResolveState.initial(), qualifier);
ResolveUtil.processAllDeclarations(declared, checker, false, qualifier);
return !checker.isFound();
}