diff --git a/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/JdkAndMockLibraryProjectDescriptor.java b/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/JdkAndMockLibraryProjectDescriptor.java index aadc32f5adf..29fd9d73b12 100644 --- a/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/JdkAndMockLibraryProjectDescriptor.java +++ b/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/JdkAndMockLibraryProjectDescriptor.java @@ -18,11 +18,15 @@ package org.jetbrains.kotlin.idea.test; import com.intellij.openapi.module.Module; +import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.impl.libraries.LibraryEx; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.util.io.FileUtilRt; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.idea.framework.JSLibraryKind; +import org.jetbrains.kotlin.idea.framework.KotlinSdkType; import org.jetbrains.kotlin.test.MockLibraryUtil; import org.jetbrains.kotlin.utils.PathUtil; @@ -74,6 +78,9 @@ public class JdkAndMockLibraryProjectDescriptor extends KotlinLightProjectDescri if (withRuntime && !isJsLibrary) { libraryModel.addRoot(getJarUrl(PathUtil.getKotlinPathsForDistDirectory().getStdlibPath()), OrderRootType.CLASSES); } + if (isJsLibrary && libraryModel instanceof LibraryEx.ModifiableModelEx) { + ((LibraryEx.ModifiableModelEx) libraryModel).setKind(JSLibraryKind.INSTANCE); + } if (withSources) { libraryModel.addRoot(jarUrl + "src/", OrderRootType.SOURCES); } @@ -85,6 +92,11 @@ public class JdkAndMockLibraryProjectDescriptor extends KotlinLightProjectDescri } } + @Override + public Sdk getSdk() { + return isJsLibrary ? new KotlinSdkType().newSdk(KotlinSdkType.DEFAULT_SDK_NAME) : PluginTestCaseBase.mockJdk(); + } + @NotNull private static String getJarUrl(@NotNull File libraryJar) { return "jar://" + FileUtilRt.toSystemIndependentName(libraryJar.getAbsolutePath()) + "!/"; diff --git a/idea/testData/decompiler/navigation/fromJSLibSource/Icon.kt b/idea/testData/decompiler/navigation/fromJSLibSource/Icon.kt new file mode 100644 index 00000000000..c2554147d50 --- /dev/null +++ b/idea/testData/decompiler/navigation/fromJSLibSource/Icon.kt @@ -0,0 +1,3 @@ +package javax.swing + +class Icon \ No newline at end of file diff --git a/idea/testData/decompiler/navigation/fromJSLibSource/lib.kt b/idea/testData/decompiler/navigation/fromJSLibSource/lib.kt new file mode 100644 index 00000000000..6bb6c74735d --- /dev/null +++ b/idea/testData/decompiler/navigation/fromJSLibSource/lib.kt @@ -0,0 +1,3 @@ +package lib + +fun foo(icon: javax.swing.Icon) {} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/AbstractNavigateFromLibrarySourcesTest.kt b/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/AbstractNavigateFromLibrarySourcesTest.kt new file mode 100644 index 00000000000..c6ad3ae88f7 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/AbstractNavigateFromLibrarySourcesTest.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.decompiler.navigation + +import com.intellij.openapi.roots.LibraryOrderEntry +import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.roots.OrderRootType +import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtLightClassForDecompiledDeclaration +import org.jetbrains.kotlin.idea.test.JdkAndMockLibraryProjectDescriptor +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.utils.sure +import kotlin.test.assertTrue + +abstract class AbstractNavigateFromLibrarySourcesTest : LightCodeInsightFixtureTestCase() { + protected fun navigationElementForReferenceInLibrarySource(filePath: String, referenceText: String): PsiElement { + val libraryOrderEntry = ModuleRootManager.getInstance(myModule!!).orderEntries.first { it is LibraryOrderEntry } + val libSourcesRoot = libraryOrderEntry.getUrls(OrderRootType.SOURCES)[0] + val vf = VirtualFileManager.getInstance().findFileByUrl(libSourcesRoot + "/$filePath")!! + val psiFile = psiManager.findFile(vf)!! + val indexOf = psiFile.text!!.indexOf(referenceText) + val reference = psiFile.findReferenceAt(indexOf) + return reference.sure { "Couldn't find reference" }.resolve().sure { "Couldn't resolve reference" }.navigationElement!! + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/NavigateFromJSLibraryTest.kt b/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/NavigateFromJSLibraryTest.kt new file mode 100644 index 00000000000..72ec3946d70 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/NavigateFromJSLibraryTest.kt @@ -0,0 +1,41 @@ +/* + * 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.decompiler.navigation + +import com.intellij.testFramework.LightProjectDescriptor +import junit.framework.TestCase +import org.jetbrains.kotlin.idea.test.JdkAndMockLibraryProjectDescriptor +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase + +class NavigateFromJSLibrarySourcesTest : AbstractNavigateFromLibrarySourcesTest() { + fun testIcon() { + TestCase.assertEquals( + "Icon.kt", + navigationElementForReferenceInLibrarySource("lib.kt", "Icon").containingFile.name + ) + } + + override fun getProjectDescriptor(): LightProjectDescriptor { + return JdkAndMockLibraryProjectDescriptor( + PluginTestCaseBase.getTestDataPathBase() + "/decompiler/navigation/fromJSLibSource", + true, + true, + true, + false + ) + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/NavigateFromLibrarySourcesTest.kt b/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/NavigateFromLibrarySourcesTest.kt index 86d757f45a5..3a324a501ba 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/NavigateFromLibrarySourcesTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/NavigateFromLibrarySourcesTest.kt @@ -16,24 +16,18 @@ package org.jetbrains.kotlin.idea.decompiler.navigation -import com.intellij.openapi.roots.LibraryOrderEntry -import com.intellij.openapi.roots.ModuleRootManager -import com.intellij.openapi.roots.OrderRootType -import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.testFramework.LightProjectDescriptor -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtLightClassForDecompiledDeclaration import org.jetbrains.kotlin.idea.test.JdkAndMockLibraryProjectDescriptor import org.jetbrains.kotlin.idea.test.PluginTestCaseBase import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.utils.sure import kotlin.test.assertTrue -class NavigateFromLibrarySourcesTest: LightCodeInsightFixtureTestCase() { +class NavigateFromLibrarySourcesTest: AbstractNavigateFromLibrarySourcesTest() { fun testJdkClass() { checkNavigationFromLibrarySource("Thread", "java.lang.Thread") } @@ -48,7 +42,7 @@ class NavigateFromLibrarySourcesTest: LightCodeInsightFixtureTestCase() { // This test is not exactly for navigation, but separating it to another class doesn't worth it. fun testLightClassForLibrarySource() { - val navigationElement = navigationElementForReferenceInLibrarySource("Foo") + val navigationElement = navigationElementForReferenceInLibrarySource("usage.kt", "Foo") assertTrue(navigationElement is KtClassOrObject, "Foo should navigate to JetClassOrObject") val lightClass = (navigationElement as KtClassOrObject).toLightClass() assertTrue(lightClass is KtLightClassForDecompiledDeclaration, @@ -57,23 +51,16 @@ class NavigateFromLibrarySourcesTest: LightCodeInsightFixtureTestCase() { } private fun checkNavigationFromLibrarySource(referenceText: String, targetFqName: String) { - checkNavigationElement(navigationElementForReferenceInLibrarySource(referenceText), targetFqName) - } - - private fun navigationElementForReferenceInLibrarySource(referenceText: String): PsiElement { - val libraryOrderEntry = ModuleRootManager.getInstance(myModule!!).orderEntries.first { it is LibraryOrderEntry } - val libSourcesRoot = libraryOrderEntry.getUrls(OrderRootType.SOURCES)[0] - val vf = VirtualFileManager.getInstance().findFileByUrl(libSourcesRoot + "/usage.kt")!! - val psiFile = psiManager.findFile(vf)!! - val indexOf = psiFile.text!!.indexOf(referenceText) - val reference = psiFile.findReferenceAt(indexOf) - return reference.sure { "Couldn't find reference" }.resolve().sure { "Couldn't resolve reference" }.navigationElement!! + checkNavigationElement(navigationElementForReferenceInLibrarySource("usage.kt", referenceText), targetFqName) } override fun getProjectDescriptor(): LightProjectDescriptor { return JdkAndMockLibraryProjectDescriptor(PluginTestCaseBase.getTestDataPathBase() + "/decompiler/navigation/fromLibSource", true, true, false, false) } + private fun navigationElementForReferenceInLibrarySource(referenceText: String) = + navigationElementForReferenceInLibrarySource("usage.kt", referenceText) + private fun checkNavigationElement(element: PsiElement, expectedFqName: String) { when (element) { is PsiClass -> {