diff --git a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java index 5f8bbf328cc..02b69ff2282 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java +++ b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java @@ -16,11 +16,15 @@ package org.jetbrains.jet.plugin.project; +import com.google.common.base.Predicates; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.libraries.LibraryUtil; import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.psi.search.GlobalSearchScope; @@ -33,11 +37,13 @@ import com.intellij.util.containers.SLRUCache; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.analyzer.AnalyzeExhaust; +import org.jetbrains.jet.asJava.LightClassUtil; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.lang.resolve.java.JetFilesProvider; import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; import org.jetbrains.jet.plugin.caches.resolve.KotlinDeclarationsCacheImpl; @@ -119,6 +125,17 @@ public final class AnalyzerFacadeWithCache { } private static AnalyzeExhaust analyzeHeadersWithCacheOnFile(@NotNull JetFile fileToCache) { + VirtualFile virtualFile = fileToCache.getVirtualFile(); + if (LightClassUtil.belongsToKotlinBuiltIns(fileToCache) || + virtualFile != null && LibraryUtil.findLibraryEntry(virtualFile, fileToCache.getProject()) != null) { + /* For library sources we should resolve it, not only project files (as KotlinCacheManager do) */ + return AnalyzerFacadeForJVM.INSTANCE.analyzeFiles( + fileToCache.getProject(), + Collections.singleton(fileToCache), + Collections.emptyList(), + Predicates.alwaysFalse() + ); + } KotlinDeclarationsCache cache = KotlinCacheManager.getInstance(fileToCache.getProject()).getDeclarationsFromProject(); return ((KotlinDeclarationsCacheImpl) cache).getAnalyzeExhaust(); } diff --git a/idea/tests/org/jetbrains/jet/plugin/libraries/NavigateToStdlibSourceRegressionTest.java b/idea/tests/org/jetbrains/jet/plugin/libraries/NavigateToStdlibSourceRegressionTest.java index 30697320344..e5838caed31 100644 --- a/idea/tests/org/jetbrains/jet/plugin/libraries/NavigateToStdlibSourceRegressionTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/libraries/NavigateToStdlibSourceRegressionTest.java @@ -22,15 +22,24 @@ import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiReference; import com.intellij.testFramework.LightPlatformTestCase; import com.intellij.testFramework.LightProjectDescriptor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.binding.PsiCodegenPredictor; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.plugin.JetWithJdkAndRuntimeLightProjectDescriptor; import java.io.File; +import java.io.IOException; public class NavigateToStdlibSourceRegressionTest extends NavigateToLibraryRegressionTest { /** @@ -41,6 +50,57 @@ public class NavigateToStdlibSourceRegressionTest extends NavigateToLibraryRegre assertEquals("Test.kt", navigationElement.getContainingFile().getName()); } + public void testJavaClass() throws IOException { + doNavigationInSourcesTest("libraries/stdlib/src/kotlin/Iterators.kt", "Collections", "java.util.Collections"); + } + + public void testKotlinClass() throws IOException { + doNavigationInSourcesTest("libraries/stdlib/src/kotlin/Iterators.kt", "FunctionIterator", "kotlin.FunctionIterator"); + } + + public void testClassWithJavaAnalog() throws IOException { + doNavigationInSourcesTest("libraries/stdlib/src/kotlin/Iterators.kt", "Iterator", "jet.Iterator"); + } + + public void testNavigationInKotlinBuiltIns() throws IOException { + doNavigationInSourcesTest("libraries/stdlib/src/generated/_Arrays.kt", "Array", "jet.Array"); + } + + private void doNavigationInSourcesTest(@NotNull String path, @NotNull String element, @NotNull String expectedFqName) throws IOException { + File file = new File(path); + PsiFile psiFile = getPsiFileForFileFromSources(file); + String text = psiFile.getText(); + int index = text.indexOf(element); + PsiReference ref = psiFile.findReferenceAt(index); + assertNotNull("Cannot find reference at " + index + ", " + + text.substring(index - 20, index) + "" + text.substring(index, index + 20), ref); + PsiElement resolvedElement = ref.resolve(); + assertNotNull("Cannot resolve reference: " + ref.getElement().getText(), resolvedElement); + PsiElement navigationElement = resolvedElement.getNavigationElement(); + checkNavigationElement(navigationElement, expectedFqName); + } + + @NotNull + private PsiFile getPsiFileForFileFromSources(@NotNull File file) { + VirtualFile virtualFile = VfsUtil.findFileByIoFile(file, false); + assertNotNull("Cannot find virtual file for " + file.getAbsolutePath(), virtualFile); + PsiFile psiFile = getPsiManager().findFile(virtualFile); + assertNotNull("Cannot find psi file for " + virtualFile.getCanonicalPath(), psiFile); + return psiFile; + } + + private void checkNavigationElement(@NotNull PsiElement element, @NotNull String expectedName) { + if (element instanceof PsiClass) { + assertEquals(expectedName, ((PsiClass) element).getQualifiedName()); + } + else if (element instanceof JetClass) { + assertEquals(expectedName, JetPsiUtil.getFQName((JetClass) element).getFqName()); + } + else { + fail("Navigation element should be JetClass or PsiClass: " + element.getClass() + ", " + element.getText()); + } + } + @Override protected void tearDown() throws Exception { // Workaround for IDEA's bug during tests.