mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 13:31:28 +07:00
[preview] IDEA-259969 Reflective preview APIs are incorrectly reported as errors
This patch adds the PreviewFeatureInspection inspection that is enabled only when the language level of the project is a preview one. It allows to register warnings and suppress all the preview warnings as it's done in javac. When the language level of the project is not a preview one, HighlightVisitorImpl runs the same visitor that can report errors instead of warnings. It cannot be suppressed. A PSI element is considered a preview feature when either: - it is annotated with PreviewFeature directly - one of its enclosing classes is annotated with PreviewFeature - its module is annotated with PreviewFeature It's worth mentioning that when a package in package-info.java is annotated with PreviewFeature this flag doesn't get to be propagated to the classes that are inside the package. Signed-off-by: Nikita Eshkeev <nikita.eshkeev@jetbrains.com> GitOrigin-RevId: 5bd22ea2e18ba83303156a2b9665bc54622f6344
This commit is contained in:
committed by
intellij-monorepo-bot
parent
aac9fd51e8
commit
735d4f05c1
@@ -3405,13 +3405,23 @@ public final class HighlightUtil {
|
||||
return feature.level;
|
||||
}
|
||||
|
||||
static HighlightInfo checkFeature(@NotNull PsiElement element,
|
||||
@NotNull HighlightingFeature feature,
|
||||
@NotNull LanguageLevel level,
|
||||
@NotNull PsiFile file) {
|
||||
public static HighlightInfo checkFeature(@NotNull PsiElement element,
|
||||
@NotNull HighlightingFeature feature,
|
||||
@NotNull LanguageLevel level,
|
||||
@NotNull PsiFile file) {
|
||||
return checkFeature(element, feature, level, file, null, HighlightInfoType.ERROR);
|
||||
}
|
||||
|
||||
public static HighlightInfo checkFeature(@NotNull PsiElement element,
|
||||
@NotNull HighlightingFeature feature,
|
||||
@NotNull LanguageLevel level,
|
||||
@NotNull PsiFile file,
|
||||
@Nullable @NlsContexts.DetailedDescription String message,
|
||||
@NotNull HighlightInfoType highlightInfoType
|
||||
) {
|
||||
if (file.getManager().isInProject(file) && !feature.isSufficient(level)) {
|
||||
String message = getUnsupportedFeatureMessage(feature, level, file);
|
||||
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create();
|
||||
message = Objects.requireNonNullElse(message, getUnsupportedFeatureMessage(feature, level, file));
|
||||
HighlightInfo info = HighlightInfo.newHighlightInfo(highlightInfoType).range(element).descriptionAndTooltip(message).create();
|
||||
if (info != null) {
|
||||
registerIncreaseLanguageLevelFixes(file, feature, new QuickFixActionRegistrarImpl(info));
|
||||
}
|
||||
@@ -3469,4 +3479,4 @@ public final class HighlightUtil {
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
package com.intellij.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.daemon.JavaErrorBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.*;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.AdjustFunctionContextFix;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.codeInspection.util.InspectionMessage;
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.lang.jvm.JvmModifier;
|
||||
import com.intellij.lang.jvm.JvmModifiersOwner;
|
||||
@@ -42,8 +45,6 @@ import com.intellij.refactoring.util.RefactoringChangeUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.MostlySingularMultiMap;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -51,6 +52,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.intellij.codeInsight.daemon.impl.analysis.HighlightingFeature.JDK_INTERNAL_JAVAC_PREVIEW_FEATURE;
|
||||
import static com.intellij.codeInsight.daemon.impl.analysis.HighlightingFeature.JDK_INTERNAL_PREVIEW_FEATURE;
|
||||
|
||||
public class HighlightVisitorImpl extends JavaElementVisitor implements HighlightVisitor {
|
||||
private HighlightInfoHolder myHolder;
|
||||
private RefCountHolder myRefCountHolder; // can be null during partial file update
|
||||
@@ -60,7 +64,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
private PsiFile myFile;
|
||||
private PsiJavaModule myJavaModule;
|
||||
|
||||
private PreviewFeatureVisitor myPreviewFeatureVisitor;
|
||||
private PsiElementVisitor myPreviewFeatureVisitor;
|
||||
|
||||
// map codeBlock->List of PsiReferenceExpression of uninitialized final variables
|
||||
private final Map<PsiElement, Collection<PsiReferenceExpression>> myUninitializedVarProblems = new HashMap<>();
|
||||
@@ -253,7 +257,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
myJavaSdkVersion = ObjectUtils
|
||||
.notNull(JavaVersionService.getInstance().getJavaSdkVersion(file), JavaSdkVersion.fromLanguageLevel(myLanguageLevel));
|
||||
myJavaModule = myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_9) ? JavaModuleGraphUtil.findDescriptorByElement(file) : null;
|
||||
myPreviewFeatureVisitor = new PreviewFeatureVisitor(myLanguageLevel, myHolder);
|
||||
myPreviewFeatureVisitor = myLanguageLevel.isPreview() ? EMPTY_VISITOR : new PreviewFeatureVisitor(myLanguageLevel, myHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1988,7 +1992,165 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
return HighlightUtil.checkFeature(element, feature, myLanguageLevel, myFile);
|
||||
}
|
||||
|
||||
private class PreviewFeatureVisitor extends JavaElementVisitor {
|
||||
/**
|
||||
* This is the base visitor that checks if an element belongs to the preview feature API.
|
||||
*/
|
||||
public static abstract class PreviewFeatureVisitorBase extends JavaElementVisitor {
|
||||
|
||||
@Override
|
||||
public void visitNewExpression(PsiNewExpression expression) {
|
||||
final PsiJavaCodeReferenceElement reference = expression.getClassOrAnonymousClassReference();
|
||||
if (reference == null) return;
|
||||
|
||||
final PsiModifierListOwner owner = getTargetOfNewExpression(expression);
|
||||
|
||||
checkPreviewFeature(expression, reference, owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
|
||||
final PsiElement resolved = reference.resolve();
|
||||
|
||||
if (PsiTreeUtil.getParentOfType(reference, PsiNewExpression.class) != null) return;
|
||||
if (!(resolved instanceof PsiModifierListOwner)) return;
|
||||
|
||||
final PsiModifierListOwner owner = (PsiModifierListOwner)resolved;
|
||||
|
||||
checkPreviewFeature(reference, reference, owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
final PsiElement resolved = expression.resolve();
|
||||
|
||||
if (PsiTreeUtil.getParentOfType(expression, PsiNewExpression.class) != null) return;
|
||||
if (!(resolved instanceof PsiModifierListOwner)) return;
|
||||
final PsiModifierListOwner owner = (PsiModifierListOwner)resolved;
|
||||
|
||||
checkPreviewFeature(expression, expression, owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitModuleStatement(PsiStatement statement) {
|
||||
if (statement instanceof PsiRequiresStatement) {
|
||||
final PsiRequiresStatement requiresStatement = (PsiRequiresStatement)statement;
|
||||
final PsiJavaModule module = requiresStatement.resolve();
|
||||
if (module == null) return;
|
||||
|
||||
final PsiAnnotation annotation = getPreviewFeatureAnnotation(module);
|
||||
final HighlightingFeature feature = HighlightingFeature.fromPreviewFeatureAnnotation(annotation);
|
||||
if (feature == null) return;
|
||||
|
||||
final String description = JavaBundle.message("inspection.preview.feature.0.is.preview.api.message", module.getName());
|
||||
registerProblem(requiresStatement.getReferenceElement(), description, feature, annotation);
|
||||
}
|
||||
else if (statement instanceof PsiProvidesStatement) {
|
||||
final PsiProvidesStatement providesStatement = (PsiProvidesStatement)statement;
|
||||
final PsiReferenceList list = providesStatement.getImplementationList();
|
||||
if (list == null) return;
|
||||
|
||||
for (PsiJavaCodeReferenceElement element : list.getReferenceElements()) {
|
||||
final PsiElement resolved = element.resolve();
|
||||
if (resolved instanceof PsiClass) {
|
||||
final PsiClass psiClass = (PsiClass)resolved;
|
||||
final PsiAnnotation annotation = getPreviewFeatureAnnotation(psiClass);
|
||||
final HighlightingFeature feature = HighlightingFeature.fromPreviewFeatureAnnotation(annotation);
|
||||
if (feature == null) continue;
|
||||
final String description =
|
||||
JavaBundle.message("inspection.preview.feature.0.is.preview.api.message", psiClass.getQualifiedName());
|
||||
registerProblem(element, description, feature, annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Participating source code means that such code can access preview feature api in the same package without warnings.
|
||||
* @param from the callsite a preview feature API is accessed
|
||||
* @param to the preview feature API that is being accessed
|
||||
* @return true if the packages of the callsite and the preview feature element are the same, false otherwise
|
||||
*/
|
||||
private static boolean isParticipating(PsiElement from, PsiElement to) {
|
||||
final PsiPackage fromPackage = JavaResolveUtil.getContainingPackage(from);
|
||||
final PsiPackage toPackage = JavaResolveUtil.getContainingPackage(to);
|
||||
return fromPackage == toPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* The method validates that the language level in the project where an element the context refers to is annotated with
|
||||
* either {@link HighlightingFeature#JDK_INTERNAL_PREVIEW_FEATURE} or
|
||||
* {@link HighlightingFeature#JDK_INTERNAL_JAVAC_PREVIEW_FEATURE} is sufficient.
|
||||
*
|
||||
* @param context
|
||||
* @param reference
|
||||
* @param owner
|
||||
*/
|
||||
private void checkPreviewFeature(PsiElement context, PsiJavaCodeReferenceElement reference, PsiModifierListOwner owner) {
|
||||
final PsiAnnotation annotation = getPreviewFeatureAnnotation(owner);
|
||||
final HighlightingFeature feature = HighlightingFeature.fromPreviewFeatureAnnotation(annotation);
|
||||
if (feature == null) return;
|
||||
if (isParticipating(reference, owner)) return;
|
||||
|
||||
@NotNull final String name;
|
||||
if (owner instanceof PsiMember) {
|
||||
final PsiMember member = (PsiMember)owner;
|
||||
final PsiClass className = member.getContainingClass();
|
||||
final String methodName = member.getName();
|
||||
if (member instanceof PsiMethod && ((PsiMethod)member).isConstructor()) {
|
||||
name = className != null && className.getQualifiedName() != null ? className.getQualifiedName() : reference.getQualifiedName();
|
||||
}
|
||||
else {
|
||||
name = className != null && methodName != null ? className.getQualifiedName() + "#" + methodName : reference.getQualifiedName();
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
name = reference.getQualifiedName();
|
||||
}
|
||||
|
||||
final String description = JavaBundle.message("inspection.preview.feature.0.is.preview.api.message", name);
|
||||
|
||||
registerProblem(context, description, feature, annotation);
|
||||
}
|
||||
|
||||
protected abstract void registerProblem(PsiElement element,
|
||||
@InspectionMessage String description,
|
||||
HighlightingFeature feature,
|
||||
PsiAnnotation annotation);
|
||||
|
||||
private static @Nullable PsiModifierListOwner getTargetOfNewExpression(@NotNull final PsiNewExpression expression) {
|
||||
final PsiMethod method = expression.resolveMethod();
|
||||
if (method != null) return method;
|
||||
|
||||
final PsiJavaCodeReferenceElement reference = expression.getClassOrAnonymousClassReference();
|
||||
if (reference == null) return null;
|
||||
return ObjectUtils.tryCast(reference.resolve(), PsiModifierListOwner.class);
|
||||
}
|
||||
|
||||
private static @Nullable PsiAnnotation getPreviewFeatureAnnotation(@Nullable PsiModifierListOwner owner) {
|
||||
return getPreviewFeatureAnnotationOptional(owner).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method check if the element, its enclosing class(-es) or its jigsaw module is annotated with PreviewFeature.
|
||||
* It doesn't take into account the element's package as per
|
||||
* <a href="https://mail.openjdk.java.net/pipermail/compiler-dev/2021-February/016306.html">the mailing list discussion</a>.
|
||||
* @param element a PSI element to check if it belongs to the preview feature API.
|
||||
* @return the PreviewFeature annotation inside of {@link Optional} that describes the preview feature api the element belongs to, {@link Optional#empty()} otherwise
|
||||
*/
|
||||
private static @NotNull Optional<PsiAnnotation> getPreviewFeatureAnnotationOptional(@Nullable PsiModifierListOwner element) {
|
||||
if (element == null) return Optional.empty();
|
||||
if (element instanceof PsiPackage) return Optional.empty();
|
||||
|
||||
return Optional.ofNullable(element.getAnnotation(JDK_INTERNAL_JAVAC_PREVIEW_FEATURE))
|
||||
.or(() -> Optional.ofNullable(element.getAnnotation(JDK_INTERNAL_PREVIEW_FEATURE)))
|
||||
.or(() -> getPreviewFeatureAnnotationOptional(PsiTreeUtil.getParentOfType(element, PsiClass.class)))
|
||||
.or(() -> getPreviewFeatureAnnotationOptional(element instanceof PsiJavaModule ? null : JavaModuleGraphUtil.findDescriptorByElement(element)))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PreviewFeatureVisitor extends PreviewFeatureVisitorBase {
|
||||
private final LanguageLevel myLanguageLevel;
|
||||
private final HighlightInfoHolder myHolder;
|
||||
|
||||
@@ -1998,176 +2160,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitImportStaticStatement(PsiImportStaticStatement statement) {
|
||||
final PsiClass owner = statement.resolveTargetClass();
|
||||
final HighlightInfo highlightInfo = checkPreviewFeatureElement(statement, owner, myLanguageLevel);
|
||||
protected void registerProblem(PsiElement element, String description, HighlightingFeature feature, PsiAnnotation annotation) {
|
||||
final boolean isReflective = Boolean.TRUE.equals(AnnotationUtil.getBooleanAttributeValue(annotation, "reflective"));
|
||||
|
||||
final HighlightInfoType type = isReflective ? HighlightInfoType.WARNING : HighlightInfoType.ERROR;
|
||||
|
||||
final HighlightInfo highlightInfo = HighlightUtil.checkFeature(element, feature, myLanguageLevel, element.getContainingFile(), description, type);
|
||||
myHolder.add(highlightInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitImportStatement(final PsiImportStatement statement) {
|
||||
final PsiModifierListOwner owner = ObjectUtils.tryCast(statement.resolve(), PsiModifierListOwner.class);
|
||||
final HighlightInfo highlightInfo = checkPreviewFeatureElement(statement, owner, myLanguageLevel);
|
||||
myHolder.add(highlightInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
|
||||
final HighlightInfo highlightInfo = checkPreviewFeatureElement(expression, expression.resolveMethod(), myLanguageLevel);
|
||||
myHolder.add(highlightInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewExpression(PsiNewExpression expression) {
|
||||
final PsiModifierListOwner owner = getTargetOfNewExpression(expression);
|
||||
|
||||
final HighlightInfo highlightInfo = checkPreviewFeatureElement(expression, owner, myLanguageLevel);
|
||||
myHolder.add(highlightInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
|
||||
super.visitReferenceElement(reference);
|
||||
|
||||
final JavaResolveResult result = resolveOptimised(reference);
|
||||
if (result == null) return;
|
||||
|
||||
final PsiElement resolved = result.getElement();
|
||||
if (!(resolved instanceof PsiModifierListOwner)) return;
|
||||
|
||||
final HighlightInfo highlightInfo = checkPreviewFeatureElement(reference, (PsiModifierListOwner)resolved, myLanguageLevel);
|
||||
myHolder.add(highlightInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
|
||||
final PsiMethod method = getMethod(expression);
|
||||
|
||||
final HighlightInfo highlightInfo = checkPreviewFeatureElement(expression, method, myLanguageLevel);
|
||||
myHolder.add(highlightInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeElement(PsiTypeElement type) {
|
||||
final PsiClass psiClass = PsiTypesUtil.getPsiClass(type.getType());
|
||||
|
||||
final HighlightInfo highlightInfo = checkPreviewFeatureElement(type, psiClass, myLanguageLevel);
|
||||
myHolder.add(highlightInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
final PsiModifierListOwner target = getTargetElement(expression);
|
||||
|
||||
final HighlightInfo highlightInfo = checkPreviewFeatureElement(expression, target, myLanguageLevel);
|
||||
myHolder.add(highlightInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitModuleStatement(PsiStatement statement) {
|
||||
final HighlightInfo highlightInfo = checkModulePreviewFeatureAnnotation(statement, myLanguageLevel);
|
||||
myHolder.add(highlightInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiModifierListOwner getTargetElement(PsiReferenceExpression expression) {
|
||||
final JavaResolveResult[] results = resolveOptimised(expression);
|
||||
if (results == null) return null;
|
||||
|
||||
final JavaResolveResult result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
|
||||
if (result == null) return null;
|
||||
|
||||
final PsiElement resolved = result.getElement();
|
||||
if (!(resolved instanceof PsiModifierListOwner)) return null;
|
||||
|
||||
return (PsiModifierListOwner)resolved;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiMethod getMethod(PsiMethodReferenceExpression expression) {
|
||||
final JavaResolveResult result;
|
||||
try {
|
||||
final JavaResolveResult[] results = expression.multiResolve(true);
|
||||
result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiElement method = result.getElement();
|
||||
if (!(method instanceof PsiMethod)) return null;
|
||||
|
||||
return (PsiMethod)method;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiModifierListOwner getTargetOfNewExpression(@NotNull final PsiNewExpression expression) {
|
||||
final PsiMethod method = expression.resolveMethod();
|
||||
if (method != null) return method;
|
||||
|
||||
final PsiJavaCodeReferenceElement reference = expression.getClassOrAnonymousClassReference();
|
||||
if (reference == null) return null;
|
||||
return ObjectUtils.tryCast(reference.resolve(), PsiModifierListOwner.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method validates that the language level of the project where the context accesses
|
||||
* the owner that is annotated with either {@link HighlightingFeature#JDK_INTERNAL_PREVIEW_FEATURE}
|
||||
* or {@link HighlightingFeature#JDK_INTERNAL_JAVAC_PREVIEW_FEATURE} is sufficient
|
||||
*
|
||||
* @param context the expression to examine
|
||||
* @param level the current language level
|
||||
* @return an instance of HighlightInfo with a quickfix to set the appropriate language level
|
||||
* if the current language level is not sufficient or null
|
||||
*/
|
||||
@Nullable
|
||||
@Contract(value = "null, _, _ -> null; _, null, _ -> null", pure = true)
|
||||
private HighlightInfo checkPreviewFeatureElement(@Nullable final PsiElement context,
|
||||
@Nullable final PsiModifierListOwner owner,
|
||||
@NotNull final LanguageLevel level) {
|
||||
if (context == null) return null;
|
||||
if (owner == null) return null;
|
||||
|
||||
final PsiAnnotation annotation = HighlightingFeature.getPreviewFeatureAnnotation(owner);
|
||||
final HighlightingFeature feature = HighlightingFeature.fromPreviewFeatureAnnotation(annotation);
|
||||
if (feature == null) return null;
|
||||
|
||||
return HighlightUtil.checkFeature(context, feature, level, context.getContainingFile());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HighlightInfo checkModulePreviewFeatureAnnotation(@Nullable final PsiStatement statement, @NotNull final LanguageLevel level) {
|
||||
if (statement instanceof PsiRequiresStatement) {
|
||||
final PsiRequiresStatement requiresStatement = (PsiRequiresStatement)statement;
|
||||
final PsiJavaModule module = requiresStatement.resolve();
|
||||
|
||||
return checkPreviewFeatureElement(statement, module, level);
|
||||
}
|
||||
else if (statement instanceof PsiPackageAccessibilityStatement) {
|
||||
final PsiPackageAccessibilityStatement accessibilityStatement = (PsiPackageAccessibilityStatement)statement;
|
||||
final PsiJavaCodeReferenceElement reference = accessibilityStatement.getPackageReference();
|
||||
if (reference == null) return null;
|
||||
|
||||
final PsiElement resolve = reference.resolve();
|
||||
if (!(resolve instanceof PsiPackage)) return null;
|
||||
|
||||
final PsiPackage psiPackage = (PsiPackage)resolve;
|
||||
return checkPreviewFeatureElement(statement, psiPackage, level);
|
||||
}
|
||||
else if (statement instanceof PsiProvidesStatement) {
|
||||
final PsiProvidesStatement providesStatement = (PsiProvidesStatement)statement;
|
||||
final PsiReferenceList list = providesStatement.getImplementationList();
|
||||
if (list == null) return null;
|
||||
|
||||
return StreamEx.of(list.getReferenceElements())
|
||||
.map(PsiReference::resolve)
|
||||
.select(PsiClass.class)
|
||||
.map(clazz -> checkPreviewFeatureElement(statement, clazz, level))
|
||||
.nonNull()
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1797,6 +1797,11 @@
|
||||
groupKey="group.names.compiler.issues" groupBundle="messages.InspectionsBundle"
|
||||
enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.valuebased.SynchronizeOnValueBasedClassInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" suppressId="preview" shortName="PreviewFeature"
|
||||
key="inspection.preview.feature" bundle="messages.JavaBundle"
|
||||
groupKey="group.names.compiler.issues" groupBundle="messages.InspectionsBundle"
|
||||
enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.preview.PreviewFeatureInspection"/>
|
||||
|
||||
<globalInspection groupPath="Java" language="JAVA" shortName="EmptyMethod" groupKey="group.names.declaration.redundancy" enabledByDefault="true" groupBundle="messages.InspectionsBundle"
|
||||
level="WARNING" implementationClass="com.intellij.codeInspection.emptyMethod.EmptyMethodInspection"
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInspection.preview;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingFeature;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PreviewFeatureInspection extends LocalInspectionTool {
|
||||
|
||||
@Override
|
||||
public @NotNull String getID() {
|
||||
return "preview";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
|
||||
boolean isOnTheFly) {
|
||||
if (!PsiUtil.getLanguageLevel(holder.getFile()).isPreview()) {
|
||||
return PsiElementVisitor.EMPTY_VISITOR;
|
||||
}
|
||||
|
||||
return new PreviewFeatureInspectionVisitor(holder);
|
||||
}
|
||||
|
||||
private static final class PreviewFeatureInspectionVisitor extends HighlightVisitorImpl.PreviewFeatureVisitorBase {
|
||||
|
||||
private final ProblemsHolder myHolder;
|
||||
|
||||
private PreviewFeatureInspectionVisitor(ProblemsHolder holder) {
|
||||
myHolder = holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerProblem(PsiElement element, String description, HighlightingFeature feature, PsiAnnotation annotation) {
|
||||
myHolder.registerProblem(element, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
import jdk.internal.javac.PreviewFeature.Feature;
|
||||
|
||||
class Main {
|
||||
@PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
Main(){}
|
||||
@PreviewFeature(feature=Feature.RECORDS)
|
||||
Main(long i){}
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
Main(String s){}
|
||||
Main(int i){}
|
||||
|
||||
static {
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">new Main()</error>;
|
||||
<error descr="Records are not supported at language level '9'">new Main(42l)</error>;
|
||||
<error descr="Text block literals are not supported at language level '9'">new Main("42")</error>;
|
||||
new Main(42);
|
||||
new <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error>() {
|
||||
public void g(){}
|
||||
};
|
||||
new <error descr="Text block literals are not supported at language level '9'">NotDirectlyAnnotatedConstructor</error>();
|
||||
<error descr="Text block literals are not supported at language level '9'">new DirectlyAnnotatedConstructor()</error>;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
class NotDirectlyAnnotatedConstructor { }
|
||||
|
||||
class DirectlyAnnotatedConstructor {
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
DirectlyAnnotatedConstructor() {}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import jdk.internal.PreviewFeature;
|
||||
import jdk.internal.PreviewFeature.Feature;
|
||||
|
||||
class Main {
|
||||
@PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
Main(){}
|
||||
@PreviewFeature(feature=Feature.RECORDS)
|
||||
Main(long i){}
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
Main(String s){}
|
||||
Main(int i){}
|
||||
|
||||
static {
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">new Main()</error>;
|
||||
<error descr="Records are not supported at language level '9'">new Main(42l)</error>;
|
||||
<error descr="Text block literals are not supported at language level '9'">new Main("42")</error>;
|
||||
new Main(42);
|
||||
new <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error>() {
|
||||
public void g(){}
|
||||
};
|
||||
new <error descr="Text block literals are not supported at language level '9'">NotDirectlyAnnotatedConstructor</error>();
|
||||
<error descr="Text block literals are not supported at language level '9'">new DirectlyAnnotatedConstructor()</error>;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
class NotDirectlyAnnotatedConstructor { }
|
||||
|
||||
class DirectlyAnnotatedConstructor {
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
DirectlyAnnotatedConstructor() {}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
import jdk.internal.javac.PreviewFeature.Feature;
|
||||
import <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error>;
|
||||
|
||||
class Main {
|
||||
static {
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">requirePatternMatching</error>();
|
||||
<error descr="Text block literals are not supported at language level '9'">Main.requireTextBlocks</error>();
|
||||
<error descr="Records are not supported at language level '9'">new Main().requireRecords</error>();
|
||||
final <error descr="Text block literals are not supported at language level '9'">NotDirectlyAnnotatedMethod</error> a = new <error descr="Text block literals are not supported at language level '9'">NotDirectlyAnnotatedMethod</error>();
|
||||
<error descr="Text block literals are not supported at language level '9'">a.f</error>();
|
||||
<error descr="Text block literals are not supported at language level '9'">NotDirectlyAnnotatedMethod</error>.g();
|
||||
}
|
||||
|
||||
@PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
static void requirePatternMatching(){}
|
||||
|
||||
@PreviewFeature(feature=jdk.internal.javac.PreviewFeature.Feature.TEXT_BLOCKS)
|
||||
static void requireTextBlocks(){}
|
||||
|
||||
@jdk.internal.javac.PreviewFeature(feature=jdk.internal.javac.PreviewFeature.Feature.RECORDS)
|
||||
void requireRecords(){}
|
||||
|
||||
}
|
||||
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
class NotDirectlyAnnotatedMethod {
|
||||
void f(){}
|
||||
static void g(){}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import jdk.internal.PreviewFeature;
|
||||
import jdk.internal.PreviewFeature.Feature;
|
||||
import <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error>;
|
||||
|
||||
class Main {
|
||||
static {
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">requirePatternMatching</error>();
|
||||
<error descr="Text block literals are not supported at language level '9'">Main.requireTextBlocks</error>();
|
||||
<error descr="Records are not supported at language level '9'">new Main().requireRecords</error>();
|
||||
final <error descr="Text block literals are not supported at language level '9'">NotDirectlyAnnotatedMethod</error> a = new <error descr="Text block literals are not supported at language level '9'">NotDirectlyAnnotatedMethod</error>();
|
||||
<error descr="Text block literals are not supported at language level '9'">a.f</error>();
|
||||
<error descr="Text block literals are not supported at language level '9'">NotDirectlyAnnotatedMethod</error>.g();
|
||||
}
|
||||
|
||||
@PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
static void requirePatternMatching(){}
|
||||
|
||||
@PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.TEXT_BLOCKS)
|
||||
static void requireTextBlocks(){}
|
||||
|
||||
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS)
|
||||
void requireRecords(){}
|
||||
|
||||
}
|
||||
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
class NotDirectlyAnnotatedMethod {
|
||||
void f(){}
|
||||
static void g(){}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
import jdk.internal.javac.PreviewFeature.Feature;
|
||||
import <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error>;
|
||||
|
||||
class Custom1 implements <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error> {
|
||||
public void g() {}
|
||||
}
|
||||
|
||||
class Custom2 implements <error descr="Patterns in 'instanceof' are not supported at language level '9'">FromPreview</error> {
|
||||
public void g() {}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import jdk.internal.PreviewFeature;
|
||||
import jdk.internal.PreviewFeature.Feature;
|
||||
import <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error>;
|
||||
|
||||
class Custom1 implements <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error> {
|
||||
public void g() {}
|
||||
}
|
||||
|
||||
class Custom2 implements <error descr="Patterns in 'instanceof' are not supported at language level '9'">FromPreview</error> {
|
||||
public void g() {}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
import jdk.internal.javac.PreviewFeature.Feature;
|
||||
|
||||
class Main {
|
||||
@PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
static String instanceOf;
|
||||
@PreviewFeature(feature=Feature.RECORDS)
|
||||
static long records;
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
String textBlocks;
|
||||
int i;
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error> preview;
|
||||
|
||||
static {
|
||||
String s = <error descr="Text block literals are not supported at language level '9'">new Main().textBlocks</error>;
|
||||
String o = <error descr="Patterns in 'instanceof' are not supported at language level '9'">Main.instanceOf</error>;
|
||||
long l = <error descr="Records are not supported at language level '9'">records</error>;
|
||||
int k = new Main().i;
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error> local = null;
|
||||
}
|
||||
void f(<error descr="Text block literals are not supported at language level '9'">NotDirectlyAnnotatedField</error> a) {
|
||||
<error descr="Text block literals are not supported at language level '9'">a.id</error> = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
class NotDirectlyAnnotatedField {
|
||||
int id;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import jdk.internal.PreviewFeature;
|
||||
import jdk.internal.PreviewFeature.Feature;
|
||||
|
||||
class Main {
|
||||
@PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
static String instanceOf;
|
||||
@PreviewFeature(feature=Feature.RECORDS)
|
||||
static long records;
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
String textBlocks;
|
||||
int i;
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error> preview;
|
||||
|
||||
static {
|
||||
String s = <error descr="Text block literals are not supported at language level '9'">new Main().textBlocks</error>;
|
||||
String o = <error descr="Patterns in 'instanceof' are not supported at language level '9'">Main.instanceOf</error>;
|
||||
long l = <error descr="Records are not supported at language level '9'">records</error>;
|
||||
int k = new Main().i;
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error> local = null;
|
||||
}
|
||||
void f(<error descr="Text block literals are not supported at language level '9'">NotDirectlyAnnotatedField</error> a) {
|
||||
<error descr="Text block literals are not supported at language level '9'">a.id</error> = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
class NotDirectlyAnnotatedField {
|
||||
int id;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error>;
|
||||
import static <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error>.f;
|
||||
import static <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error>.*;
|
||||
import static <error descr="Class 'B' is in the default package">B</error>.g;
|
||||
|
||||
class Main {
|
||||
static {
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error>.f();
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">f</error>();
|
||||
<error descr="Text block literals are not supported at language level '9'">B</error>.g();
|
||||
g();
|
||||
}
|
||||
}
|
||||
|
||||
@jdk.internal.javac.PreviewFeature(feature = jdk.internal.javac.PreviewFeature.Feature.TEXT_BLOCKS)
|
||||
class B {
|
||||
static void g() {}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error>;
|
||||
import static <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error>.f;
|
||||
import static <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error>.*;
|
||||
import static <error descr="Class 'B' is in the default package">B</error>.g;
|
||||
|
||||
class Main {
|
||||
static {
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error>.f();
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">f</error>();
|
||||
<error descr="Text block literals are not supported at language level '9'">B</error>.g();
|
||||
g();
|
||||
}
|
||||
}
|
||||
|
||||
@jdk.internal.PreviewFeature(feature = jdk.internal.PreviewFeature.Feature.TEXT_BLOCKS)
|
||||
class B {
|
||||
static void g() {}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error>;
|
||||
|
||||
class Main {
|
||||
static {
|
||||
Runnable r = <error descr="Patterns in 'instanceof' are not supported at language level '9'">FromPreview</error>::f;
|
||||
}
|
||||
void f(<error descr="Patterns in 'instanceof' are not supported at language level '9'">FromPreview</error> fp) {
|
||||
Runnable r = <error descr="Patterns in 'instanceof' are not supported at language level '9'">fp::g</error>;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error>;
|
||||
|
||||
class Main {
|
||||
static {
|
||||
Runnable r = <error descr="Patterns in 'instanceof' are not supported at language level '9'">FromPreview</error>::f;
|
||||
}
|
||||
void f(<error descr="Patterns in 'instanceof' are not supported at language level '9'">FromPreview</error> fp) {
|
||||
Runnable r = <error descr="Patterns in 'instanceof' are not supported at language level '9'">fp::g</error>;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
import jdk.internal.javac.PreviewFeature.Feature;
|
||||
|
||||
class Main {
|
||||
@PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
static class InstanceOf{
|
||||
static void f(){}
|
||||
}
|
||||
@PreviewFeature(feature=Feature.RECORDS)
|
||||
static class Records{
|
||||
static void f(){}
|
||||
}
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
static class TextBlocks{
|
||||
static void f(){}
|
||||
}
|
||||
static class Empty{
|
||||
static void f(){}
|
||||
}
|
||||
|
||||
static {
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">InstanceOf</error>.f();
|
||||
<error descr="Records are not supported at language level '9'">Records</error>.f();
|
||||
<error descr="Text block literals are not supported at language level '9'">TextBlocks</error>.f();
|
||||
Empty.f();
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import jdk.internal.PreviewFeature;
|
||||
import jdk.internal.PreviewFeature.Feature;
|
||||
|
||||
class Main {
|
||||
@PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
static class InstanceOf{
|
||||
static void f(){}
|
||||
}
|
||||
@PreviewFeature(feature=Feature.RECORDS)
|
||||
static class Records{
|
||||
static void f(){}
|
||||
}
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
static class TextBlocks{
|
||||
static void f(){}
|
||||
}
|
||||
static class Empty{
|
||||
static void f(){}
|
||||
}
|
||||
|
||||
static {
|
||||
<error descr="Patterns in 'instanceof' are not supported at language level '9'">InstanceOf</error>.f();
|
||||
<error descr="Records are not supported at language level '9'">Records</error>.f();
|
||||
<error descr="Text block literals are not supported at language level '9'">TextBlocks</error>.f();
|
||||
Empty.f();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
module consumer {
|
||||
<error descr="Text block literals are not supported at language level '9'">requires producer1;</error>
|
||||
|
||||
provides <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error> with <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.impl.FromPreviewImpl</error>;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
module consumer {
|
||||
<error descr="Text block literals are not supported at language level '9'">requires producer;</error>
|
||||
|
||||
provides <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error> with <error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.impl.FromPreviewImpl</error>;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
import jdk.internal.javac.PreviewFeature.Feature;
|
||||
|
||||
class Main {
|
||||
@PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
class InstanceOf{}
|
||||
@PreviewFeature(feature=Feature.RECORDS)
|
||||
class Records{}
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
class TextBlocks{}
|
||||
class Empty{}
|
||||
|
||||
private void f(<error descr="Patterns in 'instanceof' are not supported at language level '9'">InstanceOf</error> o, Empty e) {}
|
||||
private void f(Empty e, <error descr="Records are not supported at language level '9'">Records</error> r) {}
|
||||
private void f(<error descr="Text block literals are not supported at language level '9'">TextBlocks</error> e, <error descr="Records are not supported at language level '9'">Records</error> r) {}
|
||||
private void f(<error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.jdk.internal.javac.preview.FromPreview</error> p) {}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import jdk.internal.PreviewFeature;
|
||||
import jdk.internal.PreviewFeature.Feature;
|
||||
|
||||
class Main {
|
||||
@PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
class InstanceOf{}
|
||||
@PreviewFeature(feature=Feature.RECORDS)
|
||||
class Records{}
|
||||
@PreviewFeature(feature=Feature.TEXT_BLOCKS)
|
||||
class TextBlocks{}
|
||||
class Empty{}
|
||||
|
||||
private void f(<error descr="Patterns in 'instanceof' are not supported at language level '9'">InstanceOf</error> o, Empty e) {}
|
||||
private void f(Empty e, <error descr="Records are not supported at language level '9'">Records</error> r) {}
|
||||
private void f(<error descr="Text block literals are not supported at language level '9'">TextBlocks</error> e, <error descr="Records are not supported at language level '9'">Records</error> r) {}
|
||||
private void f(<error descr="Patterns in 'instanceof' are not supported at language level '9'">org.myorg.preview.FromPreview</error> p) {}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
import <error descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeature</error>;
|
||||
import <warning descr="com.mycom.FirstPreviewFeatureReflective is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeatureReflective</warning>;
|
||||
|
||||
class Main {
|
||||
{
|
||||
var a = <error descr="com.mycom.FirstPreviewFeature.Outer#Inner is a preview API and may be removed in a future release">new FirstPreviewFeature.Outer.Inner()</error>;
|
||||
var b = <warning descr="com.mycom.FirstPreviewFeatureReflective.Outer#Inner is a preview API and may be removed in a future release">new FirstPreviewFeatureReflective.Outer.Inner()</warning>;
|
||||
<error descr="com.mycom.FirstPreviewFeature.Outer.Inner#z is a preview API and may be removed in a future release">a.z</error>();
|
||||
<warning descr="com.mycom.FirstPreviewFeatureReflective.Outer.Inner#z is a preview API and may be removed in a future release">b.z</warning>();
|
||||
Runnable r1 = <error descr="com.mycom.FirstPreviewFeature.Outer.Inner#z is a preview API and may be removed in a future release">a::z</error>;
|
||||
Runnable r2 = <warning descr="com.mycom.FirstPreviewFeatureReflective.Outer.Inner#z is a preview API and may be removed in a future release">b::z</warning>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
import <error descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeature</error>;
|
||||
import <warning descr="com.mycom.FirstPreviewFeatureReflective is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeatureReflective</warning>;
|
||||
|
||||
class Main {
|
||||
{
|
||||
<error descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">FirstPreviewFeature</error>.g();
|
||||
Runnable r1 = <error descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">FirstPreviewFeature</error>::g;
|
||||
<warning descr="com.mycom.FirstPreviewFeatureReflective#g is a preview API and may be removed in a future release"><warning descr="com.mycom.FirstPreviewFeatureReflective is a preview API and may be removed in a future release">FirstPreviewFeatureReflective</warning>.g</warning>();
|
||||
Runnable r2 = <warning descr="com.mycom.FirstPreviewFeatureReflective#g is a preview API and may be removed in a future release"><warning descr="com.mycom.FirstPreviewFeatureReflective is a preview API and may be removed in a future release">FirstPreviewFeatureReflective</warning>::g</warning>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
class A implements <error descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeature</error> {
|
||||
public void f() {}
|
||||
|
||||
static class B implements <warning descr="com.mycom.FirstPreviewFeatureReflective is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeatureReflective</warning> {
|
||||
public void f() {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.mycom;
|
||||
|
||||
@jdk.internal.javac.PreviewFeature(feature = jdk.internal.javac.PreviewFeature.Feature.SEALED_CLASSES)
|
||||
public interface FirstPreviewFeature {
|
||||
public static final class Outer {
|
||||
public static final class Inner {
|
||||
public void z() {}
|
||||
}
|
||||
}
|
||||
void f();
|
||||
static void g() {}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.mycom;
|
||||
|
||||
@jdk.internal.javac.PreviewFeature(feature = jdk.internal.javac.PreviewFeature.Feature.SEALED_CLASSES, reflective = true)
|
||||
public interface FirstPreviewFeatureReflective {
|
||||
public static final class Outer {
|
||||
public static final class Inner {
|
||||
public void z() {}
|
||||
}
|
||||
}
|
||||
void f();
|
||||
static void g() {}
|
||||
}
|
||||
@@ -6,22 +6,18 @@ import java.lang.annotation.*;
|
||||
ElementType.CONSTRUCTOR,
|
||||
ElementType.FIELD,
|
||||
ElementType.PACKAGE,
|
||||
ElementType.MODULE,
|
||||
ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface PreviewFeature {
|
||||
/**
|
||||
* Name of the preview feature the annotated API is associated
|
||||
* with.
|
||||
*/
|
||||
public Feature feature();
|
||||
|
||||
public boolean essentialAPI() default false;
|
||||
public boolean reflective() default false;
|
||||
|
||||
public enum Feature {
|
||||
PATTERN_MATCHING_IN_INSTANCEOF,
|
||||
TEXT_BLOCKS,
|
||||
RECORDS,
|
||||
SEALED_CLASSES
|
||||
SEALED_CLASSES,
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.mycom;
|
||||
|
||||
@jdk.internal.PreviewFeature(feature = jdk.internal.PreviewFeature.Feature.SEALED_CLASSES)
|
||||
public interface FirstPreviewFeature {
|
||||
public static final class Outer {
|
||||
public static final class Inner {
|
||||
public void z() {}
|
||||
}
|
||||
}
|
||||
void f();
|
||||
static void g() {}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package org.myorg.jdk.internal.javac.preview;
|
||||
|
||||
public interface FromPreview {
|
||||
static void f() {};
|
||||
void g();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package org.myorg.jdk.internal.javac.preview.impl;
|
||||
|
||||
public class FromPreviewImpl implements FromPreview {
|
||||
void g() {}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
@jdk.internal.javac.PreviewFeature(feature=jdk.internal.javac.PreviewFeature.Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
package org.myorg.jdk.internal.javac.preview.impl;
|
||||
@@ -1,4 +0,0 @@
|
||||
@jdk.internal.PreviewFeature(feature = jdk.internal.PreviewFeature.Feature.TEXT_BLOCKS)
|
||||
module producer1 {
|
||||
exports org.myorg.jdk.internal.javac.preview;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
package org.myorg.jdk.internal.javac.preview;
|
||||
@@ -1,6 +0,0 @@
|
||||
package org.myorg.preview;
|
||||
|
||||
public interface FromPreview {
|
||||
static void f() {};
|
||||
void g();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package org.myorg.preview.impl;
|
||||
|
||||
public class FromPreviewImpl implements FromPreview {
|
||||
void g() {}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
package org.myorg.preview.impl;
|
||||
@@ -1,4 +0,0 @@
|
||||
@jdk.internal.PreviewFeature(feature = jdk.internal.PreviewFeature.Feature.TEXT_BLOCKS)
|
||||
module producer {
|
||||
exports org.myorg.preview;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.PATTERN_MATCHING_IN_INSTANCEOF)
|
||||
package org.myorg.preview;
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
import <warning descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeature</warning>;
|
||||
|
||||
class Main {
|
||||
{
|
||||
var a = <warning descr="com.mycom.FirstPreviewFeature.Outer#Inner is a preview API and may be removed in a future release">new FirstPreviewFeature.Outer.Inner()</warning>;
|
||||
<warning descr="com.mycom.FirstPreviewFeature.Outer.Inner#z is a preview API and may be removed in a future release">a.z</warning>();
|
||||
Runnable r = <warning descr="com.mycom.FirstPreviewFeature.Outer.Inner#z is a preview API and may be removed in a future release">a::z</warning>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
import <warning descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeature</warning>;
|
||||
|
||||
class Main {
|
||||
{
|
||||
<warning descr="com.mycom.FirstPreviewFeature#g is a preview API and may be removed in a future release"><warning descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">FirstPreviewFeature</warning>.g</warning>();
|
||||
Runnable r = <warning descr="com.mycom.FirstPreviewFeature#g is a preview API and may be removed in a future release"><warning descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">FirstPreviewFeature</warning>::g</warning>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
class A implements <warning descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeature</warning> {
|
||||
public void f() {}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
@SuppressWarnings("preview")
|
||||
class Main {
|
||||
{
|
||||
var a = new com.mycom.FirstPreviewFeature.Outer.Inner();
|
||||
a.z();
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.java.codeInsight.daemon.previewfeature;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PreviewFeatureAnnotationTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/previewfeature";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
configureByFiles(BASE_PATH + "/PreviewFeature.java"
|
||||
, BASE_PATH + "/JdkInternalJavacPreviewFeature.java"
|
||||
, BASE_PATH + "/packagepreview/package-info.java"
|
||||
, BASE_PATH + "/packagepreview/FromPreview.java"
|
||||
, BASE_PATH + "/packagepreview/module-info.java"
|
||||
, BASE_PATH + "/jdk.internal.javac.packagepreview/package-info.java"
|
||||
, BASE_PATH + "/jdk.internal.javac.packagepreview/FromPreview.java"
|
||||
, BASE_PATH + "/jdk.internal.javac.packagepreview/module-info.java"
|
||||
, BASE_PATH + "/packagepreview/impl/package-info.java"
|
||||
, BASE_PATH + "/packagepreview/impl/FromPreviewImpl.java"
|
||||
, BASE_PATH + "/jdk.internal.javac.packagepreview/impl/package-info.java"
|
||||
, BASE_PATH + "/jdk.internal.javac.packagepreview/impl/FromPreviewImpl.java");
|
||||
}
|
||||
|
||||
private void configureByFiles(String... files) {
|
||||
for (String file : files) {
|
||||
myFixture.configureByFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
|
||||
return JAVA_9;
|
||||
}
|
||||
|
||||
public void testCallMethodsWithPreviewFeature() { doTest(); }
|
||||
public void testCallConstructorWithPreviewFeature() { doTest(); }
|
||||
public void testTypeWithPreviewFeature() { doTest(); }
|
||||
public void testFieldsWithPreviewFeature() { doTest(); }
|
||||
public void testImportWithPreviewFeature() { doTest(); }
|
||||
public void testReferenceWithPreviewFeature() { doTest(); }
|
||||
public void testRequiresModuleWithPreviewFeature() { doTest(); }
|
||||
public void testMethodReferenceWithPreviewFeature() { doTest(); }
|
||||
public void testClassImplementsWithPreviewFeature() { doTest(); }
|
||||
|
||||
public void testCallMethodsWithJdkInternalJavacPreviewFeature() { doTest(); }
|
||||
public void testCallConstructorWithJdkInternalJavacPreviewFeature() { doTest(); }
|
||||
public void testReferenceWithJdkInternalJavacPreviewFeature() { doTest(); }
|
||||
public void testTypeWithJdkInternalJavacPreviewFeature() { doTest(); }
|
||||
public void testFieldsWithJdkInternalJavacPreviewFeature() { doTest(); }
|
||||
public void testImportWithJdkInternalJavacPreviewFeature() { doTest(); }
|
||||
public void testRequiresModuleWithJdkInternalJavacPreviewFeature() { doTest(); }
|
||||
public void testMethodReferenceWithJdkInternalJavacPreviewFeature() { doTest(); }
|
||||
public void testClassImplementsWithJdkInternalJavacPreviewFeature() { doTest(); }
|
||||
|
||||
private void doTest() {
|
||||
String filePath = BASE_PATH + "/" + getTestName(false) + ".java";
|
||||
configureByFiles(filePath);
|
||||
myFixture.checkHighlighting();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.java.codeInsight.daemon.previewfeature;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.preview.PreviewFeatureInspection;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class PreviewFeatureErrorsTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/previewfeature/errors";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFixture.enableInspections(PreviewFeatureInspection.class);
|
||||
myFixture.configureByFiles(
|
||||
BASE_PATH + "/../java.base/jdk.internal.javac/PreviewFeature.java",
|
||||
BASE_PATH + "/../java.base/jdk.internal.javac/FirstPreviewFeature.java",
|
||||
BASE_PATH + "/../java.base/jdk.internal.javac/FirstPreviewFeatureReflective.java"
|
||||
);
|
||||
}
|
||||
|
||||
public void testImplementsPreviewFeature() { doTest(); }
|
||||
public void testAccessInnerClassInsidePreviewFeatureClass() { doTest(); }
|
||||
public void testAccessStaticMethodInPreviewFeatureClass() { doTest(); }
|
||||
|
||||
@Override
|
||||
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
|
||||
return new ProjectDescriptor(LanguageLevel.JDK_15);
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
String filePath = BASE_PATH + "/" + getTestName(false) + ".java";
|
||||
myFixture.configureByFile(filePath);
|
||||
myFixture.checkHighlighting();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.java.codeInsight.daemon.previewfeature;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.preview.PreviewFeatureInspection;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class PreviewFeatureWarningsTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/previewfeature/warnings";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFixture.enableInspections(PreviewFeatureInspection.class);
|
||||
myFixture.configureByFiles(
|
||||
BASE_PATH + "/../java.base/jdk.internal/PreviewFeature.java",
|
||||
BASE_PATH + "/../java.base/jdk.internal/FirstPreviewFeature.java"
|
||||
);
|
||||
}
|
||||
|
||||
public void testImplementsPreviewFeature() { doTest(); }
|
||||
public void testAccessInnerClassInsidePreviewFeatureClass() { doTest(); }
|
||||
public void testAccessStaticMethodInPreviewFeatureClass() { doTest(); }
|
||||
public void testSuppressPreviewFeatureWarning() { doTest(); }
|
||||
|
||||
@Override
|
||||
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
|
||||
return new ProjectDescriptor(LanguageLevel.JDK_16_PREVIEW);
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
String filePath = BASE_PATH + "/" + getTestName(false) + ".java";
|
||||
myFixture.configureByFile(filePath);
|
||||
myFixture.checkHighlighting();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath();
|
||||
}
|
||||
}
|
||||
@@ -739,6 +739,7 @@ inspection.unused.symbol.check.localvars=Local variables
|
||||
inspection.unused.symbol.check.methods=Methods:
|
||||
inspection.unused.symbol.check.parameters=Parameters in
|
||||
inspection.value.based.warnings=Value-based warnings
|
||||
inspection.preview.feature=Preview Feature warning
|
||||
inspection.value.based.warnings.synchronization=Attempt to synchronize on an instance of a value-based class
|
||||
inspection.variable.assigned.to.itself.display.name=Variable is assigned to itself
|
||||
inspection.wrapper.type.may.be.primitive.fix.name=Convert wrapper type to primitive
|
||||
@@ -1511,7 +1512,7 @@ separator.mark.as.entry.point.if.annotated.by=Mark as entry point if annotated b
|
||||
separator.mark.field.as.implicitly.written.if.annotated.by=Mark field as implicitly written if annotated by
|
||||
rename.super.methods.chooser.popup.title={0} has super methods
|
||||
rename.super.base.chooser.popup.title={0}{1, choice, 0# implements|1# overrides} method of {2}
|
||||
add.methods.dialog.or=\ or
|
||||
add.methods.dialog.or=\ or
|
||||
command.name.delegate.detected.change=Delegate
|
||||
encapsulate.fields.dialog.javadoc.title=Javadoc
|
||||
find.jar.hint.text.no.libraries.found.for.fqn=No libraries found for ''{0}''
|
||||
@@ -1582,3 +1583,4 @@ press.to.navigate=Press {0} to navigate
|
||||
label.jvm.method.name=JVM method name
|
||||
link.configure.classes.excluded.from.completion=Configure classes excluded from completion
|
||||
exception.navigation.fetching.target.position=Fetching target position
|
||||
inspection.preview.feature.0.is.preview.api.message={0} is a preview API and may be removed in a future release
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
The inspection detects usage of Preview Feature API. It's enabled only if the language level of the current project is a preview one.
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user