From 2519641b2b3bf93018396997667f947327b4c38d Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Wed, 2 Sep 2015 22:08:13 +0300 Subject: [PATCH] JvmName annotation support, single-file facade case (just rename file facade class) - initial implementation of JvmFileClassesProvider - migrate some of PackagePartClassUtil usages to JvmFileClassesProvider (mostly in Codegen) - placeholder ("no resolve") implementation for migration period and unclear cases - tests --- .../codegen/CodegenFileClassesProvider.kt | 72 ++++++++++++ .../kotlin/codegen/KotlinCodegenFacade.java | 2 +- .../kotlin/codegen/MemberCodegen.java | 8 +- .../kotlin/codegen/PackageCodegen.java | 4 +- .../binding/CodegenAnnotatingVisitor.java | 10 +- .../codegen/binding/CodegenBinding.java | 15 ++- .../codegen/binding/PsiCodegenPredictor.java | 19 +++- .../codegen/inline/InlineCodegenUtil.java | 21 +++- .../KotlinToJvmSignatureMapperImpl.kt | 3 +- ...FactoryForDuplicateSignatureDiagnostics.kt | 6 +- .../kotlin/codegen/state/GenerationState.kt | 10 +- .../kotlin/codegen/state/JetTypeMapper.java | 16 ++- .../state/JetTypeMapperWithOutDirectory.java | 4 +- .../kotlin/cli/jvm/repl/ReplInterpreter.java | 4 +- .../kotlin/fileClasses/JvmFileClassInfo.kt | 51 +++++++++ .../kotlin/fileClasses/JvmFileClassUtil.kt | 106 ++++++++++++++++++ .../fileClasses/JvmFileClassesProvider.kt | 32 ++++++ .../NoResolveFileClassesProvider.kt | 26 +++++ .../load/kotlin/PackagePartClassUtils.kt | 10 +- .../kotlin/psi/stubs/StubInterfaces.kt | 1 + .../stubs/elements/JetFileElementType.java | 4 +- .../psi/stubs/impl/KotlinFileStubImpl.kt | 26 +++-- .../KotlinLightClassForExplicitDeclaration.kt | 3 +- .../testData/cli/jvm/classAndFacadeClash.args | 2 +- .../cli/jvm/classAndFileClassClash.args | 3 + .../cli/jvm/classAndFileClassClash.kt | 6 + .../cli/jvm/classAndFileClassClash.out | 7 ++ .../cli/jvm/classAndOtherFileClassClash.args | 4 + .../cli/jvm/classAndOtherFileClassClash.out | 7 ++ .../cli/jvm/classAndOtherFileClassClash1.kt | 4 + .../cli/jvm/classAndOtherFileClassClash2.kt | 3 + .../cli/jvm/fileClassAndFacadeClash.args | 3 + .../cli/jvm/fileClassAndFacadeClash.kt | 4 + .../cli/jvm/fileClassAndFacadeClash.out | 4 + .../cli/jvm/fileClassAndTImplClash.args | 3 + .../cli/jvm/fileClassAndTImplClash.kt | 4 + .../cli/jvm/fileClassAndTImplClash.out | 1 + .../cli/jvm/fileClassClashMultipleFiles.args | 4 + .../cli/jvm/fileClassClashMultipleFiles.out | 7 ++ .../cli/jvm/fileClassClashMultipleFiles1.kt | 4 + .../cli/jvm/fileClassClashMultipleFiles2.kt | 4 + .../fileClasses/differentFiles/Baz.java | 5 + .../fileClasses/differentFiles/bar.kt | 2 + .../differentFiles/differentFiles.kt | 1 + .../fileClasses/differentFiles/foo.kt | 2 + .../boxWithJava/fileClasses/simple/Bar.java | 5 + .../boxWithJava/fileClasses/simple/foo.kt | 2 + .../boxWithJava/fileClasses/simple/simple.kt | 1 + .../platformNames/renamedFileClass.kt | 8 ++ .../cli/KotlincExecutableTestGenerated.java | 30 +++++ .../BlackBoxWithJavaCodegenTestGenerated.java | 22 ++++ ...lackBoxWithStdlibCodegenTestGenerated.java | 6 + .../navigation/JetSourceNavigationHelper.java | 4 +- .../idea/stubindex/JetFileFacadeClassIndex.kt | 36 ++++++ ...ClassIndex.kt => JetFilePartClassIndex.kt} | 11 +- .../idea/stubindex/StaticFacadeIndexUtil.kt | 4 +- .../idea/stubindex/StubIndexServiceImpl.java | 25 +++-- idea/src/META-INF/plugin.xml | 3 +- 58 files changed, 615 insertions(+), 79 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/CodegenFileClassesProvider.kt create mode 100644 compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassInfo.kt create mode 100644 compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt create mode 100644 compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassesProvider.kt create mode 100644 compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/NoResolveFileClassesProvider.kt create mode 100644 compiler/testData/cli/jvm/classAndFileClassClash.args create mode 100644 compiler/testData/cli/jvm/classAndFileClassClash.kt create mode 100644 compiler/testData/cli/jvm/classAndFileClassClash.out create mode 100644 compiler/testData/cli/jvm/classAndOtherFileClassClash.args create mode 100644 compiler/testData/cli/jvm/classAndOtherFileClassClash.out create mode 100644 compiler/testData/cli/jvm/classAndOtherFileClassClash1.kt create mode 100644 compiler/testData/cli/jvm/classAndOtherFileClassClash2.kt create mode 100644 compiler/testData/cli/jvm/fileClassAndFacadeClash.args create mode 100644 compiler/testData/cli/jvm/fileClassAndFacadeClash.kt create mode 100644 compiler/testData/cli/jvm/fileClassAndFacadeClash.out create mode 100644 compiler/testData/cli/jvm/fileClassAndTImplClash.args create mode 100644 compiler/testData/cli/jvm/fileClassAndTImplClash.kt create mode 100644 compiler/testData/cli/jvm/fileClassAndTImplClash.out create mode 100644 compiler/testData/cli/jvm/fileClassClashMultipleFiles.args create mode 100644 compiler/testData/cli/jvm/fileClassClashMultipleFiles.out create mode 100644 compiler/testData/cli/jvm/fileClassClashMultipleFiles1.kt create mode 100644 compiler/testData/cli/jvm/fileClassClashMultipleFiles2.kt create mode 100644 compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/Baz.java create mode 100644 compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/bar.kt create mode 100644 compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/differentFiles.kt create mode 100644 compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/foo.kt create mode 100644 compiler/testData/codegen/boxWithJava/fileClasses/simple/Bar.java create mode 100644 compiler/testData/codegen/boxWithJava/fileClasses/simple/foo.kt create mode 100644 compiler/testData/codegen/boxWithJava/fileClasses/simple/simple.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/platformNames/renamedFileClass.kt create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/JetFileFacadeClassIndex.kt rename idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/{JetStaticFacadeClassIndex.kt => JetFilePartClassIndex.kt} (75%) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CodegenFileClassesProvider.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CodegenFileClassesProvider.kt new file mode 100644 index 00000000000..18d7c34abea --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CodegenFileClassesProvider.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2010-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. + */ + +package org.jetbrains.kotlin.codegen + +import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo +import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil +import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.JetFile +import org.jetbrains.kotlin.resolve.BindingContext +import java.util.* + +public class CodegenFileClassesProvider private constructor(private val bindingContext: BindingContext) : JvmFileClassesProvider() { + private val fileParts = hashMapOf() + + override fun getFileClassFqName(file: JetFile): FqName = + getFileClassInfo(file).fileClassFqName + + public fun getFileClassInfo(file: JetFile): JvmFileClassInfo = + fileParts.getOrPut(file) { createFileClassInfo(file) } + + private fun createFileClassInfo(file: JetFile): JvmFileClassInfo { + val fileAnnotations = JvmFileClassUtil.collectFileAnnotations(file, bindingContext) + val jvmClassNameAnnotation = JvmFileClassUtil.parseJvmFileClass(fileAnnotations) + return JvmFileClassUtil.getFileClassInfo(file, jvmClassNameAnnotation) + } + + internal fun addFileClassInfo(file: JetFile) { + if (fileParts.containsKey(file)) return + fileParts[file] = createFileClassInfo(file) + } + + companion object { + public @jvmStatic fun createForCodegenTask( + bindingContext: BindingContext, + files: Collection, + packagesWithObsoleteParts: Collection, + multifileFacadesWithObsoleteParts: Collection + ) : CodegenFileClassesProvider { + val codegenFileClassesManager = CodegenFileClassesProvider(bindingContext) + files.forEach { + codegenFileClassesManager.addFileClassInfo(it) + } + + val packagesToProcess = HashSet(packagesWithObsoleteParts) + packagesToProcess.addAll(multifileFacadesWithObsoleteParts.map { it.parent() }) + for (packageFqName in packagesToProcess) { + bindingContext.get(BindingContext.PACKAGE_TO_FILES, packageFqName)?.forEach { + codegenFileClassesManager.addFileClassInfo(it) + } + } + + return codegenFileClassesManager + } + } +} + +public class JvmMultifileFacadeClassInfo(public val facadeFqName: FqName, public val fileParts: List) \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java index 8e53614fdc5..c47523b8b1c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java @@ -44,7 +44,7 @@ public class KotlinCodegenFacade { FqName name = ScriptNameUtil.classNameForScript(script); Type type = AsmUtil.asmTypeByFqNameWithoutInnerClasses(name); - registerClassNameForScript(state.getBindingTrace(), script, type); + registerClassNameForScript(state.getBindingTrace(), script, type, state.getFileClassesManager()); } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 0995d1ea2d2..448f9159a24 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -29,8 +29,8 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl; +import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.load.java.JvmAbi; -import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.SpecialNames; import org.jetbrains.kotlin.psi.*; @@ -74,6 +74,7 @@ public abstract class MemberCodegen parentCodegen; private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages(); protected final Collection innerClasses = new LinkedHashSet(); @@ -94,6 +95,7 @@ public abstract class MemberCodegen generateCallableMemberTasks) { boolean generatePackagePart = false; - Type packagePartType = PackagePartClassUtils.getPackagePartType(file); + Type packagePartType = state.getFileClassesManager().getFileClassType(file); PackageContext packagePartContext = CodegenContext.STATIC.intoPackagePart(packageFragment, packagePartType); for (JetDeclaration declaration : file.getDeclarations()) { @@ -414,7 +414,7 @@ public class PackageCodegen { public void generateClassOrObject(@NotNull JetClassOrObject classOrObject) { JetFile file = classOrObject.getContainingJetFile(); - Type packagePartType = PackagePartClassUtils.getPackagePartType(file); + Type packagePartType = state.getFileClassesManager().getFileClassType(file); CodegenContext context = CodegenContext.STATIC.intoPackagePart(packageFragment, packagePartType); MemberCodegen.genClassOrObject(context, classOrObject, state, null); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index 4d529360e5b..ad29793b4d2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -33,8 +33,8 @@ import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil; import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl; +import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor; -import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; @@ -75,12 +75,14 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { private final BindingContext bindingContext; private final GenerationState.GenerateClassFilter filter; private final JvmRuntimeTypes runtimeTypes; + private final JvmFileClassesProvider fileClassesManager; public CodegenAnnotatingVisitor(@NotNull GenerationState state) { this.bindingTrace = state.getBindingTrace(); this.bindingContext = state.getBindingContext(); this.filter = state.getGenerateDeclaredClassFilter(); this.runtimeTypes = state.getJvmRuntimeTypes(); + this.fileClassesManager = state.getFileClassesManager(); } @NotNull @@ -333,7 +335,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { } private void recordClosure(@NotNull ClassDescriptor classDescriptor, @NotNull String name) { - CodegenBinding.recordClosure(bindingTrace, classDescriptor, peekFromStack(classStack), Type.getObjectType(name)); + CodegenBinding.recordClosure(bindingTrace, classDescriptor, peekFromStack(classStack), Type.getObjectType(name), fileClassesManager); } @Override @@ -391,7 +393,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { else if (containingDeclaration instanceof PackageFragmentDescriptor) { JetFile containingFile = DescriptorToSourceUtils.getContainingFile(descriptor); assert containingFile != null : "File not found for " + descriptor; - return PackagePartClassUtils.getPackagePartInternalName(containingFile) + '$' + name; + return fileClassesManager.getFileClassInternalName(containingFile) + '$' + name; } return null; @@ -572,7 +574,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { } } - return PackagePartClassUtils.getPackagePartInternalName(file); + return fileClassesManager.getFileClassInternalName(file); } private static T peekFromStack(@NotNull Stack stack) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java index 778cd7edc2b..db77a47cb9d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl; +import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; @@ -161,7 +162,8 @@ public class CodegenBinding { @NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor, @Nullable ClassDescriptor enclosing, - @NotNull Type asmType + @NotNull Type asmType, + @NotNull JvmFileClassesProvider fileClassesManager ) { JetElement element = (JetElement) descriptorToDeclaration(classDescriptor); assert element != null : "No source element for " + classDescriptor; @@ -172,7 +174,7 @@ public class CodegenBinding { closure.setCaptureThis(); } - assert PsiCodegenPredictor.checkPredictedNameFromPsi(classDescriptor, asmType); + assert PsiCodegenPredictor.checkPredictedNameFromPsi(classDescriptor, asmType, fileClassesManager); trace.record(ASM_TYPE, classDescriptor, asmType); trace.record(CLOSURE, classDescriptor, closure); @@ -197,7 +199,12 @@ public class CodegenBinding { } // SCRIPT: register asmType for script, move to ScriptingUtil - public static void registerClassNameForScript(@NotNull BindingTrace trace, @NotNull JetScript script, @NotNull Type asmType) { + public static void registerClassNameForScript( + @NotNull BindingTrace trace, + @NotNull JetScript script, + @NotNull Type asmType, + @NotNull JvmFileClassesProvider fileClassesManager + ) { ScriptDescriptor descriptor = trace.getBindingContext().get(SCRIPT, script); if (descriptor == null) { throw new IllegalStateException("Script descriptor is not found for PSI: " + PsiUtilPackage.getElementTextWithContext(script)); @@ -210,7 +217,7 @@ public class CodegenBinding { toSourceElement(script)); classDescriptor.initialize(JetScope.Empty.INSTANCE$, Collections.emptySet(), null); - recordClosure(trace, classDescriptor, null, asmType); + recordClosure(trace, classDescriptor, null, asmType, fileClassesManager); trace.record(CLASS_FOR_SCRIPT, descriptor, classDescriptor); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/PsiCodegenPredictor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/PsiCodegenPredictor.java index 117b4276840..8132262102b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/PsiCodegenPredictor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/PsiCodegenPredictor.java @@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.AsmUtil; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; +import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; import org.jetbrains.org.objectweb.asm.Type; @@ -33,10 +33,14 @@ public final class PsiCodegenPredictor { private PsiCodegenPredictor() { } - public static boolean checkPredictedNameFromPsi(@NotNull DeclarationDescriptor descriptor, @Nullable Type nameFromDescriptors) { + public static boolean checkPredictedNameFromPsi( + @NotNull DeclarationDescriptor descriptor, + @Nullable Type nameFromDescriptors, + @NotNull JvmFileClassesProvider fileClassesManager + ) { PsiElement element = descriptorToDeclaration(descriptor); if (element instanceof JetDeclaration) { - String classNameFromPsi = getPredefinedJvmInternalName((JetDeclaration) element); + String classNameFromPsi = getPredefinedJvmInternalName((JetDeclaration) element, fileClassesManager); assert classNameFromPsi == null || Type.getObjectType(classNameFromPsi).equals(nameFromDescriptors) : String.format("Invalid algorithm for getting qualified name from psi! Predicted: %s, actual %s\n" + "Element: %s", classNameFromPsi, nameFromDescriptors, element.getText()); @@ -49,7 +53,10 @@ public final class PsiCodegenPredictor { * @return null if no prediction can be done. */ @Nullable - public static String getPredefinedJvmInternalName(@NotNull JetDeclaration declaration) { + public static String getPredefinedJvmInternalName( + @NotNull JetDeclaration declaration, + @NotNull JvmFileClassesProvider fileClassesManager + ) { // TODO: Method won't work for declarations inside companion objects // TODO: Method won't give correct class name for traits implementations @@ -57,7 +64,7 @@ public final class PsiCodegenPredictor { String parentInternalName; if (parentDeclaration != null) { - parentInternalName = getPredefinedJvmInternalName(parentDeclaration); + parentInternalName = getPredefinedJvmInternalName(parentDeclaration, fileClassesManager); if (parentInternalName == null) { return null; } @@ -67,7 +74,7 @@ public final class PsiCodegenPredictor { if (declaration instanceof JetNamedFunction) { Name name = ((JetNamedFunction) declaration).getNameAsName(); - return name == null ? null : PackagePartClassUtils.getPackagePartInternalName(containingFile) + "$" + name.asString(); + return name == null ? null : fileClassesManager.getFileClassInternalName(containingFile) + "$" + name.asString(); } parentInternalName = AsmUtil.internalNameByFqNameWithoutInnerClasses(containingFile.getPackageFqName()); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java index d35b9448bca..24df2ae01b0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java @@ -32,10 +32,10 @@ import org.jetbrains.kotlin.codegen.context.PackageContext; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinder; import org.jetbrains.kotlin.load.kotlin.PackageClassUtils; -import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; @@ -204,11 +204,20 @@ public class InlineCodegenUtil { return null; } - public static String getInlineName(@NotNull CodegenContext codegenContext, @NotNull JetTypeMapper typeMapper) { - return getInlineName(codegenContext, codegenContext.getContextDescriptor(), typeMapper); + public static String getInlineName( + @NotNull CodegenContext codegenContext, + @NotNull JetTypeMapper typeMapper, + @NotNull JvmFileClassesProvider fileClassesManager + ) { + return getInlineName(codegenContext, codegenContext.getContextDescriptor(), typeMapper, fileClassesManager); } - private static String getInlineName(@NotNull CodegenContext codegenContext, @NotNull DeclarationDescriptor currentDescriptor, @NotNull JetTypeMapper typeMapper) { + private static String getInlineName( + @NotNull CodegenContext codegenContext, + @NotNull DeclarationDescriptor currentDescriptor, + @NotNull JetTypeMapper typeMapper, + @NotNull JvmFileClassesProvider fileClassesManager + ) { if (currentDescriptor instanceof PackageFragmentDescriptor) { PsiFile file = getContainingFile(codegenContext); @@ -218,7 +227,7 @@ public class InlineCodegenUtil { assert codegenContext instanceof PackageContext : "Expected package context but " + codegenContext; packagePartType = ((PackageContext) codegenContext).getPackagePartType(); } else { - packagePartType = PackagePartClassUtils.getPackagePartType((JetFile) file); + packagePartType = fileClassesManager.getFileClassType((JetFile) file); } if (packagePartType == null) { @@ -245,7 +254,7 @@ public class InlineCodegenUtil { String suffix = currentDescriptor.getName().isSpecial() ? "" : currentDescriptor.getName().asString(); //noinspection ConstantConditions - return getInlineName(codegenContext, currentDescriptor.getContainingDeclaration(), typeMapper) + "$" + suffix; + return getInlineName(codegenContext, currentDescriptor.getContainingDeclaration(), typeMapper, fileClassesManager) + "$" + suffix; } public static boolean isInvokeOnLambda(@NotNull String owner, @NotNull String name) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/signature/KotlinToJvmSignatureMapperImpl.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/signature/KotlinToJvmSignatureMapperImpl.kt index 255df3835ce..e76552ff041 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/signature/KotlinToJvmSignatureMapperImpl.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/signature/KotlinToJvmSignatureMapperImpl.kt @@ -19,12 +19,13 @@ package org.jetbrains.kotlin.codegen.signature import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.state.JetTypeMapper import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapper public class KotlinToJvmSignatureMapperImpl : KotlinToJvmSignatureMapper { // We use empty BindingContext, because it is only used by JetTypeMapper for purposes irrelevant to the needs of this class - private val typeMapper: JetTypeMapper = JetTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES) + private val typeMapper: JetTypeMapper = JetTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider) override fun mapToJvmMethodSignature(function: FunctionDescriptor) = typeMapper.mapSignature(function) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt index d893928fe01..79f52f9fd4d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.diagnostics.DiagnosticSink +import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider private val EXTERNAL_SOURCES_KINDS = arrayOf( JvmDeclarationOriginKind.DELEGATION_TO_TRAIT_IMPL, @@ -40,11 +41,12 @@ private val EXTERNAL_SOURCES_KINDS = arrayOf( class BuilderFactoryForDuplicateSignatureDiagnostics( builderFactory: ClassBuilderFactory, bindingContext: BindingContext, - private val diagnostics: DiagnosticSink + private val diagnostics: DiagnosticSink, + fileClassesProvider: JvmFileClassesProvider ) : SignatureCollectingClassBuilderFactory(builderFactory) { // Avoid errors when some classes are not loaded for some reason - private val typeMapper = JetTypeMapper(bindingContext, ClassBuilderMode.LIGHT_CLASSES) + private val typeMapper = JetTypeMapper(bindingContext, ClassBuilderMode.LIGHT_CLASSES, fileClassesProvider) override fun handleClashingSignatures(data: ConflictingJvmDeclarationsData) { val noOwnImplementations = data.signatureOrigins.all { it.originKind in EXTERNAL_SOURCES_KINDS } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt index faa57509228..74c380005a8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.codegen.optimization.OptimizationClassBuilderFactory import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ScriptDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink +import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.name.FqName @@ -81,10 +82,15 @@ public class GenerationState jvmOverloads constructor( } } + public val fileClassesManager: CodegenFileClassesProvider = + CodegenFileClassesProvider.createForCodegenTask(bindingContext, files, packagesWithObsoleteParts, + /* TODO */ multifileFacadesWithObsoleteParts = emptySet()) + public val classBuilderMode: ClassBuilderMode = builderFactory.getClassBuilderMode() public val bindingTrace: BindingTrace = DelegatingBindingTrace(bindingContext, "trace in GenerationState") public val bindingContext: BindingContext = bindingTrace.getBindingContext() - public val typeMapper: JetTypeMapper = JetTypeMapperWithOutDirectory(this.bindingContext, classBuilderMode, outDirectory) + public val typeMapper: JetTypeMapper = + JetTypeMapperWithOutDirectory(this.bindingContext, classBuilderMode, fileClassesManager, outDirectory) public val intrinsics: IntrinsicMethods = IntrinsicMethods() public val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this) public val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics) @@ -108,7 +114,7 @@ public class GenerationState jvmOverloads constructor( init { val optimizationClassBuilderFactory = OptimizationClassBuilderFactory(builderFactory, disableOptimization) var interceptedBuilderFactory: ClassBuilderFactory = BuilderFactoryForDuplicateSignatureDiagnostics( - optimizationClassBuilderFactory, this.bindingContext, diagnostics) + optimizationClassBuilderFactory, this.bindingContext, diagnostics, fileClassesManager) interceptedBuilderFactory = BuilderFactoryForDuplicateClassNameDiagnostics(interceptedBuilderFactory, diagnostics); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java index 7842051b0ee..0ed5e4eac04 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java @@ -30,10 +30,10 @@ import org.jetbrains.kotlin.codegen.binding.PsiCodegenPredictor; import org.jetbrains.kotlin.codegen.context.CodegenContext; import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; -import org.jetbrains.kotlin.load.kotlin.PackageClassUtils; import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeDeclarationsPackage; import org.jetbrains.kotlin.name.ClassId; @@ -82,10 +82,16 @@ import static org.jetbrains.org.objectweb.asm.Opcodes.*; public class JetTypeMapper { private final BindingContext bindingContext; private final ClassBuilderMode classBuilderMode; + private final JvmFileClassesProvider fileClassesManager; - public JetTypeMapper(@NotNull BindingContext bindingContext, @NotNull ClassBuilderMode classBuilderMode) { + public JetTypeMapper( + @NotNull BindingContext bindingContext, + @NotNull ClassBuilderMode classBuilderMode, + @NotNull JvmFileClassesProvider fileClassesManager + ) { this.bindingContext = bindingContext; this.classBuilderMode = classBuilderMode; + this.fileClassesManager = fileClassesManager; } @NotNull @@ -154,7 +160,7 @@ public class JetTypeMapper { } @NotNull - private static String internalNameForPackage( + private String internalNameForPackage( @NotNull PackageFragmentDescriptor packageFragment, @NotNull CallableMemberDescriptor descriptor, boolean insideModule @@ -162,7 +168,7 @@ public class JetTypeMapper { ///if (insideModule) { JetFile file = DescriptorToSourceUtils.getContainingFile(descriptor); if (file != null) { - return PackagePartClassUtils.getPackagePartInternalName(file); + return fileClassesManager.getFileClassInternalName(file); } CallableMemberDescriptor directMember = getDirectMember(descriptor); @@ -396,7 +402,7 @@ public class JetTypeMapper { } Type asmType = Type.getObjectType(computeAsmTypeImpl(klass)); - assert PsiCodegenPredictor.checkPredictedNameFromPsi(klass, asmType); + assert PsiCodegenPredictor.checkPredictedNameFromPsi(klass, asmType, fileClassesManager); return asmType; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapperWithOutDirectory.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapperWithOutDirectory.java index 48f0cf4d108..4b2cf4a9586 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapperWithOutDirectory.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapperWithOutDirectory.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.state; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.ClassBuilderMode; +import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.resolve.BindingContext; import java.io.File; @@ -32,9 +33,10 @@ public class JetTypeMapperWithOutDirectory extends JetTypeMapper { public JetTypeMapperWithOutDirectory( @NotNull BindingContext bindingContext, @NotNull ClassBuilderMode classBuilderMode, + @NotNull JvmFileClassesProvider fileClassesManager, @Nullable File outDirectory ) { - super(bindingContext, classBuilderMode); + super(bindingContext, classBuilderMode, fileClassesManager); this.outDirectory = outDirectory; } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java index 0d682908214..9f3566c4c9b 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java @@ -389,7 +389,7 @@ public class ReplInterpreter { PsiElement jetScript = descriptorToDeclaration(earlierDescriptor); if (jetScript != null) { - registerClassNameForScript(state.getBindingTrace(), (JetScript) jetScript, earlierClassType); + registerClassNameForScript(state.getBindingTrace(), (JetScript) jetScript, earlierClassType, state.getFileClassesManager()); earlierScriptDescriptors.add(earlierDescriptor); } } @@ -404,7 +404,7 @@ public class ReplInterpreter { @NotNull CompilationErrorHandler errorHandler ) { registerEarlierScripts(state, earlierScripts); - registerClassNameForScript(state.getBindingTrace(), script, classType); + registerClassNameForScript(state.getBindingTrace(), script, classType, state.getFileClassesManager()); state.beforeCompile(); KotlinCodegenFacade.generatePackage( diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassInfo.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassInfo.kt new file mode 100644 index 00000000000..bc77fb4b6c6 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassInfo.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-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. + */ + +package org.jetbrains.kotlin.fileClasses + +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.JetFile + +public interface JvmFileClassInfo { + public val fileClassFqName: FqName + public val facadeClassFqName: FqName + public val kind: Kind + + public enum class Kind { + FILE_CLASS, + MULTIFILE_CLASS_PART + ; + } +} + +public class JvmFileFacadeInfo( + override val fileClassFqName: FqName +) : JvmFileClassInfo { + override val facadeClassFqName: FqName + get() = fileClassFqName + override val kind: JvmFileClassInfo.Kind + get() = JvmFileClassInfo.Kind.FILE_CLASS +} + +public class JvmMultifileFacadePartInfo( + override val fileClassFqName: FqName, + override val facadeClassFqName: FqName +) : JvmFileClassInfo { + override val kind: JvmFileClassInfo.Kind + get() = JvmFileClassInfo.Kind.MULTIFILE_CLASS_PART + +} + diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt new file mode 100644 index 00000000000..b8c2a1c7a2a --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassUtil.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2010-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. + */ + +package org.jetbrains.kotlin.fileClasses + +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl +import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.constants.StringValue + +public object JvmFileClassUtil { + public val JVM_NAME: FqName = FqName("kotlin.jvm.jvmName") + public val JVM_NAME_SHORT: String = JVM_NAME.shortName().asString() + + // TODO @JvmMultifileClass + + public @jvmStatic fun getFileClassInfo(file: JetFile, jvmFileClassAnnotations: ParsedJmvFileClassAnnotations?): JvmFileClassInfo = + if (jvmFileClassAnnotations != null) + getFileClassInfoForAnnotation(file, jvmFileClassAnnotations) + else + getDefaultFileClassInfo(file) + + public @jvmStatic fun getFileClassInfoForAnnotation(file: JetFile, jvmFileClassAnnotations: ParsedJmvFileClassAnnotations): JvmFileClassInfo = + if (jvmFileClassAnnotations.multipleFiles) + JvmMultifileFacadePartInfo(getHiddenPartFqName(file, jvmFileClassAnnotations), + getFacadeFqName(file, jvmFileClassAnnotations)) + else + JvmFileFacadeInfo(getFacadeFqName(file, jvmFileClassAnnotations)) + + public @jvmStatic fun getDefaultFileClassInfo(file: JetFile): JvmFileClassInfo = + JvmFileFacadeInfo(PackagePartClassUtils.getPackagePartFqName(file.packageFqName, file.name)) + + public @jvmStatic fun getFacadeFqName(file: JetFile, jvmFileClassAnnotations: ParsedJmvFileClassAnnotations): FqName = + file.packageFqName.child(Name.identifier(jvmFileClassAnnotations.name)) + + public @jvmStatic fun getHiddenPartFqName(file: JetFile, jvmFileClassAnnotations: ParsedJmvFileClassAnnotations): FqName = + file.packageFqName.child(Name.identifier(manglePartName(jvmFileClassAnnotations.name, file.name))) + + public @jvmStatic fun manglePartName(facadeName: String, fileName: String): String = + "${facadeName}__${PackagePartClassUtils.getFilePartShortName(fileName)}" + + public @jvmStatic fun parseJvmFileClass(annotations: Annotations): ParsedJmvFileClassAnnotations? { + val jvmName = annotations.findAnnotation(JVM_NAME) + // TODO @JvmMultifileClass + return if (jvmName != null) parseJvmFileClass(jvmName) else null + } + + public @jvmStatic fun parseJvmFileClass(jvmName: AnnotationDescriptor): ParsedJmvFileClassAnnotations { + val name = jvmName.allValueArguments.values().firstOrNull()?.let { (it as? StringValue)?.value } + return ParsedJmvFileClassAnnotations(name!!, false) + } + + public @jvmStatic fun getFileClassInfoNoResolve(file: JetFile): JvmFileClassInfo = + getFileClassInfo(file, parseJvmNameOnFileNoResolve(file)) + + public @jvmStatic fun parseJvmNameOnFileNoResolve(file: JetFile): ParsedJmvFileClassAnnotations? = + findJvmNameOnFileNoResolve(file)?.let { parseJvmNameOnFileNoResolve(it) } + + public @jvmStatic fun findJvmNameOnFileNoResolve(file: JetFile): JetAnnotationEntry? = + file.fileAnnotationList?.annotationEntries?.firstOrNull { + it.calleeExpression?.constructorReferenceExpression?.getReferencedName() == JVM_NAME_SHORT + } + + public @jvmStatic fun parseJvmNameOnFileNoResolve(annotationEntry: JetAnnotationEntry): ParsedJmvFileClassAnnotations? { + val nameExpr = annotationEntry.valueArguments.firstOrNull()?.getArgumentExpression() ?: return null + val name = getLiteralStringFromRestrictedConstExpression(nameExpr) + return name?.let { ParsedJmvFileClassAnnotations(it, false) } + } + + private @jvmStatic fun getLiteralStringFromRestrictedConstExpression(argumentExpression: JetExpression?): String? { + val stringTemplate = argumentExpression as? JetStringTemplateExpression ?: return null + val stringTemplateEntries = stringTemplate.entries + if (stringTemplateEntries.size() != 1) return null + val singleEntry = stringTemplateEntries[0] as? JetLiteralStringTemplateEntry ?: return null + return singleEntry.text + } + + public @jvmStatic fun collectFileAnnotations(file: JetFile, bindingContext: BindingContext): Annotations { + val fileAnnotationsList = file.fileAnnotationList ?: return Annotations.EMPTY + val annotationDescriptors = arrayListOf() + for (annotationEntry in fileAnnotationsList.annotationEntries) { + bindingContext.get(BindingContext.ANNOTATION, annotationEntry)?.let { annotationDescriptors.add(it) } + } + return AnnotationsImpl(annotationDescriptors) + } +} + +public class ParsedJmvFileClassAnnotations(public val name: String, public val multipleFiles: Boolean) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassesProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassesProvider.kt new file mode 100644 index 00000000000..7e5c467c590 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/JvmFileClassesProvider.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-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. + */ + +package org.jetbrains.kotlin.fileClasses + +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.JetFile +import org.jetbrains.kotlin.resolve.jvm.JvmClassName +import org.jetbrains.org.objectweb.asm.Type + +public abstract class JvmFileClassesProvider { + public abstract fun getFileClassFqName(file: JetFile): FqName + + public fun getFileClassInternalName(file: JetFile): String = + JvmClassName.byFqNameWithoutInnerClasses(getFileClassFqName(file)).internalName + + public fun getFileClassType(file: JetFile): Type = + Type.getObjectType(getFileClassInternalName(file)) +} \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/NoResolveFileClassesProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/NoResolveFileClassesProvider.kt new file mode 100644 index 00000000000..042257a4b25 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/fileClasses/NoResolveFileClassesProvider.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-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. + */ + +package org.jetbrains.kotlin.fileClasses + +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.JetFile + + +public object NoResolveFileClassesProvider : JvmFileClassesProvider() { + override fun getFileClassFqName(file: JetFile): FqName = + JvmFileClassUtil.getFileClassInfo(file, JvmFileClassUtil.parseJvmNameOnFileNoResolve(file)).fileClassFqName +} \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt index 38001ec8965..c07d31b822c 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt @@ -28,10 +28,9 @@ import org.jetbrains.kotlin.psi.JetProperty import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf -import org.jetbrains.org.objectweb.asm.Type import java.util.* - public object PackagePartClassUtils { +public object PackagePartClassUtils { public @jvmStatic fun getPathHashCode(file: VirtualFile): Int = file.path.toLowerCase().hashCode() @@ -66,16 +65,14 @@ import java.util.* public @jvmStatic fun isPartClassFqName(classFqName: FqName): Boolean = classFqName.shortName().asString().endsWith(PART_CLASS_NAME_SUFFIX) - public @jvmStatic fun getPackagePartType(file: JetFile): Type = - Type.getObjectType(getPackagePartInternalName(file)) - + @deprecated("Migrate to JvmFileClassesProvider") public @jvmStatic fun getPackagePartInternalName(file: JetFile): String = JvmClassName.byFqNameWithoutInnerClasses(getPackagePartFqName(file)).internalName + @deprecated("Migrate to JvmFileClassesProvider") public @jvmStatic fun getPackagePartFqName(file: JetFile): FqName = getPackagePartFqName(file.packageFqName, file.name) - public @jvmStatic fun getPackagePartFqName(callable: DeserializedCallableMemberDescriptor): FqName { val implClassName = callable.nameResolver.getName(callable.proto.getExtension(JvmProtoBuf.implClassName)) val packageFqName = (callable.containingDeclaration as PackageFragmentDescriptor).fqName @@ -93,4 +90,5 @@ import java.util.* public @jvmStatic fun getFilePartShortName(fileName: String): String = getPartClassName(FileUtil.getNameWithoutExtension(fileName)) + } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/StubInterfaces.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/StubInterfaces.kt index b61a2b28365..ba95199fb72 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/StubInterfaces.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/StubInterfaces.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.psi.* public interface KotlinFileStub : PsiFileStub { public fun getPackageFqName(): FqName public fun getFacadeSimpleName(): String? + public fun getPartSimpleName(): String? public fun isScript(): Boolean public fun findImportsByAlias(alias: String): List } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/elements/JetFileElementType.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/elements/JetFileElementType.java index 0d1c5e48c5a..dccee234d2f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/elements/JetFileElementType.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/elements/JetFileElementType.java @@ -69,6 +69,7 @@ public class JetFileElementType extends IStubFileElementType { throws IOException { dataStream.writeName(stub.getPackageFqName().asString()); dataStream.writeName(stub.getFacadeSimpleName()); + dataStream.writeName(stub.getPartSimpleName()); dataStream.writeBoolean(stub.isScript()); } @@ -78,7 +79,8 @@ public class JetFileElementType extends IStubFileElementType { StringRef packageFqNameAsString = dataStream.readName(); boolean isScript = dataStream.readBoolean(); StringRef facadeSimpleName = dataStream.readName(); - return new KotlinFileStubImpl(null, packageFqNameAsString, facadeSimpleName, isScript); + StringRef partSimpleName = dataStream.readName(); + return new KotlinFileStubImpl(null, packageFqNameAsString, facadeSimpleName, partSimpleName, isScript); } @Override diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinFileStubImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinFileStubImpl.kt index b3940051364..e88073d76b7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinFileStubImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinFileStubImpl.kt @@ -32,15 +32,17 @@ import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes public class KotlinFileStubImpl( jetFile: JetFile?, private val packageName: StringRef, - private val facadeShortName: StringRef?, + private val facadeSimpleName: StringRef?, + private val partSimpleName: StringRef?, private val isScript: Boolean ) : PsiFileStubImpl(jetFile), KotlinFileStub, PsiClassHolderFileStub { public constructor(jetFile: JetFile?, packageName: String, isScript: Boolean) - : this(jetFile, StringRef.fromString(packageName)!!, null, isScript) + : this(jetFile, StringRef.fromString(packageName)!!, null, null, isScript) override fun getPackageFqName(): FqName = FqName(StringRef.toString(packageName)!!) - override fun getFacadeSimpleName(): String? = StringRef.toString(facadeShortName) + override fun getFacadeSimpleName(): String? = StringRef.toString(facadeSimpleName) + override fun getPartSimpleName(): String? = StringRef.toString(partSimpleName) override fun isScript(): Boolean = isScript override fun getType(): IStubFileElementType = JetStubElementTypes.FILE @@ -57,15 +59,17 @@ public class KotlinFileStubImpl( companion object { public fun forPackageStub(packageFqName: FqName, isScript: Boolean): KotlinFileStubImpl = - KotlinFileStubImpl(null, - StringRef.fromString(packageFqName.asString())!!, - null, - isScript) + KotlinFileStubImpl(jetFile = null, + packageName = StringRef.fromString(packageFqName.asString())!!, + facadeSimpleName = null, + partSimpleName = null, + isScript = isScript) public fun forFileFacadeStub(facadeFqName: FqName, isScript: Boolean): KotlinFileStubImpl = - KotlinFileStubImpl(null, - StringRef.fromString(facadeFqName.parent().asString())!!, - StringRef.fromString(facadeFqName.shortName().asString())!!, - isScript) + KotlinFileStubImpl(jetFile = null, + packageName = StringRef.fromString(facadeFqName.parent().asString())!!, + facadeSimpleName = StringRef.fromString(facadeFqName.shortName().asString())!!, + partSimpleName = StringRef.fromString(facadeFqName.shortName().asString())!!, + isScript = isScript) } } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForExplicitDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForExplicitDeclaration.kt index 0b75b4656b8..de5b252d1fb 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForExplicitDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForExplicitDeclaration.kt @@ -35,6 +35,7 @@ import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.binding.PsiCodegenPredictor import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider import org.jetbrains.kotlin.idea.JetLanguage import org.jetbrains.kotlin.lexer.JetTokens.* import org.jetbrains.kotlin.name.FqName @@ -410,7 +411,7 @@ public open class KotlinLightClassForExplicitDeclaration( val data = getLightClassDataExactly(classOrObject) return data?.jvmQualifiedName } - val internalName = PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject) + val internalName = PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject, NoResolveFileClassesProvider) return if (internalName == null) null else JvmClassName.byInternalName(internalName).fqNameForClassNameWithoutDollars } diff --git a/compiler/testData/cli/jvm/classAndFacadeClash.args b/compiler/testData/cli/jvm/classAndFacadeClash.args index 7dc958f8eb6..b22faf6a45a 100644 --- a/compiler/testData/cli/jvm/classAndFacadeClash.args +++ b/compiler/testData/cli/jvm/classAndFacadeClash.args @@ -1,3 +1,3 @@ $TESTDATA_DIR$/classAndFacadeClash.kt -d -$TEMP_DIR$ +$TEMP_DIR$ \ No newline at end of file diff --git a/compiler/testData/cli/jvm/classAndFileClassClash.args b/compiler/testData/cli/jvm/classAndFileClassClash.args new file mode 100644 index 00000000000..eb85ab9bf74 --- /dev/null +++ b/compiler/testData/cli/jvm/classAndFileClassClash.args @@ -0,0 +1,3 @@ +$TESTDATA_DIR$/classAndFileClassClash.kt +-d +$TEMP_DIR$ diff --git a/compiler/testData/cli/jvm/classAndFileClassClash.kt b/compiler/testData/cli/jvm/classAndFileClassClash.kt new file mode 100644 index 00000000000..3bde0509d2d --- /dev/null +++ b/compiler/testData/cli/jvm/classAndFileClassClash.kt @@ -0,0 +1,6 @@ +@file:jvmName("Foo") +package test + +public fun foo() {} + +class Foo {} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/classAndFileClassClash.out b/compiler/testData/cli/jvm/classAndFileClassClash.out new file mode 100644 index 00000000000..250b2cf4d64 --- /dev/null +++ b/compiler/testData/cli/jvm/classAndFileClassClash.out @@ -0,0 +1,7 @@ +compiler/testData/cli/jvm/classAndFileClassClash.kt:1:1: error: duplicate JVM class name 'test/Foo' generated from: package-fragment test, Foo +@file:jvmName("Foo") +^ +compiler/testData/cli/jvm/classAndFileClassClash.kt:6:1: error: duplicate JVM class name 'test/Foo' generated from: package-fragment test, Foo +class Foo {} +^ +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/cli/jvm/classAndOtherFileClassClash.args b/compiler/testData/cli/jvm/classAndOtherFileClassClash.args new file mode 100644 index 00000000000..8de737731b3 --- /dev/null +++ b/compiler/testData/cli/jvm/classAndOtherFileClassClash.args @@ -0,0 +1,4 @@ +$TESTDATA_DIR$/classAndOtherFileClassClash1.kt +$TESTDATA_DIR$/classAndOtherFileClassClash2.kt +-d +$TEMP_DIR$ diff --git a/compiler/testData/cli/jvm/classAndOtherFileClassClash.out b/compiler/testData/cli/jvm/classAndOtherFileClassClash.out new file mode 100644 index 00000000000..a801ad260fe --- /dev/null +++ b/compiler/testData/cli/jvm/classAndOtherFileClassClash.out @@ -0,0 +1,7 @@ +compiler/testData/cli/jvm/classAndOtherFileClassClash1.kt:1:1: error: duplicate JVM class name 'test/Foo' generated from: Foo, package-fragment test +@file:jvmName("Foo") +^ +compiler/testData/cli/jvm/classAndOtherFileClassClash2.kt:3:1: error: duplicate JVM class name 'test/Foo' generated from: Foo, package-fragment test +class Foo +^ +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/cli/jvm/classAndOtherFileClassClash1.kt b/compiler/testData/cli/jvm/classAndOtherFileClassClash1.kt new file mode 100644 index 00000000000..2f7d7627658 --- /dev/null +++ b/compiler/testData/cli/jvm/classAndOtherFileClassClash1.kt @@ -0,0 +1,4 @@ +@file:jvmName("Foo") +package test + +public fun foo() {} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/classAndOtherFileClassClash2.kt b/compiler/testData/cli/jvm/classAndOtherFileClassClash2.kt new file mode 100644 index 00000000000..ab9e2e14368 --- /dev/null +++ b/compiler/testData/cli/jvm/classAndOtherFileClassClash2.kt @@ -0,0 +1,3 @@ +package test + +class Foo \ No newline at end of file diff --git a/compiler/testData/cli/jvm/fileClassAndFacadeClash.args b/compiler/testData/cli/jvm/fileClassAndFacadeClash.args new file mode 100644 index 00000000000..61420d21be3 --- /dev/null +++ b/compiler/testData/cli/jvm/fileClassAndFacadeClash.args @@ -0,0 +1,3 @@ +$TESTDATA_DIR$/fileClassAndFacadeClash.kt +-d +$TEMP_DIR$ diff --git a/compiler/testData/cli/jvm/fileClassAndFacadeClash.kt b/compiler/testData/cli/jvm/fileClassAndFacadeClash.kt new file mode 100644 index 00000000000..55eb82fc98a --- /dev/null +++ b/compiler/testData/cli/jvm/fileClassAndFacadeClash.kt @@ -0,0 +1,4 @@ +@file:jvmName("TestPackage") +package test + +fun foo() {} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/fileClassAndFacadeClash.out b/compiler/testData/cli/jvm/fileClassAndFacadeClash.out new file mode 100644 index 00000000000..18b6c35f049 --- /dev/null +++ b/compiler/testData/cli/jvm/fileClassAndFacadeClash.out @@ -0,0 +1,4 @@ +compiler/testData/cli/jvm/fileClassAndFacadeClash.kt:1:1: error: duplicate JVM class name 'test/TestPackage' generated from: package-fragment test, package-fragment test +@file:jvmName("TestPackage") +^ +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/cli/jvm/fileClassAndTImplClash.args b/compiler/testData/cli/jvm/fileClassAndTImplClash.args new file mode 100644 index 00000000000..a447a395596 --- /dev/null +++ b/compiler/testData/cli/jvm/fileClassAndTImplClash.args @@ -0,0 +1,3 @@ +$TESTDATA_DIR$/fileClassAndTImplClash.kt +-d +$TEMP_DIR$ diff --git a/compiler/testData/cli/jvm/fileClassAndTImplClash.kt b/compiler/testData/cli/jvm/fileClassAndTImplClash.kt new file mode 100644 index 00000000000..f07cfa07fc7 --- /dev/null +++ b/compiler/testData/cli/jvm/fileClassAndTImplClash.kt @@ -0,0 +1,4 @@ +@file:jvmName("XXX\$\$TImpl") +package test + +interface XXX \ No newline at end of file diff --git a/compiler/testData/cli/jvm/fileClassAndTImplClash.out b/compiler/testData/cli/jvm/fileClassAndTImplClash.out new file mode 100644 index 00000000000..a0aba9318ad --- /dev/null +++ b/compiler/testData/cli/jvm/fileClassAndTImplClash.out @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/compiler/testData/cli/jvm/fileClassClashMultipleFiles.args b/compiler/testData/cli/jvm/fileClassClashMultipleFiles.args new file mode 100644 index 00000000000..d7e56bd9ec5 --- /dev/null +++ b/compiler/testData/cli/jvm/fileClassClashMultipleFiles.args @@ -0,0 +1,4 @@ +$TESTDATA_DIR$/fileClassClashMultipleFiles1.kt +$TESTDATA_DIR$/fileClassClashMultipleFiles2.kt +-d +$TEMP_DIR$ diff --git a/compiler/testData/cli/jvm/fileClassClashMultipleFiles.out b/compiler/testData/cli/jvm/fileClassClashMultipleFiles.out new file mode 100644 index 00000000000..fb86092613f --- /dev/null +++ b/compiler/testData/cli/jvm/fileClassClashMultipleFiles.out @@ -0,0 +1,7 @@ +compiler/testData/cli/jvm/fileClassClashMultipleFiles1.kt:1:1: error: duplicate JVM class name 'test/Util' generated from: package-fragment test, package-fragment test +@file:jvmName("Util") +^ +compiler/testData/cli/jvm/fileClassClashMultipleFiles2.kt:1:1: error: duplicate JVM class name 'test/Util' generated from: package-fragment test, package-fragment test +@file:jvmName("Util") +^ +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/cli/jvm/fileClassClashMultipleFiles1.kt b/compiler/testData/cli/jvm/fileClassClashMultipleFiles1.kt new file mode 100644 index 00000000000..f687e591e21 --- /dev/null +++ b/compiler/testData/cli/jvm/fileClassClashMultipleFiles1.kt @@ -0,0 +1,4 @@ +@file:jvmName("Util") +package test + +public fun foo() {} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/fileClassClashMultipleFiles2.kt b/compiler/testData/cli/jvm/fileClassClashMultipleFiles2.kt new file mode 100644 index 00000000000..4e4fda870f6 --- /dev/null +++ b/compiler/testData/cli/jvm/fileClassClashMultipleFiles2.kt @@ -0,0 +1,4 @@ +@file:jvmName("Util") +package test + +public fun bar() {} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/Baz.java b/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/Baz.java new file mode 100644 index 00000000000..3af00b277ef --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/Baz.java @@ -0,0 +1,5 @@ +public class Baz { + public static String baz() { + return Foo.foo() + Bar.bar(); + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/bar.kt b/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/bar.kt new file mode 100644 index 00000000000..8905df4ae01 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/bar.kt @@ -0,0 +1,2 @@ +@file:jvmName("Bar") +public fun bar(): String = "K" \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/differentFiles.kt b/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/differentFiles.kt new file mode 100644 index 00000000000..936b887daa8 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/differentFiles.kt @@ -0,0 +1 @@ +fun box(): String = Baz.baz() \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/foo.kt b/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/foo.kt new file mode 100644 index 00000000000..0a8c401ca7a --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/foo.kt @@ -0,0 +1,2 @@ +@file:jvmName("Foo") +public fun foo(): String = "O" \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/simple/Bar.java b/compiler/testData/codegen/boxWithJava/fileClasses/simple/Bar.java new file mode 100644 index 00000000000..2ef76a82c6f --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/simple/Bar.java @@ -0,0 +1,5 @@ +public class Bar { + public static String bar() { + return Foo.foo(); + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/simple/foo.kt b/compiler/testData/codegen/boxWithJava/fileClasses/simple/foo.kt new file mode 100644 index 00000000000..9d66ea22e85 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/simple/foo.kt @@ -0,0 +1,2 @@ +@file:jvmName("Foo") +public fun foo(): String = "OK" \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/fileClasses/simple/simple.kt b/compiler/testData/codegen/boxWithJava/fileClasses/simple/simple.kt new file mode 100644 index 00000000000..f60eab480fd --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/fileClasses/simple/simple.kt @@ -0,0 +1 @@ +fun box(): String = Bar.bar() diff --git a/compiler/testData/codegen/boxWithStdlib/platformNames/renamedFileClass.kt b/compiler/testData/codegen/boxWithStdlib/platformNames/renamedFileClass.kt new file mode 100644 index 00000000000..8cc4a00709e --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/platformNames/renamedFileClass.kt @@ -0,0 +1,8 @@ +@file:jvmName("Util") +package test + +fun foo(): String = bar() +fun bar(): String = qux() +fun qux(): String = "OK" + +fun box(): String = foo() \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/cli/KotlincExecutableTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cli/KotlincExecutableTestGenerated.java index c583e1fc978..38a03155760 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/KotlincExecutableTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cli/KotlincExecutableTestGenerated.java @@ -43,6 +43,18 @@ public class KotlincExecutableTestGenerated extends AbstractKotlincExecutableTes doJvmTest(fileName); } + @TestMetadata("classAndFileClassClash.args") + public void testClassAndFileClassClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/classAndFileClassClash.args"); + doJvmTest(fileName); + } + + @TestMetadata("classAndOtherFileClassClash.args") + public void testClassAndOtherFileClassClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/classAndOtherFileClassClash.args"); + doJvmTest(fileName); + } + @TestMetadata("classAndPartClash.args") public void testClassAndPartClash() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/classAndPartClash.args"); @@ -97,6 +109,24 @@ public class KotlincExecutableTestGenerated extends AbstractKotlincExecutableTes doJvmTest(fileName); } + @TestMetadata("fileClassAndFacadeClash.args") + public void testFileClassAndFacadeClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/fileClassAndFacadeClash.args"); + doJvmTest(fileName); + } + + @TestMetadata("fileClassAndTImplClash.args") + public void testFileClassAndTImplClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/fileClassAndTImplClash.args"); + doJvmTest(fileName); + } + + @TestMetadata("fileClassClashMultipleFiles.args") + public void testFileClassClashMultipleFiles() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/fileClassClashMultipleFiles.args"); + doJvmTest(fileName); + } + @TestMetadata("help.args") public void testHelp() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/help.args"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index 130d8602ab3..939ebd540f1 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -121,6 +121,28 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege } + @TestMetadata("compiler/testData/codegen/boxWithJava/fileClasses") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FileClasses extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInFileClasses() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithJava/fileClasses"), Pattern.compile("^([^\\.]+)$"), true); + } + + @TestMetadata("differentFiles") + public void testDifferentFiles() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/fileClasses/differentFiles/"); + doTestWithJava(fileName); + } + + @TestMetadata("simple") + public void testSimple() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/fileClasses/simple/"); + doTestWithJava(fileName); + } + + } + @TestMetadata("compiler/testData/codegen/boxWithJava/interfaces") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 64405261e0b..6f1d671c785 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -2244,6 +2244,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformNames/propertyName.kt"); doTestWithStdlib(fileName); } + + @TestMetadata("renamedFileClass.kt") + public void testRenamedFileClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformNames/renamedFileClass.kt"); + doTestWithStdlib(fileName); + } } @TestMetadata("compiler/testData/codegen/boxWithStdlib/platformStatic") diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/JetSourceNavigationHelper.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/JetSourceNavigationHelper.java index 817633f57c9..f7b70f4fe82 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/JetSourceNavigationHelper.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/JetSourceNavigationHelper.java @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.context.ContextPackage; import org.jetbrains.kotlin.context.MutableModuleContext; import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.ClassDescriptor; +import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider; import org.jetbrains.kotlin.frontend.di.DiPackage; import org.jetbrains.kotlin.idea.stubindex.JetFullClassNameIndex; import org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope; @@ -65,7 +66,6 @@ import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM; import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer; import org.jetbrains.kotlin.resolve.lazy.ResolveSession; import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory; -import org.jetbrains.kotlin.types.DynamicTypesSettings; import java.util.Collection; import java.util.Collections; @@ -378,7 +378,7 @@ public class JetSourceNavigationHelper { @Nullable public static PsiClass getOriginalClass(@NotNull JetClassOrObject classOrObject) { // Copied from JavaPsiImplementationHelperImpl:getOriginalClass() - String internalName = PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject); + String internalName = PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject, NoResolveFileClassesProvider.INSTANCE$); if (internalName == null) { return null; } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/JetFileFacadeClassIndex.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/JetFileFacadeClassIndex.kt new file mode 100644 index 00000000000..fbaad9ee95e --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/JetFileFacadeClassIndex.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-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. + */ + +package org.jetbrains.kotlin.idea.stubindex + +import com.intellij.openapi.project.Project +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.stubs.StringStubIndexExtension +import com.intellij.psi.stubs.StubIndexKey +import org.jetbrains.kotlin.psi.JetFile + +public class JetFileFacadeClassIndex private constructor() : StringStubIndexExtension() { + override fun getKey(): StubIndexKey = KEY + + override fun get(key: String, project: Project, scope: GlobalSearchScope) = + super.get(key, project, JetSourceFilterScope.kotlinSourcesAndLibraries(scope, project)) + + companion object { + private val KEY = KotlinIndexUtil.createIndexKey(JetFileFacadeClassIndex::class.java) + public val INSTANCE: JetFileFacadeClassIndex = JetFileFacadeClassIndex() + public @jvmStatic fun getInstance(): JetFileFacadeClassIndex = INSTANCE + } +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/JetStaticFacadeClassIndex.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/JetFilePartClassIndex.kt similarity index 75% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/JetStaticFacadeClassIndex.kt rename to idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/JetFilePartClassIndex.kt index 27cff5f29d1..ac60220b94b 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/JetStaticFacadeClassIndex.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/JetFilePartClassIndex.kt @@ -22,17 +22,16 @@ import com.intellij.psi.stubs.StringStubIndexExtension import com.intellij.psi.stubs.StubIndexKey import org.jetbrains.kotlin.psi.JetFile -public class JetStaticFacadeClassIndex private constructor() : StringStubIndexExtension() { + +public class JetFilePartClassIndex private constructor() : StringStubIndexExtension() { override fun getKey(): StubIndexKey = KEY override fun get(key: String, project: Project, scope: GlobalSearchScope) = super.get(key, project, JetSourceFilterScope.kotlinSourcesAndLibraries(scope, project)) companion object { - private val KEY = KotlinIndexUtil.createIndexKey(JetStaticFacadeClassIndex::class.java) - - public val INSTANCE: JetStaticFacadeClassIndex = JetStaticFacadeClassIndex() - - public @jvmStatic fun getInstance(): JetStaticFacadeClassIndex = INSTANCE + private val KEY = KotlinIndexUtil.createIndexKey(JetFilePartClassIndex::class.java) + public val INSTANCE: JetFilePartClassIndex = JetFilePartClassIndex() + public @jvmStatic fun getInstance(): JetFilePartClassIndex = INSTANCE } } \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/StaticFacadeIndexUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/StaticFacadeIndexUtil.kt index e6afc59b1a7..3be9bc37901 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/StaticFacadeIndexUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/StaticFacadeIndexUtil.kt @@ -30,7 +30,7 @@ public object StaticFacadeIndexUtil { searchScope: GlobalSearchScope, project: Project ) : Collection = - JetStaticFacadeClassIndex.INSTANCE.get(facadeFqName.asString(), project, searchScope) + JetFileFacadeClassIndex.INSTANCE.get(facadeFqName.asString(), project, searchScope) // TODO change as we introduce multi-file facades (this will require a separate index) @jvmStatic public fun findFilesForFilePart( @@ -39,5 +39,5 @@ public object StaticFacadeIndexUtil { project: Project ) : Collection = PackagePartClassUtils.getFilesWithCallables( - JetStaticFacadeClassIndex.INSTANCE.get(partFqName.asString(), project, searchScope)) + JetFileFacadeClassIndex.INSTANCE.get(partFqName.asString(), project, searchScope)) } \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/StubIndexServiceImpl.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/StubIndexServiceImpl.java index 63706721f10..581f3f58a5c 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/StubIndexServiceImpl.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/StubIndexServiceImpl.java @@ -17,7 +17,8 @@ package org.jetbrains.kotlin.idea.stubindex; import com.intellij.psi.stubs.IndexSink; -import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; +import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo; +import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil; import com.intellij.psi.stubs.StubElement; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; @@ -39,15 +40,21 @@ public class StubIndexServiceImpl implements StubIndexService { String facadeSimpleName = stub.getFacadeSimpleName(); if (facadeSimpleName != null) { - FqName staticFacadeFqName = packageFqName.child(Name.identifier(facadeSimpleName)); - sink.occurrence(JetStaticFacadeClassIndex.INSTANCE.getKey(), staticFacadeFqName.asString()); + FqName fileFacadeFqName = packageFqName.child(Name.identifier(facadeSimpleName)); + sink.occurrence(JetFileFacadeClassIndex.INSTANCE.getKey(), fileFacadeFqName.asString()); } - else { - JetFile psi = stub.getPsi(); - if (psi != null) { - FqName staticFacadeFqName = PackagePartClassUtils.getPackagePartFqName(psi); - sink.occurrence(JetStaticFacadeClassIndex.INSTANCE.getKey(), staticFacadeFqName.asString()); - } + + String partSimpleName = stub.getPartSimpleName(); + if (partSimpleName != null) { + FqName filePartFqName = packageFqName.child(Name.identifier(partSimpleName)); + sink.occurrence(JetFilePartClassIndex.INSTANCE.getKey(), filePartFqName.asString()); + } + + JetFile jetFile = stub.getPsi(); + if (jetFile != null) { + JvmFileClassInfo fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(jetFile); + sink.occurrence(JetFileFacadeClassIndex.INSTANCE.getKey(), fileClassInfo.getFacadeClassFqName().asString()); + sink.occurrence(JetFilePartClassIndex.INSTANCE.getKey(), fileClassInfo.getFileClassFqName().asString()); } } diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 12a84d70930..5f7a35c9a9e 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -498,7 +498,8 @@ - + +