private static PsiSubstitutor getSubstitutor(final JavaResolveResult result, PsiCallExpression methodCall) { final PsiLambdaExpression expression = PsiTreeUtil.getParentOfType(methodCall, PsiLambdaExpression.class); final PsiSubstitutor substitutor; if (expression != null) { final PsiElement parent = methodCall.getParent(); final boolean callInReturnStatement = parent == expression || parent instanceof PsiReturnStatement && PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class, true, PsiMethod.class) == expression; substitutor = callInReturnStatement ? ourThrowsGuard.doPreventingRecursion(expression, false, new Computable<PsiSubstitutor>() { @Override public PsiSubstitutor compute() { return result.getSubstitutor(); } }) : result.getSubstitutor(); } else { substitutor = result.getSubstitutor(); } return substitutor == null ? ((MethodCandidateInfo)result).getSiteSubstitutor() : substitutor; }
protected MethodCandidateInfo createCandidateInfo(@NotNull PsiMethod method, @NotNull PsiSubstitutor substitutor, final boolean staticProblem, final boolean accessible, final boolean varargs) { final PsiExpressionList argumentList = getArgumentList(); return new MethodCandidateInfo(method, substitutor, !accessible, staticProblem, argumentList, myCurrentFileContext, null, getTypeArguments(), getLanguageLevel()) { private PsiType[] myExpressionTypes; @Override public PsiType[] getArgumentTypes() { if (myExpressionTypes == null && argumentList != null) { final PsiType[] expressionTypes = getExpressionTypes(argumentList); if (MethodCandidateInfo.isOverloadCheck()) { return expressionTypes; } myExpressionTypes = expressionTypes; } return myExpressionTypes; } @Override public boolean isVarargs() { return varargs; } }; }
@Override public CandidateInfo resolveConflict(@NotNull List<CandidateInfo> conflicts){ if (conflicts.size() == 1) return conflicts.get(0); final Map<Object, CandidateInfo> uniqueItems = new HashMap<Object, CandidateInfo>(); for (CandidateInfo info : conflicts) { final PsiElement element = info.getElement(); Object key; if (info instanceof MethodCandidateInfo) { key = ((PsiMethod)element).getSignature(((MethodCandidateInfo)info).getSubstitutor(false)); } else { key = PsiUtilCore.getName(element); } if (!uniqueItems.containsKey(key)) { uniqueItems.put(key, info); } } if(uniqueItems.size() == 1) return uniqueItems.values().iterator().next(); return null; }
@Override public final CandidateInfo resolveConflict(@NotNull final List<CandidateInfo> conflicts){ /* //non-default policies final MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(myArgumentsList); if (properties != null) { final PsiMethod method = properties.getMethod(); LOG.error("Recursive conflict resolution for:" + method + "; " + myArgumentsList.getText() + "; file=" + (method == null ? "<unknown>" : method.getContainingFile())); }*/ return MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(myArgumentsList, true, new Computable<CandidateInfo>() { @Override public CandidateInfo compute() { return guardedOverloadResolution(conflicts); } }); }
protected static void checkAccessStaticLevels(@NotNull List<CandidateInfo> conflicts, boolean checkAccessible) { int conflictsCount = conflicts.size(); int maxCheckLevel = -1; int[] checkLevels = new int[conflictsCount]; int index = 0; for (final CandidateInfo conflict : conflicts) { ProgressManager.checkCanceled(); final MethodCandidateInfo method = (MethodCandidateInfo)conflict; final int level = checkAccessible ? getCheckAccessLevel(method) : getCheckStaticLevel(method); checkLevels[index++] = level; maxCheckLevel = Math.max(maxCheckLevel, level); } for (int i = conflictsCount - 1; i >= 0; i--) { // check for level if (checkLevels[i] < maxCheckLevel) { conflicts.remove(i); } } }
/** * choose to accept static interface methods during search to get "Static interface methods must be invoked on containing interface class only" error * instead of non clear javac message that symbol not found * * but these methods should be ignored during overload resolution if another methods are present */ private void checkStaticMethodsOfInterfaces(@NotNull List<CandidateInfo> conflicts) { if (!(myArgumentsList instanceof PsiExpressionList)) return; PsiClass qualifierClass = null; for (Iterator<CandidateInfo> iterator = conflicts.iterator(); iterator.hasNext(); ) { CandidateInfo conflict = iterator.next(); if (!(conflict instanceof MethodCandidateInfo)) continue; final PsiMethod method = ((MethodCandidateInfo)conflict).getElement(); if (method.hasModifierProperty(PsiModifier.STATIC)) { if (conflict.getCurrentFileResolveScope() instanceof PsiImportStaticStatement) continue; final PsiClass containingClass = method.getContainingClass(); if (containingClass != null && containingClass.isInterface()) { if (qualifierClass == null) { qualifierClass = getQualifiedClass(method); if (qualifierClass == null) return; } if (!containingClass.getManager().areElementsEquivalent(containingClass, qualifierClass)) { iterator.remove(); } } } } }
private boolean isApplicableTo(@NotNull PsiType[] types2AtSite, @NotNull PsiMethod method1, @NotNull LanguageLevel languageLevel, boolean varargsPosition, @NotNull PsiSubstitutor methodSubstitutor1, @NotNull PsiMethod method2, PsiSubstitutor siteSubstitutor1) { if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && method1.getTypeParameters().length > 0 && myArgumentsList instanceof PsiExpressionList) { final PsiElement parent = myArgumentsList.getParent(); if (parent instanceof PsiCallExpression) { return InferenceSession.isMoreSpecific(method2, method1, siteSubstitutor1, ((PsiExpressionList)myArgumentsList).getExpressions(), myArgumentsList, varargsPosition); } } final PsiUtil.ApplicabilityChecker applicabilityChecker = languageLevel.isAtLeast(LanguageLevel.JDK_1_8) ? new PsiUtil.ApplicabilityChecker() { @Override public boolean isApplicable(PsiType left, PsiType right, boolean allowUncheckedConversion, int argId) { return isTypeMoreSpecific(left, right, argId); } } : PsiUtil.ApplicabilityChecker.ASSIGNABILITY_CHECKER; final int applicabilityLevel = PsiUtil.getApplicabilityLevel(method1, methodSubstitutor1, types2AtSite, languageLevel, false, varargsPosition, applicabilityChecker); return applicabilityLevel > MethodCandidateInfo.ApplicabilityLevel.NOT_APPLICABLE; }
public void initExpressionConstraints(PsiParameter[] parameters, PsiExpression[] args, PsiElement parent, PsiMethod method, boolean varargs) { final MethodCandidateInfo.CurrentCandidateProperties currentProperties = getCurrentProperties(parent); if (method == null) { if (currentProperties != null) { method = currentProperties.getMethod(); } } if (method != null) { initThrowsConstraints(method); } if (parameters.length > 0) { for (int i = 0; i < args.length; i++) { if (args[i] != null && isPertinentToApplicability(args[i], method)) { PsiType parameterType = getParameterType(parameters, i, mySiteSubstitutor, varargs); addConstraint(new ExpressionCompatibilityConstraint(args[i], substituteWithInferenceVariables(parameterType))); } } } }
private static PsiMethod getCalledMethod(PsiCall arg) { final PsiExpressionList argumentList = arg.getArgumentList(); if (argumentList == null) { return null; } MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(argumentList); if (properties != null) { return properties.getMethod(); } final JavaResolveResult resolveResult = getMethodResult(arg); if (resolveResult instanceof MethodCandidateInfo) { return (PsiMethod)resolveResult.getElement(); } else { return null; } }
private void collectAdditionalConstraints(final Set<ConstraintFormula> additionalConstraints, final PsiCall callExpression) { PsiExpressionList argumentList = callExpression.getArgumentList(); if (argumentList != null) { final JavaResolveResult result = getMethodResult(callExpression); MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(argumentList); final PsiMethod method = result instanceof MethodCandidateInfo ? ((MethodCandidateInfo)result).getElement() : properties != null ? properties.getMethod() : null; if (method != null) { final PsiExpression[] newArgs = argumentList.getExpressions(); final PsiParameter[] newParams = method.getParameterList().getParameters(); if (newParams.length > 0) { collectAdditionalConstraints(newParams, newArgs, method, chooseSiteSubstitutor(properties, result, method), additionalConstraints, chooseVarargsMode(properties, result)); } } } }
private static JavaResolveResult getMethodResult(final PsiCall callExpression) { final PsiExpressionList argumentList = callExpression.getArgumentList(); final PsiLambdaExpression expression = PsiTreeUtil.getParentOfType(argumentList, PsiLambdaExpression.class); final Computable<JavaResolveResult> computableResolve = new Computable<JavaResolveResult>() { @Override public JavaResolveResult compute() { return getResolveResult(callExpression, argumentList); } }; MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(argumentList); return properties != null ? null : expression == null || !PsiResolveHelper.ourGraphGuard.currentStack().contains(expression) ? computableResolve.compute() : PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, false, computableResolve); }
public TypeParamsChecker(PsiElement expression, PsiClass aClass) { myClass = aClass; PsiElement parent = expression != null ? expression.getParent() : null; while (parent instanceof PsiParenthesizedExpression) { parent = parent.getParent(); } if (parent instanceof PsiExpressionList) { final PsiElement gParent = parent.getParent(); if (gParent instanceof PsiCall) { final MethodCandidateInfo.CurrentCandidateProperties pair = MethodCandidateInfo.getCurrentMethod(parent); myMethod = pair != null ? pair.getMethod() : null; if (myMethod == null) { myMethod = ((PsiCall)gParent).resolveMethod(); } if (myMethod != null && PsiTreeUtil.isAncestor(myMethod, expression, false)) { myMethod = null; } } } }
private static void registerMethodReturnFixAction(HighlightInfo highlightInfo, MethodCandidateInfo candidate, PsiCall methodCall) { if (methodCall.getParent() instanceof PsiReturnStatement) { final PsiMethod containerMethod = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class, true, PsiLambdaExpression.class); if (containerMethod != null) { final PsiMethod method = candidate.getElement(); final PsiExpression methodCallCopy = JavaPsiFacade.getElementFactory(method.getProject()).createExpressionFromText(methodCall.getText(), methodCall); PsiType methodCallTypeByArgs = methodCallCopy.getType(); //ensure type params are not included methodCallTypeByArgs = JavaPsiFacade.getElementFactory(method.getProject()) .createRawSubstitutor(method).substitute(methodCallTypeByArgs); QuickFixAction.registerQuickFixAction(highlightInfo, getFixRange(methodCall), QUICK_FIX_FACTORY.createMethodReturnFix(containerMethod, methodCallTypeByArgs, true)); } } }
@Language("HTML") private static String createAmbiguousMethodHtmlTooltipMethodRow(final MethodCandidateInfo methodCandidate) { PsiMethod method = methodCandidate.getElement(); PsiParameter[] parameters = method.getParameterList().getParameters(); PsiSubstitutor substitutor = methodCandidate.getSubstitutor(); @NonNls @Language("HTML") String ms = "<td><b>" + method.getName() + "</b></td>"; for (int j = 0; j < parameters.length; j++) { PsiParameter parameter = parameters[j]; PsiType type = substitutor.substitute(parameter.getType()); ms += "<td><b>" + (j == 0 ? "(" : "") + XmlStringUtil.escapeString(type.getPresentableText()) + (j == parameters.length - 1 ? ")" : ",") + "</b></td>"; } if (parameters.length == 0) { ms += "<td><b>()</b></td>"; } return ms; }
/** * If the compile-time declaration is applicable by variable arity invocation, * then where the last formal parameter type of the invocation type of the method is Fn[], * it is a compile-time error if the type which is the erasure of Fn is not accessible at the point of invocation. */ private static HighlightInfo checkVarargParameterErasureToBeAccessible(MethodCandidateInfo info, PsiCall place) { final PsiMethod method = info.getElement(); if (info.isVarargs() || method.isVarArgs() && !PsiUtil.isLanguageLevel8OrHigher(place)) { final PsiParameter[] parameters = method.getParameterList().getParameters(); final PsiType componentType = ((PsiEllipsisType)parameters[parameters.length - 1].getType()).getComponentType(); final PsiType substitutedTypeErasure = TypeConversionUtil.erasure(info.getSubstitutor().substitute(componentType)); final PsiClass targetClass = PsiUtil.resolveClassInClassTypeOnly(substitutedTypeErasure); if (targetClass != null && !PsiUtil.isAccessible(targetClass, place, null)) { final PsiExpressionList argumentList = place.getArgumentList(); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .descriptionAndTooltip("Formal varargs element type " + PsiFormatUtil.formatClass(targetClass, PsiFormatUtilBase.SHOW_FQ_NAME) + " is inaccessible here") .range(argumentList != null ? argumentList : place) .create(); } } return null; }
private static void registerSwapFixes(final PsiExpression[] expressions, final PsiCall callExpression, final List<PsiCall> permutations, MethodCandidateInfo candidate, final int incompatibilitiesCount, final int minIncompatibleIndex, final int maxIncompatibleIndex) throws IncorrectOperationException { PsiMethod method = candidate.getElement(); PsiSubstitutor substitutor = candidate.getSubstitutor(); if (incompatibilitiesCount >= 3) return; // no way we can fix it by swapping for (int i = minIncompatibleIndex; i < maxIncompatibleIndex; i++) { for (int j = i+1; j <= maxIncompatibleIndex; j++) { ArrayUtil.swap(expressions, i, j); if (PsiUtil.isApplicable(method, substitutor, expressions)) { PsiCall copy = (PsiCall)callExpression.copy(); PsiExpression[] copyExpressions = copy.getArgumentList().getExpressions(); copyExpressions[i].replace(expressions[i]); copyExpressions[j].replace(expressions[j]); JavaResolveResult result = copy.resolveMethodGenerics(); if (result.getElement() != null && result.isValidResult()) { permutations.add(copy); if (permutations.size() > 1) return; } } ArrayUtil.swap(expressions, i, j); } } }
public static void registerFixes(@NotNull final CandidateInfo[] candidates, @NotNull final PsiMethodCallExpression methodCall, @Nullable final HighlightInfo info) { if (info == null) return; final Set<PsiLiteralExpression> literals = new HashSet<PsiLiteralExpression>(); boolean exactMatch = false; for (CandidateInfo candidate : candidates) { if (candidate instanceof MethodCandidateInfo) { final PsiMethod method = ((MethodCandidateInfo) candidate).getElement(); exactMatch |= findMatchingExpressions(methodCall.getArgumentList().getExpressions(), method, literals); } } if (!exactMatch) { processLiterals(literals, methodCall, info); } }
public JavaMethodResolveHelper(@NotNull final PsiElement argumentList, PsiFile containingFile, @Nullable final PsiType[] argumentTypes) { myArgumentTypes = argumentTypes; final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(argumentList); final PsiConflictResolver resolver = argumentTypes == null ? DuplicateConflictResolver.INSTANCE : new JavaMethodsConflictResolver(argumentList, argumentTypes, languageLevel); myProcessor = new MethodResolverProcessor(argumentList, containingFile, new PsiConflictResolver[]{resolver}) { @Override protected MethodCandidateInfo createCandidateInfo(@NotNull final PsiMethod method, @NotNull final PsiSubstitutor substitutor, final boolean staticProblem, final boolean accessible, final boolean varargs) { return JavaMethodResolveHelper.this .createCandidateInfo(method, substitutor, staticProblem, myCurrentFileContext, !accessible, argumentList, argumentTypes, languageLevel); } @Override protected boolean isAccepted(final PsiMethod candidate) { return !candidate.isConstructor(); } }; }
protected ErrorType getResolveError(MethodCandidateInfo info) { if (myArgumentTypes == null) return ErrorType.NONE; if (!info.isApplicable()) { boolean hasNulls = false; //noinspection ConstantConditions final PsiParameter[] parameters = info.getElement().getParameterList().getParameters(); if (myArgumentTypes.length == parameters.length) { for (int i = 0; i < myArgumentTypes.length; i++) { PsiType type = myArgumentTypes[i]; if (type == null) { hasNulls = true; } else if (!parameters[i].getType().isAssignableFrom(type)) { return ErrorType.RESOLVE; } } } return hasNulls ? ErrorType.NONE : ErrorType.RESOLVE; } return ErrorType.NONE; }
public void testSelectionWithGenerics() throws Exception { configureByFile(BASE_PATH + getTestName(false) + ".java"); final MethodParameterInfoHandler handler = new MethodParameterInfoHandler(); final CreateParameterInfoContext context = new MockCreateParameterInfoContext(myEditor, myFile); final PsiExpressionList list = handler.findElementForParameterInfo(context); assertNotNull(list); final Object[] itemsToShow = context.getItemsToShow(); assertNotNull(itemsToShow); assertEquals(2, itemsToShow.length); assertTrue(itemsToShow[0] instanceof MethodCandidateInfo); final ParameterInfoUIContextEx parameterContext = ParameterInfoComponent.createContext(itemsToShow, myEditor, handler, -1); final MockUpdateParameterInfoContext updateParameterInfoContext = new MockUpdateParameterInfoContext(myEditor, myFile, itemsToShow); updateParameterInfoContext.setParameterOwner(list); handler.updateParameterInfo(list, updateParameterInfoContext); assertTrue(updateParameterInfoContext.isUIComponentEnabled(0) || updateParameterInfoContext.isUIComponentEnabled(1)); }
public void testAfterGenericsInsideCall() throws Exception { configureByFile(BASE_PATH + getTestName(false) + ".java"); final MethodParameterInfoHandler handler = new MethodParameterInfoHandler(); final CreateParameterInfoContext context = new MockCreateParameterInfoContext(myEditor, myFile); final PsiExpressionList list = handler.findElementForParameterInfo(context); assertNotNull(list); final Object[] itemsToShow = context.getItemsToShow(); assertNotNull(itemsToShow); assertEquals(2, itemsToShow.length); assertTrue(itemsToShow[0] instanceof MethodCandidateInfo); final PsiMethod method = ((MethodCandidateInfo)itemsToShow[0]).getElement(); final ParameterInfoUIContextEx parameterContext = ParameterInfoComponent.createContext(itemsToShow, myEditor, handler, 1); parameterContext.setUIComponentEnabled(true); Assert.assertEquals("<html>Class<T> type, <b>boolean tags</b></html>", MethodParameterInfoHandler .updateMethodPresentation(method, ((MethodCandidateInfo)itemsToShow[0]).getSubstitutor(), parameterContext)); }
private void doTestPresentation(String expectedString, int currentParameterIndex) { configureByFile(BASE_PATH + getTestName(false) + ".java"); final MethodParameterInfoHandler handler = new MethodParameterInfoHandler(); final CreateParameterInfoContext context = new MockCreateParameterInfoContext(myEditor, myFile); final PsiExpressionList list = handler.findElementForParameterInfo(context); assertNotNull(list); final Object[] itemsToShow = context.getItemsToShow(); assertNotNull(itemsToShow); assertEquals(1, itemsToShow.length); assertTrue(itemsToShow[0] instanceof MethodCandidateInfo); final PsiMethod method = ((MethodCandidateInfo)itemsToShow[0]).getElement(); final ParameterInfoUIContextEx parameterContext = ParameterInfoComponent.createContext(itemsToShow, myEditor, handler, currentParameterIndex); Assert.assertEquals(expectedString, MethodParameterInfoHandler .updateMethodPresentation(method, ((MethodCandidateInfo)itemsToShow[0]).getSubstitutor(), parameterContext)); }
public void testStaticImportDirect() throws Exception { final PsiReference ref = configureByFile(); final PsiElement element = ref.resolve(); assertNotNull(element); assertThat(element, instanceOf(PsiMethod.class)); final PsiMethod method = (PsiMethod)element; assertEquals("asList", method.getName()); assertEquals("java.util.Arrays", method.getContainingClass().getQualifiedName()); assertThat(ref, instanceOf(PsiReferenceExpression.class)); final PsiReferenceExpression refExpr = (PsiReferenceExpression)ref; final JavaResolveResult[] resolveResults = refExpr.multiResolve(false); assertEquals(1, resolveResults.length); final JavaResolveResult resolveResult = resolveResults[0]; assertTrue(resolveResult.isValidResult()); assertThat(resolveResult.getCurrentFileResolveScope(), instanceOf(PsiImportStaticStatement.class)); assertThat(resolveResult, instanceOf(MethodCandidateInfo.class)); final MethodCandidateInfo methodCandidateInfo = (MethodCandidateInfo)resolveResult; assertTrue(methodCandidateInfo.isApplicable()); }
public void testStaticImportConflict() throws Exception { final PsiReference ref = configureByFile(); final PsiElement element = ref.resolve(); assertNotNull(element); assertThat(element, instanceOf(PsiMethod.class)); final PsiMethod method = (PsiMethod)element; assertEquals("sort", method.getName()); assertEquals("java.util.Collections", method.getContainingClass().getQualifiedName()); assertThat(ref, instanceOf(PsiReferenceExpression.class)); final PsiReferenceExpression refExpr = (PsiReferenceExpression)ref; final JavaResolveResult[] resolveResults = refExpr.multiResolve(false); assertEquals(1, resolveResults.length); final JavaResolveResult resolveResult = resolveResults[0]; assertFalse(resolveResult.isValidResult()); assertThat(resolveResult.getCurrentFileResolveScope(), instanceOf(PsiImportStaticStatement.class)); assertThat(resolveResult, instanceOf(MethodCandidateInfo.class)); final MethodCandidateInfo methodCandidateInfo = (MethodCandidateInfo)resolveResult; assertFalse(methodCandidateInfo.isApplicable()); }
public void testGenericsAndVarargsNoConflict() throws Exception { final PsiReference ref = configureByFile(); final PsiElement element = ref.resolve(); assertNotNull(element); assertThat(element, instanceOf(PsiMethod.class)); final PsiMethod method = (PsiMethod)element; assertEquals("method", method.getName()); assertEquals(method.getTypeParameters().length, 0); assertThat(ref, instanceOf(PsiReferenceExpression.class)); final PsiReferenceExpression refExpr = (PsiReferenceExpression)ref; final JavaResolveResult[] resolveResults = refExpr.multiResolve(false); assertEquals(1, resolveResults.length); final JavaResolveResult resolveResult = resolveResults[0]; assertTrue(resolveResult.isValidResult()); assertThat(resolveResult, instanceOf(MethodCandidateInfo.class)); final MethodCandidateInfo methodCandidateInfo = (MethodCandidateInfo)resolveResult; assertTrue(methodCandidateInfo.isApplicable()); }
private static void checkAccessStaticLevels(List<CandidateInfo> conflicts, boolean checkAccessible) { int conflictsCount = conflicts.size(); int maxCheckLevel = -1; int[] checkLevels = new int[conflictsCount]; int index = 0; for (final CandidateInfo conflict : conflicts) { ProgressManager.checkCanceled(); final MethodCandidateInfo method = (MethodCandidateInfo)conflict; final int level = checkAccessible ? getCheckAccessLevel(method) : getCheckStaticLevel(method); checkLevels[index++] = level; maxCheckLevel = Math.max(maxCheckLevel, level); } for (int i = conflictsCount - 1; i >= 0; i--) { // check for level if (checkLevels[i] < maxCheckLevel) { conflicts.remove(i); } } }
public TypeParamsChecker(PsiElement expression, PsiClass aClass) { myClass = aClass; PsiElement parent = expression != null ? expression.getParent() : null; while (parent instanceof PsiParenthesizedExpression) { parent = parent.getParent(); } if (parent instanceof PsiExpressionList) { final PsiElement gParent = parent.getParent(); if (gParent instanceof PsiCall) { final Map<PsiElement, Pair<PsiMethod, PsiSubstitutor>> map = MethodCandidateInfo.CURRENT_CANDIDATE.get(); if (map != null) { final Pair<PsiMethod, PsiSubstitutor> pair = map.get(parent); myMethod = pair != null ? pair.first : null; } else { myMethod = null; } if (myMethod == null) { myMethod = ((PsiCall)gParent).resolveMethod(); } if (myMethod != null && PsiTreeUtil.isAncestor(myMethod, expression, false)) { myMethod = null; } } } }
public JavaMethodResolveHelper(@NotNull final PsiElement argumentList, PsiFile containingFile, @Nullable final PsiType[] argumentTypes) { myArgumentTypes = argumentTypes; final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(argumentList); final PsiConflictResolver resolver = argumentTypes == null ? DuplicateConflictResolver.INSTANCE : new JavaMethodsConflictResolver(argumentList, argumentTypes, languageLevel); myProcessor = new MethodResolverProcessor(argumentList, containingFile, new PsiConflictResolver[]{resolver}) { @Override protected MethodCandidateInfo createCandidateInfo(final PsiMethod method, final PsiSubstitutor substitutor, final boolean staticProblem, final boolean accessible) { return JavaMethodResolveHelper.this .createCandidateInfo(method, substitutor, staticProblem, myCurrentFileContext, !accessible, argumentList, argumentTypes, languageLevel); } @Override protected boolean isAccepted(final PsiMethod candidate) { return !candidate.isConstructor(); } }; }
@Override public final CandidateInfo resolveConflict(@NotNull final List<CandidateInfo> conflicts) { final MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(myArgumentsList); if(properties != null && properties.isApplicabilityCheck()) { final PsiMethod method = properties.getMethod(); LOG.error("Recursive conflict resolution for:" + method + "; " + myArgumentsList.getText() + "; " + "file=" + (method == null ? "<unknown>" : method.getContainingFile())); } return MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(myArgumentsList, false, new Computable<CandidateInfo>() { @Override public CandidateInfo compute() { return guardedOverloadResolution(conflicts); } }); }
private static void checkPotentiallyCompatibleMethods(@NotNull List<CandidateInfo> conflicts) { List<CandidateInfo> partiallyApplicable = new ArrayList<CandidateInfo>(); for(Iterator<CandidateInfo> iterator = conflicts.iterator(); iterator.hasNext(); ) { CandidateInfo conflict = iterator.next(); if(conflict instanceof MethodCandidateInfo) { ThreeState compatible = ((MethodCandidateInfo) conflict).isPotentiallyCompatible(); if(compatible == ThreeState.NO) { iterator.remove(); } else if(compatible == ThreeState.UNSURE) { partiallyApplicable.add(conflict); } } } if(conflicts.size() > partiallyApplicable.size()) { conflicts.removeAll(partiallyApplicable); } }
protected static void checkAccessStaticLevels(@NotNull List<CandidateInfo> conflicts, boolean checkAccessible) { int conflictsCount = conflicts.size(); int maxCheckLevel = -1; int[] checkLevels = new int[conflictsCount]; int index = 0; for(final CandidateInfo conflict : conflicts) { ProgressManager.checkCanceled(); final MethodCandidateInfo method = (MethodCandidateInfo) conflict; final int level = checkAccessible ? getCheckAccessLevel(method) : getCheckStaticLevel(method); checkLevels[index++] = level; maxCheckLevel = Math.max(maxCheckLevel, level); } for(int i = conflictsCount - 1; i >= 0; i--) { // check for level if(checkLevels[i] < maxCheckLevel) { conflicts.remove(i); } } }
@Nullable private static InferenceSession startTopLevelInference(final PsiCall topLevelCall, final ParameterTypeInferencePolicy policy) { final JavaResolveResult result = topLevelCall.resolveMethodGenerics(); if(result instanceof MethodCandidateInfo) { final PsiMethod method = ((MethodCandidateInfo) result).getElement(); final PsiParameter[] topLevelParameters = method.getParameterList().getParameters(); final PsiExpressionList topLevelCallArgumentList = topLevelCall.getArgumentList(); LOG.assertTrue(topLevelCallArgumentList != null, topLevelCall); final PsiExpression[] topLevelArguments = topLevelCallArgumentList.getExpressions(); return PsiResolveHelper.ourGraphGuard.doPreventingRecursion(topLevelCall, true, new Computable<InferenceSession>() { @Override public InferenceSession compute() { final InferenceSession topLevelSession = new InferenceSession(method.getTypeParameters(), ((MethodCandidateInfo) result).getSiteSubstitutor(), topLevelCall.getManager(), topLevelCall, policy); topLevelSession.initExpressionConstraints(topLevelParameters, topLevelArguments, topLevelCall, method, ((MethodCandidateInfo) result).isVarargs()); topLevelSession.infer(topLevelParameters, topLevelArguments, topLevelCall, ((MethodCandidateInfo) result).createProperties()); return topLevelSession; } }); } return null; }
private boolean isOverloadCheck() { if(myContext != null) { for(Object o : MethodCandidateInfo.ourOverloadGuard.currentStack()) { //method references do not contain nested arguments anyway if(o instanceof PsiExpressionList) { final PsiExpressionList element = (PsiExpressionList) o; for(PsiExpression expression : element.getExpressions()) { if(expression == myContext) { return true; } } } } return false; } return MethodCandidateInfo.isOverloadCheck(); }