mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[preview] IDEA-259969 Reflective preview APIs are incorrectly reported as errors
This patch extracts PreviewFeatureVisitorBase to the top level class. In the visitor there used to be a special case for the new expression in order to reduce the number of warnings/errors, but it appeared to be useless, since the logic to deduce the preview feature element is too complicated. We might need to circle back to it if users complain about the number of warnings in their code. GitOrigin-RevId: 3355caedc7eae3de197f652cc6af7ae605f64971
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9b63667d37
commit
fd24430a7d
-163
@@ -9,8 +9,6 @@ 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;
|
||||
@@ -53,9 +51,6 @@ 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
|
||||
@@ -1994,164 +1989,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
return HighlightUtil.checkFeature(element, feature, myLanguageLevel, myFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
// 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.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.intellij.codeInspection.util.InspectionMessage;
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* This is the base visitor that checks if an element belongs to the preview feature API.
|
||||
*/
|
||||
public abstract class PreviewFeatureVisitorBase extends JavaElementVisitor {
|
||||
|
||||
@Override
|
||||
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
|
||||
final PsiElement resolved = reference.resolve();
|
||||
|
||||
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 (!(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 PsiClass) {
|
||||
final PsiClass psiClass = (PsiClass)member;
|
||||
name = Objects.requireNonNullElseGet(psiClass.getQualifiedName(), () -> reference.getQualifiedName());
|
||||
}
|
||||
else 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();
|
||||
|
||||
final Supplier<PsiClass> containingClass = () -> element instanceof PsiMember ? ((PsiMember)element).getContainingClass() : null;
|
||||
final Supplier<PsiJavaModule> javaModule = () -> element instanceof PsiJavaModule ? null : JavaModuleGraphUtil.findDescriptorByElement(element);
|
||||
|
||||
return Optional.ofNullable(element.getAnnotation(JDK_INTERNAL_JAVAC_PREVIEW_FEATURE))
|
||||
.or(() -> Optional.ofNullable(element.getAnnotation(JDK_INTERNAL_PREVIEW_FEATURE)))
|
||||
.or(() -> getPreviewFeatureAnnotationOptional(containingClass.get()))
|
||||
.or(() -> getPreviewFeatureAnnotationOptional(javaModule.get()))
|
||||
;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
// 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.codeInsight.daemon.impl.analysis.PreviewFeatureVisitorBase;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
@@ -29,7 +29,7 @@ public class PreviewFeatureInspection extends LocalInspectionTool {
|
||||
return new PreviewFeatureInspectionVisitor(holder);
|
||||
}
|
||||
|
||||
private static final class PreviewFeatureInspectionVisitor extends HighlightVisitorImpl.PreviewFeatureVisitorBase {
|
||||
private static final class PreviewFeatureInspectionVisitor extends PreviewFeatureVisitorBase {
|
||||
|
||||
private final ProblemsHolder myHolder;
|
||||
|
||||
|
||||
+11
-2
@@ -3,12 +3,21 @@ import <error descr="com.mycom.FirstPreviewFeature is a preview API and may be r
|
||||
import <warning descr="com.mycom.FirstPreviewFeatureReflective is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeatureReflective</warning>;
|
||||
|
||||
class Main {
|
||||
public Main(String value) { }
|
||||
{
|
||||
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>;
|
||||
var a = new <error descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">FirstPreviewFeature</error>.Outer.Inner();
|
||||
var b = new <warning descr="com.mycom.FirstPreviewFeatureReflective.Outer.Inner is a preview API and may be removed in a future release"><warning descr="com.mycom.FirstPreviewFeatureReflective.Outer 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>.Outer</warning>.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>;
|
||||
new Main(<error descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">FirstPreviewFeature</error>.KEY);
|
||||
new Main(<warning descr="com.mycom.FirstPreviewFeatureReflective#KEY 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>.KEY</warning>);
|
||||
|
||||
new Main(<error descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">FirstPreviewFeature</error>.KEY + "");
|
||||
new Main(<warning descr="com.mycom.FirstPreviewFeatureReflective#KEY 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>.KEY</warning> + "");
|
||||
|
||||
new Main("" + <error descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">FirstPreviewFeature</error>.KEY);
|
||||
new Main("" + <warning descr="com.mycom.FirstPreviewFeatureReflective#KEY 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>.KEY</warning>);
|
||||
}
|
||||
}
|
||||
+1
@@ -9,4 +9,5 @@ public interface FirstPreviewFeature {
|
||||
}
|
||||
void f();
|
||||
static void g() {}
|
||||
public static final String KEY = "value";
|
||||
}
|
||||
+1
@@ -9,4 +9,5 @@ public interface FirstPreviewFeatureReflective {
|
||||
}
|
||||
void f();
|
||||
static void g() {}
|
||||
public static final String KEY = "value";
|
||||
}
|
||||
+1
@@ -9,4 +9,5 @@ public interface FirstPreviewFeature {
|
||||
}
|
||||
void f();
|
||||
static void g() {}
|
||||
public static final String KEY = "value";
|
||||
}
|
||||
+5
-1
@@ -2,9 +2,13 @@
|
||||
import <warning descr="com.mycom.FirstPreviewFeature is a preview API and may be removed in a future release">com.mycom.FirstPreviewFeature</warning>;
|
||||
|
||||
class Main {
|
||||
public Main(String s) { }
|
||||
{
|
||||
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>;
|
||||
var a = new <warning descr="com.mycom.FirstPreviewFeature.Outer.Inner is a preview API and may be removed in a future release"><warning descr="com.mycom.FirstPreviewFeature.Outer 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>.Outer</warning>.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>;
|
||||
new Main(<warning descr="com.mycom.FirstPreviewFeature#KEY 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>.KEY</warning>);
|
||||
new Main(<warning descr="com.mycom.FirstPreviewFeature#KEY 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>.KEY</warning> + "");
|
||||
new Main("" + <warning descr="com.mycom.FirstPreviewFeature#KEY 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>.KEY</warning>);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,16 @@
|
||||
<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.
|
||||
Reports usages of the Preview Feature API. The Preview Feature API is a set of elements that are annotated with <code>@PreviewFeature</code>.
|
||||
<p>
|
||||
A preview feature is a new feature of the Java language, Java Virtual Machine, or Java SE API that is fully specified, fully implemented,
|
||||
and yet impermanent. The notion of a preview feature is defined in <a href="https://openjdk.java.net/jeps/12">JEP 12</a>.
|
||||
</p>
|
||||
<p>
|
||||
If a code depends on a preview feature it might stop compiling in the future JDK versions if the feature get no positive feedback and,
|
||||
hence, it either gets removed or changed.
|
||||
</p>
|
||||
<!-- tooltip end -->
|
||||
<p>It's enabled only if the language level of the current project is a preview one.</p>
|
||||
<p><small>New in 2021.1</small></p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user