Light classes: Refactor construction
Introduce LightClassDataHolder: which now is reponsible for constructing clsDelegate Move out light big chunk of delegate building logic out of LightClassDataProvider into LightClassBuilder LightClassData only holds information about single class
This commit is contained in:
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 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.builder
|
||||||
|
|
||||||
|
import com.intellij.openapi.components.ServiceManager
|
||||||
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
|
import com.intellij.openapi.progress.ProcessCanceledException
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.SystemInfo
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.psi.ClassFileViewProvider
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiManager
|
||||||
|
import com.intellij.psi.impl.compiled.ClsFileImpl
|
||||||
|
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
||||||
|
import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl
|
||||||
|
import com.intellij.psi.stubs.StubElement
|
||||||
|
import com.intellij.util.containers.Stack
|
||||||
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
|
|
||||||
|
data class LightClassBuilderResult(val stub: PsiJavaFileStub, val bindingContext: BindingContext, val diagnostics: Diagnostics)
|
||||||
|
|
||||||
|
fun buildLightClass(
|
||||||
|
project: Project,
|
||||||
|
packageFqName: FqName,
|
||||||
|
files: Collection<KtFile>,
|
||||||
|
generateClassFilter: GenerationState.GenerateClassFilter,
|
||||||
|
context: LightClassConstructionContext,
|
||||||
|
generate: (state: GenerationState, files: Collection<KtFile>) -> Unit
|
||||||
|
): LightClassBuilderResult {
|
||||||
|
|
||||||
|
val javaFileStub = createJavaFileStub(project, packageFqName, files)
|
||||||
|
val bindingContext: BindingContext
|
||||||
|
|
||||||
|
val state: GenerationState
|
||||||
|
|
||||||
|
try {
|
||||||
|
val stubStack = Stack<StubElement<PsiElement>>()
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
stubStack.push(javaFileStub as StubElement<PsiElement>)
|
||||||
|
|
||||||
|
state = GenerationState(
|
||||||
|
project,
|
||||||
|
KotlinLightClassBuilderFactory(stubStack),
|
||||||
|
context.module,
|
||||||
|
context.bindingContext,
|
||||||
|
files.toMutableList(),
|
||||||
|
CompilerConfiguration.EMPTY,
|
||||||
|
generateClassFilter,
|
||||||
|
wantsDiagnostics = false
|
||||||
|
)
|
||||||
|
state.beforeCompile()
|
||||||
|
|
||||||
|
bindingContext = state.bindingContext
|
||||||
|
|
||||||
|
generate(state, files)
|
||||||
|
|
||||||
|
val pop = stubStack.pop()
|
||||||
|
if (pop !== javaFileStub) {
|
||||||
|
LOG.error("Unbalanced stack operations: " + pop)
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceManager.getService(project, StubComputationTracker::class.java)?.onStubComputed(javaFileStub)
|
||||||
|
return LightClassBuilderResult(javaFileStub, bindingContext, state.collectedExtraJvmDiagnostics)
|
||||||
|
}
|
||||||
|
catch (e: ProcessCanceledException) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
catch (e: RuntimeException) {
|
||||||
|
logErrorWithOSInfo(e, packageFqName, null)
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createJavaFileStub(project: Project, packageFqName: FqName, files: Collection<KtFile>): PsiJavaFileStub {
|
||||||
|
val javaFileStub = PsiJavaFileStubImpl(packageFqName.asString(), true)
|
||||||
|
javaFileStub.psiFactory = ClsWrapperStubPsiFactory.INSTANCE
|
||||||
|
|
||||||
|
val manager = PsiManager.getInstance(project)
|
||||||
|
|
||||||
|
val virtualFile = getRepresentativeVirtualFile(files)
|
||||||
|
val fakeFile = object : ClsFileImpl(ClassFileViewProvider(manager, virtualFile)) {
|
||||||
|
override fun getStub() = javaFileStub
|
||||||
|
|
||||||
|
override fun getPackageName() = packageFqName.asString()
|
||||||
|
|
||||||
|
override fun isPhysical() = false
|
||||||
|
}
|
||||||
|
|
||||||
|
javaFileStub.psi = fakeFile
|
||||||
|
return javaFileStub
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getRepresentativeVirtualFile(files: Collection<KtFile>): VirtualFile {
|
||||||
|
return files.first().viewProvider.virtualFile
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun logErrorWithOSInfo(cause: Throwable?, fqName: FqName, virtualFile: VirtualFile?) {
|
||||||
|
val path = if (virtualFile == null) "<null>" else virtualFile.path
|
||||||
|
LOG.error(
|
||||||
|
"Could not generate LightClass for $fqName declared in $path\n" +
|
||||||
|
"System: ${SystemInfo.OS_NAME} ${SystemInfo.OS_VERSION} Java Runtime: ${SystemInfo.JAVA_RUNTIME_VERSION}",
|
||||||
|
cause
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val LOG = Logger.getInstance(LightClassDataProvider::class.java)
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2016 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.builder
|
|
||||||
|
|
||||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
|
||||||
|
|
||||||
interface LightClassData {
|
|
||||||
val javaFileStub: PsiJavaFileStub
|
|
||||||
val extraDiagnostics: Diagnostics
|
|
||||||
}
|
|
||||||
|
|
||||||
object InvalidLightClassData: LightClassData {
|
|
||||||
override val javaFileStub: PsiJavaFileStub
|
|
||||||
get() = shouldNotBeCalled()
|
|
||||||
override val extraDiagnostics: Diagnostics
|
|
||||||
get() = shouldNotBeCalled()
|
|
||||||
|
|
||||||
private fun shouldNotBeCalled(): Nothing = throw UnsupportedOperationException("Should not be called")
|
|
||||||
}
|
|
||||||
|
|
||||||
data class LightClassDataImpl(
|
|
||||||
override val javaFileStub: PsiJavaFileStub,
|
|
||||||
override val extraDiagnostics: Diagnostics
|
|
||||||
): LightClassData
|
|
||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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.builder
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
|
import com.intellij.psi.impl.DebugUtil
|
||||||
|
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
||||||
|
import com.intellij.psi.stubs.StubElement
|
||||||
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
|
import org.jetbrains.kotlin.asJava.LightClassUtil.findClass
|
||||||
|
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder.javaFileStub
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
|
|
||||||
|
interface LightClassDataHolder {
|
||||||
|
val javaFileStub: PsiJavaFileStub
|
||||||
|
val extraDiagnostics: Diagnostics
|
||||||
|
|
||||||
|
fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass): LightClassData
|
||||||
|
fun findData(classOrObject: KtClassOrObject): LightClassData = findData { it.findDelegate(classOrObject) }
|
||||||
|
fun findData(classFqName: FqName): LightClassData = findData { it.findDelegate(classFqName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LightClassData {
|
||||||
|
val clsDelegate: PsiClass
|
||||||
|
}
|
||||||
|
|
||||||
|
class LightClassDataImpl(override val clsDelegate: PsiClass) : LightClassData {
|
||||||
|
}
|
||||||
|
|
||||||
|
object InvalidLightClassDataHolder : LightClassDataHolder {
|
||||||
|
override val javaFileStub: PsiJavaFileStub
|
||||||
|
get() = shouldNotBeCalled()
|
||||||
|
|
||||||
|
override val extraDiagnostics: Diagnostics
|
||||||
|
get() = shouldNotBeCalled()
|
||||||
|
|
||||||
|
override fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass) = shouldNotBeCalled()
|
||||||
|
|
||||||
|
private fun shouldNotBeCalled(): Nothing = throw UnsupportedOperationException("Should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
class LightClassDataHolderImpl(
|
||||||
|
override val javaFileStub: PsiJavaFileStub,
|
||||||
|
override val extraDiagnostics: Diagnostics
|
||||||
|
) : LightClassDataHolder {
|
||||||
|
override fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass) = findDelegate(javaFileStub).let(::LightClassDataImpl)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PsiJavaFileStub.findDelegate(classOrObject: KtClassOrObject): PsiClass {
|
||||||
|
findClass(this) {
|
||||||
|
ClsWrapperStubPsiFactory.getOriginalElement(it as StubElement<*>) == classOrObject
|
||||||
|
}?.let { return it }
|
||||||
|
|
||||||
|
val outermostClassOrObject = getOutermostClassOrObject(classOrObject)
|
||||||
|
val ktFileText: String? = try {
|
||||||
|
outermostClassOrObject.containingFile.text
|
||||||
|
}
|
||||||
|
catch (e: Exception) {
|
||||||
|
"Can't get text for outermost class"
|
||||||
|
}
|
||||||
|
|
||||||
|
val stubFileText = DebugUtil.stubTreeToString(this)
|
||||||
|
throw IllegalStateException("Couldn't get delegate for $this\nin $ktFileText\nstub: \n$stubFileText")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PsiJavaFileStub.findDelegate(classFqName: FqName): PsiClass {
|
||||||
|
return findClass(this) {
|
||||||
|
classFqName.asString() == it.qualifiedName
|
||||||
|
} ?: throw IllegalStateException("Facade class $classFqName not found; classes in Java file stub: ${collectClassNames(javaFileStub)}")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun collectClassNames(javaFileStub: PsiJavaFileStub): String {
|
||||||
|
val names = mutableListOf<String>()
|
||||||
|
LightClassUtil.findClass(javaFileStub) { cls ->
|
||||||
|
names.add(cls.qualifiedName ?: "<null>")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
return names.joinToString(prefix = "[", postfix = "]")
|
||||||
|
}
|
||||||
+54
-174
@@ -16,30 +16,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.asJava.builder
|
package org.jetbrains.kotlin.asJava.builder
|
||||||
|
|
||||||
import com.intellij.openapi.components.ServiceManager
|
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.SystemInfo
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.psi.ClassFileViewProvider
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiManager
|
|
||||||
import com.intellij.psi.impl.compiled.ClsFileImpl
|
|
||||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
||||||
import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.stubs.StubElement
|
|
||||||
import com.intellij.psi.util.CachedValueProvider
|
import com.intellij.psi.util.CachedValueProvider
|
||||||
import com.intellij.psi.util.PsiModificationTracker
|
import com.intellij.psi.util.PsiModificationTracker
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.util.containers.Stack
|
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
||||||
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
|
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
|
||||||
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
|
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
|
||||||
import org.jetbrains.kotlin.fileClasses.getFileClassType
|
import org.jetbrains.kotlin.fileClasses.getFileClassType
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -49,150 +36,37 @@ import org.jetbrains.kotlin.psi.KtPsiUtil
|
|||||||
import org.jetbrains.kotlin.psi.KtScript
|
import org.jetbrains.kotlin.psi.KtScript
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
|
||||||
|
|
||||||
abstract class LightClassDataProvider<T : LightClassData>(
|
abstract class LightClassDataProvider<T : LightClassDataHolder>(
|
||||||
private val project: Project
|
private val project: Project
|
||||||
) : CachedValueProvider<T> {
|
) : CachedValueProvider<T> {
|
||||||
|
|
||||||
abstract val files: Collection<KtFile>
|
|
||||||
abstract val packageFqName: FqName
|
|
||||||
|
|
||||||
abstract fun getContext(files: Collection<KtFile>): LightClassConstructionContext
|
|
||||||
abstract fun createLightClassData(javaFileStub: PsiJavaFileStub, bindingContext: BindingContext, extraDiagnostics: Diagnostics): T
|
|
||||||
|
|
||||||
abstract val generateClassFilter: GenerationState.GenerateClassFilter
|
|
||||||
abstract fun generate(state: GenerationState, files: Collection<KtFile>)
|
|
||||||
abstract val isLocal: Boolean
|
abstract val isLocal: Boolean
|
||||||
|
|
||||||
|
open val valueAbsent: Boolean = false
|
||||||
|
|
||||||
override fun compute(): CachedValueProvider.Result<T>? {
|
override fun compute(): CachedValueProvider.Result<T>? {
|
||||||
if (files.isEmpty()) return null
|
if (valueAbsent) return null
|
||||||
|
|
||||||
return CachedValueProvider.Result.create(
|
return CachedValueProvider.Result.create(
|
||||||
computeLightClassData(),
|
computeLightClassData(),
|
||||||
if (isLocal) PsiModificationTracker.MODIFICATION_COUNT else PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
if (isLocal) PsiModificationTracker.MODIFICATION_COUNT else PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeLightClassData(): T {
|
abstract fun computeLightClassData(): T
|
||||||
val packageFqName = packageFqName
|
|
||||||
val files = files
|
|
||||||
|
|
||||||
val context = getContext(files)
|
|
||||||
|
|
||||||
val javaFileStub = createJavaFileStub(packageFqName, files)
|
|
||||||
val bindingContext: BindingContext
|
|
||||||
|
|
||||||
val state: GenerationState
|
|
||||||
|
|
||||||
try {
|
|
||||||
val stubStack = Stack<StubElement<PsiElement>>()
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
stubStack.push(javaFileStub as StubElement<PsiElement>)
|
|
||||||
|
|
||||||
state = GenerationState(
|
|
||||||
project,
|
|
||||||
KotlinLightClassBuilderFactory(stubStack),
|
|
||||||
context.module,
|
|
||||||
context.bindingContext,
|
|
||||||
files.toMutableList(),
|
|
||||||
CompilerConfiguration.EMPTY,
|
|
||||||
generateClassFilter,
|
|
||||||
wantsDiagnostics = false
|
|
||||||
)
|
|
||||||
state.beforeCompile()
|
|
||||||
|
|
||||||
bindingContext = state.bindingContext
|
|
||||||
|
|
||||||
generate(state, files)
|
|
||||||
|
|
||||||
val pop = stubStack.pop()
|
|
||||||
if (pop !== javaFileStub) {
|
|
||||||
LOG.error("Unbalanced stack operations: " + pop)
|
|
||||||
}
|
|
||||||
|
|
||||||
ServiceManager.getService(project, StubComputationTracker::class.java)?.onStubComputed(javaFileStub)
|
|
||||||
return createLightClassData(javaFileStub, bindingContext, state.collectedExtraJvmDiagnostics)
|
|
||||||
}
|
|
||||||
catch (e: ProcessCanceledException) {
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
catch (e: RuntimeException) {
|
|
||||||
logErrorWithOSInfo(e, packageFqName, null)
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createJavaFileStub(packageFqName: FqName, files: Collection<KtFile>): PsiJavaFileStub {
|
|
||||||
val javaFileStub = PsiJavaFileStubImpl(packageFqName.asString(), true)
|
|
||||||
javaFileStub.psiFactory = ClsWrapperStubPsiFactory.INSTANCE
|
|
||||||
|
|
||||||
val manager = PsiManager.getInstance(project)
|
|
||||||
|
|
||||||
val virtualFile = getRepresentativeVirtualFile(files)
|
|
||||||
val fakeFile = object : ClsFileImpl(ClassFileViewProvider(manager, virtualFile)) {
|
|
||||||
override fun getStub() = javaFileStub
|
|
||||||
|
|
||||||
override fun getPackageName() = packageFqName.asString()
|
|
||||||
|
|
||||||
override fun isPhysical() = false
|
|
||||||
}
|
|
||||||
|
|
||||||
javaFileStub.psi = fakeFile
|
|
||||||
return javaFileStub
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getRepresentativeVirtualFile(files: Collection<KtFile>): VirtualFile {
|
|
||||||
return files.first().viewProvider.virtualFile
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun logErrorWithOSInfo(cause: Throwable?, fqName: FqName, virtualFile: VirtualFile?) {
|
|
||||||
val path = if (virtualFile == null) "<null>" else virtualFile.path
|
|
||||||
LOG.error(
|
|
||||||
"Could not generate LightClass for $fqName declared in $path\n" +
|
|
||||||
"System: ${SystemInfo.OS_NAME} ${SystemInfo.OS_VERSION} Java Runtime: ${SystemInfo.JAVA_RUNTIME_VERSION}",
|
|
||||||
cause
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val LOG = Logger.getInstance(LightClassDataProvider::class.java)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassOrObject) :
|
class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassOrObject) :
|
||||||
LightClassDataProvider<LightClassData>(classOrObject.project) {
|
LightClassDataProvider<LightClassDataHolder>(classOrObject.project) {
|
||||||
|
|
||||||
private val file: KtFile
|
|
||||||
get() = classOrObject.containingKtFile
|
|
||||||
|
|
||||||
override val isLocal: Boolean get() = classOrObject.isLocal
|
override val isLocal: Boolean get() = classOrObject.isLocal
|
||||||
|
|
||||||
override fun getContext(files: Collection<KtFile>): LightClassConstructionContext {
|
|
||||||
return LightClassGenerationSupport.getInstance(classOrObject.project).getContextForClassOrObject(classOrObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createLightClassData(
|
override fun computeLightClassData(): LightClassDataHolder {
|
||||||
javaFileStub: PsiJavaFileStub,
|
val file = classOrObject.containingKtFile
|
||||||
bindingContext: BindingContext,
|
|
||||||
extraDiagnostics: Diagnostics): LightClassData {
|
|
||||||
bindingContext.get(BindingContext.CLASS, classOrObject) ?: return InvalidLightClassData
|
|
||||||
|
|
||||||
|
val packageFqName = file.packageFqName
|
||||||
return LightClassDataImpl(
|
val generateClassFilter = object : GenerationState.GenerateClassFilter() {
|
||||||
javaFileStub,
|
|
||||||
extraDiagnostics
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val files: Collection<KtFile>
|
|
||||||
get() = listOf(file)
|
|
||||||
|
|
||||||
override val packageFqName: FqName
|
|
||||||
get() = file.packageFqName
|
|
||||||
|
|
||||||
override val generateClassFilter: GenerationState.GenerateClassFilter
|
|
||||||
get() = object : GenerationState.GenerateClassFilter() {
|
|
||||||
|
|
||||||
override fun shouldGeneratePackagePart(jetFile: KtFile): Boolean {
|
override fun shouldGeneratePackagePart(jetFile: KtFile): Boolean {
|
||||||
return true
|
return true
|
||||||
@@ -242,13 +116,24 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generate(state: GenerationState, files: Collection<KtFile>) {
|
val classConstructionContext = LightClassGenerationSupport.getInstance(classOrObject.project).getContextForClassOrObject(classOrObject)
|
||||||
val packageCodegen = state.factory.forPackage(packageFqName, files)
|
|
||||||
val file = classOrObject.containingKtFile
|
val (stub, bindingContext, diagnostics) = buildLightClass(classOrObject.project, packageFqName, listOf(file), generateClassFilter, classConstructionContext) {
|
||||||
val packagePartType = state.fileClassesProvider.getFileClassType(file)
|
state, files ->
|
||||||
val context = state.rootContext.intoPackagePart(packageCodegen.packageFragment, packagePartType, file)
|
val packageCodegen = state.factory.forPackage(packageFqName, files)
|
||||||
packageCodegen.generateClassOrObject(getOutermostClassOrObject(classOrObject), context)
|
val packagePartType = state.fileClassesProvider.getFileClassType(file)
|
||||||
state.factory.asList()
|
val context = state.rootContext.intoPackagePart(packageCodegen.packageFragment, packagePartType, file)
|
||||||
|
packageCodegen.generateClassOrObject(getOutermostClassOrObject(classOrObject), context)
|
||||||
|
state.factory.asList()
|
||||||
|
}
|
||||||
|
|
||||||
|
bindingContext.get(BindingContext.CLASS, classOrObject) ?: return InvalidLightClassDataHolder
|
||||||
|
|
||||||
|
|
||||||
|
return LightClassDataHolderImpl(
|
||||||
|
stub,
|
||||||
|
diagnostics
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
@@ -256,28 +141,17 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class LightClassDataProviderForFileFacade private constructor(
|
sealed class LightClassDataProviderForFileFacade constructor(
|
||||||
protected val project: Project, protected val facadeFqName: FqName
|
protected val project: Project, protected val facadeFqName: FqName
|
||||||
) : LightClassDataProvider<LightClassDataImpl>(project) {
|
) : LightClassDataProvider<LightClassDataHolderImpl>(project) {
|
||||||
override val packageFqName: FqName
|
|
||||||
get() = facadeFqName.parent()
|
|
||||||
|
|
||||||
override val isLocal: Boolean get() = false
|
override val isLocal: Boolean get() = false
|
||||||
|
abstract val files: Collection<KtFile>
|
||||||
|
|
||||||
override fun getContext(files: Collection<KtFile>): LightClassConstructionContext {
|
override val valueAbsent: Boolean
|
||||||
return LightClassGenerationSupport.getInstance(project).getContextForFacade(files)
|
get() = files.isEmpty()
|
||||||
}
|
|
||||||
|
|
||||||
override fun createLightClassData(
|
override fun computeLightClassData(): LightClassDataHolderImpl {
|
||||||
javaFileStub: PsiJavaFileStub,
|
val generateClassFilter = object : GenerationState.GenerateClassFilter() {
|
||||||
bindingContext: BindingContext,
|
|
||||||
extraDiagnostics: Diagnostics
|
|
||||||
): LightClassDataImpl {
|
|
||||||
return LightClassDataImpl(javaFileStub, extraDiagnostics)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val generateClassFilter: GenerationState.GenerateClassFilter
|
|
||||||
get() = object : GenerationState.GenerateClassFilter() {
|
|
||||||
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean {
|
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean {
|
||||||
return shouldGenerateClass(processingClassOrObject)
|
return shouldGenerateClass(processingClassOrObject)
|
||||||
}
|
}
|
||||||
@@ -295,21 +169,27 @@ sealed class LightClassDataProviderForFileFacade private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generate(state: GenerationState, files: Collection<KtFile>) {
|
val packageFqName = facadeFqName.parent()
|
||||||
if (!files.isEmpty()) {
|
|
||||||
val representativeFile = files.iterator().next()
|
val (stub, _, diagnostics) = buildLightClass(project, packageFqName, files, generateClassFilter, LightClassGenerationSupport.getInstance(project).getContextForFacade(files)) generate@ {
|
||||||
val fileClassInfo = NoResolveFileClassesProvider.getFileClassInfo(representativeFile)
|
state, files ->
|
||||||
if (!fileClassInfo.withJvmMultifileClass) {
|
if (!files.isEmpty()) {
|
||||||
val codegen = state.factory.forPackage(representativeFile.packageFqName, files)
|
val representativeFile = files.iterator().next()
|
||||||
codegen.generate(CompilationErrorHandler.THROW_EXCEPTION)
|
val fileClassInfo = NoResolveFileClassesProvider.getFileClassInfo(representativeFile)
|
||||||
state.factory.asList()
|
if (!fileClassInfo.withJvmMultifileClass) {
|
||||||
return
|
val codegen = state.factory.forPackage(representativeFile.packageFqName, files)
|
||||||
|
codegen.generate(CompilationErrorHandler.THROW_EXCEPTION)
|
||||||
|
state.factory.asList()
|
||||||
|
return@generate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val codegen = state.factory.forMultifileClass(facadeFqName, files)
|
||||||
|
codegen.generate(CompilationErrorHandler.THROW_EXCEPTION)
|
||||||
|
state.factory.asList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val codegen = state.factory.forMultifileClass(facadeFqName, files)
|
return LightClassDataHolderImpl(stub, diagnostics)
|
||||||
codegen.generate(CompilationErrorHandler.THROW_EXCEPTION)
|
|
||||||
state.factory.asList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|||||||
+8
-24
@@ -20,7 +20,6 @@ import com.intellij.openapi.components.ServiceManager
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.Comparing
|
import com.intellij.openapi.util.Comparing
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
|
||||||
import com.intellij.psi.impl.light.LightEmptyImplementsList
|
import com.intellij.psi.impl.light.LightEmptyImplementsList
|
||||||
import com.intellij.psi.impl.light.LightModifierList
|
import com.intellij.psi.impl.light.LightModifierList
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
@@ -30,8 +29,7 @@ import com.intellij.psi.util.CachedValuesManager
|
|||||||
import com.intellij.psi.util.PsiModificationTracker
|
import com.intellij.psi.util.PsiModificationTracker
|
||||||
import com.intellij.util.containers.SLRUCache
|
import com.intellij.util.containers.SLRUCache
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataImpl
|
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForFileFacade
|
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForFileFacade
|
||||||
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
|
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||||
@@ -51,17 +49,17 @@ import javax.swing.Icon
|
|||||||
class KtLightClassForFacade private constructor(
|
class KtLightClassForFacade private constructor(
|
||||||
manager: PsiManager,
|
manager: PsiManager,
|
||||||
private val facadeClassFqName: FqName,
|
private val facadeClassFqName: FqName,
|
||||||
private val lightClassDataCache: CachedValue<LightClassDataImpl>,
|
private val lightClassDataCache: CachedValue<LightClassDataHolder>,
|
||||||
files: Collection<KtFile>
|
files: Collection<KtFile>
|
||||||
) : KtLightClassBase(manager) {
|
) : KtLightClassBase(manager) {
|
||||||
private data class StubCacheKey(val fqName: FqName, val searchScope: GlobalSearchScope)
|
private data class StubCacheKey(val fqName: FqName, val searchScope: GlobalSearchScope)
|
||||||
|
|
||||||
class FacadeStubCache(private val project: Project) {
|
class FacadeStubCache(private val project: Project) {
|
||||||
private inner class FacadeCacheData {
|
private inner class FacadeCacheData {
|
||||||
val cache = object : SLRUCache<StubCacheKey, CachedValue<LightClassDataImpl>>(20, 30) {
|
val cache = object : SLRUCache<StubCacheKey, CachedValue<LightClassDataHolder>>(20, 30) {
|
||||||
override fun createValue(key: StubCacheKey): CachedValue<LightClassDataImpl> {
|
override fun createValue(key: StubCacheKey): CachedValue<LightClassDataHolder> {
|
||||||
val stubProvider = LightClassDataProviderForFileFacade.ByProjectSource(project, key.fqName, key.searchScope)
|
val stubProvider = LightClassDataProviderForFileFacade.ByProjectSource(project, key.fqName, key.searchScope)
|
||||||
return CachedValuesManager.getManager(project).createCachedValue<LightClassDataImpl>(stubProvider, /*trackValue = */false)
|
return CachedValuesManager.getManager(project).createCachedValue<LightClassDataHolder>(stubProvider, /*trackValue = */false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +68,7 @@ class KtLightClassForFacade private constructor(
|
|||||||
{ CachedValueProvider.Result.create(FacadeCacheData(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT) },
|
{ CachedValueProvider.Result.create(FacadeCacheData(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT) },
|
||||||
/*trackValue = */ false)
|
/*trackValue = */ false)
|
||||||
|
|
||||||
operator fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): CachedValue<LightClassDataImpl> {
|
operator fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): CachedValue<LightClassDataHolder> {
|
||||||
synchronized (cachedValue) {
|
synchronized (cachedValue) {
|
||||||
return cachedValue.value.cache.get(StubCacheKey(qualifiedName, searchScope))
|
return cachedValue.value.cache.get(StubCacheKey(qualifiedName, searchScope))
|
||||||
}
|
}
|
||||||
@@ -197,21 +195,7 @@ class KtLightClassForFacade private constructor(
|
|||||||
override fun copy() = KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files)
|
override fun copy() = KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files)
|
||||||
|
|
||||||
override val clsDelegate: PsiClass
|
override val clsDelegate: PsiClass
|
||||||
get() {
|
get() = lightClassDataCache.value.findData(facadeClassFqName).clsDelegate
|
||||||
val javaFileStub = lightClassDataCache.value.javaFileStub
|
|
||||||
return LightClassUtil.findClass(javaFileStub) {
|
|
||||||
facadeClassFqName.asString() == it.qualifiedName
|
|
||||||
} ?: throw IllegalStateException("Facade class $facadeClassFqName not found; classes in Java file stub: ${collectClassNames(javaFileStub)}")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun collectClassNames(javaFileStub: PsiJavaFileStub): String {
|
|
||||||
val names = mutableListOf<String>()
|
|
||||||
LightClassUtil.findClass(javaFileStub) { cls ->
|
|
||||||
names.add(cls.qualifiedName ?: "<null>")
|
|
||||||
false
|
|
||||||
}
|
|
||||||
return names.joinToString(prefix = "[", postfix = "]")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getNavigationElement() = files.iterator().next()
|
override fun getNavigationElement() = files.iterator().next()
|
||||||
|
|
||||||
@@ -284,7 +268,7 @@ class KtLightClassForFacade private constructor(
|
|||||||
): KtLightClassForFacade {
|
): KtLightClassForFacade {
|
||||||
// TODO: refactor, using cached value doesn't make sense for this case
|
// TODO: refactor, using cached value doesn't make sense for this case
|
||||||
val cachedValue = CachedValuesManager.getManager(manager.project).
|
val cachedValue = CachedValuesManager.getManager(manager.project).
|
||||||
createCachedValue<LightClassDataImpl>(
|
createCachedValue<LightClassDataHolder>(
|
||||||
LightClassDataProviderForFileFacade.ByFile(manager.project, facadeClassFqName, file), /*trackValue = */false
|
LightClassDataProviderForFileFacade.ByFile(manager.project, facadeClassFqName, file), /*trackValue = */false
|
||||||
)
|
)
|
||||||
return KtLightClassForFacade(manager, facadeClassFqName, cachedValue, listOf(file))
|
return KtLightClassForFacade(manager, facadeClassFqName, cachedValue, listOf(file))
|
||||||
|
|||||||
+8
-9
@@ -17,17 +17,16 @@
|
|||||||
package org.jetbrains.kotlin.asJava.classes
|
package org.jetbrains.kotlin.asJava.classes
|
||||||
|
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
import com.intellij.psi.impl.DebugUtil
|
||||||
import com.intellij.psi.stubs.StubElement
|
|
||||||
import com.intellij.util.IncorrectOperationException
|
import com.intellij.util.IncorrectOperationException
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
import org.jetbrains.kotlin.asJava.builder.LightClassData
|
||||||
import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory
|
import org.jetbrains.kotlin.asJava.builder.findDelegate
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
|
||||||
class KtLightClassForInterfaceDefaultImpls(
|
class KtLightClassForInterfaceDefaultImpls(
|
||||||
classOrObject: KtClassOrObject)
|
classOrObject: KtClassOrObject)
|
||||||
: KtLightClassForSourceDeclaration(classOrObject){
|
: KtLightClassForSourceDeclaration(classOrObject) {
|
||||||
override fun getQualifiedName(): String? = containingClass?.qualifiedName?.let { it + ".${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}" }
|
override fun getQualifiedName(): String? = containingClass?.qualifiedName?.let { it + ".${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}" }
|
||||||
|
|
||||||
override fun getName() = JvmAbi.DEFAULT_IMPLS_CLASS_NAME
|
override fun getName() = JvmAbi.DEFAULT_IMPLS_CLASS_NAME
|
||||||
@@ -37,11 +36,11 @@ class KtLightClassForInterfaceDefaultImpls(
|
|||||||
return KtLightClassForInterfaceDefaultImpls(classOrObject.copy() as KtClassOrObject)
|
return KtLightClassForInterfaceDefaultImpls(classOrObject.copy() as KtClassOrObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findDelegateClass(javaFileStub: PsiJavaFileStub): PsiClass? {
|
override fun findLightClassData(): LightClassData {
|
||||||
val interfaceClass = LightClassUtil.findClass(javaFileStub) {
|
return getLightClassDataHolder().findData {
|
||||||
ClsWrapperStubPsiFactory.getOriginalElement(it as StubElement<*>) == classOrObject
|
it.findDelegate(classOrObject).findInnerClassByName(JvmAbi.DEFAULT_IMPLS_CLASS_NAME, false)
|
||||||
|
?: throw IllegalStateException("Couldn't get delegate for $this\n in ${DebugUtil.stubTreeToString(it)}")
|
||||||
}
|
}
|
||||||
return interfaceClass?.findInnerClassByName(JvmAbi.DEFAULT_IMPLS_CLASS_NAME, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTypeParameterList(): PsiTypeParameterList? = null
|
override fun getTypeParameterList(): PsiTypeParameterList? = null
|
||||||
|
|||||||
+13
-31
@@ -21,7 +21,6 @@ import com.intellij.openapi.diagnostic.Logger
|
|||||||
import com.intellij.openapi.util.Comparing
|
import com.intellij.openapi.util.Comparing
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.DebugUtil
|
|
||||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
||||||
import com.intellij.psi.scope.PsiScopeProcessor
|
import com.intellij.psi.scope.PsiScopeProcessor
|
||||||
import com.intellij.psi.search.SearchScope
|
import com.intellij.psi.search.SearchScope
|
||||||
@@ -34,9 +33,9 @@ import com.intellij.util.containers.ContainerUtil
|
|||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory.getOriginalElement
|
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassData
|
import org.jetbrains.kotlin.asJava.builder.LightClassData
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataImpl
|
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForClassOrObject
|
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForClassOrObject
|
||||||
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
|
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
|
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
|
||||||
@@ -79,41 +78,24 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
abstract override fun getParent(): PsiElement?
|
abstract override fun getParent(): PsiElement?
|
||||||
abstract override fun getQualifiedName(): String?
|
abstract override fun getQualifiedName(): String?
|
||||||
|
|
||||||
override val clsDelegate: PsiClass by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
override val clsDelegate: PsiClass get() = lightClassData.clsDelegate
|
||||||
val javaFileStub = getJavaFileStub()
|
|
||||||
|
|
||||||
findDelegateClass(javaFileStub) ?: run {
|
private val lightClassData: LightClassData by lazy(LazyThreadSafetyMode.PUBLICATION) { findLightClassData() }
|
||||||
val outermostClassOrObject = getOutermostClassOrObject(classOrObject)
|
|
||||||
val ktFileText: String? = try {
|
|
||||||
outermostClassOrObject.containingFile.text
|
|
||||||
}
|
|
||||||
catch (e: Exception) {
|
|
||||||
"Can't get text for outermost class"
|
|
||||||
}
|
|
||||||
|
|
||||||
val stubFileText = DebugUtil.stubTreeToString(javaFileStub)
|
open protected fun findLightClassData() = getLightClassDataHolder().findData(classOrObject)
|
||||||
throw IllegalStateException("Couldn't get delegate for $this\nin $ktFileText\nstub: \n$stubFileText")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected open fun findDelegateClass(javaFileStub: PsiJavaFileStub): PsiClass? {
|
private fun getJavaFileStub(): PsiJavaFileStub = getLightClassDataHolder().javaFileStub
|
||||||
return LightClassUtil.findClass(javaFileStub) {
|
|
||||||
getOriginalElement(it as StubElement<*>) == classOrObject
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getJavaFileStub(): PsiJavaFileStub = getLightClassData().javaFileStub
|
|
||||||
|
|
||||||
protected fun getDescriptor(): ClassDescriptor? {
|
protected fun getDescriptor(): ClassDescriptor? {
|
||||||
return LightClassGenerationSupport.getInstance(project).resolveToDescriptor(classOrObject) as? ClassDescriptor
|
return LightClassGenerationSupport.getInstance(project).resolveToDescriptor(classOrObject) as? ClassDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLightClassData(): LightClassDataImpl {
|
protected fun getLightClassDataHolder(): LightClassDataHolder {
|
||||||
val lightClassData = getLightClassData(classOrObject)
|
val lightClassData = getLightClassDataHolder(classOrObject)
|
||||||
if (lightClassData !is LightClassDataImpl) {
|
if (lightClassData is InvalidLightClassDataHolder) {
|
||||||
LOG.error("Invalid light class data for existing light class:\n$lightClassData\n${classOrObject.getElementTextWithContext()}")
|
LOG.error("Invalid light class data for existing light class:\n$lightClassData\n${classOrObject.getElementTextWithContext()}")
|
||||||
}
|
}
|
||||||
return lightClassData as LightClassDataImpl
|
return lightClassData
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _containingFile: PsiFile by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
private val _containingFile: PsiFile by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
@@ -341,7 +323,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
override fun getImplementsList() = _implementsList
|
override fun getImplementsList() = _implementsList
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val JAVA_API_STUB = Key.create<CachedValue<LightClassData>>("JAVA_API_STUB")
|
private val JAVA_API_STUB = Key.create<CachedValue<LightClassDataHolder>>("JAVA_API_STUB")
|
||||||
|
|
||||||
private val jetTokenToPsiModifier = listOf(
|
private val jetTokenToPsiModifier = listOf(
|
||||||
PUBLIC_KEYWORD to PsiModifier.PUBLIC,
|
PUBLIC_KEYWORD to PsiModifier.PUBLIC,
|
||||||
@@ -382,11 +364,11 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
return classOrObject.getBody()?.declarations?.isEmpty() ?: true
|
return classOrObject.getBody()?.declarations?.isEmpty() ?: true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLightClassData(classOrObject: KtClassOrObject): LightClassData {
|
fun getLightClassDataHolder(classOrObject: KtClassOrObject): LightClassDataHolder {
|
||||||
return getLightClassCachedValue(classOrObject).value
|
return getLightClassCachedValue(classOrObject).value
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<LightClassData> {
|
fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<LightClassDataHolder> {
|
||||||
var value =
|
var value =
|
||||||
getOutermostClassOrObject(classOrObject).getUserData(JAVA_API_STUB) // stub computed for outer class can be used for inner/nested
|
getOutermostClassOrObject(classOrObject).getUserData(JAVA_API_STUB) // stub computed for outer class can be used for inner/nested
|
||||||
?: classOrObject.getUserData(JAVA_API_STUB)
|
?: classOrObject.getUserData(JAVA_API_STUB)
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ package org.jetbrains.kotlin.asJava
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataImpl
|
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory.cast
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory.cast
|
||||||
@@ -42,7 +42,11 @@ fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostic
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getDiagnosticsForClass(ktClassOrObject: KtClassOrObject): Diagnostics {
|
fun getDiagnosticsForClass(ktClassOrObject: KtClassOrObject): Diagnostics {
|
||||||
return (KtLightClassForSourceDeclaration.getLightClassData(ktClassOrObject) as? LightClassDataImpl)?.extraDiagnostics ?: Diagnostics.EMPTY
|
val lightClassDataHolder = KtLightClassForSourceDeclaration.getLightClassDataHolder(ktClassOrObject)
|
||||||
|
if (lightClassDataHolder is InvalidLightClassDataHolder) {
|
||||||
|
return Diagnostics.EMPTY
|
||||||
|
}
|
||||||
|
return lightClassDataHolder.extraDiagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doGetDiagnostics(): Diagnostics? {
|
fun doGetDiagnostics(): Diagnostics? {
|
||||||
|
|||||||
Reference in New Issue
Block a user