[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:
Nikita Eshkeev
2021-02-11 02:16:09 +03:00
committed by intellij-monorepo-bot
parent aac9fd51e8
commit 735d4f05c1
49 changed files with 443 additions and 662 deletions

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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"

View File

@@ -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);
}
}
}

View File

@@ -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() {}
}

View File

@@ -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() {}
}

View File

@@ -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(){}
}

View File

@@ -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(){}
}

View File

@@ -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() {}
}

View File

@@ -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() {}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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() {}
}

View File

@@ -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() {}
}

View File

@@ -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>;
}
}

View File

@@ -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>;
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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>;
}

View File

@@ -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>;
}

View File

@@ -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) {}
}

View File

@@ -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) {}
}

View File

@@ -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>;
}
}

View File

@@ -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>;
}
}

View File

@@ -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() {}
}
}

View File

@@ -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() {}
}

View File

@@ -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() {}
}

View File

@@ -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,
;
}
}

View File

@@ -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() {}
}

View File

@@ -1,6 +0,0 @@
package org.myorg.jdk.internal.javac.preview;
public interface FromPreview {
static void f() {};
void g();
}

View File

@@ -1,5 +0,0 @@
package org.myorg.jdk.internal.javac.preview.impl;
public class FromPreviewImpl implements FromPreview {
void g() {}
}

View File

@@ -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;

View File

@@ -1,4 +0,0 @@
@jdk.internal.PreviewFeature(feature = jdk.internal.PreviewFeature.Feature.TEXT_BLOCKS)
module producer1 {
exports org.myorg.jdk.internal.javac.preview;
}

View File

@@ -1,2 +0,0 @@
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.PATTERN_MATCHING_IN_INSTANCEOF)
package org.myorg.jdk.internal.javac.preview;

View File

@@ -1,6 +0,0 @@
package org.myorg.preview;
public interface FromPreview {
static void f() {};
void g();
}

View File

@@ -1,5 +0,0 @@
package org.myorg.preview.impl;
public class FromPreviewImpl implements FromPreview {
void g() {}
}

View File

@@ -1,2 +0,0 @@
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.PATTERN_MATCHING_IN_INSTANCEOF)
package org.myorg.preview.impl;

View File

@@ -1,4 +0,0 @@
@jdk.internal.PreviewFeature(feature = jdk.internal.PreviewFeature.Feature.TEXT_BLOCKS)
module producer {
exports org.myorg.preview;
}

View File

@@ -1,2 +0,0 @@
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.PATTERN_MATCHING_IN_INSTANCEOF)
package org.myorg.preview;

View File

@@ -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>;
}
}

View File

@@ -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>;
}
}

View File

@@ -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() {}
}

View File

@@ -0,0 +1,8 @@
@SuppressWarnings("preview")
class Main {
{
var a = new com.mycom.FirstPreviewFeature.Outer.Inner();
a.z();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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>