diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java index 9f135d75c83..e1dc5028461 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor; import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityUtilsKt; import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping; +import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.Call; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtFunction; @@ -281,7 +282,13 @@ public class JvmCodegenUtil { @NotNull public static String getModuleName(ModuleDescriptor module) { - return StringsKt.removeSurrounding(module.getName().asString(), "<", ">"); + Name name = module.getStableName(); + if (name == null) { + // Defensive fallback to possibly unstable name, to not fail with exception + return StringsKt.removeSurrounding(module.getName().asString(), "<", ">"); + } else { + return StringsKt.removeSurrounding(name.asString(), "<", ">"); + } } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index 33ba88743e1..ce04fc6dd2c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -247,7 +247,11 @@ class ResolverForProjectImpl( private fun createModuleDescriptor(module: M): ModuleData { val moduleDescriptor = ModuleDescriptorImpl( module.name, - projectContext.storageManager, builtIns, modulePlatforms(module), module.capabilities + projectContext.storageManager, + builtIns, + modulePlatforms(module), + module.capabilities, + module.stableName ) moduleInfoByDescriptor[moduleDescriptor] = module setupModuleDescriptor(module, moduleDescriptor) @@ -274,6 +278,8 @@ interface ModuleInfo { fun modulesWhoseInternalsAreVisible(): Collection = listOf() val capabilities: Map, Any?> get() = mapOf(Capability to this) + val stableName: Name? + get() = null // For common modules, we add built-ins at the beginning of the dependencies list, after the SDK. // This is needed because if a JVM module depends on the common module, we should use JVM built-ins for resolution of both modules. diff --git a/compiler/testData/asJava/lightClasses/ideRegression/OverridingFinalInternal.java b/compiler/testData/asJava/lightClasses/ideRegression/OverridingFinalInternal.java index 26a506f0a73..9a6100bdbb1 100644 --- a/compiler/testData/asJava/lightClasses/ideRegression/OverridingFinalInternal.java +++ b/compiler/testData/asJava/lightClasses/ideRegression/OverridingFinalInternal.java @@ -1,7 +1,7 @@ public final class C extends p.A { - public int getAp$production_sources_for_module_light_idea_test_case() { /* compiled code */ } + public int getAp$light_idea_test_case() { /* compiled code */ } - public int af$production_sources_for_module_light_idea_test_case() { /* compiled code */ } + public int af$light_idea_test_case() { /* compiled code */ } public C() { /* compiled code */ } } diff --git a/compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.java b/compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.java index 7033a501f69..f0d91e0149e 100644 --- a/compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.java +++ b/compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.java @@ -1,13 +1,13 @@ public final class C extends p.A implements p.I { private final int ip = 5; - public int getAp$production_sources_for_module_light_idea_test_case() { /* compiled code */ } + public int getAp$light_idea_test_case() { /* compiled code */ } - public int af$production_sources_for_module_light_idea_test_case() { /* compiled code */ } + public int af$light_idea_test_case() { /* compiled code */ } - public int getIp$production_sources_for_module_light_idea_test_case() { /* compiled code */ } + public int getIp$light_idea_test_case() { /* compiled code */ } - public int $$$production_sources_for_module_light_idea_test_case /* Real name is '$production_sources_for_module_light_idea_test_case' */() { /* compiled code */ } + public int $$$light_idea_test_case /* Real name is '$light_idea_test_case' */() { /* compiled code */ } public C() { /* compiled code */ } } \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt index 584075ca5aa..99315fc8da1 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ModuleDescriptor.kt @@ -25,6 +25,11 @@ interface ModuleDescriptor : DeclarationDescriptor { val builtIns: KotlinBuiltIns + /** + * Stable name of *Kotlin* module. Can be used for ABI (e.g. for mangling of declarations) + */ + val stableName: Name? + fun shouldSeeInternalsOf(targetModule: ModuleDescriptor): Boolean override fun accept(visitor: DeclarationDescriptorVisitor, data: D): R { diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt index c9bbc0a6934..1b08b7a5133 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt @@ -35,7 +35,8 @@ class ModuleDescriptorImpl @JvmOverloads constructor( override val builtIns: KotlinBuiltIns, // May be null in compiler context, should be not-null in IDE context multiTargetPlatform: MultiTargetPlatform? = null, - capabilities: Map, Any?> = emptyMap() + capabilities: Map, Any?> = emptyMap(), + override val stableName: Name? = null ) : DeclarationDescriptorImpl(Annotations.EMPTY, moduleName), ModuleDescriptor { init { if (!moduleName.isSpecial) { diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java index 6a784198812..5fe3e503d33 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorUtils.java @@ -74,6 +74,12 @@ public class ErrorUtils { return Name.special(""); } + @NotNull + @Override + public Name getStableName() { + return Name.special(""); + } + @NotNull @Override public PackageViewDescriptor getPackage(@NotNull FqName fqName) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/lightClasses/IDELightClassContexts.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/lightClasses/IDELightClassContexts.kt index 6e323f3b364..205d2a542df 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/lightClasses/IDELightClassContexts.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/lightClasses/IDELightClassContexts.kt @@ -281,7 +281,8 @@ internal object IDELightClassContexts { private fun setupAdHocResolve(project: Project, realWorldModule: ModuleDescriptor, files: List): ResolveSession { val trace = BindingTraceContext() val sm = LockBasedStorageManager.NO_LOCKS - val moduleDescriptor = ModuleDescriptorImpl(realWorldModule.name, sm, realWorldModule.builtIns) + val moduleDescriptor = + ModuleDescriptorImpl(realWorldModule.name, sm, realWorldModule.builtIns, stableName = realWorldModule.stableName) moduleDescriptor.setDependencies(moduleDescriptor, moduleDescriptor.builtIns.builtInsModule) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt index c572f65b051..8573b0e4339 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/IdeaModuleInfos.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.core.isInTestSourceContentKotlinAware import org.jetbrains.kotlin.idea.framework.getLibraryPlatform import org.jetbrains.kotlin.idea.project.KotlinModuleModificationTracker import org.jetbrains.kotlin.idea.project.TargetPlatformDetector +import org.jetbrains.kotlin.idea.project.getStableName import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.idea.util.isInSourceContentWithoutInjected import org.jetbrains.kotlin.idea.util.rootManager @@ -158,6 +159,8 @@ data class ModuleProductionSourceInfo internal constructor( override val name = Name.special("") + override val stableName: Name = module.getStableName() + override fun contentScope(): GlobalSearchScope = ModuleProductionSourceScope(module) override fun createCachedValueProvider(f: () -> CachedValueProvider.Result) = CachedValueProvider { f() } @@ -170,6 +173,8 @@ data class ModuleTestSourceInfo internal constructor(override val module: Module override val name = Name.special("") + override val stableName: Name = module.getStableName() + override val displayedName get() = module.name + " (test)" override fun contentScope(): GlobalSearchScope = ModuleTestSourceScope(module) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/Platform.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/Platform.kt index a55ddf4f2e2..b79848fe91f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/Platform.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/Platform.kt @@ -24,6 +24,7 @@ import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.roots.ProjectRootModificationTracker import com.intellij.openapi.util.Key +import com.intellij.openapi.util.io.FileUtil import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager @@ -36,11 +37,13 @@ import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgume import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings import org.jetbrains.kotlin.idea.facet.getLibraryLanguageLevel +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.UserDataProperty import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.utils.Jsr305State +import java.io.File val KtElement.platform: TargetPlatform get() = TargetPlatformDetector.getPlatform(containingKtFile) @@ -78,6 +81,32 @@ fun Module.getAndCacheLanguageLevelByDependencies(): LanguageVersion { return languageLevel } +/** + * Returns stable binary name of module from the *Kotlin* point of view. + * Having correct module name is critical for compiler, e.g. for 'internal'-visibility + * mangling (see KT-23668). + * + * Note that build systems and IDEA have their own module systems and, potentially, their + * names can be different from Kotlin module name (though this is the rare case). + */ +fun Module.getStableName(): Name { + // Here we check ideal situation: we have a facet, and it has 'moduleName' argument. + // This should be the case for the most environments + val arguments = KotlinFacetSettingsProvider.getInstance(project).getInitializedSettings(this).mergedCompilerArguments + val explicitNameFromArguments = when (arguments) { + is K2JVMCompilerArguments -> arguments.moduleName + is K2JSCompilerArguments -> arguments.outputFile?.let { FileUtil.getNameWithoutExtension(File(it)) } + is K2MetadataCompilerArguments -> arguments.moduleName + else -> null // Actually, only 'null' possible here + } + + // Here we handle pessimistic case: no facet is found or it declares no 'moduleName' + // We heuristically assume that name of Module in IDEA is the same as Kotlin module (which may be not the case) + val stableNameApproximation = explicitNameFromArguments ?: name + + return Name.special("<$stableNameApproximation>") +} + @JvmOverloads fun Project.getLanguageVersionSettings( contextModule: Module? = null, diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt index a5f2a46e817..3396b7b2be6 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt @@ -28,10 +28,13 @@ import com.intellij.openapi.roots.impl.libraries.LibraryEx import org.jetbrains.jps.model.java.JavaResourceRootType import org.jetbrains.jps.model.java.JavaSourceRootType import org.jetbrains.jps.model.module.JpsModuleSourceRootType +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.idea.caches.project.productionSourceInfo +import org.jetbrains.kotlin.idea.caches.project.testSourceInfo import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinStatus import org.jetbrains.kotlin.idea.configuration.ModuleSourceRootMap @@ -43,6 +46,9 @@ import org.jetbrains.kotlin.idea.framework.KotlinSdkType import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.util.projectStructure.allModules import org.jetbrains.kotlin.idea.util.projectStructure.sdk +import org.jetbrains.kotlin.js.resolve.JsPlatform +import org.jetbrains.kotlin.resolve.TargetPlatform +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.test.KotlinTestUtils import org.junit.Assert import org.junit.Test @@ -2150,6 +2156,88 @@ compileTestKotlin { assertAllModulesConfigured() } + @Test + fun testStableModuleNameWhileUsingGradle_JS() { + createProjectSubFile( + "build.gradle", """ + buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.50") + } + } + + apply plugin: 'kotlin2js' + + repositories { + mavenCentral() + } + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:1.2.50" + } + + """ + ) + importProject() + + checkStableModuleName("project_main", "project", JsPlatform, isProduction = true) + // Note "_test" suffix: this is current behavior of K2JS Compiler + checkStableModuleName("project_test", "project_test", JsPlatform, isProduction = false) + + assertAllModulesConfigured() + } + + @Test + fun testStableModuleNameWhileUsingGradle_JVM() { + createProjectSubFile( + "build.gradle", """ + buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.50") + } + } + + apply plugin: 'kotlin' + + repositories { + mavenCentral() + } + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:1.2.50" + } + + compileKotlin { + kotlinOptions.languageVersion = "1.2" + } + """ + ) + importProject() + + checkStableModuleName("project_main", "project", JvmPlatform, isProduction = true) + checkStableModuleName("project_test", "project", JvmPlatform, isProduction = false) + + assertAllModulesConfigured() + } + + private fun checkStableModuleName(projectName: String, expectedName: String, platform: TargetPlatform, isProduction: Boolean) { + val module = getModule(projectName) + val moduleInfo = if (isProduction) module.productionSourceInfo() else module.testSourceInfo() + + val resolutionFacade = KotlinCacheService.getInstance(myProject).getResolutionFacadeByModuleInfo(moduleInfo!!, platform)!! + val moduleDescriptor = resolutionFacade.moduleDescriptor + + Assert.assertEquals("<$expectedName>", moduleDescriptor.name.asString()) + } + private fun assertAllModulesConfigured() { runReadAction { for (moduleGroup in ModuleSourceRootMap(myProject).groupByBaseModules(myProject.allModules())) { diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt.as31 b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt.as31 index 3b940b76266..2c1f5f3c2e9 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt.as31 +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt.as31 @@ -25,10 +25,13 @@ import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.impl.libraries.LibraryEx +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.idea.caches.project.productionSourceInfo +import org.jetbrains.kotlin.idea.caches.project.testSourceInfo import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinStatus import org.jetbrains.kotlin.idea.configuration.ModuleSourceRootMap @@ -38,6 +41,10 @@ import org.jetbrains.kotlin.idea.framework.CommonLibraryKind import org.jetbrains.kotlin.idea.framework.JSLibraryKind import org.jetbrains.kotlin.idea.framework.KotlinSdkType import org.jetbrains.kotlin.idea.util.projectStructure.allModules +import org.jetbrains.kotlin.idea.util.projectStructure.sdk +import org.jetbrains.kotlin.js.resolve.JsPlatform +import org.jetbrains.kotlin.resolve.TargetPlatform +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.test.KotlinTestUtils import org.junit.Assert import org.junit.Test @@ -1899,6 +1906,87 @@ compileTestKotlin { Assert.assertTrue(ModuleRootManager.getInstance(getModule("project_test")).sdk!!.sdkType is KotlinSdkType) } + @Test + fun testStableModuleNameWhileUsingGradle_JS() { + createProjectSubFile( + "build.gradle", """ + buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.50") + } + } + + apply plugin: 'kotlin2js' + + repositories { + mavenCentral() + } + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:1.2.50" + } + + """ + ) + importProject() + + checkStableModuleName("project", "project", JsPlatform, isProduction = true) + checkStableModuleName("project", "project", JsPlatform, isProduction = false) + + assertAllModulesConfigured() + } + + @Test + fun testStableModuleNameWhileUsingGradle_JVM() { + createProjectSubFile( + "build.gradle", """ + buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.50") + } + } + + apply plugin: 'kotlin' + + repositories { + mavenCentral() + } + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:1.2.50" + } + + compileKotlin { + kotlinOptions.languageVersion = "1.2" + } + """ + ) + importProject() + + checkStableModuleName("project", "project", JvmPlatform, isProduction = true) + checkStableModuleName("project", "project", JvmPlatform, isProduction = false) + + assertAllModulesConfigured() + } + + private fun checkStableModuleName(projectName: String, expectedName: String, platform: TargetPlatform, isProduction: Boolean) { + val module = getModule(projectName) + val moduleInfo = if (isProduction) module.productionSourceInfo() else module.testSourceInfo() + + val resolutionFacade = KotlinCacheService.getInstance(myProject).getResolutionFacadeByModuleInfo(moduleInfo!!, platform)!! + val moduleDescriptor = resolutionFacade.moduleDescriptor + + Assert.assertEquals("<$expectedName>", moduleDescriptor.name.asString()) + } + private fun assertAllModulesConfigured() { runReadAction { for (moduleGroup in ModuleSourceRootMap(myProject).groupByBaseModules(myProject.allModules())) { diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt.as32 b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt.as32 index 3b940b76266..2c1f5f3c2e9 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt.as32 +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleFacetImportTest.kt.as32 @@ -25,10 +25,13 @@ import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.impl.libraries.LibraryEx +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.idea.caches.project.productionSourceInfo +import org.jetbrains.kotlin.idea.caches.project.testSourceInfo import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinStatus import org.jetbrains.kotlin.idea.configuration.ModuleSourceRootMap @@ -38,6 +41,10 @@ import org.jetbrains.kotlin.idea.framework.CommonLibraryKind import org.jetbrains.kotlin.idea.framework.JSLibraryKind import org.jetbrains.kotlin.idea.framework.KotlinSdkType import org.jetbrains.kotlin.idea.util.projectStructure.allModules +import org.jetbrains.kotlin.idea.util.projectStructure.sdk +import org.jetbrains.kotlin.js.resolve.JsPlatform +import org.jetbrains.kotlin.resolve.TargetPlatform +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.test.KotlinTestUtils import org.junit.Assert import org.junit.Test @@ -1899,6 +1906,87 @@ compileTestKotlin { Assert.assertTrue(ModuleRootManager.getInstance(getModule("project_test")).sdk!!.sdkType is KotlinSdkType) } + @Test + fun testStableModuleNameWhileUsingGradle_JS() { + createProjectSubFile( + "build.gradle", """ + buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.50") + } + } + + apply plugin: 'kotlin2js' + + repositories { + mavenCentral() + } + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:1.2.50" + } + + """ + ) + importProject() + + checkStableModuleName("project", "project", JsPlatform, isProduction = true) + checkStableModuleName("project", "project", JsPlatform, isProduction = false) + + assertAllModulesConfigured() + } + + @Test + fun testStableModuleNameWhileUsingGradle_JVM() { + createProjectSubFile( + "build.gradle", """ + buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.50") + } + } + + apply plugin: 'kotlin' + + repositories { + mavenCentral() + } + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:1.2.50" + } + + compileKotlin { + kotlinOptions.languageVersion = "1.2" + } + """ + ) + importProject() + + checkStableModuleName("project", "project", JvmPlatform, isProduction = true) + checkStableModuleName("project", "project", JvmPlatform, isProduction = false) + + assertAllModulesConfigured() + } + + private fun checkStableModuleName(projectName: String, expectedName: String, platform: TargetPlatform, isProduction: Boolean) { + val module = getModule(projectName) + val moduleInfo = if (isProduction) module.productionSourceInfo() else module.testSourceInfo() + + val resolutionFacade = KotlinCacheService.getInstance(myProject).getResolutionFacadeByModuleInfo(moduleInfo!!, platform)!! + val moduleDescriptor = resolutionFacade.moduleDescriptor + + Assert.assertEquals("<$expectedName>", moduleDescriptor.name.asString()) + } + private fun assertAllModulesConfigured() { runReadAction { for (moduleGroup in ModuleSourceRootMap(myProject).groupByBaseModules(myProject.allModules())) { diff --git a/idea/idea-maven/test/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt b/idea/idea-maven/test/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt index fbeb5ddb110..ee8daac7c19 100644 --- a/idea/idea-maven/test/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt +++ b/idea/idea-maven/test/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt @@ -28,9 +28,12 @@ import com.intellij.util.PathUtil import junit.framework.TestCase import org.jetbrains.jps.model.java.JavaResourceRootType import org.jetbrains.jps.model.java.JavaSourceRootType +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.idea.caches.project.productionSourceInfo +import org.jetbrains.kotlin.idea.caches.project.testSourceInfo import org.jetbrains.kotlin.idea.caches.resolve.analyzeAndGetResult import org.jetbrains.kotlin.idea.facet.KotlinFacet import org.jetbrains.kotlin.idea.framework.CommonLibraryKind @@ -38,7 +41,10 @@ import org.jetbrains.kotlin.idea.framework.JSLibraryKind import org.jetbrains.kotlin.idea.framework.KotlinSdkType import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.refactoring.toPsiFile +import org.jetbrains.kotlin.js.resolve.JsPlatform import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.resolve.TargetPlatform +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.junit.Assert import java.io.File @@ -2774,6 +2780,127 @@ class KotlinMavenImporterTest : MavenImportingTestCase() { ) } + fun testStableModuleNameWhileUsingMaven_JVM() { + createProjectSubDirs("src/main/kotlin") + + importProject( + """ + test + project + 1.0.0 + + + + org.jetbrains.kotlin + kotlin-stdlib + $kotlinVersion + + + + + src/main/kotlin + + + + org.jetbrains.kotlin + kotlin-maven-plugin + + + + compile + compile + + compile + + + + + 1.2 + 1.8 + + + + + """ + ) + + assertImporterStatePresent() + + checkStableModuleName("project", "project", JvmPlatform, isProduction = true) + checkStableModuleName("project", "project", JvmPlatform, isProduction = false) + } + + fun testStableModuleNameWhileUsngMaven_JS() { + createProjectSubDirs("src/main/kotlin", "src/main/kotlin.jvm", "src/test/kotlin", "src/test/kotlin.jvm") + + importProject( + """ + test + project + 1.0.0 + + + + org.jetbrains.kotlin + kotlin-stdlib-js + $kotlinVersion + + + + + src/main/kotlin + + + + org.jetbrains.kotlin + kotlin-maven-plugin + + + + compile + compile + + js + + + + + 1.1 + 1.0 + true + true + + -Xcoroutines=enable + + true + test.js + true + commonjs + + + + + """ + ) + + assertImporterStatePresent() + + // Note that we check name induced by '-output-file' -- may be it's not the best + // decision, but we don't have a better one + checkStableModuleName("project", "test", JsPlatform, isProduction = true) + checkStableModuleName("project", "test", JsPlatform, isProduction = false) + } + + private fun checkStableModuleName(projectName: String, expectedName: String, platform: TargetPlatform, isProduction: Boolean) { + val module = getModule(projectName) + val moduleInfo = if (isProduction) module.productionSourceInfo() else module.testSourceInfo() + + val resolutionFacade = KotlinCacheService.getInstance(myProject).getResolutionFacadeByModuleInfo(moduleInfo!!, platform)!! + val moduleDescriptor = resolutionFacade.moduleDescriptor + + Assert.assertEquals("<$expectedName>", moduleDescriptor.name.asString()) + } + private fun assertImporterStatePresent() { assertNotNull("Kotlin importer component is not present", myTestFixture.module.getComponent(KotlinImporterComponent::class.java)) } diff --git a/idea/testData/refactoring/rename/internalFunWithOverrides/after/J.java b/idea/testData/refactoring/rename/internalFunWithOverrides/after/J.java index e068d64ee0e..878ff8cb9cd 100644 --- a/idea/testData/refactoring/rename/internalFunWithOverrides/after/J.java +++ b/idea/testData/refactoring/rename/internalFunWithOverrides/after/J.java @@ -1,6 +1,6 @@ class J extends X.Y { @Override - public int newOverridableMethod$production_sources_for_module_light_idea_test_case(int x) { - return super.newOverridableMethod$production_sources_for_module_light_idea_test_case(x); + public int newOverridableMethod$light_idea_test_case(int x) { + return super.newOverridableMethod$light_idea_test_case(x); } } \ No newline at end of file diff --git a/idea/testData/refactoring/rename/internalFunWithOverrides/before/J.java b/idea/testData/refactoring/rename/internalFunWithOverrides/before/J.java index 8ef83c80828..d0191158855 100644 --- a/idea/testData/refactoring/rename/internalFunWithOverrides/before/J.java +++ b/idea/testData/refactoring/rename/internalFunWithOverrides/before/J.java @@ -1,6 +1,6 @@ class J extends X.Y { @Override - public int overridableMethod$production_sources_for_module_light_idea_test_case(int x) { - return super.overridableMethod$production_sources_for_module_light_idea_test_case(x); + public int overridableMethod$light_idea_test_case(int x) { + return super.overridableMethod$light_idea_test_case(x); } } \ No newline at end of file diff --git a/idea/testData/refactoring/rename/internalVarWithOverrides/after/J.java b/idea/testData/refactoring/rename/internalVarWithOverrides/after/J.java index 2022758dd30..9075813bf7a 100644 --- a/idea/testData/refactoring/rename/internalVarWithOverrides/after/J.java +++ b/idea/testData/refactoring/rename/internalVarWithOverrides/after/J.java @@ -1,11 +1,11 @@ class J extends X.Y { @Override - public int getNewOverridableVar$production_sources_for_module_light_idea_test_case() { - return super.getNewOverridableVar$production_sources_for_module_light_idea_test_case(); + public int getNewOverridableVar$light_idea_test_case() { + return super.getNewOverridableVar$light_idea_test_case(); } @Override - public void setNewOverridableVar$production_sources_for_module_light_idea_test_case(int value) { - super.setNewOverridableVar$production_sources_for_module_light_idea_test_case(value); + public void setNewOverridableVar$light_idea_test_case(int value) { + super.setNewOverridableVar$light_idea_test_case(value); } } \ No newline at end of file diff --git a/idea/testData/refactoring/rename/internalVarWithOverrides/before/J.java b/idea/testData/refactoring/rename/internalVarWithOverrides/before/J.java index eb75f56b21c..e7f88fd3d8d 100644 --- a/idea/testData/refactoring/rename/internalVarWithOverrides/before/J.java +++ b/idea/testData/refactoring/rename/internalVarWithOverrides/before/J.java @@ -1,11 +1,11 @@ class J extends X.Y { @Override - public int getOverridableVar$production_sources_for_module_light_idea_test_case() { - return super.getOverridableVar$production_sources_for_module_light_idea_test_case(); + public int getOverridableVar$light_idea_test_case() { + return super.getOverridableVar$light_idea_test_case(); } @Override - public void setOverridableVar$production_sources_for_module_light_idea_test_case(int value) { - super.setOverridableVar$production_sources_for_module_light_idea_test_case(value); + public void setOverridableVar$light_idea_test_case(int value) { + super.setOverridableVar$light_idea_test_case(value); } } \ No newline at end of file