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 eb5ff19c098c..06a12b9e8ad3 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 @@ -18,6 +18,7 @@ import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider; import com.intellij.codeInspection.LocalQuickFixOnPsiElementAsIntentionAdapter; import com.intellij.java.analysis.JavaAnalysisBundle; import com.intellij.lang.findUsages.LanguageFindUsages; +import com.intellij.lang.jvm.JvmModifier; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.EffectiveLanguageLevelUtil; import com.intellij.openapi.module.Module; @@ -1625,6 +1626,11 @@ public final class HighlightUtil { final PsiAnnotation annotation = owner.getAnnotation(HighlightingFeature.JDK_INTERNAL_PREVIEW_FEATURE); if (annotation != null) return annotation; + if (!(owner instanceof PsiClass) || !owner.hasModifier(JvmModifier.STATIC)) { + final PsiAnnotation result = getPreviewFeatureAnnotation(PsiTreeUtil.getParentOfType(owner, PsiClass.class)); + if (result != null) return result; + } + final PsiPackage psiPackage = JavaResolveUtil.getContainingPackage(owner); if (psiPackage == null) return null; 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 02004e79246f..22d246ffba94 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 @@ -1177,6 +1177,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (result != null) { PsiElement resolved = result.getElement(); if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkRawOnParameterizedType(ref, resolved)); + if (!myHolder.hasErrorResults() && resolved instanceof PsiModifierListOwner) { + myHolder.add(HighlightUtil.checkPreviewFeatureElement(ref, (PsiModifierListOwner)resolved, myLanguageLevel)); + } } } @@ -1615,6 +1618,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh myHolder.add(info); } } + if (!myHolder.hasErrorResults() && method instanceof PsiModifierListOwner) { + myHolder.add(HighlightUtil.checkPreviewFeatureElement(expression, (PsiModifierListOwner)method, myLanguageLevel)); + } } /** diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallConstructorWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallConstructorWithPreviewFeature.java index b6d0c16ab3b5..f0d16e38cfff 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallConstructorWithPreviewFeature.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallConstructorWithPreviewFeature.java @@ -15,9 +15,19 @@ class Main { new Main(42l); new Main("42"); new Main(42); - new org.myorg.preview.FromPreview() { + new org.myorg.preview.FromPreview() { public void g(){} - }; + }; + new NotDirectlyAnnotatedConstructor(); + new DirectlyAnnotatedConstructor(); } } + +@PreviewFeature(feature=Feature.TEXT_BLOCKS) +class NotDirectlyAnnotatedConstructor { } + +class DirectlyAnnotatedConstructor { + @PreviewFeature(feature=Feature.TEXT_BLOCKS) + DirectlyAnnotatedConstructor() {} +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallMethodsWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallMethodsWithPreviewFeature.java index 8682e4b1dbda..e3b779af2956 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallMethodsWithPreviewFeature.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/CallMethodsWithPreviewFeature.java @@ -1,11 +1,15 @@ import jdk.internal.PreviewFeature; import jdk.internal.PreviewFeature.Feature; +import org.myorg.preview.FromPreview; class Main { static { requirePatternMatching(); Main.requireTextBlocks(); new Main().requireRecords(); + final NotDirectlyAnnotatedMethod a = new NotDirectlyAnnotatedMethod(); + a.f(); + NotDirectlyAnnotatedMethod.g(); } @PreviewFeature(feature=Feature.PATTERN_MATCHING_IN_INSTANCEOF) @@ -18,3 +22,9 @@ class Main { void requireRecords(){} } + +@PreviewFeature(feature=Feature.TEXT_BLOCKS) +class NotDirectlyAnnotatedMethod { + void f(){} + static void g(){} +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ClassImplementsWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ClassImplementsWithPreviewFeature.java new file mode 100644 index 000000000000..6aad1e999aa0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ClassImplementsWithPreviewFeature.java @@ -0,0 +1,11 @@ +import jdk.internal.PreviewFeature; +import jdk.internal.PreviewFeature.Feature; +import org.myorg.preview.FromPreview; + +class Custom1 implements org.myorg.preview.FromPreview { + public void g() {} +} + +class Custom2 implements FromPreview { + public void g() {} +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/FieldsWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/FieldsWithPreviewFeature.java index 3953efbf7e34..330c2225303a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/FieldsWithPreviewFeature.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/FieldsWithPreviewFeature.java @@ -18,5 +18,13 @@ class Main { int k = new Main().i; org.myorg.preview.FromPreview local = null; } + void f(NotDirectlyAnnotatedField a) { + a.id = 0; + } } + +@PreviewFeature(feature=Feature.TEXT_BLOCKS) +class NotDirectlyAnnotatedField { + int id; +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ImportWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ImportWithPreviewFeature.java index 4f7bbb53d072..9e6aec0b9dca 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ImportWithPreviewFeature.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/ImportWithPreviewFeature.java @@ -1,6 +1,6 @@ -import org.myorg.preview.FromPreview; -import static org.myorg.preview.FromPreview.f; -import static org.myorg.preview.FromPreview.*; +import org.myorg.preview.FromPreview; +import static org.myorg.preview.FromPreview.f; +import static org.myorg.preview.FromPreview.*; class Main { static { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/MethodReferenceWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/MethodReferenceWithPreviewFeature.java new file mode 100644 index 000000000000..4c53135b182d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/MethodReferenceWithPreviewFeature.java @@ -0,0 +1,10 @@ +import org.myorg.preview.FromPreview; + +class Main { + static { + Runnable r = FromPreview::f; + } + void f(FromPreview fp) { + Runnable r = fp::g; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/RequiresModuleWithPreviewFeature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/RequiresModuleWithPreviewFeature.java index 1adb941ef95e..de7bd0db1cc8 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/RequiresModuleWithPreviewFeature.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/RequiresModuleWithPreviewFeature.java @@ -1,5 +1,5 @@ module consumer { requires producer; - provides org.myorg.preview.FromPreview with org.myorg.preview.impl.FromPreviewImpl; + provides org.myorg.preview.FromPreview with org.myorg.preview.impl.FromPreviewImpl; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/FromPreview.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/FromPreview.java index 593e6c475fa9..1288fd517dd2 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/FromPreview.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/previewfeature/packagepreview/FromPreview.java @@ -1,6 +1,6 @@ package org.myorg.preview; public interface FromPreview { - static void f(); + static void f() {}; void g(); } 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 index b6c1d7b3347d..1eae8135bdbc 100644 --- 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 @@ -41,6 +41,8 @@ public class PreviewFeatureAnnotationTest extends LightJavaCodeInsightFixtureTes public void testImportWithPreviewFeature() { doTest(); } public void testReferenceWithPreviewFeature() { doTest(); } public void testRequiresModuleWithPreviewFeature() { doTest(); } + public void testMethodReferenceWithPreviewFeature() { doTest(); } + public void testClassImplementsWithPreviewFeature() { doTest(); } private void doTest() { String filePath = BASE_PATH + "/" + getTestName(false) + ".java";