Commit 0c60dfb4 authored by Roman Shevchenko's avatar Roman Shevchenko
Browse files

[java] handling for automatic modules with invalid names (IDEA-184590)

Shows a descriptive error, doesn't suggest "add requires" quick fix, and excludes such modules from completion.
parent 831aa13a
Branches unavailable Tags unavailable
Showing with 40 additions and 55 deletions
+40 -55
// 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.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
......@@ -938,7 +940,9 @@ public class JavaCompletionContributor extends CompletionContributor {
VirtualFile[] roots = ModuleRootManager.getInstance(module).orderEntries().withoutSdk().librariesOnly().getClassesRoots();
scope = GlobalSearchScope.filesScope(project, Arrays.asList(roots));
for (String name : JavaAutoModuleNameIndex.getAllKeys(project)) {
if (JavaAutoModuleNameIndex.getFilesByKey(name, scope).size() > 0 && filter.add(name)) {
if (JavaAutoModuleNameIndex.getFilesByKey(name, scope).size() > 0 &&
PsiNameHelper.isValidModuleName(name, parent) &&
filter.add(name)) {
LookupElement lookup = LookupElementBuilder.create(name).withIcon(AllIcons.FileTypes.Archive);
lookup = TailTypeDecorator.withTail(lookup, TailType.SEMICOLON);
lookup = PrioritizedLookupElement.withPriority(lookup, -1);
......
// 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.psi.impl
import com.intellij.codeInsight.JavaModuleSystemEx
......@@ -119,9 +121,13 @@ class JavaPlatformModuleSystem : JavaModuleSystemEx {
}
if (!(targetName == PsiJavaModule.JAVA_BASE || JavaModuleGraphUtil.reads(useModule, targetModule))) {
return if (quick) ERR else ErrorWithFixes(
JavaErrorMessages.message("module.access.does.not.read", packageName, targetName, useName),
listOf(AddRequiresDirectiveFix(useModule, targetName)))
return when {
quick -> ERR
PsiNameHelper.isValidModuleName(targetName, useModule) -> ErrorWithFixes(
JavaErrorMessages.message("module.access.does.not.read", packageName, targetName, useName),
listOf(AddRequiresDirectiveFix(useModule, targetName)))
else -> ErrorWithFixes(JavaErrorMessages.message("module.access.bad.name", packageName, targetName))
}
}
}
else if (useModule != null) {
......
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* 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.refactoring.rename;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement;
......@@ -35,9 +22,6 @@ public class JavaModuleRenameValidator implements RenameInputValidator {
@Override
public boolean isInputValid(@NotNull String newName, @NotNull PsiElement element, @NotNull ProcessingContext context) {
if (StringUtil.isEmptyOrSpaces(newName)) return false;
PsiNameHelper helper = PsiNameHelper.getInstance(element.getProject());
return StringUtil.split(newName, ".", true, false).stream().allMatch(helper::isIdentifier);
return PsiNameHelper.isValidModuleName(newName, element);
}
}
\ No newline at end of file
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* 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.psi;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
......@@ -304,4 +294,10 @@ public abstract class PsiNameHelper {
}
return updated;
}
}
public static boolean isValidModuleName(@NotNull String name, @NotNull PsiElement context) {
PsiNameHelper helper = getInstance(context.getProject());
LanguageLevel level = PsiUtil.getLanguageLevel(context);
return StringUtil.split(name, ".", true, false).stream().allMatch(part -> helper.isIdentifier(part, level));
}
}
\ No newline at end of file
......@@ -437,6 +437,7 @@ module.access.from.named=Package ''{0}'' is declared in module ''{1}'', which do
module.access.from.unnamed=Package ''{0}'' is declared in module ''{1}'', which does not export it to the unnamed module
module.access.does.not.read=Package ''{0}'' is declared in module ''{1}'', but module ''{2}'' does not read it
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}'')
feature.generics=Generics
feature.annotations=Annotations
......
File added
// 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.java.codeInsight.daemon
import com.intellij.codeInsight.daemon.impl.JavaHighlightInfoTypes
......@@ -273,6 +275,8 @@ class ModuleHighlightingTest : LightJava9ModulesCodeInsightFixtureTestCase() {
import java.util.List;
import java.util.function.Supplier;
import <error descr="Package 'pkg.libInvalid' is declared in module with an invalid name ('lib.invalid.1.2')">pkg.libInvalid</error>.LCInv;
/** See also {@link C2Impl#I} and {@link C2Impl#make} */
class C {{
<error descr="Package 'pkg.m2.impl' is declared in module 'M2', which does not export it to module 'M'">C2Impl</error>.I = 0;
......
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* 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.psi.impl.light
......@@ -26,6 +14,7 @@ class JavaModuleNameDetectionTest {
@Test fun replacing() = doTest("foo_bar", "foo.bar")
@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")
private fun doTest(original: String, expected: String) = assertEquals(expected, LightJavaModule.moduleName(original))
}
\ No newline at end of file
// 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.java.testFramework.fixtures
import com.intellij.openapi.application.ex.PathManagerEx
......@@ -74,6 +74,7 @@ object MultiModuleJava9ProjectDescriptor : DefaultLightProjectDescriptor() {
ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib-auto-1.0.jar!/")
ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib-auto-2.0.jar!/")
ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib-multi-release.jar!/")
ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib_invalid_1_2.jar!/")
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment