HighlightUtil decomposition: fix-related methods moved to HighlightFixUtil

This commit is contained in:
Tagir Valeev
2017-09-19 13:26:23 +07:00
parent defb0e089a
commit b6ed0a0d12
7 changed files with 325 additions and 285 deletions
@@ -802,7 +802,7 @@ public class GenericsHighlightUtil {
return null;
}
HighlightInfo highlightInfo = HighlightUtil.createIncompatibleTypeHighlightInfo(itemType, parameterType, parameter.getTextRange(), 0);
HighlightUtil.registerChangeVariableTypeFixes(parameter, itemType, expression, highlightInfo);
HighlightFixUtil.registerChangeVariableTypeFixes(parameter, itemType, expression, highlightInfo);
return highlightInfo;
}
@@ -1421,7 +1421,7 @@ public class GenericsHighlightUtil {
}
PsiSubstitutor substitutor = factory.createSubstitutor(map);
PsiType suggestedType = factory.createType(aClass, substitutor);
HighlightUtil.registerChangeVariableTypeFixes(variable, suggestedType, variable.getInitializer(), highlightInfo);
HighlightFixUtil.registerChangeVariableTypeFixes(variable, suggestedType, variable.getInitializer(), highlightInfo);
}
}
}
@@ -0,0 +1,298 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.daemon.impl.quickfix.ReplaceAssignmentFromVoidWithStatementIntentionAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInsight.intention.impl.PriorityActionWrapper;
import com.intellij.codeInsight.quickfix.ChangeVariableTypeQuickFixProvider;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class HighlightFixUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.analysis.HighlightFixUtil");
private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance();
static void registerCollectionToArrayFixAction(@Nullable HighlightInfo info,
@Nullable PsiType fromType,
@Nullable PsiType toType,
@NotNull PsiExpression expression) {
if (toType instanceof PsiArrayType) {
PsiType arrayComponentType = ((PsiArrayType)toType).getComponentType();
if (!(arrayComponentType instanceof PsiPrimitiveType) &&
!(PsiUtil.resolveClassInType(arrayComponentType) instanceof PsiTypeParameter) &&
InheritanceUtil.isInheritor(fromType, CommonClassNames.JAVA_UTIL_COLLECTION)) {
PsiType collectionItemType = JavaGenericsUtil.getCollectionItemType(fromType, expression.getResolveScope());
if (collectionItemType != null && arrayComponentType.isAssignableFrom(collectionItemType)) {
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createCollectionToArrayFix(expression, (PsiArrayType)toType));
}
}
}
}
/**
* make element protected/package-private/public suggestion
* for private method in the interface it should add default modifier as well
*/
static void registerAccessQuickFixAction(@NotNull PsiMember refElement,
@NotNull PsiJavaCodeReferenceElement place,
@Nullable HighlightInfo errorResult,
final PsiElement fileResolveScope) {
if (errorResult == null) return;
PsiClass accessObjectClass = null;
PsiElement qualifier = place.getQualifier();
if (qualifier instanceof PsiExpression) {
accessObjectClass = (PsiClass)PsiUtil.getAccessObjectClass((PsiExpression)qualifier).getElement();
}
registerReplaceInaccessibleFieldWithGetterSetterFix(refElement, place, accessObjectClass,
errorResult);
if (refElement instanceof PsiCompiledElement) return;
PsiModifierList modifierList = refElement.getModifierList();
if (modifierList == null) return;
PsiClass packageLocalClassInTheMiddle = getPackageLocalClassInTheMiddle(place);
if (packageLocalClassInTheMiddle != null) {
IntentionAction fix =
QUICK_FIX_FACTORY.createModifierListFix(packageLocalClassInTheMiddle, PsiModifier.PUBLIC, true, true);
QuickFixAction.registerQuickFixAction(errorResult, fix);
return;
}
try {
Project project = refElement.getProject();
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
PsiModifierList modifierListCopy = facade.getElementFactory().createFieldFromText("int a;", null).getModifierList();
assert modifierListCopy != null;
modifierListCopy.setModifierProperty(PsiModifier.STATIC, modifierList.hasModifierProperty(PsiModifier.STATIC));
String minModifier = PsiModifier.PACKAGE_LOCAL;
if (refElement.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) {
minModifier = PsiModifier.PROTECTED;
}
if (refElement.hasModifierProperty(PsiModifier.PROTECTED)) {
minModifier = PsiModifier.PUBLIC;
}
PsiClass containingClass = refElement.getContainingClass();
if (containingClass != null && containingClass.isInterface()) {
minModifier = PsiModifier.PUBLIC;
}
String[] modifiers = {PsiModifier.PACKAGE_LOCAL, PsiModifier.PROTECTED, PsiModifier.PUBLIC,};
for (int i = ArrayUtil.indexOf(modifiers, minModifier); i < modifiers.length; i++) {
@PsiModifier.ModifierConstant String modifier = modifiers[i];
modifierListCopy.setModifierProperty(modifier, true);
if (facade.getResolveHelper().isAccessible(refElement, modifierListCopy, place, accessObjectClass, fileResolveScope)) {
IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(refElement, modifier, true, true);
TextRange fixRange = new TextRange(errorResult.startOffset, errorResult.endOffset);
PsiElement ref = place.getReferenceNameElement();
if (ref != null) {
fixRange = fixRange.union(ref.getTextRange());
}
QuickFixAction.registerQuickFixAction(errorResult, fixRange, fix);
}
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
@Nullable
static PsiClass getPackageLocalClassInTheMiddle(@NotNull PsiElement place) {
if (place instanceof PsiReferenceExpression) {
// check for package-private classes in the middle
PsiReferenceExpression expression = (PsiReferenceExpression)place;
while (true) {
PsiElement resolved = expression.resolve();
if (resolved instanceof PsiField) {
PsiField field = (PsiField)resolved;
PsiClass aClass = field.getContainingClass();
if (aClass != null && aClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) &&
!JavaPsiFacade.getInstance(aClass.getProject()).arePackagesTheSame(aClass, place)) {
return aClass;
}
}
PsiExpression qualifier = expression.getQualifierExpression();
if (!(qualifier instanceof PsiReferenceExpression)) break;
expression = (PsiReferenceExpression)qualifier;
}
}
return null;
}
static void registerChangeVariableTypeFixes(@NotNull PsiExpression expression,
@NotNull PsiType type,
@Nullable final PsiExpression lExpr,
@Nullable HighlightInfo highlightInfo) {
if (highlightInfo == null || !(expression instanceof PsiReferenceExpression)) return;
final PsiElement element = ((PsiReferenceExpression)expression).resolve();
if (!(element instanceof PsiVariable)) return;
registerChangeVariableTypeFixes((PsiVariable)element, type, lExpr, highlightInfo);
if (lExpr instanceof PsiMethodCallExpression && lExpr.getParent() instanceof PsiAssignmentExpression) {
final PsiElement parent = lExpr.getParent();
if (parent.getParent() instanceof PsiStatement) {
final PsiMethod method = ((PsiMethodCallExpression)lExpr).resolveMethod();
if (method != null && PsiType.VOID.equals(method.getReturnType())) {
QuickFixAction.registerQuickFixAction(highlightInfo, new ReplaceAssignmentFromVoidWithStatementIntentionAction(parent, lExpr));
}
}
}
}
static void registerUnhandledExceptionFixes(PsiElement element, HighlightInfo errorResult, List<PsiClassType> unhandled) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createAddExceptionToCatchFix());
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createAddExceptionToThrowsFix(element));
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createAddExceptionFromFieldInitializerToConstructorThrowsFix(element));
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createSurroundWithTryCatchFix(element));
if (unhandled.size() == 1) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createGeneralizeCatchFix(element, unhandled.get(0)));
}
}
static void registerStaticProblemQuickFixAction(@NotNull PsiElement refElement, HighlightInfo errorResult, @NotNull PsiJavaCodeReferenceElement place) {
if (refElement instanceof PsiModifierListOwner) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createModifierListFix((PsiModifierListOwner)refElement, PsiModifier.STATIC, true, false));
}
// make context non static
PsiModifierListOwner staticParent = PsiUtil.getEnclosingStaticElement(place, null);
if (staticParent != null && isInstanceReference(place)) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createModifierListFix(staticParent, PsiModifier.STATIC, false, false));
}
if (place instanceof PsiReferenceExpression && refElement instanceof PsiField) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createCreateFieldFromUsageFix((PsiReferenceExpression)place));
}
}
private static boolean isInstanceReference(@NotNull PsiJavaCodeReferenceElement place) {
PsiElement qualifier = place.getQualifier();
if (qualifier == null) return true;
if (!(qualifier instanceof PsiJavaCodeReferenceElement)) return false;
PsiElement q = ((PsiReference)qualifier).resolve();
if (q instanceof PsiClass) return false;
if (q != null) return true;
String qname = ((PsiJavaCodeReferenceElement)qualifier).getQualifiedName();
return qname == null || !Character.isLowerCase(qname.charAt(0));
}
static void registerChangeVariableTypeFixes(@NotNull PsiVariable parameter,
PsiType itemType,
@Nullable PsiExpression expr,
@NotNull HighlightInfo highlightInfo) {
for (IntentionAction action : getChangeVariableTypeFixes(parameter, itemType)) {
QuickFixAction.registerQuickFixAction(highlightInfo, action);
}
if (expr instanceof PsiMethodCallExpression) {
final PsiMethod method = ((PsiMethodCallExpression)expr).resolveMethod();
if (method != null) {
QuickFixAction.registerQuickFixAction(highlightInfo, PriorityActionWrapper
.lowPriority(method, QUICK_FIX_FACTORY.createMethodReturnFix(method, parameter.getType(), true)));
}
}
}
@NotNull
public static List<IntentionAction> getChangeVariableTypeFixes(@NotNull PsiVariable parameter, PsiType itemType) {
if (itemType instanceof PsiMethodReferenceType) return Collections.emptyList();
List<IntentionAction> result = new ArrayList<>();
if (itemType != null) {
for (ChangeVariableTypeQuickFixProvider fixProvider : Extensions.getExtensions(ChangeVariableTypeQuickFixProvider.EP_NAME)) {
Collections.addAll(result, fixProvider.getFixes(parameter, itemType));
}
}
IntentionAction changeFix = getChangeParameterClassFix(parameter.getType(), itemType);
if (changeFix != null) result.add(changeFix);
return result;
}
@Nullable
static IntentionAction getChangeParameterClassFix(PsiType lType, PsiType rType) {
final PsiClass lClass = PsiUtil.resolveClassInClassTypeOnly(lType);
final PsiClass rClass = PsiUtil.resolveClassInClassTypeOnly(rType);
if (rClass == null || lClass == null) return null;
if (rClass instanceof PsiAnonymousClass) return null;
if (rClass.isInheritor(lClass, true)) return null;
if (lClass.isInheritor(rClass, true)) return null;
if (lClass == rClass) return null;
return QUICK_FIX_FACTORY.createChangeParameterClassFix(rClass, (PsiClassType)lType);
}
private static void registerReplaceInaccessibleFieldWithGetterSetterFix(PsiMember refElement,
PsiJavaCodeReferenceElement place,
PsiClass accessObjectClass,
HighlightInfo error) {
if (refElement instanceof PsiField && place instanceof PsiReferenceExpression) {
final PsiField psiField = (PsiField)refElement;
final PsiClass containingClass = psiField.getContainingClass();
if (containingClass != null) {
if (PsiUtil.isOnAssignmentLeftHand((PsiExpression)place)) {
final PsiMethod setterPrototype = PropertyUtilBase.generateSetterPrototype(psiField);
final PsiMethod setter = containingClass.findMethodBySignature(setterPrototype, true);
if (setter != null && PsiUtil.isAccessible(setter, place, accessObjectClass)) {
final PsiElement element = PsiTreeUtil.skipParentsOfType(place, PsiParenthesizedExpression.class);
if (element instanceof PsiAssignmentExpression && ((PsiAssignmentExpression)element).getOperationTokenType() == JavaTokenType.EQ) {
QuickFixAction.registerQuickFixAction(error, QUICK_FIX_FACTORY.createReplaceInaccessibleFieldWithGetterSetterFix(place, setter, true));
}
}
}
else if (PsiUtil.isAccessedForReading((PsiExpression)place)) {
final PsiMethod getterPrototype = PropertyUtilBase.generateGetterPrototype(psiField);
final PsiMethod getter = containingClass.findMethodBySignature(getterPrototype, true);
if (getter != null && PsiUtil.isAccessible(getter, place, accessObjectClass)) {
QuickFixAction.registerQuickFixAction(error, QUICK_FIX_FACTORY.createReplaceInaccessibleFieldWithGetterSetterFix(place, getter, false));
}
}
}
}
}
static void registerLambdaReturnTypeFixes(HighlightInfo info, PsiLambdaExpression lambda, PsiExpression expression) {
PsiType type = LambdaUtil.getFunctionalInterfaceReturnType(lambda);
if (type != null) {
PsiType exprType = expression.getType();
if (exprType != null && TypeConversionUtil.areTypesConvertible(exprType, type)) {
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createAddTypeCastFix(type, expression));
}
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapWithOptionalFix(type, expression));
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapExpressionFix(type, expression));
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapWithAdapterFix(type, expression));
}
}
static void registerChangeParameterClassFix(PsiType lType, PsiType rType, HighlightInfo info) {
QuickFixAction.registerQuickFixAction(info, getChangeParameterClassFix(lType, rType));
}
}
@@ -538,7 +538,7 @@ public class HighlightMethodUtil {
if (rType != null && !variable.getType().isAssignableFrom(rType)) {
PsiType expectedTypeByApplicabilityConstraints = resolveResult.getSubstitutor(false).substitute(resolved.getReturnType());
if (expectedTypeByApplicabilityConstraints != null && !expectedTypeByApplicabilityConstraints.equals(rType)) {
HighlightUtil.registerChangeVariableTypeFixes(variable, expectedTypeByApplicabilityConstraints, methodCall, highlightInfo);
HighlightFixUtil.registerChangeVariableTypeFixes(variable, expectedTypeByApplicabilityConstraints, methodCall, highlightInfo);
}
}
}
@@ -719,7 +719,7 @@ public class HighlightMethodUtil {
HighlightInfo.newHighlightInfo(highlightInfoType).range(elementToHighlight).description(description).escapedToolTip(toolTip).create();
registerMethodCallIntentions(info, methodCall, list, resolveHelper);
if (element != null && !resolveResult.isStaticsScopeCorrect()) {
HighlightUtil.registerStaticProblemQuickFixAction(element, info, referenceToMethod);
HighlightFixUtil.registerStaticProblemQuickFixAction(element, info, referenceToMethod);
}
TextRange fixRange = getFixRange(elementToHighlight);
@@ -794,10 +794,10 @@ public class HighlightMethodUtil {
registerMethodCallIntentions(info, methodCall, list, resolveHelper);
}
if (!resolveResult.isAccessible() && resolveResult.isStaticsScopeCorrect() && methodCandidate2 != null) {
HighlightUtil.registerAccessQuickFixAction((PsiMember)element, referenceToMethod, info, resolveResult.getCurrentFileResolveScope());
HighlightFixUtil.registerAccessQuickFixAction((PsiMember)element, referenceToMethod, info, resolveResult.getCurrentFileResolveScope());
}
if (element != null && !resolveResult.isStaticsScopeCorrect()) {
HighlightUtil.registerStaticProblemQuickFixAction(element, info, referenceToMethod);
HighlightFixUtil.registerStaticProblemQuickFixAction(element, info, referenceToMethod);
}
TextRange fixRange = getFixRange(elementToHighlight);
@@ -898,7 +898,7 @@ public class HighlightMethodUtil {
for (CandidateInfo methodCandidate : methodCandidates) {
PsiMethod method = (PsiMethod)methodCandidate.getElement();
if (!methodCandidate.isAccessible() && PsiUtil.isApplicable(method, methodCandidate.getSubstitutor(), exprList)) {
HighlightUtil.registerAccessQuickFixAction(method, methodCall.getMethodExpression(), highlightInfo, methodCandidate.getCurrentFileResolveScope());
HighlightFixUtil.registerAccessQuickFixAction(method, methodCall.getMethodExpression(), highlightInfo, methodCandidate.getCurrentFileResolveScope());
}
}
}
@@ -1645,7 +1645,7 @@ public class HighlightMethodUtil {
String description = HighlightUtil.buildProblemWithAccessDescription(classReference, aClass, typeResolveResult);
PsiElement element = ObjectUtils.notNull(classReference.getReferenceNameElement(), classReference);
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create();
HighlightUtil.registerAccessQuickFixAction(aClass, classReference, info, null);
HighlightFixUtil.registerAccessQuickFixAction(aClass, classReference, info, null);
holder.add(info);
return;
}
@@ -1801,7 +1801,7 @@ public class HighlightMethodUtil {
String description = HighlightUtil.buildProblemWithAccessDescription(ref, resolved, result);
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref).descriptionAndTooltip(description).navigationShift(+1).create();
if (result.isStaticsScopeCorrect()) {
HighlightUtil.registerAccessQuickFixAction(resolved, ref, info, result.getCurrentFileResolveScope());
HighlightFixUtil.registerAccessQuickFixAction(resolved, ref, info, result.getCurrentFileResolveScope());
}
return info;
}
@@ -26,18 +26,14 @@ import com.intellij.codeInsight.daemon.impl.quickfix.*;
import com.intellij.codeInsight.highlighting.HighlightUsagesDescriptionLocation;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInsight.intention.impl.PriorityActionWrapper;
import com.intellij.codeInsight.quickfix.ChangeVariableTypeQuickFixProvider;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.codeInspection.LocalQuickFixOnPsiElementAsIntentionAdapter;
import com.intellij.lang.findUsages.LanguageFindUsages;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.EffectiveLanguageLevelUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.impl.FilePropertyPusher;
@@ -63,7 +59,6 @@ import com.intellij.psi.util.*;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashSet;
@@ -201,96 +196,6 @@ public class HighlightUtil extends HighlightUtilBase {
return null;
}
/**
* make element protected/package-private/public suggestion
* for private method in the interface it should add default modifier as well
*/
static void registerAccessQuickFixAction(@NotNull PsiMember refElement,
@NotNull PsiJavaCodeReferenceElement place,
@Nullable HighlightInfo errorResult,
final PsiElement fileResolveScope) {
if (errorResult == null) return;
PsiClass accessObjectClass = null;
PsiElement qualifier = place.getQualifier();
if (qualifier instanceof PsiExpression) {
accessObjectClass = (PsiClass)PsiUtil.getAccessObjectClass((PsiExpression)qualifier).getElement();
}
registerReplaceInaccessibleFieldWithGetterSetterFix(refElement, place, accessObjectClass,
errorResult);
if (refElement instanceof PsiCompiledElement) return;
PsiModifierList modifierList = refElement.getModifierList();
if (modifierList == null) return;
PsiClass packageLocalClassInTheMiddle = getPackageLocalClassInTheMiddle(place);
if (packageLocalClassInTheMiddle != null) {
IntentionAction fix =
QUICK_FIX_FACTORY.createModifierListFix(packageLocalClassInTheMiddle, PsiModifier.PUBLIC, true, true);
QuickFixAction.registerQuickFixAction(errorResult, fix);
return;
}
try {
Project project = refElement.getProject();
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
PsiModifierList modifierListCopy = facade.getElementFactory().createFieldFromText("int a;", null).getModifierList();
assert modifierListCopy != null;
modifierListCopy.setModifierProperty(PsiModifier.STATIC, modifierList.hasModifierProperty(PsiModifier.STATIC));
String minModifier = PsiModifier.PACKAGE_LOCAL;
if (refElement.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) {
minModifier = PsiModifier.PROTECTED;
}
if (refElement.hasModifierProperty(PsiModifier.PROTECTED)) {
minModifier = PsiModifier.PUBLIC;
}
PsiClass containingClass = refElement.getContainingClass();
if (containingClass != null && containingClass.isInterface()) {
minModifier = PsiModifier.PUBLIC;
}
String[] modifiers = {PsiModifier.PACKAGE_LOCAL, PsiModifier.PROTECTED, PsiModifier.PUBLIC,};
for (int i = ArrayUtil.indexOf(modifiers, minModifier); i < modifiers.length; i++) {
@PsiModifier.ModifierConstant String modifier = modifiers[i];
modifierListCopy.setModifierProperty(modifier, true);
if (facade.getResolveHelper().isAccessible(refElement, modifierListCopy, place, accessObjectClass, fileResolveScope)) {
IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(refElement, modifier, true, true);
TextRange fixRange = new TextRange(errorResult.startOffset, errorResult.endOffset);
PsiElement ref = place.getReferenceNameElement();
if (ref != null) {
fixRange = fixRange.union(ref.getTextRange());
}
QuickFixAction.registerQuickFixAction(errorResult, fixRange, fix);
}
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
@Nullable
private static PsiClass getPackageLocalClassInTheMiddle(@NotNull PsiElement place) {
if (place instanceof PsiReferenceExpression) {
// check for package-private classes in the middle
PsiReferenceExpression expression = (PsiReferenceExpression)place;
while (true) {
PsiElement resolved = expression.resolve();
if (resolved instanceof PsiField) {
PsiField field = (PsiField)resolved;
PsiClass aClass = field.getContainingClass();
if (aClass != null && aClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) &&
!JavaPsiFacade.getInstance(aClass.getProject()).arePackagesTheSame(aClass, place)) {
return aClass;
}
}
PsiExpression qualifier = expression.getQualifierExpression();
if (!(qualifier instanceof PsiReferenceExpression)) break;
expression = (PsiReferenceExpression)qualifier;
}
}
return null;
}
@Nullable
static HighlightInfo checkInstanceOfApplicable(@NotNull PsiInstanceOfExpression expression) {
@@ -484,35 +389,13 @@ public class HighlightUtil extends HighlightUtilBase {
if (highlightInfo == null) {
return null;
}
registerChangeVariableTypeFixes(lExpr, rType, rExpr, highlightInfo);
HighlightFixUtil.registerChangeVariableTypeFixes(lExpr, rType, rExpr, highlightInfo);
if (lType != null) {
registerChangeVariableTypeFixes(rExpr, lType, lExpr, highlightInfo);
HighlightFixUtil.registerChangeVariableTypeFixes(rExpr, lType, lExpr, highlightInfo);
}
return highlightInfo;
}
private static void registerChangeVariableTypeFixes(@NotNull PsiExpression expression,
@NotNull PsiType type,
@Nullable final PsiExpression lExpr,
@Nullable HighlightInfo highlightInfo) {
if (highlightInfo == null || !(expression instanceof PsiReferenceExpression)) return;
final PsiElement element = ((PsiReferenceExpression)expression).resolve();
if (!(element instanceof PsiVariable)) return;
registerChangeVariableTypeFixes((PsiVariable)element, type, lExpr, highlightInfo);
if (lExpr instanceof PsiMethodCallExpression && lExpr.getParent() instanceof PsiAssignmentExpression) {
final PsiElement parent = lExpr.getParent();
if (parent.getParent() instanceof PsiStatement) {
final PsiMethod method = ((PsiMethodCallExpression)lExpr).resolveMethod();
if (method != null && PsiType.VOID.equals(method.getReturnType())) {
QuickFixAction.registerQuickFixAction(highlightInfo, new ReplaceAssignmentFromVoidWithStatementIntentionAction(parent, lExpr));
}
}
}
}
private static boolean isCastIntentionApplicable(@NotNull PsiExpression expression, @Nullable PsiType toType) {
while (expression instanceof PsiTypeCastExpression || expression instanceof PsiParenthesizedExpression) {
if (expression instanceof PsiTypeCastExpression) {
@@ -540,8 +423,8 @@ public class HighlightUtil extends HighlightUtilBase {
int end = variable.getTextRange().getEndOffset();
HighlightInfo highlightInfo = checkAssignability(lType, rType, initializer, new TextRange(start, end), 0);
if (highlightInfo != null) {
registerChangeVariableTypeFixes(variable, rType, variable.getInitializer(), highlightInfo);
registerChangeVariableTypeFixes(initializer, lType, null, highlightInfo);
HighlightFixUtil.registerChangeVariableTypeFixes(variable, rType, variable.getInitializer(), highlightInfo);
HighlightFixUtil.registerChangeVariableTypeFixes(initializer, lType, null, highlightInfo);
}
return highlightInfo;
}
@@ -617,7 +500,7 @@ public class HighlightUtil extends HighlightUtilBase {
QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createWrapExpressionFix(lType, expression));
QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createWrapWithAdapterFix(lType, expression));
AddTypeArgumentsConditionalFix.register(highlightInfo, expression, lType);
registerCollectionToArrayFixAction(highlightInfo, rType, lType, expression);
HighlightFixUtil.registerCollectionToArrayFixAction(highlightInfo, rType, lType, expression);
}
ChangeNewOperatorTypeFix.register(highlightInfo, expression, lType);
return highlightInfo;
@@ -674,14 +557,14 @@ public class HighlightUtil extends HighlightUtilBase {
if (!PsiType.VOID.equals(valueType)) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createMethodReturnFix(method, valueType, true));
}
registerChangeParameterClassFix(returnType, valueType, errorResult);
HighlightFixUtil.registerChangeParameterClassFix(returnType, valueType, errorResult);
if (returnType instanceof PsiArrayType) {
final PsiType erasedValueType = TypeConversionUtil.erasure(valueType);
if (erasedValueType != null && TypeConversionUtil.isAssignable(((PsiArrayType)returnType).getComponentType(), erasedValueType)) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createSurroundWithArrayFix(null, returnValue));
}
}
registerCollectionToArrayFixAction(errorResult, valueType, returnType, returnValue);
HighlightFixUtil.registerCollectionToArrayFixAction(errorResult, valueType, returnType, returnValue);
}
}
}
@@ -695,23 +578,6 @@ public class HighlightUtil extends HighlightUtilBase {
return errorResult;
}
private static void registerCollectionToArrayFixAction(@Nullable HighlightInfo info,
@Nullable PsiType fromType,
@Nullable PsiType toType,
@NotNull PsiExpression expression) {
if (toType instanceof PsiArrayType) {
PsiType arrayComponentType = ((PsiArrayType)toType).getComponentType();
if (!(arrayComponentType instanceof PsiPrimitiveType) &&
!(PsiUtil.resolveClassInType(arrayComponentType) instanceof PsiTypeParameter) &&
InheritanceUtil.isInheritor(fromType, CommonClassNames.JAVA_UTIL_COLLECTION)) {
PsiType collectionItemType = JavaGenericsUtil.getCollectionItemType(fromType, expression.getResolveScope());
if (collectionItemType != null && arrayComponentType.isAssignableFrom(collectionItemType)) {
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createCollectionToArrayFix(expression, (PsiArrayType)toType));
}
}
}
}
@NotNull
public static String getUnhandledExceptionsDescriptor(@NotNull final Collection<PsiClassType> unhandled) {
return getUnhandledExceptionsDescriptor(unhandled, null);
@@ -859,7 +725,7 @@ public class HighlightUtil extends HighlightUtilBase {
if (textRange == null) textRange = element.getTextRange();
final String description = getUnhandledExceptionsDescriptor(unhandledExceptions);
HighlightInfo errorResult = HighlightInfo.newHighlightInfo(highlightType).range(textRange).descriptionAndTooltip(description).create();
registerUnhandledExceptionFixes(element, errorResult, unhandledExceptions);
HighlightFixUtil.registerUnhandledExceptionFixes(element, errorResult, unhandledExceptions);
return errorResult;
}
@@ -873,20 +739,10 @@ public class HighlightUtil extends HighlightUtilBase {
String description = getUnhandledExceptionsDescriptor(unhandled, "auto-closeable resource");
HighlightInfo highlight = HighlightInfo.newHighlightInfo(highlightType).range(resource).descriptionAndTooltip(description).create();
registerUnhandledExceptionFixes(resource, highlight, unhandled);
HighlightFixUtil.registerUnhandledExceptionFixes(resource, highlight, unhandled);
return highlight;
}
private static void registerUnhandledExceptionFixes(PsiElement element, HighlightInfo errorResult, List<PsiClassType> unhandled) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createAddExceptionToCatchFix());
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createAddExceptionToThrowsFix(element));
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createAddExceptionFromFieldInitializerToConstructorThrowsFix(element));
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createSurroundWithTryCatchFix(element));
if (unhandled.size() == 1) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createGeneralizeCatchFix(element, unhandled.get(0)));
}
}
@Nullable
private static HighlightInfoType getUnhandledExceptionHighlightType(PsiElement element) {
// JSP top level errors are handled by UnhandledExceptionInJSP inspection
@@ -1516,19 +1372,6 @@ public class HighlightUtil extends HighlightUtilBase {
return null;
}
static void addLambdaReturnTypeFixes(HighlightInfo info, PsiLambdaExpression lambda, PsiExpression expression) {
PsiType type = LambdaUtil.getFunctionalInterfaceReturnType(lambda);
if (type != null) {
PsiType exprType = expression.getType();
if (exprType != null && TypeConversionUtil.areTypesConvertible(exprType, type)) {
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createAddTypeCastFix(type, expression));
}
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapWithOptionalFix(type, expression));
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapExpressionFix(type, expression));
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapWithAdapterFix(type, expression));
}
}
private enum SelectorKind { INT, ENUM, STRING }
private static SelectorKind getSwitchSelectorKind(@NotNull PsiType type) {
@@ -1739,31 +1582,6 @@ public class HighlightUtil extends HighlightUtilBase {
return JavaErrorMessages.message("non.static.symbol.referenced.from.static.context", type, name);
}
static void registerStaticProblemQuickFixAction(@NotNull PsiElement refElement, HighlightInfo errorResult, @NotNull PsiJavaCodeReferenceElement place) {
if (refElement instanceof PsiModifierListOwner) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createModifierListFix((PsiModifierListOwner)refElement, PsiModifier.STATIC, true, false));
}
// make context non static
PsiModifierListOwner staticParent = PsiUtil.getEnclosingStaticElement(place, null);
if (staticParent != null && isInstanceReference(place)) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createModifierListFix(staticParent, PsiModifier.STATIC, false, false));
}
if (place instanceof PsiReferenceExpression && refElement instanceof PsiField) {
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createCreateFieldFromUsageFix((PsiReferenceExpression)place));
}
}
private static boolean isInstanceReference(@NotNull PsiJavaCodeReferenceElement place) {
PsiElement qualifier = place.getQualifier();
if (qualifier == null) return true;
if (!(qualifier instanceof PsiJavaCodeReferenceElement)) return false;
PsiElement q = ((PsiReference)qualifier).resolve();
if (q instanceof PsiClass) return false;
if (q != null) return true;
String qname = ((PsiJavaCodeReferenceElement)qualifier).getQualifiedName();
return qname == null || !Character.isLowerCase(qname.charAt(0));
}
@NotNull
static String buildProblemWithAccessDescription(@NotNull PsiElement ref, @NotNull PsiElement resolved, @NotNull JavaResolveResult result) {
return accessProblemTextAndFixes(ref, resolved, result).first;
@@ -1785,7 +1603,7 @@ public class HighlightUtil extends HighlightUtilBase {
String containerName = getContainerName(refElement, result.getSubstitutor());
return Pair.create(JavaErrorMessages.message("protected.symbol", symbolName, containerName), null);
}
PsiClass packageLocalClass = getPackageLocalClassInTheMiddle(reference);
PsiClass packageLocalClass = HighlightFixUtil.getPackageLocalClassInTheMiddle(reference);
if (packageLocalClass != null) {
refElement = packageLocalClass;
symbolName = HighlightMessageUtil.getSymbolName(refElement, result.getSubstitutor());
@@ -2853,7 +2671,7 @@ public class HighlightUtil extends HighlightUtilBase {
problem.second.forEach(fix -> QuickFixAction.registerQuickFixAction(info, fix));
}
else if (result.isStaticsScopeCorrect() && resolved instanceof PsiMember) {
registerAccessQuickFixAction((PsiMember)resolved, ref, info, result.getCurrentFileResolveScope());
HighlightFixUtil.registerAccessQuickFixAction((PsiMember)resolved, ref, info, result.getCurrentFileResolveScope());
if (ref instanceof PsiReferenceExpression) {
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createRenameWrongRefFix((PsiReferenceExpression)ref));
}
@@ -2866,7 +2684,7 @@ public class HighlightUtil extends HighlightUtilBase {
String description = buildProblemWithStaticDescription(resolved);
HighlightInfo info =
HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(refName).descriptionAndTooltip(description).create();
registerStaticProblemQuickFixAction(resolved, info, ref);
HighlightFixUtil.registerStaticProblemQuickFixAction(resolved, info, ref);
if (ref instanceof PsiReferenceExpression) {
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createRenameWrongRefFix((PsiReferenceExpression)ref));
}
@@ -3018,36 +2836,6 @@ public class HighlightUtil extends HighlightUtilBase {
return info;
}
static void registerChangeVariableTypeFixes(@NotNull PsiVariable parameter,
PsiType itemType,
@Nullable PsiExpression expr,
@NotNull HighlightInfo highlightInfo) {
for (IntentionAction action : getChangeVariableTypeFixes(parameter, itemType)) {
QuickFixAction.registerQuickFixAction(highlightInfo, action);
}
if (expr instanceof PsiMethodCallExpression) {
final PsiMethod method = ((PsiMethodCallExpression)expr).resolveMethod();
if (method != null) {
QuickFixAction.registerQuickFixAction(highlightInfo, PriorityActionWrapper
.lowPriority(method, QUICK_FIX_FACTORY.createMethodReturnFix(method, parameter.getType(), true)));
}
}
}
@NotNull
public static List<IntentionAction> getChangeVariableTypeFixes(@NotNull PsiVariable parameter, PsiType itemType) {
if (itemType instanceof PsiMethodReferenceType) return Collections.emptyList();
List<IntentionAction> result = new ArrayList<>();
if (itemType != null) {
for (ChangeVariableTypeQuickFixProvider fixProvider : Extensions.getExtensions(ChangeVariableTypeQuickFixProvider.EP_NAME)) {
Collections.addAll(result, fixProvider.getFixes(parameter, itemType));
}
}
IntentionAction changeFix = getChangeParameterClassFix(parameter.getType(), itemType);
if (changeFix != null) result.add(changeFix);
return result;
}
@Nullable
static HighlightInfo checkAnnotationMethodParameters(@NotNull PsiParameterList list) {
final PsiElement parent = list.getParent();
@@ -3076,52 +2864,6 @@ public class HighlightUtil extends HighlightUtilBase {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(init).descriptionAndTooltip(message).create();
}
private static void registerChangeParameterClassFix(PsiType lType, PsiType rType, HighlightInfo info) {
QuickFixAction.registerQuickFixAction(info, getChangeParameterClassFix(lType, rType));
}
@Nullable
private static IntentionAction getChangeParameterClassFix(PsiType lType, PsiType rType) {
final PsiClass lClass = PsiUtil.resolveClassInClassTypeOnly(lType);
final PsiClass rClass = PsiUtil.resolveClassInClassTypeOnly(rType);
if (rClass == null || lClass == null) return null;
if (rClass instanceof PsiAnonymousClass) return null;
if (rClass.isInheritor(lClass, true)) return null;
if (lClass.isInheritor(rClass, true)) return null;
if (lClass == rClass) return null;
return QUICK_FIX_FACTORY.createChangeParameterClassFix(rClass, (PsiClassType)lType);
}
private static void registerReplaceInaccessibleFieldWithGetterSetterFix(PsiMember refElement,
PsiJavaCodeReferenceElement place,
PsiClass accessObjectClass,
HighlightInfo error) {
if (refElement instanceof PsiField && place instanceof PsiReferenceExpression) {
final PsiField psiField = (PsiField)refElement;
final PsiClass containingClass = psiField.getContainingClass();
if (containingClass != null) {
if (PsiUtil.isOnAssignmentLeftHand((PsiExpression)place)) {
final PsiMethod setterPrototype = PropertyUtilBase.generateSetterPrototype(psiField);
final PsiMethod setter = containingClass.findMethodBySignature(setterPrototype, true);
if (setter != null && PsiUtil.isAccessible(setter, place, accessObjectClass)) {
final PsiElement element = PsiTreeUtil.skipParentsOfType(place, PsiParenthesizedExpression.class);
if (element instanceof PsiAssignmentExpression && ((PsiAssignmentExpression)element).getOperationTokenType() == JavaTokenType.EQ) {
QuickFixAction.registerQuickFixAction(error, QUICK_FIX_FACTORY.createReplaceInaccessibleFieldWithGetterSetterFix(place, setter, true));
}
}
}
else if (PsiUtil.isAccessedForReading((PsiExpression)place)) {
final PsiMethod getterPrototype = PropertyUtilBase.generateGetterPrototype(psiField);
final PsiMethod getter = containingClass.findMethodBySignature(getterPrototype, true);
if (getter != null && PsiUtil.isAccessible(getter, place, accessObjectClass)) {
QuickFixAction.registerQuickFixAction(error, QUICK_FIX_FACTORY.createReplaceInaccessibleFieldWithGetterSetterFix(place, getter, false));
}
}
}
}
}
public enum Feature {
GENERICS(LanguageLevel.JDK_1_5, "feature.generics"),
ANNOTATIONS(LanguageLevel.JDK_1_5, "feature.annotations"),
@@ -382,7 +382,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
QuickFixAction.registerQuickFixAction(info, AdjustFunctionContextFix.createFix(entry.getKey()));
if (entry.getKey() instanceof PsiExpression) {
PsiExpression expr = (PsiExpression)entry.getKey();
HighlightUtil.addLambdaReturnTypeFixes(info, expression, expr);
HighlightFixUtil.registerLambdaReturnTypeFixes(info, expression, expr);
}
myHolder.add(info);
}
@@ -1349,7 +1349,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (method != null && !result.isAccessible()) {
String accessProblem = HighlightUtil.buildProblemWithAccessDescription(expression, method, result);
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(accessProblem).create();
HighlightUtil.registerAccessQuickFixAction((PsiMember)method, expression, info, result.getCurrentFileResolveScope());
HighlightFixUtil.registerAccessQuickFixAction((PsiMember)method, expression, info, result.getCurrentFileResolveScope());
myHolder.add(info);
}
else {
@@ -17,7 +17,7 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightFixUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
@@ -142,7 +142,7 @@ public class VariableTypeFromCallFix implements IntentionAction {
}
final PsiElement resolve = ((PsiReferenceExpression)expression).resolve();
if (resolve instanceof PsiVariable) {
result.addAll(HighlightUtil.getChangeVariableTypeFixes((PsiVariable)resolve, parameterType));
result.addAll(HighlightFixUtil.getChangeVariableTypeFixes((PsiVariable)resolve, parameterType));
}
}
return result;
@@ -1,7 +1,7 @@
package org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightFixUtil;
import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.*;
@@ -156,7 +156,7 @@ public class JavaFxEventHandlerInspection extends XmlSuppressableInspectionTool
final PsiType eventTypeArgument = eventSubstitutor.substitute(typeParameter);
final PsiClassType rawEventArgument = eventTypeArgument instanceof PsiClassType ? ((PsiClassType)eventTypeArgument).rawType() : null;
if (rawFieldType.equals(rawEventArgument)) {
final List<IntentionAction> fixes = HighlightUtil.getChangeVariableTypeFixes(tagField, eventTypeArgument);
final List<IntentionAction> fixes = HighlightFixUtil.getChangeVariableTypeFixes(tagField, eventTypeArgument);
for (IntentionAction action : fixes) {
if (action instanceof LocalQuickFix) {
quickFixes.add((LocalQuickFix)action);