mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
usage of inaccessible api: show language level where the api appeared; quickfix to increase language level (IDEA-168695)
This commit is contained in:
+28
-22
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.EffectiveLanguageLevelUtil;
|
||||
@@ -233,7 +234,8 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(reference.getElement());
|
||||
if (module != null) {
|
||||
final LanguageLevel languageLevel = getEffectiveLanguageLevel(module);
|
||||
if (isForbiddenApiUsage((PsiMember)resolved, languageLevel)) {
|
||||
LanguageLevel sinceLanguageLevel = getLastIncompatibleLanguageLevel((PsiMember)resolved, languageLevel);
|
||||
if (sinceLanguageLevel != null) {
|
||||
PsiClass psiClass = null;
|
||||
final PsiElement qualifier = reference.getQualifier();
|
||||
if (qualifier != null) {
|
||||
@@ -250,7 +252,7 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
if (isIgnored(superClass)) return;
|
||||
}
|
||||
}
|
||||
registerError(reference, languageLevel);
|
||||
registerError(reference, sinceLanguageLevel);
|
||||
} else if (resolved instanceof PsiClass && isInProject(reference)&& !languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
|
||||
final PsiReferenceParameterList parameterList = reference.getParameterList();
|
||||
if (parameterList != null && parameterList.getTypeParameterElements().length > 0) {
|
||||
@@ -296,8 +298,9 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
if (module != null) {
|
||||
final LanguageLevel languageLevel = getEffectiveLanguageLevel(module);
|
||||
if (constructor instanceof PsiCompiledElement) {
|
||||
if (isForbiddenApiUsage(constructor, languageLevel)) {
|
||||
registerError(expression.getClassReference(), languageLevel);
|
||||
LanguageLevel sinceLanguageLevel = getLastIncompatibleLanguageLevel(constructor, languageLevel);
|
||||
if (sinceLanguageLevel != null) {
|
||||
registerError(expression.getClassReference(), sinceLanguageLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,12 +312,14 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
PsiAnnotation annotation = !method.isConstructor() ? AnnotationUtil.findAnnotation(method, CommonClassNames.JAVA_LANG_OVERRIDE) : null;
|
||||
if (annotation != null) {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(annotation);
|
||||
LanguageLevel sinceLanguageLevel = null;
|
||||
if (module != null) {
|
||||
final LanguageLevel languageLevel = getEffectiveLanguageLevel(module);
|
||||
final PsiMethod[] methods = method.findSuperMethods();
|
||||
for (PsiMethod superMethod : methods) {
|
||||
if (superMethod instanceof PsiCompiledElement) {
|
||||
if (!isForbiddenApiUsage(superMethod, languageLevel)) {
|
||||
sinceLanguageLevel = getLastIncompatibleLanguageLevel(superMethod, languageLevel);
|
||||
if (sinceLanguageLevel == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -323,7 +328,7 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
}
|
||||
if (methods.length > 0) {
|
||||
registerError(annotation.getNameReferenceElement(), languageLevel);
|
||||
registerError(annotation.getNameReferenceElement(), sinceLanguageLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -337,7 +342,9 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
private void registerError(PsiJavaCodeReferenceElement reference, LanguageLevel api) {
|
||||
if (reference != null && isInProject(reference)) {
|
||||
//noinspection DialogTitleCapitalization
|
||||
myHolder.registerProblem(reference, InspectionsBundle.message("inspection.1.5.problem.descriptor", getShortName(api)));
|
||||
myHolder.registerProblem(reference,
|
||||
InspectionsBundle.message("inspection.1.5.problem.descriptor", getShortName(api)),
|
||||
myOnTheFly ? new LocalQuickFix[] {(LocalQuickFix)QuickFixFactory.getInstance().createIncreaseLanguageLevelFix(LanguageLevel.values()[api.ordinal() + 1])} : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,33 +354,32 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
return presentableText.substring(0, presentableText.indexOf(' '));
|
||||
}
|
||||
|
||||
public static boolean isForbiddenApiUsage(@NotNull PsiMember member, @NotNull LanguageLevel languageLevel) {
|
||||
if (member instanceof PsiAnonymousClass) return false;
|
||||
public static LanguageLevel getLastIncompatibleLanguageLevel(@NotNull PsiMember member, @NotNull LanguageLevel languageLevel) {
|
||||
if (member instanceof PsiAnonymousClass) return null;
|
||||
PsiClass containingClass = member.getContainingClass();
|
||||
if (containingClass instanceof PsiAnonymousClass) return false;
|
||||
if (member instanceof PsiClass && !(member.getParent() instanceof PsiClass || member.getParent() instanceof PsiFile)) return false;
|
||||
if (containingClass instanceof PsiAnonymousClass) return null;
|
||||
if (member instanceof PsiClass && !(member.getParent() instanceof PsiClass || member.getParent() instanceof PsiFile)) return null;
|
||||
|
||||
return isForbiddenSignature(member, languageLevel) ||
|
||||
containingClass != null && isForbiddenApiUsage(containingClass, languageLevel);
|
||||
|
||||
}
|
||||
|
||||
private static boolean isForbiddenSignature(@NotNull PsiMember member, @NotNull LanguageLevel languageLevel) {
|
||||
Set<String> forbiddenApi = getForbiddenApi(languageLevel);
|
||||
String signature = getSignature(member);
|
||||
return forbiddenApi != null && signature != null && isForbiddenSignature(signature, languageLevel, forbiddenApi);
|
||||
if (forbiddenApi != null && signature != null) {
|
||||
LanguageLevel lastIncompatibleLanguageLevel = getLastIncompatibleLanguageLevelForSignature(signature, languageLevel, forbiddenApi);
|
||||
if (lastIncompatibleLanguageLevel != null) return lastIncompatibleLanguageLevel;
|
||||
}
|
||||
return containingClass != null ? getLastIncompatibleLanguageLevel(containingClass, languageLevel) : null;
|
||||
|
||||
}
|
||||
|
||||
private static boolean isForbiddenSignature(@NotNull String signature, @NotNull LanguageLevel languageLevel, @NotNull Set<String> forbiddenApi) {
|
||||
private static LanguageLevel getLastIncompatibleLanguageLevelForSignature(@NotNull String signature, @NotNull LanguageLevel languageLevel, @NotNull Set<String> forbiddenApi) {
|
||||
if (forbiddenApi.contains(signature)) {
|
||||
return true;
|
||||
return languageLevel;
|
||||
}
|
||||
if (languageLevel.compareTo(ourHighestKnownLanguage) == 0) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
LanguageLevel nextLanguageLevel = LanguageLevel.values()[languageLevel.ordinal() + 1];
|
||||
Set<String> nextForbiddenApi = getForbiddenApi(nextLanguageLevel);
|
||||
return nextForbiddenApi != null && isForbiddenSignature(signature, nextLanguageLevel, nextForbiddenApi);
|
||||
return nextForbiddenApi != null ? getLastIncompatibleLanguageLevelForSignature(signature, nextLanguageLevel, nextForbiddenApi) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -144,7 +144,7 @@ public class FunctionalInterfaceSuggester {
|
||||
final Project project = element.getProject();
|
||||
final Set<PsiType> types = new HashSet<>();
|
||||
final Processor<PsiMember> consumer = member -> {
|
||||
if (member instanceof PsiClass && !Java15APIUsageInspectionBase.isForbiddenApiUsage(member, PsiUtil.getLanguageLevel(element))) {
|
||||
if (member instanceof PsiClass && Java15APIUsageInspectionBase.getLastIncompatibleLanguageLevel(member, PsiUtil.getLanguageLevel(element)) == null) {
|
||||
if (!JavaResolveUtil.isAccessible(member, null, member.getModifierList(), element, null, null)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ public class JavaCompletionUtil {
|
||||
|
||||
private static boolean shouldMarkRed(@NotNull Object object, @NotNull PsiElement place) {
|
||||
if (!(object instanceof PsiMember)) return false;
|
||||
if (Java15APIUsageInspectionBase.isForbiddenApiUsage((PsiMember)object, PsiUtil.getLanguageLevel(place))) return true;
|
||||
if (Java15APIUsageInspectionBase.getLastIncompatibleLanguageLevel((PsiMember)object, PsiUtil.getLanguageLevel(place)) != null) return true;
|
||||
|
||||
if (object instanceof PsiEnumConstant) {
|
||||
return findConstantsUsedInSwitch(place).contains(CompletionUtil.getOriginalOrSelf((PsiEnumConstant)object));
|
||||
|
||||
+18
-4
@@ -17,6 +17,8 @@ package com.intellij.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -29,13 +31,14 @@ import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author cdr
|
||||
*/
|
||||
public class IncreaseLanguageLevelFix implements IntentionAction {
|
||||
public class IncreaseLanguageLevelFix implements IntentionAction, LocalQuickFix {
|
||||
private static final Logger LOG = Logger.getInstance("#" + IncreaseLanguageLevelFix.class.getName());
|
||||
|
||||
private final LanguageLevel myLevel;
|
||||
@@ -50,12 +53,25 @@ public class IncreaseLanguageLevelFix implements IntentionAction {
|
||||
return CodeInsightBundle.message("set.language.level.to.0", myLevel.getPresentableText());
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return CodeInsightBundle.message("set.language.level");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getPsiElement();
|
||||
invoke(project, null, element.getContainingFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
|
||||
final VirtualFile virtualFile = file.getVirtualFile();
|
||||
@@ -67,9 +83,7 @@ public class IncreaseLanguageLevelFix implements IntentionAction {
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
|
||||
final VirtualFile virtualFile = file.getVirtualFile();
|
||||
LOG.assertTrue(virtualFile != null);
|
||||
final Module module = ModuleUtilCore.findModuleForFile(virtualFile, project);
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(file);
|
||||
if (module == null) return;
|
||||
|
||||
JavaProjectModelModificationService.getInstance(project).changeLanguageLevel(module, myLevel);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<file>Test.java</file>
|
||||
<line>4</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Usages of API documented as @since 1.5 (1.6|1.7)</problem_class>
|
||||
<description>Usage of API documented as @since 1.7+</description>
|
||||
<description>Usage of API documented as @since 1.8+</description>
|
||||
</problem>
|
||||
|
||||
</problems>
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class Java15FormInspection extends BaseFormInspection {
|
||||
final PsiMethod getter = PropertyUtil.findPropertyGetter(aClass, prop.getName(), false, true);
|
||||
if (getter == null) continue;
|
||||
final LanguageLevel languageLevel = LanguageLevelUtil.getEffectiveLanguageLevel(module);
|
||||
if (Java15APIUsageInspection.isForbiddenApiUsage(getter, languageLevel)) {
|
||||
if (Java15APIUsageInspection.getLastIncompatibleLanguageLevel(getter, languageLevel) != null) {
|
||||
registerError(component, collector, prop, "@since " + Java15APIUsageInspection.getShortName(languageLevel));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user