From 3a3a63bcc18d69aebcbd07a04a64996469ac924b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 7 Feb 2018 19:04:03 +0100 Subject: [PATCH] [java] highlights illegal modifiers in 'requires java.base' (IDEA-184708) --- .../impl/analysis/HighlightVisitorImpl.java | 3 +++ .../impl/analysis/ModuleHighlightUtil.java | 21 ++++++++++++++++++- .../JavacQuirksInspectionVisitor.java | 19 +++++++++++++++++ .../daemon/impl/quickfix/ModifierFix.java | 4 +++- .../src/messages/JavaErrorMessages.properties | 2 ++ .../daemon/LightJava10HighlightingTest.kt | 16 ++++++++++++++ 6 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightJava10HighlightingTest.kt 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 a56a3415034a..e9850d52d56c 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 @@ -1745,6 +1745,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh PsiJavaModule container = (PsiJavaModule)statement.getParent(); PsiJavaModuleReferenceElement ref = statement.getReferenceElement(); if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkModuleReference(ref, container)); + if (!myHolder.hasErrorResults() && myLanguageLevel.isAtLeast(LanguageLevel.JDK_10)) { + myHolder.addAll(ModuleHighlightUtil.checkModifiers(statement)); + } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java index aff924559eba..55f3ef0172fe 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java @@ -1,4 +1,4 @@ -// Copyright 2000-2017 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. +// Copyright 2000-2018 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.codeInsight.daemon.JavaErrorMessages; @@ -47,6 +47,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import static com.intellij.openapi.module.ModuleUtilCore.findModuleForFile; +import static com.intellij.psi.SyntaxTraverser.psiTraverser; public class ModuleHighlightUtil { private static final Attributes.Name MULTI_RELEASE = new Attributes.Name("Multi-Release"); @@ -444,6 +445,24 @@ public class ModuleHighlightUtil { return null; } + @Nullable + static List checkModifiers(@NotNull PsiRequiresStatement statement) { + PsiModifierList modList = statement.getModifierList(); + if (modList != null && PsiJavaModule.JAVA_BASE.equals(statement.getModuleName())) { + return psiTraverser().children(modList) + .filter(PsiKeyword.class) + .map(keyword -> { + @PsiModifier.ModifierConstant String modifier = keyword.getText(); + String message = JavaErrorMessages.message("modifier.not.allowed", modifier); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(keyword).descriptionAndTooltip(message).create(); + QuickFixAction.registerQuickFixAction(info, factory().createModifierListFix(modList, modifier, false, false)); + return info; + }).toList(); + } + + return null; + } + private static HighlightInfo moduleResolveError(PsiJavaModuleReferenceElement refElement, PsiPolyVariantReference ref) { if (ref.multiResolve(true).length == 0) { String message = JavaErrorMessages.message("module.not.found", refElement.getReferenceText()); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java index 5937e7edb402..4eebdac160b2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java @@ -177,6 +177,25 @@ public class JavacQuirksInspectionVisitor extends JavaElementVisitor { } } + @Override + public void visitKeyword(PsiKeyword keyword) { + super.visitKeyword(keyword); + if (myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_9) && !myLanguageLevel.isAtLeast(LanguageLevel.JDK_10)) { + @PsiModifier.ModifierConstant String modifier = keyword.getText(); + if (PsiKeyword.STATIC.equals(modifier) || PsiKeyword.TRANSITIVE.equals(modifier)) { + PsiElement parent = keyword.getParent(); + if (parent instanceof PsiModifierList) { + PsiElement grand = parent.getParent(); + if (grand instanceof PsiRequiresStatement && PsiJavaModule.JAVA_BASE.equals(((PsiRequiresStatement)grand).getModuleName())) { + String message = JavaErrorMessages.message("module.unwanted.modifier"); + LocalQuickFix fix = QuickFixFactory.getInstance().createModifierListFix((PsiModifierList)parent, modifier, false, false); + myHolder.registerProblem(keyword, message, fix); + } + } + } + } + } + @Override public void visitBinaryExpression(PsiBinaryExpression expression) { super.visitBinaryExpression(expression); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java index 89fc3ff4095d..054047a1f505 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java @@ -84,9 +84,11 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement { : containingClass != null ? containingClass.getName() : "unknown"; name = QuickFixBundle.message("class.initializer.presentation", className); } + else if (parent instanceof PsiRequiresStatement) { + name = "requires " + ((PsiRequiresStatement)parent).getModuleName(); + } String modifierText = VisibilityUtil.toPresentableText(myModifier); - return QuickFixBundle.message(myShouldHave ? "add.modifier.fix" : "remove.modifier.fix", name, modifierText); } diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index 260d9d626789..ed8db7cfda5b 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -440,6 +440,8 @@ module.access.does.not.read=Package ''{0}'' is declared in module ''{1}'', but m module.access.not.in.graph=Package ''{0}'' is declared in module ''{1}'', which is not in the module graph module.access.bad.name=Package ''{0}'' is declared in module with an invalid name (''{1}'') +module.unwanted.modifier=Since Java 10, modifiers on 'requires java.base' are prohibited + feature.generics=Generics feature.annotations=Annotations feature.static.imports=Static imports diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightJava10HighlightingTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightJava10HighlightingTest.kt new file mode 100644 index 000000000000..db71fa403f54 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightJava10HighlightingTest.kt @@ -0,0 +1,16 @@ +// Copyright 2000-2018 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 + +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase + +class LightJava10HighlightingTest : LightCodeInsightFixtureTestCase() { + override fun getProjectDescriptor() = JAVA_10 + + fun testRequiresJavaBase() { + myFixture.configureByText("module-info.java", """ + module M { + requires static transitive java.base; + }""".trimIndent()) + myFixture.checkHighlighting() + } +} \ No newline at end of file