From 2fcfda59c09144dfb0fee6b63a924a86e6e69854 Mon Sep 17 00:00:00 2001 From: Aleksey Dobrynin Date: Fri, 16 Feb 2024 10:56:00 +0100 Subject: [PATCH] [java, fix] handle invalid module names GitOrigin-RevId: 2b2a88ae4536a47376ee5e9d21d418c7165e4d69 --- .../impl/analysis/JavaModuleGraphUtil.java | 3 +- .../ide/actions/CreateModuleInfoAction.java | 9 ++++-- .../psi/impl/light/LightJavaModule.java | 6 ++-- .../invalidLibraryName/after/.idea/misc.xml | 6 ++++ .../after/.idea/modules.xml | 8 +++++ .../invalidLibraryName/after/main.iml | 29 ++++++++++++++++++ .../after/test/MainTest.java | 9 ++++++ .../after/test/module-info.java | 3 ++ .../invalidLibraryName/before/.idea/misc.xml | 6 ++++ .../before/.idea/modules.xml | 8 +++++ .../invalidLibraryName/before/main.iml | 29 ++++++++++++++++++ .../before/test/MainTest.java | 9 ++++++ .../before/test/module-info.java | 2 ++ .../emptyModuleInfoFile/lib/lib-for-test.jar | Bin 0 -> 732 bytes ...JavaEmptyModuleInfoFileInspectionTest.java | 6 +++- .../ide/actions/CreateModuleInfoActionTest.kt | 24 +++++++++++++-- .../impl/light/JavaModuleNameDetectionTest.kt | 5 ++- 17 files changed, 150 insertions(+), 12 deletions(-) create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/.idea/misc.xml create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/.idea/modules.xml create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/main.iml create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/test/MainTest.java create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/test/module-info.java create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/.idea/misc.xml create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/.idea/modules.xml create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/main.iml create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/test/MainTest.java create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/test/module-info.java create mode 100644 java/java-tests/testData/inspection/emptyModuleInfoFile/lib/lib-for-test.jar diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaModuleGraphUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaModuleGraphUtil.java index 462abf70f99d..78f8dfdbd597 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaModuleGraphUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaModuleGraphUtil.java @@ -99,7 +99,7 @@ public final class JavaModuleGraphUtil { return CachedValuesManager.getCachedValue(rootPsi, () -> { VirtualFile _root = rootPsi.getVirtualFile(); LightJavaModule result = LightJavaModule.create(rootPsi.getManager(), _root, LightJavaModule.moduleName(_root)); - return Result.create(result, _root, ProjectRootModificationTracker.getInstance(rootPsi.getProject())); + return Result.create(result, _root, ProjectRootModificationTracker.getInstance(rootPsi.getProject())); }); } } @@ -249,6 +249,7 @@ public final class JavaModuleGraphUtil { @Nullable DependencyScope scope) { if (to.getName().equals(JAVA_BASE)) return false; if (!PsiUtil.isAvailable(JavaFeature.MODULES, from)) return false; + if (!PsiNameHelper.isValidModuleName(to.getName(), to)) return false; if (alreadyContainsRequires(from, to.getName())) return false; PsiUtil.addModuleStatement(from, PsiKeyword.REQUIRES + " " + (isStaticModule(to.getName(), scope) ? PsiKeyword.STATIC + " " : "") + diff --git a/java/java-impl/src/com/intellij/ide/actions/CreateModuleInfoAction.java b/java/java-impl/src/com/intellij/ide/actions/CreateModuleInfoAction.java index 540e9bfdea0a..607f39d2df1e 100644 --- a/java/java-impl/src/com/intellij/ide/actions/CreateModuleInfoAction.java +++ b/java/java-impl/src/com/intellij/ide/actions/CreateModuleInfoAction.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide.actions; import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil; @@ -18,6 +18,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.JavaFeature; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiNameHelper; import com.intellij.psi.impl.light.LightJavaModule; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; @@ -32,6 +33,8 @@ import static com.intellij.ide.fileTemplates.JavaTemplateUtil.INTERNAL_MODULE_IN import static com.intellij.psi.PsiJavaModule.MODULE_INFO_CLASS; public class CreateModuleInfoAction extends CreateFromTemplateActionBase { + private static final String DEFAULT_MODULE_NAME = "module_name"; + public CreateModuleInfoAction() { super(JavaBundle.messagePointer("action.create.new.module-info.title"), JavaBundle.messagePointer("action.create.new.module-info.description"), AllIcons.FileTypes.Java); } @@ -86,6 +89,8 @@ public class CreateModuleInfoAction extends CreateFromTemplateActionBase { @Override protected Map getLiveTemplateDefaults(@NotNull DataContext ctx, @NotNull PsiFile file) { Module module = PlatformCoreDataKeys.MODULE.getData(ctx); - return Collections.singletonMap("MODULE_NAME", module != null ? LightJavaModule.moduleName(module.getName()) : "module_name"); + String moduleName = module != null ? LightJavaModule.moduleName(module.getName()) : DEFAULT_MODULE_NAME; + moduleName = PsiNameHelper.isValidModuleName(moduleName, file) ? moduleName : DEFAULT_MODULE_NAME; + return Collections.singletonMap("MODULE_NAME", moduleName); } } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightJavaModule.java b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightJavaModule.java index 56aa29fb3775..1b32ec64ba0d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightJavaModule.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightJavaModule.java @@ -1,4 +1,4 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.psi.impl.light; import com.intellij.lang.java.JavaLanguage; @@ -254,7 +254,7 @@ public final class LightJavaModule extends LightElement implements PsiJavaModule public static @Nullable String claimedModuleName(@NotNull VirtualFile manifest) { try (InputStream stream = manifest.getInputStream()) { - return new Manifest(stream).getMainAttributes().getValue(PsiJavaModule.AUTO_MODULE_NAME); + return new Manifest(stream).getMainAttributes().getValue(AUTO_MODULE_NAME); } catch (IOException e) { Logger.getInstance(LightJavaModule.class).warn(manifest.getPath(), e); @@ -274,7 +274,7 @@ public final class LightJavaModule extends LightElement implements PsiJavaModule *

Implements a name deriving for automatic modules as described in ModuleFinder.of(Path...) method documentation.

* *

Please note that the result may not be a valid module name when the source contains a sequence that starts with a digit - * (e.g. "org.7gnomes..."). One may validate the result with {@link PsiNameHelper#isValidModuleName}.

+ * (e.g. "org.7gnomes...", "module.for...."). One may validate the result with {@link PsiNameHelper#isValidModuleName}.

* * @param name a .jar file name without the extension * @see ModuleFinder.of(Path...) diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/.idea/misc.xml b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/.idea/misc.xml new file mode 100644 index 000000000000..07115cdf15dd --- /dev/null +++ b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/.idea/modules.xml b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/.idea/modules.xml new file mode 100644 index 000000000000..122a9054e101 --- /dev/null +++ b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/main.iml b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/main.iml new file mode 100644 index 000000000000..10ee07cacd4b --- /dev/null +++ b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/main.iml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/test/MainTest.java b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/test/MainTest.java new file mode 100644 index 000000000000..9ad4a2508071 --- /dev/null +++ b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/test/MainTest.java @@ -0,0 +1,9 @@ +import org.jetbrains.org.jetbrains.intellij.java.test.library.*; +import l.InLib; + +public class MainTest { + public static void main(String[] args) { + System.out.println(Util.name()); + System.out.println(InLib.class); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/test/module-info.java b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/test/module-info.java new file mode 100644 index 000000000000..f09df9a06253 --- /dev/null +++ b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/after/test/module-info.java @@ -0,0 +1,3 @@ +module main { + requires intellij.java.test.library; +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/.idea/misc.xml b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/.idea/misc.xml new file mode 100644 index 000000000000..07115cdf15dd --- /dev/null +++ b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/.idea/modules.xml b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/.idea/modules.xml new file mode 100644 index 000000000000..122a9054e101 --- /dev/null +++ b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/main.iml b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/main.iml new file mode 100644 index 000000000000..10ee07cacd4b --- /dev/null +++ b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/main.iml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/test/MainTest.java b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/test/MainTest.java new file mode 100644 index 000000000000..9ad4a2508071 --- /dev/null +++ b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/test/MainTest.java @@ -0,0 +1,9 @@ +import org.jetbrains.org.jetbrains.intellij.java.test.library.*; +import l.InLib; + +public class MainTest { + public static void main(String[] args) { + System.out.println(Util.name()); + System.out.println(InLib.class); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/test/module-info.java b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/test/module-info.java new file mode 100644 index 000000000000..2bae5daaa7ad --- /dev/null +++ b/java/java-tests/testData/inspection/emptyModuleInfoFile/invalidLibraryName/before/test/module-info.java @@ -0,0 +1,2 @@ +module main { +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/emptyModuleInfoFile/lib/lib-for-test.jar b/java/java-tests/testData/inspection/emptyModuleInfoFile/lib/lib-for-test.jar new file mode 100644 index 0000000000000000000000000000000000000000..5b7ca99b6ad69ce11c225121a9837800dbc19ae0 GIT binary patch literal 732 zcmWIWW@Zs#-~hscNHJ3eB*4kQ!r%LW z$)nOUG&5MHKhyk?rY8PWJX~!0l4oMt70*;(XMQUBSi}f+h~J~Rr`&m_W+bP+? zO5jXt*_4*J6+t^S*H1k2UCC?4m%}<@Cmo-7{g#?_H1aOTS_95&nJX4a9=w~HDtCJ7 zrRwdACU@`P=2z2c3RdUbx6D!LQt*aeJtIAXhJ*88D&_TUzV)W*6!WzooK+tZ4kT{X zezEA}tG~<{8?QfqtM&9RI9#fw;?M5|`sxc12Y53wi7=qXFD&vv@rw%J5eABFbgjt2 z4T@a^umv*VT9M)!WC9lh?r1@na16)Bm;2DsaqmLA60p6@^AZZpL Ld;z5IF@ksi()7NY literal 0 HcmV?d00001 diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/java19api/JavaEmptyModuleInfoFileInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/java19api/JavaEmptyModuleInfoFileInspectionTest.java index 629b92fe086e..d4376a142dff 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/java19api/JavaEmptyModuleInfoFileInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/java19api/JavaEmptyModuleInfoFileInspectionTest.java @@ -55,6 +55,10 @@ public class JavaEmptyModuleInfoFileInspectionTest extends LightMultiFileTestCas doTest("test/module-info.java"); } + public void testInvalidLibraryName() { + doTest("test/module-info.java"); + } + public void testMultiModuleProject() { doTest("src/module-info.java", "main/"); } @@ -76,6 +80,6 @@ public class JavaEmptyModuleInfoFileInspectionTest extends LightMultiFileTestCas myFixture.launchAction(intention); NonBlockingReadActionImpl.waitForAsyncTaskCompletion(); } - myFixture.checkResultByFile(getTestName(false) + "/after/" + dir + path); + myFixture.checkResultByFile(getTestName(true) + "/after/" + dir + path); } } diff --git a/java/java-tests/testSrc/com/intellij/java/ide/actions/CreateModuleInfoActionTest.kt b/java/java-tests/testSrc/com/intellij/java/ide/actions/CreateModuleInfoActionTest.kt index 0b14e8e00ba4..889d1a96c5da 100644 --- a/java/java-tests/testSrc/com/intellij/java/ide/actions/CreateModuleInfoActionTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/ide/actions/CreateModuleInfoActionTest.kt @@ -1,14 +1,16 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.java.ide.actions import com.intellij.ide.IdeView import com.intellij.ide.fileTemplates.FileTemplateManager import com.intellij.java.testFramework.fixtures.LightJava9ModulesCodeInsightFixtureTestCase +import com.intellij.java.testFramework.fixtures.MultiModuleJava9ProjectDescriptor.ModuleDescriptor.M2 import com.intellij.java.testFramework.fixtures.MultiModuleJava9ProjectDescriptor.ModuleDescriptor.MAIN import com.intellij.openapi.actionSystem.ActionManager import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.LangDataKeys import com.intellij.openapi.actionSystem.PlatformCoreDataKeys +import com.intellij.openapi.module.ModuleManager import com.intellij.psi.PsiDirectory import com.intellij.psi.PsiJavaModule import com.intellij.psi.PsiManager @@ -17,6 +19,24 @@ import com.intellij.testFramework.PlatformTestUtil class CreateModuleInfoActionTest : LightJava9ModulesCodeInsightFixtureTestCase() { fun test() { + val testModule = ModuleManager.getInstance(project).findModuleByName(M2.moduleName)!! + val dir = PsiManager.getInstance(project).findDirectory(M2.sourceRoot()!!)!! + val ctx = MapDataContext(mapOf(LangDataKeys.IDE_VIEW to TestIdeView(dir), PlatformCoreDataKeys.MODULE to testModule)) + val event = AnActionEvent.createFromDataContext("", null, ctx) + ActionManager.getInstance().getAction("NewModuleInfo")!!.actionPerformed(event) + + val file = dir.findFile(PsiJavaModule.MODULE_INFO_FILE)!! + val p = FileTemplateManager.getInstance(project).defaultProperties + assertEquals(""" + /** + * Created by ${p["USER"]} on ${p["DATE"]}. + */ + module light.idea.test.m2 { + }""".trimIndent(), file.text) + } + + fun testNotValidName() { + module.name val dir = PsiManager.getInstance(project).findDirectory(MAIN.sourceRoot()!!)!! val ctx = MapDataContext(mapOf(LangDataKeys.IDE_VIEW to TestIdeView(dir), PlatformCoreDataKeys.MODULE to module)) val event = AnActionEvent.createFromDataContext("", null, ctx) @@ -28,7 +48,7 @@ class CreateModuleInfoActionTest : LightJava9ModulesCodeInsightFixtureTestCase() /** * Created by ${p["USER"]} on ${p["DATE"]}. */ - module light.idea.test.case { + module module_name { }""".trimIndent(), file.text) } diff --git a/java/java-tests/testSrc/com/intellij/java/psi/impl/light/JavaModuleNameDetectionTest.kt b/java/java-tests/testSrc/com/intellij/java/psi/impl/light/JavaModuleNameDetectionTest.kt index f252904b72fb..cf1671adab12 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/impl/light/JavaModuleNameDetectionTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/psi/impl/light/JavaModuleNameDetectionTest.kt @@ -1,6 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.java.psi.impl.light import com.intellij.psi.impl.light.LightJavaModule @@ -15,6 +13,7 @@ class JavaModuleNameDetectionTest { @Test fun collapsing() = doTest("foo...bar", "foo.bar") @Test fun trimming() = doTest("...foo.bar...", "foo.bar") @Test fun invalid() = doTest("lib_invalid_1_2", "lib.invalid.1.2") + @Test fun withKeywords() = doTest("lib.for.ide", "lib.for.ide") private fun doTest(original: String, expected: String) = assertEquals(expected, LightJavaModule.moduleName(original)) } \ No newline at end of file