From 1a127adafd40b868f5bda3f4e76be17bbd3f7a42 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 17 Oct 2012 16:09:03 +0200 Subject: [PATCH] EA-39528 - NPE: TypeInferenceHelper$InferenceCache.findDependencies --- .../dataFlow/types/TypeInferenceHelper.java | 85 +++++++------------ .../statements/expressions/TypesUtil.java | 4 +- 2 files changed, 32 insertions(+), 57 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java index 08679aef8320..41ae01be0137 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java @@ -73,42 +73,6 @@ public class TypeInferenceHelper { return context != null ? context : InferenceContext.TOP_CONTEXT; } - @Nullable - public static PsiType getInferredTypeOld(@NotNull final GrReferenceExpression refExpr) { - return RecursionManager.doPreventingRecursion(refExpr, true, new NullableComputable() { - @Override - public PsiType compute() { - final GrControlFlowOwner scope = ControlFlowUtils.findControlFlowOwner(refExpr); - if (scope == null) return null; - - final Instruction[] flow = scope.getControlFlow(); - ReadWriteVariableInstruction instruction = ControlFlowUtils.findRWInstruction(refExpr, flow); - if (instruction == null) return null; - - if (instruction.isWrite()) { - return getInitializerType(refExpr); - } - - final DFAType type = getInferredType(refExpr.getReferenceName(), instruction, flow, scope, new HashSet()); - return type == null ? null : type.getResultType(); - } - }); - } - - @Nullable - public static PsiType getInferredTypeOld(@NotNull PsiElement place, String variableName) { - final GrControlFlowOwner scope = ControlFlowUtils.findControlFlowOwner(place); - if (scope == null) return null; - - final Instruction[] flow = scope.getControlFlow(); - Instruction instruction = ControlFlowUtils.findNearestInstruction(place, flow); - if (instruction == null) return null; - - final DFAType type = getInferredType(variableName, instruction, flow, scope, new HashSet()); - return type != null ? type.getResultType() : null; - } - - @Nullable public static PsiType getInferredType(@NotNull final GrReferenceExpression refExpr) { final GrControlFlowOwner scope = ControlFlowUtils.findControlFlowOwner(refExpr); @@ -144,13 +108,10 @@ public class TypeInferenceHelper { @Nullable private static DFAType getInferredType(@NotNull String varName, @NotNull Instruction instruction, @NotNull Instruction[] flow, @NotNull GrControlFlowOwner scope, Set trace) { final Pair> pair = getDefUseMaps(scope); - - List dfaResult = pair.second; - if (dfaResult == null) return null; + if (pair == null) return null; final int varIndex = pair.first.getVarIndex(varName); - - final DefinitionMap allDefs = dfaResult.get(instruction.num()); + final DefinitionMap allDefs = pair.second.get(instruction.num()); final int[] varDefs = allDefs.getDefinitions(varIndex); if (varDefs == null) return null; @@ -169,6 +130,7 @@ public class TypeInferenceHelper { return result; } + @Nullable private static Pair> getDefUseMaps(final GrControlFlowOwner scope) { return CachedValuesManager.getManager(scope.getProject()).getCachedValue(scope, new CachedValueProvider>>() { @Override @@ -188,8 +150,10 @@ public class TypeInferenceHelper { } } else if (instruction instanceof ArgumentInstruction) { - final int varIndex = getVarIndex(((ArgumentInstruction)instruction).getVariableName()); - m.registerDef(instruction, varIndex); + String variableName = ((ArgumentInstruction)instruction).getVariableName(); + if (variableName != null) { + m.registerDef(instruction, getVarIndex(variableName)); + } } else { super.fun(m, instruction); @@ -199,7 +163,8 @@ public class TypeInferenceHelper { final ReachingDefinitionsSemilattice lattice = new ReachingDefinitionsSemilattice(); final DFAEngine engine = new DFAEngine(flow, dfaInstance, lattice); final List dfaResult = engine.performDFAWithTimeout(); - return Result.create(Pair.create(dfaInstance, dfaResult), PsiModificationTracker.MODIFICATION_COUNT); + Pair> result = dfaResult == null ? null : Pair.create(dfaInstance, dfaResult); + return Result.create(result, PsiModificationTracker.MODIFICATION_COUNT); } }); } @@ -401,7 +366,13 @@ public class TypeInferenceHelper { TypeDfaState cache = varTypes.get().get(instruction.num()); if (!cache.containsVariable(variableName)) { - Set interesting = collectRequiredInstructions(instruction, variableName); + Pair> defUse = getDefUseMaps(scope); + if (defUse == null) { + tooComplex.add(instruction); + return null; + } + + Set interesting = collectRequiredInstructions(instruction, variableName, defUse); List dfaResult = performTypeDfa(scope, flow, interesting); if (dfaResult == null) { tooComplex.addAll(interesting); @@ -426,9 +397,9 @@ public class TypeInferenceHelper { return dfaType == null ? null : dfaType.negate(instruction); } - private Set collectRequiredInstructions(Instruction instruction, String variableName) { - Pair> defUse = getDefUseMaps(scope); - + private Set collectRequiredInstructions(@NotNull Instruction instruction, + @NotNull String variableName, + @NotNull Pair> defUse) { Set interesting = ContainerUtil.newHashSet(instruction); LinkedList> queue = ContainerUtil.newLinkedList(); queue.add(Pair.create(instruction, variableName)); @@ -445,22 +416,26 @@ public class TypeInferenceHelper { } private Set> findDependencies(Pair> defUse, - Instruction insn, - String varName) { - int[] definitions = defUse.second.get(insn.num()).getDefinitions(defUse.first.getVarIndex(varName)); + @NotNull Instruction insn, + @NotNull String varName) { + DefinitionMap definitionMap = defUse.second.get(insn.num()); + int varIndex = defUse.first.getVarIndex(varName); + int[] definitions = definitionMap.getDefinitions(varIndex); if (definitions == null) return Collections.emptySet(); - HashSet> pairs = ContainerUtil.newHashSet(); + LinkedHashSet> pairs = ContainerUtil.newLinkedHashSet(); for (int defIndex : definitions) { Instruction write = flow[defIndex]; pairs.add(Pair.create(write, varName)); PsiElement statement = findDependencyScope(write.getElement()); - pairs.addAll(findAllInstructionsInside(statement)); + if (statement != null) { + pairs.addAll(findAllInstructionsInside(statement)); + } } return pairs; } - private List> findAllInstructionsInside(PsiElement scope) { + private List> findAllInstructionsInside(@NotNull PsiElement scope) { final List> result = ContainerUtil.newArrayList(); scope.accept(new PsiRecursiveElementWalkingVisitor() { @Override @@ -480,7 +455,7 @@ public class TypeInferenceHelper { } @Nullable - private static PsiElement findDependencyScope(PsiElement element) { + private static PsiElement findDependencyScope(@Nullable PsiElement element) { return PsiTreeUtil.findFirstParent(element, new Condition() { @Override public boolean value(PsiElement element) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java index 6c8598abeaf0..1b974232bda8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java @@ -405,7 +405,7 @@ public class TypesUtil { return type; } - public static PsiType boxPrimitiveType(PsiType result, @NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope, boolean boxVoid) { + public static PsiType boxPrimitiveType(@Nullable PsiType result, @NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope, boolean boxVoid) { if (result instanceof PsiPrimitiveType && (boxVoid || result != PsiType.VOID)) { PsiPrimitiveType primitive = (PsiPrimitiveType)result; String boxedTypeName = primitive.getBoxedTypeName(); @@ -417,7 +417,7 @@ public class TypesUtil { return result; } - public static PsiType boxPrimitiveType(PsiType result, @NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) { + public static PsiType boxPrimitiveType(@Nullable PsiType result, @NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) { return boxPrimitiveType(result, manager, resolveScope, false); } @NotNull