From 6cdf8f6eefa7cd453195e95fc4e0a69f0b1136b2 Mon Sep 17 00:00:00 2001 From: Nikita Eshkeev Date: Wed, 17 Jun 2020 23:48:19 +0300 Subject: [PATCH] [codeInsight] IDEA-238740 Support the jdk.internal.PreviewFeature annotation This patch adds support of the jdk.internal.PreviewFeature annotation Signed-off-by: Nikita Eshkeev GitOrigin-RevId: b2f56d62c3b12475690f667628811e5345b1d1cf --- .../impl/analysis/GenericsHighlightUtil.java | 54 +++++++++++++++++++ .../impl/analysis/HighlightClassUtil.java | 20 +++++++ .../impl/analysis/HighlightMethodUtil.java | 25 ++++++++- .../daemon/impl/analysis/HighlightUtil.java | 32 +++++++++++ .../impl/analysis/HighlightVisitorImpl.java | 8 +++ .../impl/analysis/HighlightingFeature.java | 15 ++++++ .../impl/source/resolve/JavaResolveUtil.java | 5 ++ .../CallConstructorWithPreviewFeature.java | 20 +++++++ .../CallMethodsWithPreviewFeature.java | 20 +++++++ .../FieldsWithPreviewFeature.java | 22 ++++++++ .../ImportWithPreviewFeature.java | 3 ++ .../previewfeature/PreviewFeature.java | 26 +++++++++ .../TypeWithPreviewFeature.java | 17 ++++++ .../packagepreview/FromPreview.java | 3 ++ .../packagepreview/package-info.java | 2 + .../PreviewFeatureAnnotationTest.java | 50 +++++++++++++++++ .../com/intellij/psi/CommonClassNames.java | 2 + 17 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallConstructorWithPreviewFeature.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallMethodsWithPreviewFeature.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/FieldsWithPreviewFeature.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ImportWithPreviewFeature.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/PreviewFeature.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/TypeWithPreviewFeature.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/FromPreview.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/package-info.java create mode 100644 java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/previewfeature/PreviewFeatureAnnotationTest.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index fbb90cdaf9cd..7089cc697eb7 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -7,6 +7,10 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction; import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixActionRegistrarImpl; import com.intellij.codeInsight.intention.QuickFixFactory; +import com.intellij.lang.jvm.JvmEnumField; +import com.intellij.lang.jvm.annotation.JvmAnnotationAttribute; +import com.intellij.lang.jvm.annotation.JvmAnnotationAttributeValue; +import com.intellij.lang.jvm.annotation.JvmAnnotationEnumFieldValue; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.IndexNotReadyException; @@ -22,6 +26,7 @@ import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.impl.PsiClassImplUtil; import com.intellij.psi.impl.PsiImplUtil; +import com.intellij.psi.impl.source.resolve.JavaResolveUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.search.searches.SuperMethodsSearch; @@ -32,12 +37,15 @@ import com.intellij.util.containers.ContainerUtil; import com.siyeh.ig.psiutils.VariableAccessUtils; import gnu.trove.THashMap; import gnu.trove.THashSet; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import static com.intellij.util.ObjectUtils.tryCast; + public class GenericsHighlightUtil { private static final Logger LOG = Logger.getInstance(GenericsHighlightUtil.class); @@ -1548,4 +1556,50 @@ public class GenericsHighlightUtil { } return null; } + + @Nullable + @Contract(value = "null -> null", pure = true) + static HighlightingFeature extractHighlightingFeature(@Nullable final PsiAnnotation annotation) { + if (annotation == null) return null; + if (!CommonClassNames.JDK_INTERNAL_PREVIEW_FEATURE.equals(annotation.getQualifiedName())) return null; + + final JvmAnnotationAttribute feature = annotation.findAttribute("feature"); + if (feature == null) return null; + + final JvmAnnotationAttributeValue attributeValue = feature.getAttributeValue(); + if (attributeValue == null) return null; + + final JvmAnnotationEnumFieldValue annotationEnumFieldValue = tryCast(attributeValue, JvmAnnotationEnumFieldValue.class); + if (annotationEnumFieldValue == null) return null; + + final JvmEnumField field = annotationEnumFieldValue.getField(); + if (field == null) return null; + + return HighlightingFeature.convertFromPreviewFeature(field.getName()); + } + + public static HighlightInfo checkTypePreviewFeatureAnnotation(@NotNull final PsiTypeElement type, + @NotNull final LanguageLevel level) { + final PsiClass clazz = PsiTypesUtil.getPsiClass(type.getType()); + + final PsiAnnotation annotation = getPreviewFeatureAnnotation(clazz); + if (annotation == null) return null; + + final HighlightingFeature feature = extractHighlightingFeature(annotation); + if (feature == null) return null; + + return HighlightUtil.checkFeature(type, feature, level, type.getContainingFile()); + } + + @Nullable + @Contract(value = "null -> null", pure = true) + private static PsiAnnotation getPreviewFeatureAnnotation(@Nullable final PsiClass clazz) { + if (clazz == null) return null; + final PsiAnnotation annotation = clazz.getAnnotation(CommonClassNames.JDK_INTERNAL_PREVIEW_FEATURE); + if (annotation != null) return annotation; + + final PsiPackage psiPackage = JavaResolveUtil.getContainingPackage(clazz); + if (psiPackage == null) return null; + return psiPackage.getAnnotation(CommonClassNames.JDK_INTERNAL_PREVIEW_FEATURE); + } } \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java index e041b05c8217..7af37992e1c8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java @@ -860,6 +860,26 @@ public class HighlightClassUtil { return checkCreateInnerClassFromStaticContext(expression, qualifier, aClass); } + /** + * This method validates that the language level of the project where a new expression accesses + * the constructor that is annotated with {@link CommonClassNames#JDK_INTERNAL_PREVIEW_FEATURE} is sufficient + * + * @param expression 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 + */ + static HighlightInfo checkConstructorPreviewFeature(@NotNull final PsiNewExpression expression, + @NotNull final LanguageLevel level) { + final PsiMethod method = expression.resolveMethod(); + if (method == null) return null; + + final HighlightingFeature feature = GenericsHighlightUtil.extractHighlightingFeature(method.getAnnotation(CommonClassNames.JDK_INTERNAL_PREVIEW_FEATURE)); + if (feature == null) return null; + + return HighlightUtil.checkFeature(expression, feature, level, expression.getContainingFile()); + } + public static HighlightInfo checkCreateInnerClassFromStaticContext(@NotNull PsiElement element, @Nullable PsiExpression qualifier, @Nullable PsiClass aClass) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index 75371eb41cd4..11ea420d1208 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -55,6 +55,8 @@ import java.util.*; import java.util.function.Predicate; import java.util.stream.Stream; +import static com.intellij.util.ObjectUtils.tryCast; + public class HighlightMethodUtil { private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance(); private static final Logger LOG = Logger.getInstance(HighlightMethodUtil.class); @@ -1285,7 +1287,7 @@ public class HighlightMethodUtil { if (!JavaPsiConstructorUtil.isConstructorCall(methodCall)) return null; PsiElement codeBlock = methodCall.getParent().getParent(); if (codeBlock instanceof PsiCodeBlock) { - PsiMethod ctor = ObjectUtils.tryCast(codeBlock.getParent(), PsiMethod.class); + PsiMethod ctor = tryCast(codeBlock.getParent(), PsiMethod.class); if (ctor != null && ctor.isConstructor()) { if (JavaPsiRecordUtil.isCompactConstructor(ctor) || JavaPsiRecordUtil.isExplicitCanonicalConstructor(ctor)) { @@ -1317,6 +1319,27 @@ public class HighlightMethodUtil { return null; } + /** + * This method validates that the language level of the project where a call expression accesses + * the method that is annotated with {@link CommonClassNames#JDK_INTERNAL_PREVIEW_FEATURE} is sufficient + * + * @param methodCallExpression 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 + */ + static HighlightInfo checkMethodCallPreviewFeatureAnnotation(@NotNull final PsiMethodCallExpression methodCallExpression, + @NotNull final LanguageLevel level) { + final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); + final PsiElement targetMethod = methodExpression.resolve(); + if (!(targetMethod instanceof PsiJvmModifiersOwner)) return null; + + final PsiAnnotation annotation = ((PsiJvmModifiersOwner)targetMethod).getAnnotation(CommonClassNames.JDK_INTERNAL_PREVIEW_FEATURE); + final HighlightingFeature feature = GenericsHighlightUtil.extractHighlightingFeature(annotation); + if (feature == null) return null; + + return HighlightUtil.checkFeature(methodCallExpression, feature, level, methodCallExpression.getContainingFile()); + } static HighlightInfo checkConstructorCallsBaseClassConstructor(@NotNull PsiMethod constructor, @Nullable RefCountHolder refCountHolder, diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index e02efb254839..4e0c4382db99 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -1592,6 +1592,38 @@ public class HighlightUtil { return null; } + public static HighlightInfo checkFieldPreviewFeatureAnnotation(@NotNull final PsiReferenceExpression expression, + @NotNull final PsiField field, + @NotNull final LanguageLevel level) { + final HighlightingFeature feature = GenericsHighlightUtil.extractHighlightingFeature(field.getAnnotation(CommonClassNames.JDK_INTERNAL_PREVIEW_FEATURE)); + if (feature == null) return null; + + return checkFeature(expression, feature, level, expression.getContainingFile()); + } + + public static HighlightInfo checkPackagePreviewFeatureAnnotation(@NotNull final PsiImportStatement statement, + @NotNull final LanguageLevel level) { + final PsiElement resolve = statement.resolve(); + final PsiPackage psiPackage; + if (resolve instanceof PsiPackage) { + psiPackage = (PsiPackage)resolve; + } + else if (resolve instanceof PsiClass) { + psiPackage = JavaResolveUtil.getContainingPackage((PsiClass)resolve); + } + else { + return null; + } + + if (psiPackage == null) return null; + + final PsiAnnotation annotation = psiPackage.getAnnotation(CommonClassNames.JDK_INTERNAL_PREVIEW_FEATURE); + final HighlightingFeature feature = GenericsHighlightUtil.extractHighlightingFeature(annotation); + if (feature == null) return null; + + return checkFeature(statement, feature, level, statement.getContainingFile()); + } + private enum SelectorKind { INT, ENUM, STRING } private static SelectorKind getSwitchSelectorKind(@NotNull PsiType type) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index b4a1a2c0905c..70250ad56adc 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -760,6 +760,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) { myHolder.add(HighlightUtil.checkSingleImportClassConflict(statement, mySingleImportedClasses,myFile)); } + if (!myHolder.hasErrorResults()) { + myHolder.add(HighlightUtil.checkPackagePreviewFeatureAnnotation(statement, myLanguageLevel)); + } } @Override @@ -990,6 +993,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkSuperAbstractMethodDirectCall(expression)); if (!myHolder.hasErrorResults()) visitExpression(expression); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodCallPreviewFeatureAnnotation(expression, myLanguageLevel)); } @Override @@ -1081,6 +1085,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) registerConstructorCall(expression); if (!myHolder.hasErrorResults()) visitExpression(expression); + + if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkConstructorPreviewFeature(expression, myLanguageLevel)); } @Override @@ -1399,6 +1405,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults() && resolved instanceof PsiField) { try { myHolder.add(HighlightUtil.checkIllegalForwardReferenceToField(expression, (PsiField)resolved)); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkFieldPreviewFeatureAnnotation(expression, (PsiField)resolved, myLanguageLevel)); } catch (IndexNotReadyException ignored) { } } @@ -1806,6 +1813,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalType(type)); if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type, myLanguageLevel)); if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkWildcardUsage(type)); + if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypePreviewFeatureAnnotation(type, myLanguageLevel)); } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightingFeature.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightingFeature.java index 8f77b73447ed..609132bf1245 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightingFeature.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightingFeature.java @@ -7,6 +7,7 @@ import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.PropertyKey; public enum HighlightingFeature { @@ -89,4 +90,18 @@ public enum HighlightingFeature { LanguageLevel getStandardLevel() { return level.isPreview() ? null : level; } + + @Nullable + public static HighlightingFeature convertFromPreviewFeature(@NotNull final String feature) { + switch (feature) { + case "PATTERN_MATCHING_IN_INSTANCEOF": + return PATTERNS; + case "TEXT_BLOCKS": + return TEXT_BLOCKS; + case "RECORDS": + return RECORDS; + default: + return null; + } + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java index aa114f84b724..412c4b4b514f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java @@ -300,4 +300,9 @@ public class JavaResolveUtil { return PsiResolveHelper.SERVICE.getInstance(project) .resolveConstructor(PsiTypesUtil.getClassType(superClassWhichTheSuperCallMustResolveTo), expressionList, place).getElement(); } + + public static PsiPackage getContainingPackage(@NotNull PsiClass psiClass) { + PsiDirectory directory = psiClass.getContainingFile().getContainingDirectory(); + return directory == null ? null : JavaDirectoryService.getInstance().getPackage(directory); + } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallConstructorWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallConstructorWithPreviewFeature.java new file mode 100644 index 000000000000..2218481f2e98 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallConstructorWithPreviewFeature.java @@ -0,0 +1,20 @@ +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 { + new Main(); + new Main(42l); + new Main("42"); + new Main(42); + } + +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallMethodsWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallMethodsWithPreviewFeature.java new file mode 100644 index 000000000000..f6398c56d47f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallMethodsWithPreviewFeature.java @@ -0,0 +1,20 @@ +import jdk.internal.PreviewFeature; +import jdk.internal.PreviewFeature.Feature; + +class Main { + static { + requirePatternMatching(); + Main.requireTextBlocks(); + new Main().requireRecords(); + } + + @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(){} + +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/FieldsWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/FieldsWithPreviewFeature.java new file mode 100644 index 000000000000..f0900ba2fb3a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/FieldsWithPreviewFeature.java @@ -0,0 +1,22 @@ +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; + org.myorg.preview.FromPreview preview; + + static { + String s = new Main().textBlocks; + String o = Main.instanceOf; + long l = records; + int k = new Main().i; + org.myorg.preview.FromPreview local = null; + } + +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ImportWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ImportWithPreviewFeature.java new file mode 100644 index 000000000000..322aec36102d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ImportWithPreviewFeature.java @@ -0,0 +1,3 @@ +import org.myorg.preview.FromPreview; + +class Main { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/PreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/PreviewFeature.java new file mode 100644 index 000000000000..e1e1ac37ab3a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/PreviewFeature.java @@ -0,0 +1,26 @@ +package jdk.internal; + +import java.lang.annotation.*; + +@Target({ElementType.METHOD, + ElementType.CONSTRUCTOR, + ElementType.FIELD, + ElementType.PACKAGE, + 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 enum Feature { + PATTERN_MATCHING_IN_INSTANCEOF, + TEXT_BLOCKS, + RECORDS, + ; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/TypeWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/TypeWithPreviewFeature.java new file mode 100644 index 000000000000..6077bf3cf6a9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/TypeWithPreviewFeature.java @@ -0,0 +1,17 @@ +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(InstanceOf o, Empty e) {} + private void f(Empty e, Records r) {} + private void f(TextBlocks e, Records r) {} + private void f(org.myorg.preview.FromPreview p) {} +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/FromPreview.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/FromPreview.java new file mode 100644 index 000000000000..23889c67d448 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/FromPreview.java @@ -0,0 +1,3 @@ +package org.myorg.preview; + +public interface FromPreview {} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/package-info.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/package-info.java new file mode 100644 index 000000000000..96aa0cab3435 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/package-info.java @@ -0,0 +1,2 @@ +@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.PATTERN_MATCHING_IN_INSTANCEOF) +package org.myorg.preview; \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/previewfeature/PreviewFeatureAnnotationTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/previewfeature/PreviewFeatureAnnotationTest.java new file mode 100644 index 000000000000..4ac57e48e07f --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/previewfeature/PreviewFeatureAnnotationTest.java @@ -0,0 +1,50 @@ +// Copyright 2000-2020 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(); + final String previewFeatureAnnotation = BASE_PATH + "/PreviewFeature.java"; + final String packagePreview = BASE_PATH + "/" + "packagepreview/package-info.java"; + final String interfaceInPreviewPackage = BASE_PATH + "/" + "packagepreview/FromPreview.java"; + myFixture.configureByFile(previewFeatureAnnotation); + myFixture.configureByFile(packagePreview); + myFixture.configureByFile(interfaceInPreviewPackage); + } + + @Override + protected @NotNull LightProjectDescriptor getProjectDescriptor() { + return JAVA_8; + } + + public void testCallMethodsWithPreviewFeature() { doTest(); } + public void testCallConstructorWithPreviewFeature() { doTest(); } + public void testTypeWithPreviewFeature() { doTest(); } + public void testFieldsWithPreviewFeature() { doTest(); } + public void testImportWithPreviewFeature() { doTest();} + + private void doTest() { + String filePath = BASE_PATH + "/" + getTestName(false) + ".java"; + myFixture.configureByFile(filePath); + myFixture.checkHighlighting(); + } + + @Override + protected String getTestDataPath() { + return JavaTestUtil.getJavaTestDataPath(); + } + + //@Override + //protected String getBasePath() { + // return BASE_PATH; + //} +} diff --git a/platform/core-api/src/com/intellij/psi/CommonClassNames.java b/platform/core-api/src/com/intellij/psi/CommonClassNames.java index dbed2e1d289b..f777684d044f 100644 --- a/platform/core-api/src/com/intellij/psi/CommonClassNames.java +++ b/platform/core-api/src/com/intellij/psi/CommonClassNames.java @@ -115,6 +115,8 @@ public interface CommonClassNames { String JAVA_UTIL_FUNCTION_BI_FUNCTION = "java.util.function.BiFunction"; String JAVA_UTIL_FUNCTION_SUPPLIER = "java.util.function.Supplier"; + String JDK_INTERNAL_PREVIEW_FEATURE = "jdk.internal.PreviewFeature"; + String JAVA_LANG_INVOKE_MH_POLYMORPHIC = "java.lang.invoke.MethodHandle.PolymorphicSignature"; String CLASS_FILE_EXTENSION = ".class";