From 1afd0504fa985563a9426c306381ef288cb6c646 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 1 Oct 2013 22:50:49 +0400 Subject: [PATCH] Make compiled package fragments not show up in completion, go-to, etc. --- .../lang/resolve/java/PackageClassUtils.java | 8 +-- idea/src/META-INF/plugin.xml | 2 + ...yPackageFragmentClsStubBuilderFactory.java | 57 +++++++++++++++++++ ...NoPackageFragmentsInJavaPsiFacadeTest.java | 49 ++++++++++++++++ 4 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java create mode 100644 idea/tests/org/jetbrains/jet/plugin/javaFacade/NoPackageFragmentsInJavaPsiFacadeTest.java diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/PackageClassUtils.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/PackageClassUtils.java index e5f0861bfad..e7ed0309445 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/PackageClassUtils.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/PackageClassUtils.java @@ -22,8 +22,8 @@ import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; public final class PackageClassUtils { - - private static final String DEFAULT_PACKAGE = "_DefaultPackage"; + public static final String PACKAGE_CLASS_NAME_SUFFIX = "Package"; + private static final String DEFAULT_PACKAGE_CLASS_NAME = "_Default" + PACKAGE_CLASS_NAME_SUFFIX; private PackageClassUtils() { } @@ -31,9 +31,9 @@ public final class PackageClassUtils { // ex. -> _DefaultPackage, a -> APackage, a.b -> BPackage public static String getPackageClassName(@NotNull FqName packageFQN) { if (packageFQN.isRoot()) { - return DEFAULT_PACKAGE; + return DEFAULT_PACKAGE_CLASS_NAME; } - return StringUtil.capitalize(packageFQN.shortName().asString()) + "Package"; + return StringUtil.capitalize(packageFQN.shortName().asString()) + PACKAGE_CLASS_NAME_SUFFIX; } public static FqName getPackageClassFqName(@NotNull FqName packageFQN) { diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index ee04e6f494f..47b11c1ee18 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -292,6 +292,8 @@ + + diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java b/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java new file mode 100644 index 00000000000..cf89042a635 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2013 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. + */ + +package org.jetbrains.jet.plugin.stubindex.builder; + +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiJavaFile; +import com.intellij.psi.impl.compiled.ClsStubBuilderFactory; +import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl; +import com.intellij.psi.stubs.PsiFileStub; +import com.intellij.util.cls.ClsFormatException; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; +import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass; +import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassFileHeader; +import org.jetbrains.jet.lang.resolve.kotlin.header.PackageFragmentClassFileHeader; + +/** + * This class is needed to build an empty PSI stub for compiled package fragment classes. This results in these classes not showing up + * in completion, go-to-class, etc. + */ +public class EmptyPackageFragmentClsStubBuilderFactory extends ClsStubBuilderFactory { + @Nullable + @Override + public PsiFileStub buildFileStub(VirtualFile file, byte[] bytes) throws ClsFormatException { + return new PsiJavaFileStubImpl(null, true); + } + + @Override + public boolean canBeProcessed(VirtualFile file, byte[] bytes) { + if (file.getName().contains(PackageClassUtils.PACKAGE_CLASS_NAME_SUFFIX + "-") && + StdFileTypes.CLASS.getDefaultExtension().equals(file.getExtension())) { + KotlinClassFileHeader header = KotlinClassFileHeader.readKotlinHeaderFromClassFile(new VirtualFileKotlinClass(file)); + return header instanceof PackageFragmentClassFileHeader; + } + return false; + } + + @Override + public boolean isInnerClass(VirtualFile file) { + return false; + } +} diff --git a/idea/tests/org/jetbrains/jet/plugin/javaFacade/NoPackageFragmentsInJavaPsiFacadeTest.java b/idea/tests/org/jetbrains/jet/plugin/javaFacade/NoPackageFragmentsInJavaPsiFacadeTest.java new file mode 100644 index 00000000000..473c7041e98 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/javaFacade/NoPackageFragmentsInJavaPsiFacadeTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2013 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. + */ + +package org.jetbrains.jet.plugin.javaFacade; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiPackage; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.plugin.JetWithJdkAndRuntimeLightProjectDescriptor; + +import java.util.Set; +import java.util.TreeSet; + +public class NoPackageFragmentsInJavaPsiFacadeTest extends LightCodeInsightFixtureTestCase { + public void testPackageFragmentsAreNotVisible() { + PsiPackage psiPackage = myFixture.findPackage("kotlin"); + + Set packageFragments = new TreeSet(); + for (PsiClass psiClass : psiPackage.getClasses()) { + String qualifiedName = psiClass.getQualifiedName(); + if (qualifiedName != null && qualifiedName.contains("-")) { + packageFragments.add(qualifiedName); + } + } + + assertEmpty("Package fragment classes should not be found via JavaPsiFacade:\n" + packageFragments, packageFragments); + } + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE; + } +}