diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.java index 005a840a390..371b2abfc1b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFile.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi; import com.intellij.extapi.psi.PsiFileBase; import com.intellij.lang.ASTNode; import com.intellij.lang.FileASTNode; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.psi.*; import com.intellij.psi.stubs.StubElement; @@ -163,6 +164,11 @@ public class KtFile extends PsiFileBase implements KtDeclarationContainer, KtAnn @NotNull @Override public PsiClass[] getClasses() { + KtFileClassProvider fileClassProvider = ServiceManager.getService(getProject(), KtFileClassProvider.class); + // TODO We don't currently support finding light classes for scripts + if (fileClassProvider != null && !isScript()) { + return fileClassProvider.getFileClasses(this); + } return PsiClass.EMPTY_ARRAY; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFileClassProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFileClassProvider.kt new file mode 100644 index 00000000000..195c7ff897e --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtFileClassProvider.kt @@ -0,0 +1,23 @@ +/* + * 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.psi + +import com.intellij.psi.PsiClass + +interface KtFileClassProvider { + fun getFileClasses(file: KtFile): Array +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt index 8b9004b5f3f..d57e0c360d2 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt @@ -309,7 +309,7 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG return getClassRelativeName(parent).child(name) } - private fun createLightClassForDecompiledKotlinFile(file: KtFile): KtLightClassForDecompiledDeclaration? { + fun createLightClassForDecompiledKotlinFile(file: KtFile): KtLightClassForDecompiledDeclaration? { val virtualFile = file.virtualFile ?: return null val classOrObject = file.declarations.filterIsInstance().singleOrNull() @@ -351,3 +351,21 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG private val LOG = Logger.getInstance(IDELightClassGenerationSupport::class.java) } } + +class KtFileClassProviderImpl(val lightClassGenerationSupport: LightClassGenerationSupport) : KtFileClassProvider { + override fun getFileClasses(file: KtFile): Array { + if (file.isCompiled) { + return arrayOf() + } + + val result = arrayListOf() + file.declarations.filterIsInstance().map { lightClassGenerationSupport.getPsiClass(it) }.filterNotNullTo(result) + + val moduleInfo = file.getModuleInfo() + val fileClassFqName = file.javaFileFacadeFqName + lightClassGenerationSupport.getFacadeClasses(fileClassFqName, moduleInfo.contentScope()).filterTo(result) { + it is KtLightClassForFacade && file in it.files + } + return result.toTypedArray() + } +} diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index d15fc3001ee..a83595a0e2b 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -224,6 +224,9 @@ + + diff --git a/idea/tests/org/jetbrains/kotlin/asJava/KtFileLightClassTest.kt b/idea/tests/org/jetbrains/kotlin/asJava/KtFileLightClassTest.kt new file mode 100644 index 00000000000..fef23a88e66 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/asJava/KtFileLightClassTest.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.asJava + +import com.intellij.testFramework.LightProjectDescriptor +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor +import org.jetbrains.kotlin.psi.KtFile + +class KtFileLightClassTest : KotlinLightCodeInsightFixtureTestCase() { + override fun getProjectDescriptor(): LightProjectDescriptor = KotlinLightProjectDescriptor.INSTANCE + + fun testSimple() { + val file = myFixture.configureByText("A.kt", "class C {}\nobject O {}") as KtFile + val classes = file.classes + assertEquals(2, classes.size) + assertEquals("C", classes[0].qualifiedName) + assertEquals("O", classes[1].qualifiedName) + } + + fun testFileClass() { + val file = myFixture.configureByText("A.kt", "fun f() {}") as KtFile + val classes = file.classes + assertEquals(1, classes.size) + assertEquals("AKt", classes[0].qualifiedName) + } +}