[jvm] Code and documentation improvements to Java API inspection

GitOrigin-RevId: 752f3ac5b9bea956323585f75327149582dfbf3f
This commit is contained in:
Bart van Helvert
2022-08-22 15:14:26 +00:00
committed by intellij-monorepo-bot
parent 33341ece35
commit afd09dde1c
2 changed files with 20 additions and 16 deletions
@@ -88,6 +88,10 @@ public class LanguageLevelUtil {
return ourPresentableShortMessage.get(languageLevel);
}
/**
* For performance reasons the forbidden API is pre-generated.
* @see com.intellij.codeInspection.tests.JavaApiUsageGenerator
*/
@Nullable
private static Set<String> getForbiddenApi(@NotNull LanguageLevel languageLevel) {
if (!ourPresentableShortMessage.containsKey(languageLevel)) return null;
@@ -110,7 +114,8 @@ public class LanguageLevelUtil {
/**
* @param member The {@link PsiMember} to get the language level from
* @param languageLevel The effective language level
* @return The last compatible language level for a {@link PsiMember} as annotated by the @since javadoc
* @return The last incompatible language level for a {@link PsiMember} as annotated by the @since javadoc or null if it is unknown.
* For example, if a method is annotated as @since 9 this method will return {@link LanguageLevel#JDK_1_8}.
*/
public static @Nullable LanguageLevel getLastIncompatibleLanguageLevel(@NotNull PsiMember member, @NotNull LanguageLevel languageLevel) {
if (member instanceof PsiAnonymousClass) return null;
@@ -161,13 +161,12 @@ class JavaApiUsageInspection : AbstractBaseUastLocalInspectionTool() {
val sourcePsi = method.sourcePsi ?: return
val module = ModuleUtilCore.findModuleForPsiElement(sourcePsi) ?: return
val languageLevel = getEffectiveLanguageLevel(module)
val sinceLanguageLevel = overriddenMethods.mapNotNull { overriddenMethod ->
val lastIncompatibleLevel = overriddenMethods.mapNotNull { overriddenMethod ->
LanguageLevelUtil.getLastIncompatibleLanguageLevel(overriddenMethod, languageLevel)
}.minOrNull() ?: return
val toHighlight = overrideAnnotation?.uastAnchor?.sourcePsi ?: method.uastAnchor?.sourcePsi ?: return
val jdkVersion = JavaVersionService.getInstance().getJavaSdkVersion(sourcePsi) ?: return
if (checkSdkLevel(sinceLanguageLevel, jdkVersion)) return
registerError(toHighlight, sinceLanguageLevel, holder, isOnTheFly)
if (shouldReportSinceLevelForElement(lastIncompatibleLevel, sourcePsi) == true) return
registerError(toHighlight, lastIncompatibleLevel, holder, isOnTheFly)
}
}
@@ -179,10 +178,9 @@ class JavaApiUsageInspection : AbstractBaseUastLocalInspectionTool() {
val sourcePsi = sourceNode.sourcePsi ?: return
val module = ModuleUtilCore.findModuleForPsiElement(sourcePsi) ?: return
val languageLevel = getEffectiveLanguageLevel(module)
val sinceLanguageLevel = LanguageLevelUtil.getLastIncompatibleLanguageLevel(constructor, languageLevel) ?: return
val jdkVersion = JavaVersionService.getInstance().getJavaSdkVersion(sourcePsi) ?: return
if (checkSdkLevel(sinceLanguageLevel, jdkVersion)) return
registerError(sourcePsi, sinceLanguageLevel, holder, isOnTheFly)
val lastIncompatibleLevel = LanguageLevelUtil.getLastIncompatibleLanguageLevel(constructor, languageLevel) ?: return
if (shouldReportSinceLevelForElement(lastIncompatibleLevel, sourcePsi) == true) return
registerError(sourcePsi, lastIncompatibleLevel, holder, isOnTheFly)
}
override fun processReference(sourceNode: UElement, target: PsiModifierListOwner, qualifier: UExpression?) {
@@ -190,10 +188,9 @@ class JavaApiUsageInspection : AbstractBaseUastLocalInspectionTool() {
if (target !is PsiMember) return
val module = ModuleUtilCore.findModuleForPsiElement(sourcePsi) ?: return
val languageLevel = getEffectiveLanguageLevel(module)
val sinceLanguageLevel = LanguageLevelUtil.getLastIncompatibleLanguageLevel(target, languageLevel)
if (sinceLanguageLevel != null) {
val jdkVersion = JavaVersionService.getInstance().getJavaSdkVersion(sourcePsi) ?: return
if (checkSdkLevel(sinceLanguageLevel, jdkVersion)) return
val lastIncompatibleLevel = LanguageLevelUtil.getLastIncompatibleLanguageLevel(target, languageLevel)
if (lastIncompatibleLevel != null) {
if (shouldReportSinceLevelForElement(lastIncompatibleLevel, sourcePsi) == true) return
val psiClass = if (qualifier != null) {
PsiUtil.resolveClassInType(qualifier.getExpressionType())
}
@@ -206,7 +203,7 @@ class JavaApiUsageInspection : AbstractBaseUastLocalInspectionTool() {
if (isIgnored(superClass)) return
}
}
registerError(sourcePsi, sinceLanguageLevel, holder, isOnTheFly)
registerError(sourcePsi, lastIncompatibleLevel, holder, isOnTheFly)
}
else if (target is PsiClass && !languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
for (generifiedClass in generifiedClasses) {
@@ -240,8 +237,10 @@ class JavaApiUsageInspection : AbstractBaseUastLocalInspectionTool() {
}
/** Only runs in production because tests have incorrect SDKs when no mock SDK is available. */
private fun checkSdkLevel(sinceLanguageLevel: LanguageLevel, jdkVersion: JavaSdkVersion) =
sinceLanguageLevel.isAtLeast(jdkVersion.maxLanguageLevel) && !ApplicationManager.getApplication().isUnitTestMode
private fun shouldReportSinceLevelForElement(lastIncompatibleLevel: LanguageLevel, context: PsiElement): Boolean? {
val jdkVersion = JavaVersionService.getInstance().getJavaSdkVersion(context) ?: return null
return lastIncompatibleLevel.isAtLeast(jdkVersion.maxLanguageLevel) && !ApplicationManager.getApplication().isUnitTestMode
}
private fun registerError(reference: PsiElement, sinceLanguageLevel: LanguageLevel, holder: ProblemsHolder, isOnTheFly: Boolean) {
val targetLanguageLevel = LanguageLevelUtil.getNextLanguageLevel(sinceLanguageLevel) ?: run {