mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
let "analyze dataflow to this" go through StringUtil.notNullize(String)
This commit is contained in:
@@ -376,6 +376,14 @@ class SliceUtil {
|
||||
final int paramSeqNo = ArrayUtilRt.find(actualParameters, parameter);
|
||||
assert paramSeqNo != -1;
|
||||
|
||||
// first, check if we are looking for a specific method call.
|
||||
// it happens when we were processing that very same method() return values somewhere up the tree
|
||||
PsiCall specificMethodCall = findSpecificMethodCallUpTheTree(parent, method);
|
||||
if (specificMethodCall != null) {
|
||||
return processMethodCall(parent, parentSubstitutor, indexNesting, syntheticField, processor, actualParameterType, actualParameters,
|
||||
paramSeqNo, specificMethodCall);
|
||||
}
|
||||
|
||||
Collection<PsiMethod> superMethods = new THashSet<>(Arrays.asList(method.findDeepestSuperMethods()));
|
||||
superMethods.add(method);
|
||||
|
||||
@@ -387,91 +395,9 @@ class SliceUtil {
|
||||
if (!processed.add(reference)) return true;
|
||||
}
|
||||
PsiElement refElement = reference.getElement();
|
||||
PsiExpressionList argumentList;
|
||||
JavaResolveResult result;
|
||||
if (refElement instanceof PsiCall) {
|
||||
// the case of enum constant decl
|
||||
PsiCall call = (PsiCall)refElement;
|
||||
argumentList = call.getArgumentList();
|
||||
result = call.resolveMethodGenerics();
|
||||
}
|
||||
else {
|
||||
PsiElement element = refElement.getParent();
|
||||
if (element instanceof PsiCompiledElement) return true;
|
||||
if (element instanceof PsiAnonymousClass) {
|
||||
PsiAnonymousClass anon = (PsiAnonymousClass)element;
|
||||
argumentList = anon.getArgumentList();
|
||||
PsiElement callExp = element.getParent();
|
||||
if (!(callExp instanceof PsiCallExpression)) return true;
|
||||
result = ((PsiCall)callExp).resolveMethodGenerics();
|
||||
}
|
||||
else if (element instanceof PsiCall) {
|
||||
PsiCall call = (PsiCall)element;
|
||||
argumentList = call.getArgumentList();
|
||||
result = call.resolveMethodGenerics();
|
||||
}
|
||||
else {
|
||||
return processIfInForeignLanguage(parent, parentSubstitutor, indexNesting, syntheticField, processor, refElement);
|
||||
}
|
||||
}
|
||||
PsiSubstitutor substitutor = result.getSubstitutor();
|
||||
|
||||
PsiExpression[] expressions = argumentList.getExpressions();
|
||||
if (paramSeqNo >= expressions.length) {
|
||||
return true;
|
||||
}
|
||||
PsiElement passExpression;
|
||||
PsiType actualExpressionType;
|
||||
if (actualParameterType instanceof PsiEllipsisType) {
|
||||
passExpression = argumentList;
|
||||
actualExpressionType = expressions[paramSeqNo].getType();
|
||||
}
|
||||
else {
|
||||
passExpression = expressions[paramSeqNo];
|
||||
actualExpressionType = ((PsiExpression)passExpression).getType();
|
||||
}
|
||||
|
||||
Project project = argumentList.getProject();
|
||||
PsiElement element = result.getElement();
|
||||
if (element instanceof PsiCompiledElement) {
|
||||
element = element.getNavigationElement();
|
||||
}
|
||||
|
||||
// for erased method calls for which we cannot determine target substitutor,
|
||||
// rely on call argument types. I.e. new Pair(1,2) -> Pair<Integer, Integer>
|
||||
if (element instanceof PsiTypeParameterListOwner && PsiUtil.isRawSubstitutor((PsiTypeParameterListOwner)element, substitutor)) {
|
||||
PsiTypeParameter[] typeParameters = substitutor.getSubstitutionMap().keySet().toArray(PsiTypeParameter.EMPTY_ARRAY);
|
||||
|
||||
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
|
||||
substitutor = resolveHelper.inferTypeArguments(typeParameters, actualParameters, expressions, parentSubstitutor, argumentList,
|
||||
DefaultParameterTypeInferencePolicy.INSTANCE);
|
||||
}
|
||||
|
||||
substitutor = removeRawMappingsLeftFromResolve(substitutor);
|
||||
|
||||
PsiSubstitutor combined = unify(substitutor, parentSubstitutor, project);
|
||||
if (combined == null) return true;
|
||||
//PsiType substituted = combined.substitute(passExpression.getType());
|
||||
PsiType substituted = combined.substitute(actualExpressionType);
|
||||
if (substituted instanceof PsiPrimitiveType) {
|
||||
final PsiClassType boxedType = ((PsiPrimitiveType)substituted).getBoxedType(argumentList);
|
||||
substituted = boxedType != null ? boxedType : substituted;
|
||||
}
|
||||
if (substituted == null) return true;
|
||||
PsiType typeToCheck;
|
||||
if (actualParameterType instanceof PsiEllipsisType) {
|
||||
// there may be the case of passing the vararg argument to the other vararg method: foo(int... ints) { bar(ints); } bar(int... ints) {}
|
||||
if (TypeConversionUtil.areTypesConvertible(substituted, actualParameterType)) {
|
||||
return handToProcessor(expressions[paramSeqNo], processor, parent, combined, indexNesting, syntheticField);
|
||||
}
|
||||
typeToCheck = ((PsiEllipsisType)actualParameterType).getComponentType();
|
||||
}
|
||||
else {
|
||||
typeToCheck = actualParameterType;
|
||||
}
|
||||
if (!TypeConversionUtil.areTypesConvertible(substituted, typeToCheck)) return true;
|
||||
|
||||
return handToProcessor(passExpression, processor, parent, combined, indexNesting, syntheticField);
|
||||
return processMethodCall(parent, parentSubstitutor, indexNesting, syntheticField, processor, actualParameterType, actualParameters,
|
||||
paramSeqNo,
|
||||
refElement);
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
@@ -480,6 +406,113 @@ class SliceUtil {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static PsiCall findSpecificMethodCallUpTheTree(SliceUsage parent, PsiMethod method) {
|
||||
while (parent != null) {
|
||||
PsiElement element = parent.getElement();
|
||||
if (element instanceof PsiCall && ((PsiCall)element).resolveMethod() == method) {
|
||||
return (PsiCall)element;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean processMethodCall(@NotNull SliceUsage parent,
|
||||
@NotNull PsiSubstitutor parentSubstitutor,
|
||||
int indexNesting,
|
||||
@NotNull String syntheticField,
|
||||
@NotNull Processor<SliceUsage> processor,
|
||||
PsiType actualParameterType,
|
||||
PsiParameter[] actualParameters,
|
||||
int paramSeqNo,
|
||||
PsiElement refElement) {
|
||||
PsiExpressionList argumentList;
|
||||
JavaResolveResult result;
|
||||
if (refElement instanceof PsiCall) {
|
||||
// the case of enum constant decl
|
||||
PsiCall call = (PsiCall)refElement;
|
||||
argumentList = call.getArgumentList();
|
||||
result = call.resolveMethodGenerics();
|
||||
}
|
||||
else {
|
||||
PsiElement element = refElement.getParent();
|
||||
if (element instanceof PsiCompiledElement) return true;
|
||||
if (element instanceof PsiAnonymousClass) {
|
||||
PsiAnonymousClass anon = (PsiAnonymousClass)element;
|
||||
argumentList = anon.getArgumentList();
|
||||
PsiElement callExp = element.getParent();
|
||||
if (!(callExp instanceof PsiCallExpression)) return true;
|
||||
result = ((PsiCall)callExp).resolveMethodGenerics();
|
||||
}
|
||||
else if (element instanceof PsiCall) {
|
||||
PsiCall call = (PsiCall)element;
|
||||
argumentList = call.getArgumentList();
|
||||
result = call.resolveMethodGenerics();
|
||||
}
|
||||
else {
|
||||
return processIfInForeignLanguage(parent, parentSubstitutor, indexNesting, syntheticField, processor, refElement);
|
||||
}
|
||||
}
|
||||
PsiSubstitutor substitutor = result.getSubstitutor();
|
||||
|
||||
PsiExpression[] expressions = argumentList.getExpressions();
|
||||
if (paramSeqNo >= expressions.length) {
|
||||
return true;
|
||||
}
|
||||
PsiElement passExpression;
|
||||
PsiType actualExpressionType;
|
||||
if (actualParameterType instanceof PsiEllipsisType) {
|
||||
passExpression = argumentList;
|
||||
actualExpressionType = expressions[paramSeqNo].getType();
|
||||
}
|
||||
else {
|
||||
passExpression = expressions[paramSeqNo];
|
||||
actualExpressionType = ((PsiExpression)passExpression).getType();
|
||||
}
|
||||
|
||||
Project project = argumentList.getProject();
|
||||
PsiElement element = result.getElement();
|
||||
if (element instanceof PsiCompiledElement) {
|
||||
element = element.getNavigationElement();
|
||||
}
|
||||
|
||||
// for erased method calls for which we cannot determine target substitutor,
|
||||
// rely on call argument types. I.e. new Pair(1,2) -> Pair<Integer, Integer>
|
||||
if (element instanceof PsiTypeParameterListOwner && PsiUtil.isRawSubstitutor((PsiTypeParameterListOwner)element, substitutor)) {
|
||||
PsiTypeParameter[] typeParameters = substitutor.getSubstitutionMap().keySet().toArray(PsiTypeParameter.EMPTY_ARRAY);
|
||||
|
||||
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
|
||||
substitutor = resolveHelper.inferTypeArguments(typeParameters, actualParameters, expressions, parentSubstitutor, argumentList,
|
||||
DefaultParameterTypeInferencePolicy.INSTANCE);
|
||||
}
|
||||
|
||||
substitutor = removeRawMappingsLeftFromResolve(substitutor);
|
||||
|
||||
PsiSubstitutor combined = unify(substitutor, parentSubstitutor, project);
|
||||
if (combined == null) return true;
|
||||
//PsiType substituted = combined.substitute(passExpression.getType());
|
||||
PsiType substituted = combined.substitute(actualExpressionType);
|
||||
if (substituted instanceof PsiPrimitiveType) {
|
||||
final PsiClassType boxedType = ((PsiPrimitiveType)substituted).getBoxedType(argumentList);
|
||||
substituted = boxedType != null ? boxedType : substituted;
|
||||
}
|
||||
if (substituted == null) return true;
|
||||
PsiType typeToCheck;
|
||||
if (actualParameterType instanceof PsiEllipsisType) {
|
||||
// there may be the case of passing the vararg argument to the other vararg method: foo(int... ints) { bar(ints); } bar(int... ints) {}
|
||||
if (TypeConversionUtil.areTypesConvertible(substituted, actualParameterType)) {
|
||||
return handToProcessor(expressions[paramSeqNo], processor, parent, combined, indexNesting, syntheticField);
|
||||
}
|
||||
typeToCheck = ((PsiEllipsisType)actualParameterType).getComponentType();
|
||||
}
|
||||
else {
|
||||
typeToCheck = actualParameterType;
|
||||
}
|
||||
if (!TypeConversionUtil.areTypesConvertible(substituted, typeToCheck)) return true;
|
||||
|
||||
return handToProcessor(passExpression, processor, parent, combined, indexNesting, syntheticField);
|
||||
}
|
||||
|
||||
private static boolean processIfInForeignLanguage(@NotNull SliceUsage parent,
|
||||
@NotNull PsiSubstitutor parentSubstitutor,
|
||||
int indexNesting,
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
class WW {
|
||||
void f(String <flown11111>ddd) {
|
||||
void f(String ddd) {
|
||||
if (hashCode() == 0)
|
||||
ddd = <flown11112>"dd";
|
||||
foo(<flown1111>ddd);
|
||||
ddd = "dd";
|
||||
foo(ddd);
|
||||
}
|
||||
|
||||
{
|
||||
f(<flown111111>"xxx");
|
||||
f("xxx");
|
||||
}
|
||||
|
||||
{
|
||||
x(<flown111211>"zzz");
|
||||
x(<flown111111>"zzz");
|
||||
}
|
||||
|
||||
String x(String <flown11121>g) {
|
||||
String d = <flown1>foo(<flown1112>g);
|
||||
String x(String <flown11111>g) {
|
||||
String d = <flown1>foo(<flown1111>g);
|
||||
return <caret>d;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user