Reformat caches package
This commit is contained in:
@@ -25,13 +25,13 @@ data class CachedAttributeData<out T>(val value: T, val timeStamp: Long)
|
||||
interface FileAttributeService {
|
||||
fun register(id: String, version: Int, fixedSize: Boolean = true) {}
|
||||
|
||||
fun <T: Enum<T>> writeEnumAttribute(id: String, file: VirtualFile, value: T): CachedAttributeData<T> =
|
||||
CachedAttributeData(value, timeStamp = file.timeStamp)
|
||||
fun <T : Enum<T>> writeEnumAttribute(id: String, file: VirtualFile, value: T): CachedAttributeData<T> =
|
||||
CachedAttributeData(value, timeStamp = file.timeStamp)
|
||||
|
||||
fun <T: Enum<T>> readEnumAttribute(id: String, file: VirtualFile, klass: Class<T>): CachedAttributeData<T>? = null
|
||||
fun <T : Enum<T>> readEnumAttribute(id: String, file: VirtualFile, klass: Class<T>): CachedAttributeData<T>? = null
|
||||
|
||||
fun writeBooleanAttribute(id: String, file: VirtualFile, value: Boolean): CachedAttributeData<Boolean> =
|
||||
CachedAttributeData(value, timeStamp = file.timeStamp)
|
||||
CachedAttributeData(value, timeStamp = file.timeStamp)
|
||||
|
||||
fun readBooleanAttribute(id: String, file: VirtualFile): CachedAttributeData<Boolean>? = null
|
||||
|
||||
|
||||
@@ -63,10 +63,10 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
|
||||
val allFqNames = HashSet<FqName?>()
|
||||
|
||||
KotlinClassShortNameIndex.getInstance().get(name, project, effectiveScope)
|
||||
.mapTo(allFqNames) { it.fqName }
|
||||
.mapTo(allFqNames) { it.fqName }
|
||||
|
||||
KotlinFileFacadeShortNameIndex.INSTANCE.get(name, project, effectiveScope)
|
||||
.mapTo(allFqNames) { it.javaFileFacadeFqName }
|
||||
.mapTo(allFqNames) { it.javaFileFacadeFqName }
|
||||
|
||||
val result = ArrayList<PsiClass>()
|
||||
for (fqName in allFqNames) {
|
||||
@@ -111,15 +111,15 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
|
||||
val functionIndex = KotlinFunctionShortNameIndex.getInstance()
|
||||
|
||||
val kotlinFunctionsPsi = functionIndex.get(name, project, scope).asSequence()
|
||||
.flatMap { LightClassUtil.getLightClassMethods(it).asSequence() }
|
||||
.filter { it.name == name }
|
||||
.flatMap { LightClassUtil.getLightClassMethods(it).asSequence() }
|
||||
.filter { it.name == name }
|
||||
|
||||
val propertyAccessorsPsi = sequenceOfLazyValues({ getPropertyNamesCandidatesByAccessorName(Name.identifier(name)) })
|
||||
.flatMap { it.asSequence() }
|
||||
.flatMap { propertiesIndex.get(it.asString(), project, scope).asSequence() }
|
||||
.flatMap { it.getAccessorLightMethods().allDeclarations.asSequence() }
|
||||
.filter { it.name == name }
|
||||
.map { it as? PsiMethod }
|
||||
.flatMap { it.asSequence() }
|
||||
.flatMap { propertiesIndex.get(it.asString(), project, scope).asSequence() }
|
||||
.flatMap { it.getAccessorLightMethods().allDeclarations.asSequence() }
|
||||
.filter { it.name == name }
|
||||
.map { it as? PsiMethod }
|
||||
|
||||
return sequenceOfLazyValues({ kotlinFunctionsPsi }, { propertyAccessorsPsi }).flatMap { it }.filterNotNull()
|
||||
}
|
||||
@@ -142,8 +142,8 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
|
||||
return limitedByMaxCount.toTypedArray()
|
||||
}
|
||||
|
||||
override fun processMethodsWithName(name: String, scope: GlobalSearchScope, processor: Processor<PsiMethod>): Boolean
|
||||
= ContainerUtil.process(getMethodsByName(name, scope), processor)
|
||||
override fun processMethodsWithName(name: String, scope: GlobalSearchScope, processor: Processor<PsiMethod>): Boolean =
|
||||
ContainerUtil.process(getMethodsByName(name, scope), processor)
|
||||
|
||||
override fun getAllMethodNames(): Array<String> {
|
||||
val functionIndex = KotlinFunctionShortNameIndex.getInstance()
|
||||
@@ -151,7 +151,7 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
|
||||
|
||||
val propertiesIndex = KotlinPropertyShortNameIndex.getInstance()
|
||||
val propertyAccessorNames = propertiesIndex.getAllKeys(project)
|
||||
.flatMap(::getAccessorNamesCandidatesByPropertyName)
|
||||
.flatMap(::getAccessorNamesCandidatesByPropertyName)
|
||||
|
||||
return (functionNames + propertyAccessorNames).toTypedArray()
|
||||
}
|
||||
@@ -162,8 +162,8 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
|
||||
|
||||
private fun getFieldSequenceByName(name: String, scope: GlobalSearchScope): Sequence<PsiField> {
|
||||
return KotlinPropertyShortNameIndex.getInstance().get(name, project, scope).asSequence()
|
||||
.map { LightClassUtil.getLightClassBackingField(it) }
|
||||
.filterNotNull()
|
||||
.map { LightClassUtil.getLightClassBackingField(it) }
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getFieldsByName(name: String, scope: GlobalSearchScope): Array<PsiField> {
|
||||
|
||||
+15
-20
@@ -46,9 +46,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
|
||||
class KotlinPackageContentModificationListener(
|
||||
private val project: Project
|
||||
) {
|
||||
class KotlinPackageContentModificationListener(private val project: Project) {
|
||||
init {
|
||||
val connection = project.messageBus.connect()
|
||||
|
||||
@@ -57,22 +55,21 @@ class KotlinPackageContentModificationListener(
|
||||
override fun after(events: List<VFileEvent>) = onEvents(events)
|
||||
|
||||
private fun isRelevant(it: VFileEvent): Boolean =
|
||||
it is VFileMoveEvent || it is VFileCreateEvent || it is VFileCopyEvent || it is VFileDeleteEvent
|
||||
it is VFileMoveEvent || it is VFileCreateEvent || it is VFileCopyEvent || it is VFileDeleteEvent
|
||||
|
||||
fun onEvents(events: List<VFileEvent>) {
|
||||
|
||||
val service = ServiceManager.getService(project, PerModulePackageCacheService::class.java)
|
||||
if (events.size >= FULL_DROP_THRESHOLD) {
|
||||
service.onTooComplexChange()
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
events
|
||||
.asSequence()
|
||||
.filter { it.file != null }
|
||||
.filter(::isRelevant)
|
||||
.mapNotNull { it.file }
|
||||
.filter { it.isDirectory || FileTypeRegistry.getInstance().getFileTypeByFileName(it.name) == KotlinFileType.INSTANCE }
|
||||
.forEach { file -> service.notifyPackageChange(file) }
|
||||
.asSequence()
|
||||
.filter { it.file != null }
|
||||
.filter(::isRelevant)
|
||||
.mapNotNull { it.file }
|
||||
.filter { it.isDirectory || FileTypeRegistry.getInstance().getFileTypeByFileName(it.name) == KotlinFileType.INSTANCE }
|
||||
.forEach { file -> service.notifyPackageChange(file) }
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -139,8 +136,7 @@ class PerModulePackageCacheService(private val project: Project) {
|
||||
private fun checkPendingChanges() = synchronized(this) {
|
||||
if (pendingVFileChanges.size + pendingKtFileChanges.size >= FULL_DROP_THRESHOLD) {
|
||||
onTooComplexChange()
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
|
||||
pendingVFileChanges.forEach { vfile ->
|
||||
// When VirtualFile !isValid (deleted for example), it impossible to use getModuleInfoByVirtualFile
|
||||
@@ -149,13 +145,12 @@ class PerModulePackageCacheService(private val project: Project) {
|
||||
for ((module, data) in cache) {
|
||||
val sourceRootUrls = module.rootManager.sourceRootUrls
|
||||
if (sourceRootUrls.any { url ->
|
||||
vfile.containedInOrContains(url)
|
||||
}) {
|
||||
vfile.containedInOrContains(url)
|
||||
}) {
|
||||
data.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
(getModuleInfoByVirtualFile(project, vfile) as? ModuleSourceInfo)?.let {
|
||||
invalidateCacheForModuleSourceInfo(it)
|
||||
}
|
||||
@@ -174,8 +169,8 @@ class PerModulePackageCacheService(private val project: Project) {
|
||||
}
|
||||
|
||||
private fun VirtualFile.containedInOrContains(root: String) =
|
||||
(VfsUtilCore.isEqualOrAncestor(url, root)
|
||||
|| isDirectory && VfsUtilCore.isEqualOrAncestor(root, url))
|
||||
(VfsUtilCore.isEqualOrAncestor(url, root)
|
||||
|| isDirectory && VfsUtilCore.isEqualOrAncestor(root, url))
|
||||
|
||||
|
||||
fun packageExists(packageFqName: FqName, moduleInfo: ModuleSourceInfo): Boolean {
|
||||
|
||||
+35
-25
@@ -35,12 +35,11 @@ import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
|
||||
import javax.inject.Inject
|
||||
|
||||
class CodeFragmentAnalyzer(
|
||||
private val resolveSession: ResolveSession,
|
||||
private val qualifierResolver: QualifiedExpressionResolver,
|
||||
private val expressionTypingServices: ExpressionTypingServices,
|
||||
private val typeResolver: TypeResolver
|
||||
private val resolveSession: ResolveSession,
|
||||
private val qualifierResolver: QualifiedExpressionResolver,
|
||||
private val expressionTypingServices: ExpressionTypingServices,
|
||||
private val typeResolver: TypeResolver
|
||||
) {
|
||||
|
||||
// component dependency cycle
|
||||
var resolveElementCache: ResolveElementCache? = null
|
||||
@Inject set
|
||||
@@ -54,20 +53,28 @@ class CodeFragmentAnalyzer(
|
||||
|
||||
when (codeFragmentElement) {
|
||||
is KtExpression -> {
|
||||
PreliminaryDeclarationVisitor.createForExpression(codeFragmentElement, trace,
|
||||
expressionTypingServices.languageVersionSettings)
|
||||
PreliminaryDeclarationVisitor.createForExpression(
|
||||
codeFragmentElement, trace,
|
||||
expressionTypingServices.languageVersionSettings
|
||||
)
|
||||
expressionTypingServices.getTypeInfo(
|
||||
scopeForContextElement,
|
||||
codeFragmentElement,
|
||||
TypeUtils.NO_EXPECTED_TYPE,
|
||||
dataFlowInfo,
|
||||
trace,
|
||||
false
|
||||
scopeForContextElement,
|
||||
codeFragmentElement,
|
||||
TypeUtils.NO_EXPECTED_TYPE,
|
||||
dataFlowInfo,
|
||||
trace,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
is KtTypeReference -> {
|
||||
val context = TypeResolutionContext(scopeForContextElement, trace, true, true, codeFragment.suppressDiagnosticsInDebugMode()).noBareTypes()
|
||||
val context = TypeResolutionContext(
|
||||
scopeForContextElement,
|
||||
trace,
|
||||
true,
|
||||
true,
|
||||
codeFragment.suppressDiagnosticsInDebugMode()
|
||||
).noBareTypes()
|
||||
typeResolver.resolvePossiblyBareType(context, codeFragmentElement)
|
||||
}
|
||||
}
|
||||
@@ -76,17 +83,17 @@ class CodeFragmentAnalyzer(
|
||||
//TODO: this code should be moved into debugger which should set correct context for its code fragment
|
||||
private fun KtElement.correctContextForElement(): KtElement {
|
||||
return when (this) {
|
||||
is KtProperty -> this.delegateExpressionOrInitializer
|
||||
is KtFunctionLiteral -> this.bodyExpression?.statements?.lastOrNull()
|
||||
is KtDeclarationWithBody -> this.bodyExpression
|
||||
is KtBlockExpression -> this.statements.lastOrNull()
|
||||
else -> null
|
||||
} ?: this
|
||||
is KtProperty -> this.delegateExpressionOrInitializer
|
||||
is KtFunctionLiteral -> this.bodyExpression?.statements?.lastOrNull()
|
||||
is KtDeclarationWithBody -> this.bodyExpression
|
||||
is KtBlockExpression -> this.statements.lastOrNull()
|
||||
else -> null
|
||||
} ?: this
|
||||
}
|
||||
|
||||
private fun getScopeAndDataFlowForAnalyzeFragment(
|
||||
codeFragment: KtCodeFragment,
|
||||
resolveToElement: (KtElement) -> BindingContext
|
||||
codeFragment: KtCodeFragment,
|
||||
resolveToElement: (KtElement) -> BindingContext
|
||||
): Pair<LexicalScope, DataFlowInfo>? {
|
||||
val context = codeFragment.context
|
||||
|
||||
@@ -103,7 +110,8 @@ class CodeFragmentAnalyzer(
|
||||
|
||||
when (context) {
|
||||
is KtPrimaryConstructor -> {
|
||||
val descriptor = (getClassDescriptor(context.getContainingClassOrObject()) as? ClassDescriptorWithResolutionScopes) ?: return null
|
||||
val descriptor =
|
||||
(getClassDescriptor(context.getContainingClassOrObject()) as? ClassDescriptorWithResolutionScopes) ?: return null
|
||||
|
||||
scopeForContextElement = descriptor.scopeForInitializerResolution
|
||||
dataFlowInfo = DataFlowInfo.EMPTY
|
||||
@@ -145,8 +153,10 @@ class CodeFragmentAnalyzer(
|
||||
}
|
||||
|
||||
val importScopes = importList.imports.mapNotNull {
|
||||
qualifierResolver.processImportReference(it, resolveSession.moduleDescriptor, resolveSession.trace,
|
||||
excludedImportNames = emptyList(), packageFragmentForVisibilityCheck = null)
|
||||
qualifierResolver.processImportReference(
|
||||
it, resolveSession.moduleDescriptor, resolveSession.trace,
|
||||
excludedImportNames = emptyList(), packageFragmentForVisibilityCheck = null
|
||||
)
|
||||
}
|
||||
|
||||
return scopeForContextElement.addImportingScopes(importScopes) to dataFlowInfo
|
||||
|
||||
+44
-44
@@ -54,20 +54,19 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
|
||||
return if (classOrObject.isLocal) {
|
||||
LazyLightClassDataHolder.ForClass(
|
||||
builder,
|
||||
classOrObject.project,
|
||||
exactContextProvider = { IDELightClassContexts.contextForLocalClassOrObject(classOrObject) },
|
||||
dummyContextProvider = null,
|
||||
isLocal = true
|
||||
builder,
|
||||
classOrObject.project,
|
||||
exactContextProvider = { IDELightClassContexts.contextForLocalClassOrObject(classOrObject) },
|
||||
dummyContextProvider = null,
|
||||
isLocal = true
|
||||
)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LazyLightClassDataHolder.ForClass(
|
||||
builder,
|
||||
classOrObject.project,
|
||||
exactContextProvider = { IDELightClassContexts.contextForNonLocalClassOrObject(classOrObject) },
|
||||
dummyContextProvider = { IDELightClassContexts.lightContextForClassOrObject(classOrObject) },
|
||||
isLocal = false
|
||||
builder,
|
||||
classOrObject.project,
|
||||
exactContextProvider = { IDELightClassContexts.contextForNonLocalClassOrObject(classOrObject) },
|
||||
dummyContextProvider = { IDELightClassContexts.lightContextForClassOrObject(classOrObject) },
|
||||
isLocal = false
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -79,19 +78,19 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
val sortedFiles = files.sortedWith(scopeFileComparator)
|
||||
|
||||
return LazyLightClassDataHolder.ForFacade(
|
||||
builder,
|
||||
files.first().project,
|
||||
exactContextProvider = { IDELightClassContexts.contextForFacade(sortedFiles) },
|
||||
dummyContextProvider = { IDELightClassContexts.lightContextForFacade(sortedFiles) }
|
||||
builder,
|
||||
files.first().project,
|
||||
exactContextProvider = { IDELightClassContexts.contextForFacade(sortedFiles) },
|
||||
dummyContextProvider = { IDELightClassContexts.lightContextForFacade(sortedFiles) }
|
||||
)
|
||||
}
|
||||
|
||||
override fun createDataHolderForScript(script: KtScript, builder: LightClassBuilder): LightClassDataHolder.ForScript {
|
||||
return LazyLightClassDataHolder.ForScript(
|
||||
builder,
|
||||
script.project,
|
||||
exactContextProvider = { IDELightClassContexts.contextForScript(script) },
|
||||
dummyContextProvider = { IDELightClassContexts.lightContextForScript(script) }
|
||||
builder,
|
||||
script.project,
|
||||
exactContextProvider = { IDELightClassContexts.contextForScript(script) },
|
||||
dummyContextProvider = { IDELightClassContexts.lightContextForScript(script) }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -108,11 +107,12 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
}
|
||||
|
||||
override fun findClassOrObjectDeclarationsInPackage(
|
||||
packageFqName: FqName,
|
||||
searchScope: GlobalSearchScope
|
||||
packageFqName: FqName,
|
||||
searchScope: GlobalSearchScope
|
||||
): Collection<KtClassOrObject> {
|
||||
return KotlinTopLevelClassByPackageIndex.getInstance().get(
|
||||
packageFqName.asString(), project, sourceAndClassFiles(searchScope, project))
|
||||
packageFqName.asString(), project, sourceAndClassFiles(searchScope, project)
|
||||
)
|
||||
}
|
||||
|
||||
override fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean {
|
||||
@@ -136,7 +136,8 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
}
|
||||
}
|
||||
if ((classOrObject.containingFile as? KtFile)?.analysisContext != null ||
|
||||
classOrObject.containingFile.originalFile.virtualFile != null) {
|
||||
classOrObject.containingFile.originalFile.virtualFile != null
|
||||
) {
|
||||
// explicit request to create light class from dummy.kt
|
||||
return KtLightClassForSourceDeclaration.create(classOrObject)
|
||||
}
|
||||
@@ -146,8 +147,8 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
override fun getLightClassForScript(script: KtScript): KtLightClassForScript? = KtLightClassForScript.create(script)
|
||||
|
||||
private fun withFakeLightClasses(
|
||||
lightClassForFacade: KtLightClassForFacade?,
|
||||
facadeFiles: List<KtFile>
|
||||
lightClassForFacade: KtLightClassForFacade?,
|
||||
facadeFiles: List<KtFile>
|
||||
): List<PsiClass> {
|
||||
if (lightClassForFacade == null) return emptyList()
|
||||
|
||||
@@ -191,8 +192,7 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
val partClassFile = facadeKtFile.virtualFile.parent.findChild(partClassFileShortName) ?: return@mapNotNull null
|
||||
val javaClsClass = createClsJavaClassFromVirtualFile(facadeKtFile, partClassFile, null) ?: return@mapNotNull null
|
||||
KtLightClassForDecompiledDeclaration(javaClsClass, null, facadeKtFile)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// TODO should we build light classes for parts from source?
|
||||
null
|
||||
}
|
||||
@@ -204,18 +204,18 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
}
|
||||
|
||||
fun createLightClassForFileFacade(
|
||||
facadeFqName: FqName,
|
||||
facadeFiles: List<KtFile>,
|
||||
moduleInfo: IdeaModuleInfo
|
||||
facadeFqName: FqName,
|
||||
facadeFiles: List<KtFile>,
|
||||
moduleInfo: IdeaModuleInfo
|
||||
): List<PsiClass> {
|
||||
val (clsFiles, sourceFiles) = facadeFiles.partition { it is KtClsFile }
|
||||
val lightClassesForClsFacades = clsFiles.mapNotNull { createLightClassForDecompiledKotlinFile(it as KtClsFile) }
|
||||
if (moduleInfo is ModuleSourceInfo && sourceFiles.isNotEmpty()) {
|
||||
val lightClassForFacade = KtLightClassForFacade.createForFacade(
|
||||
psiManager, facadeFqName, moduleInfo.contentScope(), sourceFiles)
|
||||
psiManager, facadeFqName, moduleInfo.contentScope(), sourceFiles
|
||||
)
|
||||
return withFakeLightClasses(lightClassForFacade, sourceFiles) + lightClassesForClsFacades
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return lightClassesForClsFacades
|
||||
}
|
||||
}
|
||||
@@ -229,8 +229,7 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
override fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor? {
|
||||
try {
|
||||
return declaration.resolveToDescriptorIfAny(BodyResolveMode.FULL)
|
||||
}
|
||||
catch (e: NoDescriptorForDeclarationException) {
|
||||
} catch (e: NoDescriptorForDeclarationException) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -272,8 +271,8 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
}
|
||||
|
||||
private fun findCorrespondingLightClass(
|
||||
decompiledClassOrObject: KtClassOrObject,
|
||||
rootLightClassForDecompiledFile: KtLightClassForDecompiledDeclaration
|
||||
decompiledClassOrObject: KtClassOrObject,
|
||||
rootLightClassForDecompiledFile: KtLightClassForDecompiledDeclaration
|
||||
): KtLightClassForDecompiledDeclaration {
|
||||
val relativeFqName = getClassRelativeName(decompiledClassOrObject)
|
||||
val iterator = relativeFqName.pathSegments().iterator()
|
||||
@@ -306,17 +305,17 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
val classOrObject = file.declarations.filterIsInstance<KtClassOrObject>().singleOrNull()
|
||||
|
||||
val javaClsClass = createClsJavaClassFromVirtualFile(
|
||||
file, virtualFile,
|
||||
correspondingClassOrObject = classOrObject
|
||||
file, virtualFile,
|
||||
correspondingClassOrObject = classOrObject
|
||||
) ?: return null
|
||||
|
||||
return KtLightClassForDecompiledDeclaration(javaClsClass, classOrObject, file)
|
||||
}
|
||||
|
||||
private fun createClsJavaClassFromVirtualFile(
|
||||
mirrorFile: KtFile,
|
||||
classFile: VirtualFile,
|
||||
correspondingClassOrObject: KtClassOrObject?
|
||||
mirrorFile: KtFile,
|
||||
classFile: VirtualFile,
|
||||
correspondingClassOrObject: KtClassOrObject?
|
||||
): ClsClassImpl? {
|
||||
val javaFileStub = ClsJavaStubByVirtualFileCache.getInstance(project).get(classFile) ?: return null
|
||||
javaFileStub.psiFactory = ClsWrapperStubPsiFactory.INSTANCE
|
||||
@@ -363,7 +362,8 @@ class KtFileClassProviderImpl(val lightClassGenerationSupport: LightClassGenerat
|
||||
|
||||
file.hasTopLevelCallables() ->
|
||||
(lightClassGenerationSupport as IDELightClassGenerationSupport).createLightClassForFileFacade(
|
||||
fileClassFqName, listOf(file), moduleInfo)
|
||||
fileClassFqName, listOf(file), moduleInfo
|
||||
)
|
||||
|
||||
else -> emptyList<PsiClass>()
|
||||
}
|
||||
|
||||
+4
-4
@@ -26,15 +26,15 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
class IDEPackagePartProvider(val scope: GlobalSearchScope) : PackagePartProvider {
|
||||
override fun findPackageParts(packageFqName: String): List<String> =
|
||||
getPackageParts(packageFqName).flatMap(PackageParts::parts).distinct()
|
||||
getPackageParts(packageFqName).flatMap(PackageParts::parts).distinct()
|
||||
|
||||
override fun findMetadataPackageParts(packageFqName: String): List<String> =
|
||||
getPackageParts(packageFqName).flatMap(PackageParts::metadataParts).distinct()
|
||||
getPackageParts(packageFqName).flatMap(PackageParts::metadataParts).distinct()
|
||||
|
||||
private fun getPackageParts(packageFqName: String): MutableList<PackageParts> =
|
||||
FileBasedIndex.getInstance().getValues(KotlinModuleMappingIndex.KEY, packageFqName, scope)
|
||||
FileBasedIndex.getInstance().getValues(KotlinModuleMappingIndex.KEY, packageFqName, scope)
|
||||
|
||||
// Note that in case of several modules with the same name, we return all annotations on all of them, which is probably incorrect
|
||||
override fun getAnnotationsOnBinaryModule(moduleName: String): List<ClassId> =
|
||||
FileBasedIndex.getInstance().getValues(KotlinJvmModuleAnnotationsIndex.KEY, moduleName, scope).flatten()
|
||||
FileBasedIndex.getInstance().getValues(KotlinJvmModuleAnnotationsIndex.KEY, moduleName, scope).flatten()
|
||||
}
|
||||
|
||||
+17
-14
@@ -68,8 +68,7 @@ private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry, for
|
||||
val module = orderEntry.module ?: return emptyList()
|
||||
if (forProduction && orderEntry is ModuleOrderEntryImpl && orderEntry.isProductionOnTestDependency) {
|
||||
listOfNotNull(module.testSourceInfo())
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
module.toInfos()
|
||||
}
|
||||
}
|
||||
@@ -93,10 +92,10 @@ fun <T> Module.cached(provider: CachedValueProvider<T>): T {
|
||||
|
||||
private fun OrderEntry.acceptAsDependency(forProduction: Boolean): Boolean {
|
||||
return this !is ExportableOrderEntry
|
||||
|| !forProduction
|
||||
// this is needed for Maven/Gradle projects with "production-on-test" dependency
|
||||
|| this is ModuleOrderEntryImpl && isProductionOnTestDependency
|
||||
|| scope.isForProductionCompile
|
||||
|| !forProduction
|
||||
// this is needed for Maven/Gradle projects with "production-on-test" dependency
|
||||
|| this is ModuleOrderEntryImpl && isProductionOnTestDependency
|
||||
|| scope.isForProductionCompile
|
||||
}
|
||||
|
||||
private fun ideaModelDependencies(module: Module, forProduction: Boolean): List<IdeaModuleInfo> {
|
||||
@@ -143,7 +142,7 @@ interface ModuleSourceInfo : IdeaModuleInfo, TrackableModuleInfo {
|
||||
get() = TargetPlatformDetector.getPlatform(module)
|
||||
|
||||
override fun createModificationTracker(): ModificationTracker =
|
||||
KotlinModuleModificationTracker(module)
|
||||
KotlinModuleModificationTracker(module)
|
||||
}
|
||||
|
||||
sealed class ModuleSourceInfoWithExpectedBy(private val forProduction: Boolean) : ModuleSourceInfo {
|
||||
@@ -157,7 +156,8 @@ sealed class ModuleSourceInfoWithExpectedBy(private val forProduction: Boolean)
|
||||
override fun dependencies(): List<IdeaModuleInfo> = module.cached(createCachedValueProvider {
|
||||
CachedValueProvider.Result(
|
||||
ideaModelDependencies(module, forProduction),
|
||||
ProjectRootModificationTracker.getInstance(module.project))
|
||||
ProjectRootModificationTracker.getInstance(module.project)
|
||||
)
|
||||
})
|
||||
|
||||
// NB: CachedValueProvider must exist separately in Production / Test source info,
|
||||
@@ -213,7 +213,7 @@ private fun Module.hasProductionRoots() = hasRootsOfType(JavaSourceRootType.SOUR
|
||||
private fun Module.hasTestRoots() = hasRootsOfType(JavaSourceRootType.TEST_SOURCE)
|
||||
|
||||
private fun Module.hasRootsOfType(sourceRootType: JavaSourceRootType): Boolean =
|
||||
rootManager.contentEntries.any { it.getSourceFolders(sourceRootType).isNotEmpty() }
|
||||
rootManager.contentEntries.any { it.getSourceFolders(sourceRootType).isNotEmpty() }
|
||||
|
||||
private abstract class ModuleSourceScope(val module: Module) : GlobalSearchScope(module.project), GlobalSearchScopeWithModuleSources {
|
||||
override fun compare(file1: VirtualFile, file2: VirtualFile) = 0
|
||||
@@ -228,10 +228,12 @@ private class ModuleProductionSourceScope(module: Module) : ModuleSourceScope(mo
|
||||
if (this === other) return true
|
||||
return (other is ModuleProductionSourceScope && module == other.module)
|
||||
}
|
||||
|
||||
// KT-6206
|
||||
override fun hashCode(): Int = 31 * module.hashCode()
|
||||
|
||||
override fun contains(file: VirtualFile) = moduleFileIndex.isInSourceContentWithoutInjected(file) && !moduleFileIndex.isInTestSourceContent(file)
|
||||
override fun contains(file: VirtualFile) =
|
||||
moduleFileIndex.isInSourceContentWithoutInjected(file) && !moduleFileIndex.isInTestSourceContent(file)
|
||||
|
||||
override fun toString() = "ModuleProductionSourceScope($module)"
|
||||
}
|
||||
@@ -243,6 +245,7 @@ private class ModuleTestSourceScope(module: Module) : ModuleSourceScope(module)
|
||||
if (this === other) return true
|
||||
return (other is ModuleTestSourceScope && module == other.module)
|
||||
}
|
||||
|
||||
// KT-6206
|
||||
override fun hashCode(): Int = 37 * module.hashCode()
|
||||
|
||||
@@ -278,7 +281,7 @@ class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo,
|
||||
get() = LibrarySourceInfo(project, library)
|
||||
|
||||
override fun getLibraryRoots(): Collection<String> =
|
||||
library.getFiles(OrderRootType.CLASSES).mapNotNull(PathUtil::getLocalPath)
|
||||
library.getFiles(OrderRootType.CLASSES).mapNotNull(PathUtil::getLocalPath)
|
||||
|
||||
override fun toString() = "LibraryInfo(libraryName=${library.name})"
|
||||
|
||||
@@ -331,7 +334,7 @@ object NotUnderContentRootModuleInfo : IdeaModuleInfo {
|
||||
}
|
||||
|
||||
private class LibraryWithoutSourceScope(project: Project, private val library: Library) :
|
||||
LibraryScopeBase(project, library.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
||||
LibraryScopeBase(project, library.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
||||
|
||||
override fun getFileRoot(file: VirtualFile): VirtualFile? = myIndex.getClassRootForFile(file)
|
||||
|
||||
@@ -343,7 +346,7 @@ private class LibraryWithoutSourceScope(project: Project, private val library: L
|
||||
}
|
||||
|
||||
private class LibrarySourceScope(project: Project, private val library: Library) :
|
||||
LibraryScopeBase(project, arrayOf<VirtualFile>(), library.getFiles(OrderRootType.SOURCES)) {
|
||||
LibraryScopeBase(project, arrayOf<VirtualFile>(), library.getFiles(OrderRootType.SOURCES)) {
|
||||
|
||||
override fun getFileRoot(file: VirtualFile): VirtualFile? = myIndex.getSourceRootForFile(file)
|
||||
|
||||
@@ -356,7 +359,7 @@ private class LibrarySourceScope(project: Project, private val library: Library)
|
||||
|
||||
//TODO: (module refactoring) android sdk has modified scope
|
||||
private class SdkScope(project: Project, private val sdk: Sdk) :
|
||||
LibraryScopeBase(project, sdk.rootProvider.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
||||
LibraryScopeBase(project, sdk.rootProvider.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
||||
|
||||
override fun equals(other: Any?) = other is SdkScope && sdk == other.sdk
|
||||
|
||||
|
||||
+4
-5
@@ -91,15 +91,14 @@ fun PsiParameter.getParameterDescriptor(resolutionFacade: ResolutionFacade = jav
|
||||
}
|
||||
|
||||
fun PsiClass.resolveToDescriptor(
|
||||
resolutionFacade: ResolutionFacade,
|
||||
declarationTranslator: (KtClassOrObject) -> KtClassOrObject? = { it }
|
||||
resolutionFacade: ResolutionFacade,
|
||||
declarationTranslator: (KtClassOrObject) -> KtClassOrObject? = { it }
|
||||
): ClassDescriptor? {
|
||||
return if (this is KtLightClass && this !is KtLightClassForDecompiledDeclaration) {
|
||||
val origin = this.kotlinOrigin ?: return null
|
||||
val declaration = declarationTranslator(origin) ?: return null
|
||||
resolutionFacade.resolveToDescriptor(declaration)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
getJavaClassDescriptor(resolutionFacade)
|
||||
} as? ClassDescriptor
|
||||
}
|
||||
@@ -143,4 +142,4 @@ private fun <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElemen
|
||||
}
|
||||
|
||||
fun PsiElement.javaResolutionFacade() =
|
||||
KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform)
|
||||
KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform)
|
||||
|
||||
+140
-118
@@ -71,27 +71,27 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
override fun getSuppressionCache(): KotlinSuppressCache = kotlinSuppressCache.value
|
||||
|
||||
private val globalFacadesPerPlatformAndSdk: SLRUCache<PlatformAnalysisSettings, GlobalFacade> =
|
||||
object : SLRUCache<PlatformAnalysisSettings, GlobalFacade>(2 * 3 * 2, 2 * 3 * 2) {
|
||||
override fun createValue(settings: PlatformAnalysisSettings): GlobalFacade {
|
||||
return GlobalFacade(settings)
|
||||
}
|
||||
object : SLRUCache<PlatformAnalysisSettings, GlobalFacade>(2 * 3 * 2, 2 * 3 * 2) {
|
||||
override fun createValue(settings: PlatformAnalysisSettings): GlobalFacade {
|
||||
return GlobalFacade(settings)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val facadesForScriptDependencies: SLRUCache<ScriptModuleInfo, ProjectResolutionFacade> =
|
||||
object : SLRUCache<ScriptModuleInfo, ProjectResolutionFacade>(2, 3) {
|
||||
override fun createValue(scriptModuleInfo: ScriptModuleInfo?): ProjectResolutionFacade {
|
||||
return createFacadeForScriptDependencies(ScriptDependenciesModuleInfo(project, scriptModuleInfo))
|
||||
}
|
||||
object : SLRUCache<ScriptModuleInfo, ProjectResolutionFacade>(2, 3) {
|
||||
override fun createValue(scriptModuleInfo: ScriptModuleInfo?): ProjectResolutionFacade {
|
||||
return createFacadeForScriptDependencies(ScriptDependenciesModuleInfo(project, scriptModuleInfo))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFacadeForScriptDependencies(scriptModuleInfo: ScriptModuleInfo) = synchronized(facadesForScriptDependencies) {
|
||||
facadesForScriptDependencies.get(scriptModuleInfo)
|
||||
}
|
||||
|
||||
private fun createFacadeForScriptDependencies(
|
||||
dependenciesModuleInfo: ScriptDependenciesModuleInfo,
|
||||
syntheticFiles: Collection<KtFile> = listOf()
|
||||
dependenciesModuleInfo: ScriptDependenciesModuleInfo,
|
||||
syntheticFiles: Collection<KtFile> = listOf()
|
||||
): ProjectResolutionFacade {
|
||||
val sdk = findJdk(dependenciesModuleInfo.scriptModuleInfo?.externalDependencies, project)
|
||||
val platform = JvmPlatform // TODO: Js scripts?
|
||||
@@ -99,18 +99,18 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
val sdkFacade = GlobalFacade(facadeKey).facadeForSdk
|
||||
val globalContext = sdkFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker()
|
||||
return ProjectResolutionFacade(
|
||||
"facadeForScriptDependencies", "dependencies of scripts",
|
||||
project, globalContext, facadeKey,
|
||||
reuseDataFrom = sdkFacade,
|
||||
allModules = dependenciesModuleInfo.dependencies(),
|
||||
//TODO: provide correct trackers
|
||||
dependencies = listOf(
|
||||
LibraryModificationTracker.getInstance(project),
|
||||
ProjectRootModificationTracker.getInstance(project),
|
||||
ScriptDependenciesModificationTracker.getInstance(project)
|
||||
),
|
||||
moduleFilter = { it == dependenciesModuleInfo },
|
||||
syntheticFiles = syntheticFiles
|
||||
"facadeForScriptDependencies", "dependencies of scripts",
|
||||
project, globalContext, facadeKey,
|
||||
reuseDataFrom = sdkFacade,
|
||||
allModules = dependenciesModuleInfo.dependencies(),
|
||||
//TODO: provide correct trackers
|
||||
dependencies = listOf(
|
||||
LibraryModificationTracker.getInstance(project),
|
||||
ProjectRootModificationTracker.getInstance(project),
|
||||
ScriptDependenciesModificationTracker.getInstance(project)
|
||||
),
|
||||
moduleFilter = { it == dependenciesModuleInfo },
|
||||
syntheticFiles = syntheticFiles
|
||||
)
|
||||
}
|
||||
|
||||
@@ -118,51 +118,51 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
private inner class GlobalFacade(settings: PlatformAnalysisSettings) {
|
||||
private val sdkContext = GlobalContext()
|
||||
val facadeForSdk = ProjectResolutionFacade(
|
||||
"facadeForSdk", "sdk ${settings.sdk}",
|
||||
project, sdkContext, settings,
|
||||
moduleFilter = { it is SdkInfo },
|
||||
dependencies = listOf(
|
||||
LibraryModificationTracker.getInstance(project),
|
||||
ProjectRootModificationTracker.getInstance(project)
|
||||
),
|
||||
invalidateOnOOCB = false,
|
||||
reuseDataFrom = null
|
||||
"facadeForSdk", "sdk ${settings.sdk}",
|
||||
project, sdkContext, settings,
|
||||
moduleFilter = { it is SdkInfo },
|
||||
dependencies = listOf(
|
||||
LibraryModificationTracker.getInstance(project),
|
||||
ProjectRootModificationTracker.getInstance(project)
|
||||
),
|
||||
invalidateOnOOCB = false,
|
||||
reuseDataFrom = null
|
||||
)
|
||||
|
||||
private val librariesContext = sdkContext.contextWithNewLockAndCompositeExceptionTracker()
|
||||
val facadeForLibraries = ProjectResolutionFacade(
|
||||
"facadeForLibraries", "project libraries for platform ${settings.sdk}",
|
||||
project, librariesContext, settings,
|
||||
reuseDataFrom = facadeForSdk,
|
||||
moduleFilter = { it is LibraryInfo },
|
||||
invalidateOnOOCB = false,
|
||||
dependencies = listOf(
|
||||
LibraryModificationTracker.getInstance(project),
|
||||
ProjectRootModificationTracker.getInstance(project)
|
||||
)
|
||||
"facadeForLibraries", "project libraries for platform ${settings.sdk}",
|
||||
project, librariesContext, settings,
|
||||
reuseDataFrom = facadeForSdk,
|
||||
moduleFilter = { it is LibraryInfo },
|
||||
invalidateOnOOCB = false,
|
||||
dependencies = listOf(
|
||||
LibraryModificationTracker.getInstance(project),
|
||||
ProjectRootModificationTracker.getInstance(project)
|
||||
)
|
||||
)
|
||||
|
||||
private val modulesContext = librariesContext.contextWithNewLockAndCompositeExceptionTracker()
|
||||
val facadeForModules = ProjectResolutionFacade(
|
||||
"facadeForModules", "project source roots and libraries for platform ${settings.platform}",
|
||||
project, modulesContext, settings,
|
||||
reuseDataFrom = facadeForLibraries,
|
||||
moduleFilter = { !it.isLibraryClasses() },
|
||||
dependencies = listOf(
|
||||
LibraryModificationTracker.getInstance(project),
|
||||
ProjectRootModificationTracker.getInstance(project)
|
||||
)
|
||||
"facadeForModules", "project source roots and libraries for platform ${settings.platform}",
|
||||
project, modulesContext, settings,
|
||||
reuseDataFrom = facadeForLibraries,
|
||||
moduleFilter = { !it.isLibraryClasses() },
|
||||
dependencies = listOf(
|
||||
LibraryModificationTracker.getInstance(project),
|
||||
ProjectRootModificationTracker.getInstance(project)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun IdeaModuleInfo.supportsAdditionalBuiltInsMembers(): Boolean {
|
||||
return IDELanguageSettingsProvider
|
||||
.getLanguageVersionSettings(this, project)
|
||||
.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)
|
||||
.getLanguageVersionSettings(this, project)
|
||||
.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)
|
||||
}
|
||||
|
||||
private fun globalFacade(settings: PlatformAnalysisSettings) =
|
||||
getOrBuildGlobalFacade(settings).facadeForModules
|
||||
getOrBuildGlobalFacade(settings).facadeForModules
|
||||
|
||||
private fun librariesFacade(settings: PlatformAnalysisSettings) = getOrBuildGlobalFacade(settings).facadeForLibraries
|
||||
|
||||
@@ -183,38 +183,40 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
ModificationTracker {
|
||||
files.sumByLong { it.outOfBlockModificationCount }
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ModificationTracker {
|
||||
files.sumByLong { it.outOfBlockModificationCount + it.modificationStamp }
|
||||
}
|
||||
}
|
||||
|
||||
val dependenciesForSyntheticFileCache = listOf(
|
||||
val dependenciesForSyntheticFileCache =
|
||||
listOf(
|
||||
PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT,
|
||||
filesModificationTracker,
|
||||
ScriptDependenciesModificationTracker.getInstance(project)
|
||||
)
|
||||
|
||||
val resolverDebugName = "completion/highlighting in $syntheticFileModule for files ${files.joinToString { it.name }} for platform $targetPlatform"
|
||||
val resolverDebugName =
|
||||
"completion/highlighting in $syntheticFileModule for files ${files.joinToString { it.name }} for platform $targetPlatform"
|
||||
|
||||
fun makeProjectResolutionFacade(debugName: String,
|
||||
globalContext: GlobalContextImpl,
|
||||
reuseDataFrom: ProjectResolutionFacade? = null,
|
||||
moduleFilter: (IdeaModuleInfo) -> Boolean = { true },
|
||||
allModules: Collection<IdeaModuleInfo>? = null
|
||||
fun makeProjectResolutionFacade(
|
||||
debugName: String,
|
||||
globalContext: GlobalContextImpl,
|
||||
reuseDataFrom: ProjectResolutionFacade? = null,
|
||||
moduleFilter: (IdeaModuleInfo) -> Boolean = { true },
|
||||
allModules: Collection<IdeaModuleInfo>? = null
|
||||
): ProjectResolutionFacade {
|
||||
return ProjectResolutionFacade(
|
||||
debugName,
|
||||
resolverDebugName,
|
||||
project,
|
||||
globalContext,
|
||||
settings,
|
||||
syntheticFiles = files,
|
||||
reuseDataFrom = reuseDataFrom,
|
||||
moduleFilter = moduleFilter,
|
||||
dependencies = dependenciesForSyntheticFileCache,
|
||||
allModules = allModules
|
||||
debugName,
|
||||
resolverDebugName,
|
||||
project,
|
||||
globalContext,
|
||||
settings,
|
||||
syntheticFiles = files,
|
||||
reuseDataFrom = reuseDataFrom,
|
||||
moduleFilter = moduleFilter,
|
||||
dependencies = dependenciesForSyntheticFileCache,
|
||||
allModules = allModules
|
||||
)
|
||||
}
|
||||
|
||||
@@ -224,10 +226,10 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
val modulesFacade = globalFacade(settings)
|
||||
val globalContext = modulesFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker()
|
||||
makeProjectResolutionFacade(
|
||||
"facadeForSynthetic in ModuleSourceInfo",
|
||||
globalContext,
|
||||
reuseDataFrom = modulesFacade,
|
||||
moduleFilter = { it in dependentModules }
|
||||
"facadeForSynthetic in ModuleSourceInfo",
|
||||
globalContext,
|
||||
reuseDataFrom = modulesFacade,
|
||||
moduleFilter = { it in dependentModules }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -235,11 +237,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
val facadeForScriptDependencies = getFacadeForScriptDependencies(syntheticFileModule)
|
||||
val globalContext = facadeForScriptDependencies.globalContext.contextWithNewLockAndCompositeExceptionTracker()
|
||||
makeProjectResolutionFacade(
|
||||
"facadeForSynthetic in ScriptModuleInfo",
|
||||
globalContext,
|
||||
reuseDataFrom = facadeForScriptDependencies,
|
||||
allModules = syntheticFileModule.dependencies(),
|
||||
moduleFilter = { it == syntheticFileModule }
|
||||
"facadeForSynthetic in ScriptModuleInfo",
|
||||
globalContext,
|
||||
reuseDataFrom = facadeForScriptDependencies,
|
||||
allModules = syntheticFileModule.dependencies(),
|
||||
moduleFilter = { it == syntheticFileModule }
|
||||
)
|
||||
}
|
||||
syntheticFileModule is ScriptDependenciesModuleInfo -> {
|
||||
@@ -250,11 +252,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
val facadeForScriptDependencies = createFacadeForScriptDependencies(syntheticFileModule.binariesModuleInfo, files)
|
||||
val globalContext = facadeForScriptDependencies.globalContext.contextWithNewLockAndCompositeExceptionTracker()
|
||||
makeProjectResolutionFacade(
|
||||
"facadeForSynthetic in ScriptDependenciesSourceModuleInfo",
|
||||
globalContext,
|
||||
reuseDataFrom = facadeForScriptDependencies,
|
||||
allModules = syntheticFileModule.dependencies(),
|
||||
moduleFilter = { it == syntheticFileModule }
|
||||
"facadeForSynthetic in ScriptDependenciesSourceModuleInfo",
|
||||
globalContext,
|
||||
reuseDataFrom = facadeForScriptDependencies,
|
||||
allModules = syntheticFileModule.dependencies(),
|
||||
moduleFilter = { it == syntheticFileModule }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -262,10 +264,10 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
val librariesFacade = librariesFacade(settings)
|
||||
val globalContext = librariesFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker()
|
||||
makeProjectResolutionFacade(
|
||||
"facadeForSynthetic in LibrarySourceInfo or NotUnderContentRootModuleInfo",
|
||||
globalContext,
|
||||
reuseDataFrom = librariesFacade,
|
||||
moduleFilter = { it == syntheticFileModule }
|
||||
"facadeForSynthetic in LibrarySourceInfo or NotUnderContentRootModuleInfo",
|
||||
globalContext,
|
||||
reuseDataFrom = librariesFacade,
|
||||
moduleFilter = { it == syntheticFileModule }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -276,8 +278,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
LOG.warn("Creating cache with synthetic files ($files) in classes of library $syntheticFileModule")
|
||||
val globalContext = GlobalContext()
|
||||
makeProjectResolutionFacade(
|
||||
"facadeForSynthetic for file under both classes and root",
|
||||
globalContext
|
||||
"facadeForSynthetic for file under both classes and root",
|
||||
globalContext
|
||||
)
|
||||
}
|
||||
|
||||
@@ -286,33 +288,54 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
}
|
||||
|
||||
private val suppressAnnotationShortName = KotlinBuiltIns.FQ_NAMES.suppress.shortName().identifier
|
||||
private val kotlinSuppressCache: CachedValue<KotlinSuppressCache> = CachedValuesManager.getManager(project).createCachedValue({
|
||||
CachedValueProvider.Result<KotlinSuppressCache>(object : KotlinSuppressCache() {
|
||||
override fun getSuppressionAnnotations(annotated: KtAnnotated): List<AnnotationDescriptor> {
|
||||
if (annotated.annotationEntries.none {
|
||||
it.calleeExpression?.text?.endsWith(suppressAnnotationShortName) ?: false }) {
|
||||
// Avoid running resolve heuristics
|
||||
// TODO: Check aliases in imports
|
||||
return emptyList()
|
||||
}
|
||||
private val kotlinSuppressCache: CachedValue<KotlinSuppressCache> = CachedValuesManager.getManager(project).createCachedValue(
|
||||
{
|
||||
CachedValueProvider.Result<KotlinSuppressCache>(
|
||||
object : KotlinSuppressCache() {
|
||||
override fun getSuppressionAnnotations(annotated: KtAnnotated): List<AnnotationDescriptor> {
|
||||
if (annotated.annotationEntries.none {
|
||||
it.calleeExpression?.text?.endsWith(suppressAnnotationShortName) == true
|
||||
}
|
||||
) {
|
||||
// Avoid running resolve heuristics
|
||||
// TODO: Check aliases in imports
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val context = when (annotated) {
|
||||
is KtFile -> annotated.fileAnnotationList?.analyze(BodyResolveMode.PARTIAL) ?: return emptyList()
|
||||
is KtModifierListOwner -> annotated.modifierList?.analyze(BodyResolveMode.PARTIAL) ?: return emptyList()
|
||||
else -> annotated.analyze(BodyResolveMode.PARTIAL)
|
||||
}
|
||||
val context =
|
||||
when (annotated) {
|
||||
is KtFile -> {
|
||||
annotated.fileAnnotationList?.analyze(BodyResolveMode.PARTIAL)
|
||||
?: return emptyList()
|
||||
}
|
||||
is KtModifierListOwner -> {
|
||||
annotated.modifierList?.analyze(BodyResolveMode.PARTIAL)
|
||||
?: return emptyList()
|
||||
}
|
||||
else ->
|
||||
annotated.analyze(BodyResolveMode.PARTIAL)
|
||||
}
|
||||
|
||||
val annotatedDescriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, annotated)
|
||||
val annotatedDescriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, annotated)
|
||||
|
||||
return if (annotatedDescriptor != null) {
|
||||
annotatedDescriptor.annotations.toList()
|
||||
}
|
||||
else {
|
||||
annotated.annotationEntries.mapNotNull { context.get(BindingContext.ANNOTATION, it) }
|
||||
}
|
||||
}
|
||||
}, LibraryModificationTracker.getInstance(project), PsiModificationTracker.MODIFICATION_COUNT)
|
||||
}, false)
|
||||
if (annotatedDescriptor != null) {
|
||||
return annotatedDescriptor.annotations.toList()
|
||||
}
|
||||
|
||||
return annotated.annotationEntries.mapNotNull {
|
||||
context.get(
|
||||
BindingContext.ANNOTATION,
|
||||
it
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
LibraryModificationTracker.getInstance(project),
|
||||
PsiModificationTracker.MODIFICATION_COUNT
|
||||
)
|
||||
},
|
||||
false
|
||||
)
|
||||
|
||||
private val syntheticFileCachesLock = Any()
|
||||
|
||||
@@ -342,8 +365,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
return if (notInSourceFiles.isNotEmpty()) {
|
||||
val projectFacade = getFacadeForSyntheticFiles(notInSourceFiles)
|
||||
ResolutionFacadeImpl(projectFacade, moduleInfo)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val platform = TargetPlatformDetector.getPlatform(file)
|
||||
getResolutionFacadeByModuleInfo(moduleInfo, platform)
|
||||
}
|
||||
@@ -363,7 +385,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
}
|
||||
|
||||
override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? =
|
||||
(moduleInfo as? IdeaModuleInfo)?.let { getResolutionFacadeByModuleInfo(it, platform) }
|
||||
(moduleInfo as? IdeaModuleInfo)?.let { getResolutionFacadeByModuleInfo(it, platform) }
|
||||
|
||||
private fun Collection<KtFile>.filterNotInProjectSource(moduleInfo: IdeaModuleInfo) = mapNotNull {
|
||||
if (it is KtCodeFragment) it.getContextFile() else it
|
||||
@@ -374,7 +396,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
|
||||
private fun KtCodeFragment.getContextFile(): KtFile? {
|
||||
val contextElement = context ?: return null
|
||||
val contextFile = (contextElement as? KtElement)?.containingKtFile
|
||||
?: throw AssertionError("Analyzing kotlin code fragment of type ${this::class.java} with java context of type ${contextElement::class.java}")
|
||||
?: throw AssertionError("Analyzing kotlin code fragment of type ${this::class.java} with java context of type ${contextElement::class.java}")
|
||||
return if (contextFile is KtCodeFragment) contextFile.getContextFile() else contextFile
|
||||
}
|
||||
}
|
||||
|
||||
+40
-42
@@ -68,7 +68,7 @@ internal class PerFileAnalysisCache(val file: KtFile, val componentProvider: Com
|
||||
}
|
||||
|
||||
fun getAnalysisResults(element: KtElement): AnalysisResult {
|
||||
assert (element.containingKtFile == file) { "Wrong file. Expected $file, but was ${element.containingKtFile}" }
|
||||
assert(element.containingKtFile == file) { "Wrong file. Expected $file, but was ${element.containingKtFile}" }
|
||||
|
||||
val analyzableParent = KotlinResolveDataProvider.findAnalyzableParent(element)
|
||||
|
||||
@@ -93,14 +93,11 @@ internal class PerFileAnalysisCache(val file: KtFile, val componentProvider: Com
|
||||
|
||||
try {
|
||||
return KotlinResolveDataProvider.analyze(project, componentProvider, analyzableElement)
|
||||
}
|
||||
catch (e: ProcessCanceledException) {
|
||||
} catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: IndexNotReadyException) {
|
||||
} catch (e: IndexNotReadyException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
} catch (e: Throwable) {
|
||||
DiagnosticUtils.throwIfRunningOnServer(e)
|
||||
LOG.error(e)
|
||||
|
||||
@@ -111,19 +108,19 @@ internal class PerFileAnalysisCache(val file: KtFile, val componentProvider: Com
|
||||
|
||||
private object KotlinResolveDataProvider {
|
||||
private val topmostElementTypes = arrayOf<Class<out PsiElement?>?>(
|
||||
KtNamedFunction::class.java,
|
||||
KtAnonymousInitializer::class.java,
|
||||
KtProperty::class.java,
|
||||
KtImportDirective::class.java,
|
||||
KtPackageDirective::class.java,
|
||||
KtCodeFragment::class.java,
|
||||
// TODO: Non-analyzable so far, add more granular analysis
|
||||
KtAnnotationEntry::class.java,
|
||||
KtTypeConstraint::class.java,
|
||||
KtSuperTypeList::class.java,
|
||||
KtTypeParameter::class.java,
|
||||
KtParameter::class.java,
|
||||
KtTypeAlias::class.java
|
||||
KtNamedFunction::class.java,
|
||||
KtAnonymousInitializer::class.java,
|
||||
KtProperty::class.java,
|
||||
KtImportDirective::class.java,
|
||||
KtPackageDirective::class.java,
|
||||
KtCodeFragment::class.java,
|
||||
// TODO: Non-analyzable so far, add more granular analysis
|
||||
KtAnnotationEntry::class.java,
|
||||
KtTypeConstraint::class.java,
|
||||
KtSuperTypeList::class.java,
|
||||
KtTypeParameter::class.java,
|
||||
KtParameter::class.java,
|
||||
KtTypeAlias::class.java
|
||||
)
|
||||
|
||||
fun findAnalyzableParent(element: KtElement): KtElement {
|
||||
@@ -145,10 +142,10 @@ private object KotlinResolveDataProvider {
|
||||
// Class initializer should be replaced by containing class to provide full analysis
|
||||
if (analyzableElement is KtClassInitializer) return analyzableElement.containingDeclaration
|
||||
return analyzableElement
|
||||
// if none of the above worked, take the outermost declaration
|
||||
?: PsiTreeUtil.getTopmostParentOfType(element, KtDeclaration::class.java)
|
||||
// if even that didn't work, take the whole file
|
||||
?: element.containingKtFile
|
||||
// if none of the above worked, take the outermost declaration
|
||||
?: PsiTreeUtil.getTopmostParentOfType(element, KtDeclaration::class.java)
|
||||
// if even that didn't work, take the whole file
|
||||
?: element.containingKtFile
|
||||
}
|
||||
|
||||
fun analyze(project: Project, componentProvider: ComponentProvider, analyzableElement: KtElement): AnalysisResult {
|
||||
@@ -159,32 +156,33 @@ private object KotlinResolveDataProvider {
|
||||
}
|
||||
|
||||
val resolveSession = componentProvider.get<ResolveSession>()
|
||||
val trace = DelegatingBindingTrace(resolveSession.bindingContext, "Trace for resolution of " + analyzableElement, allowSliceRewrite = true)
|
||||
val trace = DelegatingBindingTrace(
|
||||
resolveSession.bindingContext,
|
||||
"Trace for resolution of " + analyzableElement,
|
||||
allowSliceRewrite = true
|
||||
)
|
||||
|
||||
val targetPlatform = TargetPlatformDetector.getPlatform(analyzableElement.containingKtFile)
|
||||
|
||||
val lazyTopDownAnalyzer = createContainerForLazyBodyResolve(
|
||||
//TODO: should get ModuleContext
|
||||
componentProvider.get<GlobalContext>().withProject(project).withModule(module),
|
||||
resolveSession,
|
||||
trace,
|
||||
targetPlatform,
|
||||
componentProvider.get<BodyResolveCache>(),
|
||||
analyzableElement.jvmTarget,
|
||||
analyzableElement.languageVersionSettings
|
||||
//TODO: should get ModuleContext
|
||||
componentProvider.get<GlobalContext>().withProject(project).withModule(module),
|
||||
resolveSession,
|
||||
trace,
|
||||
targetPlatform,
|
||||
componentProvider.get<BodyResolveCache>(),
|
||||
analyzableElement.jvmTarget,
|
||||
analyzableElement.languageVersionSettings
|
||||
).get<LazyTopDownAnalyzer>()
|
||||
|
||||
lazyTopDownAnalyzer.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, listOf(analyzableElement))
|
||||
|
||||
return AnalysisResult.success(trace.bindingContext, module)
|
||||
}
|
||||
catch (e: ProcessCanceledException) {
|
||||
} catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: IndexNotReadyException) {
|
||||
} catch (e: IndexNotReadyException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
} catch (e: Throwable) {
|
||||
DiagnosticUtils.throwIfRunningOnServer(e)
|
||||
LOG.error(e)
|
||||
|
||||
@@ -195,9 +193,9 @@ private object KotlinResolveDataProvider {
|
||||
private fun analyzeExpressionCodeFragment(componentProvider: ComponentProvider, codeFragment: KtCodeFragment): BindingContext {
|
||||
val trace = BindingTraceContext()
|
||||
componentProvider.get<CodeFragmentAnalyzer>().analyzeCodeFragment(
|
||||
codeFragment,
|
||||
trace,
|
||||
BodyResolveMode.PARTIAL_FOR_COMPLETION //TODO: discuss it
|
||||
codeFragment,
|
||||
trace,
|
||||
BodyResolveMode.PARTIAL_FOR_COMPLETION //TODO: discuss it
|
||||
)
|
||||
return trace.bindingContext
|
||||
}
|
||||
|
||||
+6
-5
@@ -48,12 +48,14 @@ interface LibraryDependenciesCache {
|
||||
class LibraryDependenciesCacheImpl(private val project: Project) : LibraryDependenciesCache {
|
||||
|
||||
val cache by CachedValue(project) {
|
||||
CachedValueProvider.Result(ContainerUtil.createConcurrentWeakMap<Library, LibrariesAndSdks>(),
|
||||
ProjectRootManager.getInstance(project))
|
||||
CachedValueProvider.Result(
|
||||
ContainerUtil.createConcurrentWeakMap<Library, LibrariesAndSdks>(),
|
||||
ProjectRootManager.getInstance(project)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getLibrariesAndSdksUsedWith(library: Library): LibrariesAndSdks =
|
||||
cache.getOrPut(library) { computeLibrariesAndSdksUsedWith(library) }
|
||||
cache.getOrPut(library) { computeLibrariesAndSdksUsedWith(library) }
|
||||
|
||||
|
||||
//NOTE: used LibraryRuntimeClasspathScope as reference
|
||||
@@ -63,8 +65,7 @@ class LibraryDependenciesCacheImpl(private val project: Project) : LibraryDepend
|
||||
if (orderEntry is ModuleOrderEntry) {
|
||||
val module = orderEntry.module
|
||||
module != null && module !in processedModules
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -109,4 +109,5 @@ class LibraryModificationTracker(project: Project) : SimpleModificationTracker()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isRelevantEvent(vFileEvent: VFileEvent) = vFileEvent is VFileCreateEvent || vFileEvent is VFileMoveEvent || vFileEvent is VFileCopyEvent
|
||||
private fun isRelevantEvent(vFileEvent: VFileEvent) =
|
||||
vFileEvent is VFileCreateEvent || vFileEvent is VFileMoveEvent || vFileEvent is VFileCopyEvent
|
||||
@@ -44,7 +44,7 @@ object MapPsiToAsmDesc {
|
||||
is PsiTypeParameter -> resolved.superTypes.firstOrNull()?.let { typeDesc(it) } ?: "Ljava/lang/Object;"
|
||||
is PsiClass -> classDesc(resolved)
|
||||
null -> unknownSignature()
|
||||
else -> error("Resolved to unexpected $resolved of class ${resolved::class.java}" )
|
||||
else -> error("Resolved to unexpected $resolved of class ${resolved::class.java}")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,7 +71,7 @@ object MapPsiToAsmDesc {
|
||||
psiMethod.returnType?.let {
|
||||
append(typeDesc(it))
|
||||
}
|
||||
?: return unknownSignature() // TODO: support constructors, there seems to be additional logic in java that doesn't work correctly for compiled kotlin
|
||||
?: return unknownSignature() // TODO: support constructors, there seems to be additional logic in java that doesn't work correctly for compiled kotlin
|
||||
}
|
||||
|
||||
private fun unknownSignature() = ""
|
||||
@@ -79,6 +79,7 @@ object MapPsiToAsmDesc {
|
||||
LOG.error(message)
|
||||
return unknownSignature()
|
||||
}
|
||||
|
||||
private fun primitive(asmType: Type) = asmType.descriptor
|
||||
|
||||
private val LOG = Logger.getInstance(this::class.java)
|
||||
|
||||
+30
-30
@@ -42,17 +42,17 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
||||
|
||||
fun createModuleResolverProvider(
|
||||
debugName: String,
|
||||
project: Project,
|
||||
globalContext: GlobalContextImpl,
|
||||
analysisSettings: PlatformAnalysisSettings,
|
||||
syntheticFiles: Collection<KtFile>,
|
||||
delegateResolver: ResolverForProject<IdeaModuleInfo>,
|
||||
moduleFilter: (IdeaModuleInfo) -> Boolean,
|
||||
allModules: Collection<IdeaModuleInfo>?,
|
||||
providedBuiltIns: KotlinBuiltIns?, // null means create new builtins based on SDK
|
||||
dependencies: Collection<Any>,
|
||||
invalidateOnOOCB: Boolean = true
|
||||
debugName: String,
|
||||
project: Project,
|
||||
globalContext: GlobalContextImpl,
|
||||
analysisSettings: PlatformAnalysisSettings,
|
||||
syntheticFiles: Collection<KtFile>,
|
||||
delegateResolver: ResolverForProject<IdeaModuleInfo>,
|
||||
moduleFilter: (IdeaModuleInfo) -> Boolean,
|
||||
allModules: Collection<IdeaModuleInfo>?,
|
||||
providedBuiltIns: KotlinBuiltIns?, // null means create new builtins based on SDK
|
||||
dependencies: Collection<Any>,
|
||||
invalidateOnOOCB: Boolean = true
|
||||
): ModuleResolverProvider {
|
||||
val builtIns = providedBuiltIns ?: createBuiltIns(analysisSettings, globalContext)
|
||||
|
||||
@@ -74,19 +74,19 @@ fun createModuleResolverProvider(
|
||||
}
|
||||
|
||||
val resolverForProject = ResolverForProjectImpl(
|
||||
debugName, globalContext.withProject(project), modulesToCreateResolversFor,
|
||||
{ module ->
|
||||
val platform = module.platform ?: analysisSettings.platform
|
||||
IdePlatformSupport.facades[platform] ?: throw UnsupportedOperationException("Unsupported platform $platform")
|
||||
},
|
||||
modulesContent, jvmPlatformParameters,
|
||||
IdeaEnvironment, builtIns,
|
||||
delegateResolver, { _, c -> IDEPackagePartProvider(c.moduleContentScope) },
|
||||
analysisSettings.sdk?.let { SdkInfo(project, it) },
|
||||
modulePlatforms = { module -> module.platform?.multiTargetPlatform },
|
||||
packageOracleFactory = ServiceManager.getService(project, IdePackageOracleFactory::class.java),
|
||||
languageSettingsProvider = IDELanguageSettingsProvider,
|
||||
invalidateOnOOCB = invalidateOnOOCB
|
||||
debugName, globalContext.withProject(project), modulesToCreateResolversFor,
|
||||
{ module ->
|
||||
val platform = module.platform ?: analysisSettings.platform
|
||||
IdePlatformSupport.facades[platform] ?: throw UnsupportedOperationException("Unsupported platform $platform")
|
||||
},
|
||||
modulesContent, jvmPlatformParameters,
|
||||
IdeaEnvironment, builtIns,
|
||||
delegateResolver, { _, c -> IDEPackagePartProvider(c.moduleContentScope) },
|
||||
analysisSettings.sdk?.let { SdkInfo(project, it) },
|
||||
modulePlatforms = { module -> module.platform?.multiTargetPlatform },
|
||||
packageOracleFactory = ServiceManager.getService(project, IdePackageOracleFactory::class.java),
|
||||
languageSettingsProvider = IDELanguageSettingsProvider,
|
||||
invalidateOnOOCB = invalidateOnOOCB
|
||||
)
|
||||
|
||||
if (providedBuiltIns == null && builtIns is JvmBuiltIns) {
|
||||
@@ -95,9 +95,9 @@ fun createModuleResolverProvider(
|
||||
}
|
||||
|
||||
return ModuleResolverProvider(
|
||||
resolverForProject,
|
||||
builtIns,
|
||||
dependencies + listOf(globalContext.exceptionTracker)
|
||||
resolverForProject,
|
||||
builtIns,
|
||||
dependencies + listOf(globalContext.exceptionTracker)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ fun getAllProjectSdks(): Collection<Sdk> {
|
||||
|
||||
|
||||
class ModuleResolverProvider(
|
||||
val resolverForProject: ResolverForProject<IdeaModuleInfo>,
|
||||
val builtIns: KotlinBuiltIns,
|
||||
val cacheDependencies: Collection<Any>
|
||||
val resolverForProject: ResolverForProject<IdeaModuleInfo>,
|
||||
val builtIns: KotlinBuiltIns,
|
||||
val cacheDependencies: Collection<Any>
|
||||
)
|
||||
|
||||
+39
-35
@@ -33,40 +33,40 @@ import org.jetbrains.kotlin.resolve.CompositeBindingContext
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
internal class ProjectResolutionFacade(
|
||||
private val debugString: String,
|
||||
private val resolverDebugName: String,
|
||||
val project: Project,
|
||||
val globalContext: GlobalContextImpl,
|
||||
val settings: PlatformAnalysisSettings,
|
||||
val reuseDataFrom: ProjectResolutionFacade?,
|
||||
val moduleFilter: (IdeaModuleInfo) -> Boolean,
|
||||
val dependencies: List<Any>,
|
||||
private val invalidateOnOOCB: Boolean = true,
|
||||
val syntheticFiles: Collection<KtFile> = listOf(),
|
||||
val allModules: Collection<IdeaModuleInfo>? = null // null means create resolvers for modules from idea model
|
||||
private val debugString: String,
|
||||
private val resolverDebugName: String,
|
||||
val project: Project,
|
||||
val globalContext: GlobalContextImpl,
|
||||
val settings: PlatformAnalysisSettings,
|
||||
val reuseDataFrom: ProjectResolutionFacade?,
|
||||
val moduleFilter: (IdeaModuleInfo) -> Boolean,
|
||||
val dependencies: List<Any>,
|
||||
private val invalidateOnOOCB: Boolean = true,
|
||||
val syntheticFiles: Collection<KtFile> = listOf(),
|
||||
val allModules: Collection<IdeaModuleInfo>? = null // null means create resolvers for modules from idea model
|
||||
) {
|
||||
private val cachedValue = CachedValuesManager.getManager(project).createCachedValue(
|
||||
{
|
||||
val resolverProvider = computeModuleResolverProvider()
|
||||
CachedValueProvider.Result.create(resolverProvider, resolverProvider.cacheDependencies)
|
||||
},
|
||||
/* trackValue = */ false
|
||||
{
|
||||
val resolverProvider = computeModuleResolverProvider()
|
||||
CachedValueProvider.Result.create(resolverProvider, resolverProvider.cacheDependencies)
|
||||
},
|
||||
/* trackValue = */ false
|
||||
)
|
||||
|
||||
private fun computeModuleResolverProvider(): ModuleResolverProvider {
|
||||
val delegateResolverProvider = reuseDataFrom?.moduleResolverProvider
|
||||
val delegateResolverForProject = delegateResolverProvider?.resolverForProject ?: EmptyResolverForProject()
|
||||
return createModuleResolverProvider(
|
||||
resolverDebugName,
|
||||
project,
|
||||
globalContext,
|
||||
settings,
|
||||
syntheticFiles = syntheticFiles,
|
||||
delegateResolver = delegateResolverForProject, moduleFilter = moduleFilter,
|
||||
allModules = allModules,
|
||||
providedBuiltIns = delegateResolverProvider?.builtIns,
|
||||
dependencies = dependencies,
|
||||
invalidateOnOOCB = invalidateOnOOCB
|
||||
resolverDebugName,
|
||||
project,
|
||||
globalContext,
|
||||
settings,
|
||||
syntheticFiles = syntheticFiles,
|
||||
delegateResolver = delegateResolverForProject, moduleFilter = moduleFilter,
|
||||
allModules = allModules,
|
||||
providedBuiltIns = delegateResolverProvider?.builtIns,
|
||||
dependencies = dependencies,
|
||||
invalidateOnOOCB = invalidateOnOOCB
|
||||
)
|
||||
}
|
||||
|
||||
@@ -91,17 +91,21 @@ internal class ProjectResolutionFacade(
|
||||
}
|
||||
|
||||
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue(
|
||||
{
|
||||
val resolverProvider = moduleResolverProvider
|
||||
val results = object : SLRUCache<KtFile, PerFileAnalysisCache>(2, 3) {
|
||||
override fun createValue(file: KtFile): PerFileAnalysisCache {
|
||||
return PerFileAnalysisCache(file, resolverProvider.resolverForProject.resolverForModule(file.getModuleInfo()).componentProvider)
|
||||
}
|
||||
{
|
||||
val resolverProvider = moduleResolverProvider
|
||||
val results = object : SLRUCache<KtFile, PerFileAnalysisCache>(2, 3) {
|
||||
override fun createValue(file: KtFile): PerFileAnalysisCache {
|
||||
return PerFileAnalysisCache(
|
||||
file,
|
||||
resolverProvider.resolverForProject.resolverForModule(file.getModuleInfo()).componentProvider
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val allDependencies = resolverProvider.cacheDependencies + listOf(PsiModificationTracker.MODIFICATION_COUNT)
|
||||
CachedValueProvider.Result.create(results, allDependencies)
|
||||
}, false)
|
||||
val allDependencies = resolverProvider.cacheDependencies + listOf(PsiModificationTracker.MODIFICATION_COUNT)
|
||||
CachedValueProvider.Result.create(results, allDependencies)
|
||||
}, false
|
||||
)
|
||||
|
||||
fun getAnalysisResultsForElements(elements: Collection<KtElement>): AnalysisResult {
|
||||
assert(elements.isNotEmpty()) { "elements collection should not be empty" }
|
||||
|
||||
+7
-8
@@ -36,8 +36,8 @@ import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
internal class ResolutionFacadeImpl(
|
||||
private val projectFacade: ProjectResolutionFacade,
|
||||
private val moduleInfo: IdeaModuleInfo
|
||||
private val projectFacade: ProjectResolutionFacade,
|
||||
private val moduleInfo: IdeaModuleInfo
|
||||
) : ResolutionFacade {
|
||||
override val project: Project
|
||||
get() = projectFacade.project
|
||||
@@ -59,22 +59,21 @@ internal class ResolutionFacadeImpl(
|
||||
return resolveElementCache.resolveToElements(elements, bodyResolveMode)
|
||||
}
|
||||
|
||||
override fun analyzeFullyAndGetResult(elements: Collection<KtElement>): AnalysisResult
|
||||
= projectFacade.getAnalysisResultsForElements(elements)
|
||||
override fun analyzeFullyAndGetResult(elements: Collection<KtElement>): AnalysisResult =
|
||||
projectFacade.getAnalysisResultsForElements(elements)
|
||||
|
||||
override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor {
|
||||
return if (KtPsiUtil.isLocal(declaration)) {
|
||||
val bindingContext = analyze(declaration, bodyResolveMode)
|
||||
bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
|
||||
?: getFrontendService(moduleInfo, AbsentDescriptorHandler::class.java).diagnoseDescriptorNotFound(declaration)
|
||||
}
|
||||
else {
|
||||
?: getFrontendService(moduleInfo, AbsentDescriptorHandler::class.java).diagnoseDescriptorNotFound(declaration)
|
||||
} else {
|
||||
val resolveSession = projectFacade.resolverForElement(declaration).componentProvider.get<ResolveSession>()
|
||||
resolveSession.resolveToDescriptor(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T : Any> getFrontendService(serviceClass: Class<T>): T = getFrontendService(moduleInfo, serviceClass)
|
||||
override fun <T : Any> getFrontendService(serviceClass: Class<T>): T = getFrontendService(moduleInfo, serviceClass)
|
||||
|
||||
override fun <T : Any> getIdeService(serviceClass: Class<T>): T {
|
||||
return projectFacade.resolverForModuleInfo(moduleInfo).componentProvider.create(serviceClass)
|
||||
|
||||
+19
-15
@@ -38,9 +38,9 @@ class ScriptModuleSearchScope(val scriptFile: VirtualFile, baseScope: GlobalSear
|
||||
}
|
||||
|
||||
data class ScriptModuleInfo(
|
||||
val project: Project,
|
||||
val scriptFile: VirtualFile,
|
||||
val scriptDefinition: KotlinScriptDefinition
|
||||
val project: Project,
|
||||
val scriptFile: VirtualFile,
|
||||
val scriptDefinition: KotlinScriptDefinition
|
||||
) : IdeaModuleInfo {
|
||||
override val moduleOrigin: ModuleOrigin
|
||||
get() = ModuleOrigin.OTHER
|
||||
@@ -54,27 +54,30 @@ data class ScriptModuleInfo(
|
||||
|
||||
override fun dependencies(): List<IdeaModuleInfo> {
|
||||
return listOf(
|
||||
this, ScriptDependenciesModuleInfo(project, this)
|
||||
this, ScriptDependenciesModuleInfo(project, this)
|
||||
) + sdkDependencies(externalDependencies, project)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sdkDependencies(scriptDependencies: ScriptDependencies?, project: Project): List<SdkInfo>
|
||||
= listOfNotNull(findJdk(scriptDependencies, project)?.let { SdkInfo(project, it) })
|
||||
private fun sdkDependencies(scriptDependencies: ScriptDependencies?, project: Project): List<SdkInfo> =
|
||||
listOfNotNull(findJdk(scriptDependencies, project)?.let { SdkInfo(project, it) })
|
||||
|
||||
fun findJdk(dependencies: ScriptDependencies?, project: Project): Sdk? {
|
||||
val allJdks = getAllProjectSdks()
|
||||
// workaround for mismatched gradle wrapper and plugin version
|
||||
val javaHome = try { dependencies?.javaHome?.canonicalPath } catch (e: Throwable) { null }
|
||||
val javaHome = try {
|
||||
dependencies?.javaHome?.canonicalPath
|
||||
} catch (e: Throwable) {
|
||||
null
|
||||
}
|
||||
|
||||
return allJdks.find { javaHome != null && it.homePath == javaHome } ?:
|
||||
ProjectRootManager.getInstance(project).projectSdk ?:
|
||||
allJdks.firstOrNull()
|
||||
return allJdks.find { javaHome != null && it.homePath == javaHome } ?: ProjectRootManager.getInstance(project).projectSdk
|
||||
?: allJdks.firstOrNull()
|
||||
}
|
||||
|
||||
class ScriptDependenciesModuleInfo(
|
||||
val project: Project,
|
||||
val scriptModuleInfo: ScriptModuleInfo?
|
||||
val project: Project,
|
||||
val scriptModuleInfo: ScriptModuleInfo?
|
||||
) : IdeaModuleInfo, BinaryModuleInfo {
|
||||
override fun dependencies() = (listOf(this) + sdkDependencies(scriptModuleInfo?.externalDependencies, project))
|
||||
|
||||
@@ -84,7 +87,7 @@ class ScriptDependenciesModuleInfo(
|
||||
if (scriptModuleInfo == null) {
|
||||
// we do not know which scripts these dependencies are
|
||||
return KotlinSourceFilterScope.libraryClassFiles(
|
||||
ScriptDependenciesManager.getInstance(project).getAllScriptsClasspathScope(), project
|
||||
ScriptDependenciesManager.getInstance(project).getAllScriptsClasspathScope(), project
|
||||
)
|
||||
}
|
||||
return ServiceManager.getService(project, ScriptBinariesScopeCache::class.java).get(scriptModuleInfo.externalDependencies)
|
||||
@@ -93,6 +96,7 @@ class ScriptDependenciesModuleInfo(
|
||||
// NOTE: intentionally not taking corresponding script info into account
|
||||
// otherwise there is no way to implement getModuleInfo
|
||||
override fun hashCode() = project.hashCode()
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is ScriptDependenciesModuleInfo && this.project == other.project
|
||||
|
||||
override val moduleOrigin: ModuleOrigin
|
||||
@@ -103,7 +107,7 @@ class ScriptDependenciesModuleInfo(
|
||||
}
|
||||
|
||||
data class ScriptDependenciesSourceModuleInfo(
|
||||
val project: Project
|
||||
val project: Project
|
||||
) : IdeaModuleInfo, SourceForBinaryModuleInfo {
|
||||
override val name = Name.special("<Source for script dependencies>")
|
||||
|
||||
@@ -111,7 +115,7 @@ data class ScriptDependenciesSourceModuleInfo(
|
||||
get() = ScriptDependenciesModuleInfo(project, null)
|
||||
|
||||
override fun sourceScope(): GlobalSearchScope = KotlinSourceFilterScope.librarySources(
|
||||
ScriptDependenciesManager.getInstance(project).getAllLibrarySourcesScope(), project
|
||||
ScriptDependenciesManager.getInstance(project).getAllLibrarySourcesScope(), project
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -43,43 +43,44 @@ fun PsiElement.getNullableModuleInfo(): IdeaModuleInfo? = this.collectInfos(Modu
|
||||
fun PsiElement.getModuleInfos(): Sequence<IdeaModuleInfo> = this.collectInfos(ModuleInfoCollector.ToSequence)
|
||||
|
||||
fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFile): IdeaModuleInfo? = collectInfosByVirtualFile(
|
||||
project, virtualFile,
|
||||
treatAsLibrarySource = false,
|
||||
onOccurrence = { return@getModuleInfoByVirtualFile it }
|
||||
project, virtualFile,
|
||||
treatAsLibrarySource = false,
|
||||
onOccurrence = { return@getModuleInfoByVirtualFile it }
|
||||
)
|
||||
|
||||
fun getBinaryLibrariesModuleInfos(project: Project, virtualFile: VirtualFile)
|
||||
= collectModuleInfosByType<BinaryModuleInfo>(project, virtualFile)
|
||||
fun getLibrarySourcesModuleInfos(project: Project, virtualFile: VirtualFile)
|
||||
= collectModuleInfosByType<LibrarySourceInfo>(project, virtualFile)
|
||||
fun getBinaryLibrariesModuleInfos(project: Project, virtualFile: VirtualFile) =
|
||||
collectModuleInfosByType<BinaryModuleInfo>(project, virtualFile)
|
||||
|
||||
fun getLibrarySourcesModuleInfos(project: Project, virtualFile: VirtualFile) =
|
||||
collectModuleInfosByType<LibrarySourceInfo>(project, virtualFile)
|
||||
|
||||
private typealias VirtualFileProcessor<T> = (Project, VirtualFile, Boolean) -> T
|
||||
|
||||
private sealed class ModuleInfoCollector<out T>(
|
||||
val onResult: (IdeaModuleInfo?) -> T,
|
||||
val onFailure: (String) -> T,
|
||||
val virtualFileProcessor: VirtualFileProcessor<T>
|
||||
val onResult: (IdeaModuleInfo?) -> T,
|
||||
val onFailure: (String) -> T,
|
||||
val virtualFileProcessor: VirtualFileProcessor<T>
|
||||
) {
|
||||
object NotNullTakeFirst : ModuleInfoCollector<IdeaModuleInfo>(
|
||||
onResult = { it ?: NotUnderContentRootModuleInfo },
|
||||
onFailure = { reason ->
|
||||
LOG.error("Could not find correct module information.\nReason: $reason")
|
||||
NotUnderContentRootModuleInfo
|
||||
},
|
||||
virtualFileProcessor = processor@ { project, virtualFile, isLibrarySource ->
|
||||
collectInfosByVirtualFile(project, virtualFile, isLibrarySource, { return@processor it ?: NotUnderContentRootModuleInfo })
|
||||
}
|
||||
onResult = { it ?: NotUnderContentRootModuleInfo },
|
||||
onFailure = { reason ->
|
||||
LOG.error("Could not find correct module information.\nReason: $reason")
|
||||
NotUnderContentRootModuleInfo
|
||||
},
|
||||
virtualFileProcessor = processor@ { project, virtualFile, isLibrarySource ->
|
||||
collectInfosByVirtualFile(project, virtualFile, isLibrarySource, { return@processor it ?: NotUnderContentRootModuleInfo })
|
||||
}
|
||||
)
|
||||
|
||||
object NullableTakeFirst: ModuleInfoCollector<IdeaModuleInfo?>(
|
||||
onResult = { it },
|
||||
onFailure = { reason ->
|
||||
LOG.warn("Could not find correct module information.\nReason: $reason")
|
||||
null
|
||||
},
|
||||
virtualFileProcessor = processor@ { project, virtualFile, isLibrarySource ->
|
||||
collectInfosByVirtualFile(project, virtualFile, isLibrarySource, { return@processor it })
|
||||
}
|
||||
object NullableTakeFirst : ModuleInfoCollector<IdeaModuleInfo?>(
|
||||
onResult = { it },
|
||||
onFailure = { reason ->
|
||||
LOG.warn("Could not find correct module information.\nReason: $reason")
|
||||
null
|
||||
},
|
||||
virtualFileProcessor = processor@ { project, virtualFile, isLibrarySource ->
|
||||
collectInfosByVirtualFile(project, virtualFile, isLibrarySource, { return@processor it })
|
||||
}
|
||||
)
|
||||
|
||||
object ToSequence : ModuleInfoCollector<Sequence<IdeaModuleInfo>>(
|
||||
@@ -105,8 +106,8 @@ private fun <T> PsiElement.collectInfos(c: ModuleInfoCollector<T>): T {
|
||||
return this.processLightElement(c)
|
||||
}
|
||||
|
||||
val containingFile = containingFile ?:
|
||||
return c.onFailure("Analyzing element of type ${this::class.java} with no containing file\nText:\n$text")
|
||||
val containingFile =
|
||||
containingFile ?: return c.onFailure("Analyzing element of type ${this::class.java} with no containing file\nText:\n$text")
|
||||
|
||||
val containingKtFile = (this as? KtElement)?.containingFile as? KtFile
|
||||
containingKtFile?.analysisContext?.let {
|
||||
@@ -123,18 +124,18 @@ private fun <T> PsiElement.collectInfos(c: ModuleInfoCollector<T>): T {
|
||||
}
|
||||
|
||||
if (containingKtFile is KtCodeFragment) {
|
||||
val context = containingKtFile.getContext() ?:
|
||||
return c.onFailure("Analyzing code fragment of type ${containingKtFile::class.java} with no context element\nText:\n${containingKtFile.getText()}")
|
||||
val context = containingKtFile.getContext()
|
||||
?: return c.onFailure("Analyzing code fragment of type ${containingKtFile::class.java} with no context element\nText:\n${containingKtFile.getText()}")
|
||||
return context.collectInfos(c)
|
||||
}
|
||||
|
||||
val virtualFile = containingFile.originalFile.virtualFile
|
||||
?: return c.onFailure("Analyzing element of type ${this::class.java} in non-physical file $containingFile of type ${containingFile::class.java}\nText:\n$text")
|
||||
?: return c.onFailure("Analyzing element of type ${this::class.java} in non-physical file $containingFile of type ${containingFile::class.java}\nText:\n$text")
|
||||
|
||||
return c.virtualFileProcessor(
|
||||
project,
|
||||
virtualFile,
|
||||
(containingFile as? KtFile)?.isCompiled ?: false
|
||||
project,
|
||||
virtualFile,
|
||||
(containingFile as? KtFile)?.isCompiled ?: false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -142,9 +143,9 @@ private fun <T> KtLightElement<*, *>.processLightElement(c: ModuleInfoCollector<
|
||||
val decompiledClass = this.getParentOfType<KtLightClassForDecompiledDeclaration>(strict = false)
|
||||
if (decompiledClass != null) {
|
||||
return c.virtualFileProcessor(
|
||||
project,
|
||||
containingFile.virtualFile.sure { "Decompiled class should be build from physical file" },
|
||||
false
|
||||
project,
|
||||
containingFile.virtualFile.sure { "Decompiled class should be build from physical file" },
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -158,8 +159,8 @@ private fun <T> KtLightElement<*, *>.processLightElement(c: ModuleInfoCollector<
|
||||
}
|
||||
|
||||
private inline fun <T> collectInfosByVirtualFile(
|
||||
project: Project, virtualFile: VirtualFile,
|
||||
treatAsLibrarySource: Boolean, onOccurrence: (IdeaModuleInfo?) -> T
|
||||
project: Project, virtualFile: VirtualFile,
|
||||
treatAsLibrarySource: Boolean, onOccurrence: (IdeaModuleInfo?) -> T
|
||||
): T {
|
||||
val projectFileIndex = ProjectFileIndex.SERVICE.getInstance(project)
|
||||
|
||||
@@ -168,8 +169,7 @@ private inline fun <T> collectInfosByVirtualFile(
|
||||
val moduleFileIndex = ModuleRootManager.getInstance(module).fileIndex
|
||||
if (moduleFileIndex.isInTestSourceContent(virtualFile)) {
|
||||
onOccurrence(module.testSourceInfo())
|
||||
}
|
||||
else if (moduleFileIndex.isInSourceContentWithoutInjected(virtualFile)) {
|
||||
} else if (moduleFileIndex.isInSourceContentWithoutInjected(virtualFile)) {
|
||||
onOccurrence(module.productionSourceInfo())
|
||||
}
|
||||
}
|
||||
@@ -188,8 +188,7 @@ private inline fun <T> collectInfosByVirtualFile(
|
||||
if (isBinary && virtualFile in scriptConfigurationManager.getAllScriptsClasspathScope()) {
|
||||
if (treatAsLibrarySource) {
|
||||
onOccurrence(ScriptDependenciesSourceModuleInfo(project))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
onOccurrence(ScriptDependenciesModuleInfo(project, null))
|
||||
}
|
||||
}
|
||||
@@ -210,9 +209,9 @@ private inline fun <reified T : IdeaModuleInfo> collectModuleInfosByType(project
|
||||
}
|
||||
|
||||
private fun OrderEntry.toIdeaModuleInfo(
|
||||
project: Project,
|
||||
virtualFile: VirtualFile,
|
||||
treatAsLibrarySource: Boolean = false
|
||||
project: Project,
|
||||
virtualFile: VirtualFile,
|
||||
treatAsLibrarySource: Boolean = false
|
||||
): IdeaModuleInfo? {
|
||||
if (this is ModuleOrderEntry) return null
|
||||
if (!isValid) return null
|
||||
@@ -222,8 +221,7 @@ private fun OrderEntry.toIdeaModuleInfo(
|
||||
val library = library ?: return null
|
||||
if (ProjectRootsUtil.isLibraryClassFile(project, virtualFile) && !treatAsLibrarySource) {
|
||||
return LibraryInfo(project, library)
|
||||
}
|
||||
else if (ProjectRootsUtil.isLibraryFile(project, virtualFile) || treatAsLibrarySource) {
|
||||
} else if (ProjectRootsUtil.isLibraryFile(project, virtualFile) || treatAsLibrarySource) {
|
||||
return LibrarySourceInfo(project, library)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -49,11 +49,9 @@ class ClsJavaStubByVirtualFileCache {
|
||||
|
||||
try {
|
||||
return ClsFileImpl.buildFileStub(file, file.contentsToByteArray(false))
|
||||
}
|
||||
catch (e: ClsFormatException) {
|
||||
} catch (e: ClsFormatException) {
|
||||
LOG.error("Failed to build java cls class for " + file.canonicalPath!!, e)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
} catch (e: IOException) {
|
||||
LOG.error("Failed to build java cls class for " + file.canonicalPath!!, e)
|
||||
}
|
||||
|
||||
|
||||
+53
-45
@@ -75,8 +75,8 @@ import org.jetbrains.kotlin.types.WrappedTypeFactory
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
|
||||
|
||||
class IDELightClassConstructionContext(bindingContext: BindingContext, module: ModuleDescriptor, val mode: Mode)
|
||||
: LightClassConstructionContext(bindingContext, module) {
|
||||
class IDELightClassConstructionContext(bindingContext: BindingContext, module: ModuleDescriptor, val mode: Mode) :
|
||||
LightClassConstructionContext(bindingContext, module) {
|
||||
enum class Mode {
|
||||
LIGHT,
|
||||
EXACT
|
||||
@@ -95,9 +95,8 @@ object IDELightClassContexts {
|
||||
// need to make sure default values for parameters are resolved
|
||||
// because java resolve depends on whether there is a default value for an annotation attribute
|
||||
resolutionFacade.getFrontendService(ResolveElementCache::class.java)
|
||||
.resolvePrimaryConstructorParametersDefaultValues(classOrObject)
|
||||
}
|
||||
else {
|
||||
.resolvePrimaryConstructorParametersDefaultValues(classOrObject)
|
||||
} else {
|
||||
resolutionFacade.analyze(classOrObject)
|
||||
}
|
||||
val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject).sure {
|
||||
@@ -149,7 +148,11 @@ object IDELightClassContexts {
|
||||
fun lightContextForClassOrObject(classOrObject: KtClassOrObject): LightClassConstructionContext? {
|
||||
if (!isDummyResolveApplicable(classOrObject)) return null
|
||||
|
||||
val resolveSession = setupAdHocResolve(classOrObject.project, classOrObject.getResolutionFacade().moduleDescriptor, listOf(classOrObject.containingKtFile))
|
||||
val resolveSession = setupAdHocResolve(
|
||||
classOrObject.project,
|
||||
classOrObject.getResolutionFacade().moduleDescriptor,
|
||||
listOf(classOrObject.containingKtFile)
|
||||
)
|
||||
|
||||
ForceResolveUtil.forceResolveAllContents(resolveSession.resolveToDescriptor(classOrObject))
|
||||
|
||||
@@ -167,9 +170,10 @@ object IDELightClassContexts {
|
||||
|
||||
fun lightContextForScript(script: KtScript): LightClassConstructionContext {
|
||||
val resolveSession = setupAdHocResolve(
|
||||
script.project,
|
||||
script.getResolutionFacade().moduleDescriptor,
|
||||
listOf(script.containingKtFile))
|
||||
script.project,
|
||||
script.getResolutionFacade().moduleDescriptor,
|
||||
listOf(script.containingKtFile)
|
||||
)
|
||||
|
||||
ForceResolveUtil.forceResolveAllContents(resolveSession.resolveToDescriptor(script))
|
||||
|
||||
@@ -188,22 +192,23 @@ object IDELightClassContexts {
|
||||
return classOrObject.declarations.filterIsInstance<KtClassOrObject>().all { isDummyResolveApplicable(it) }
|
||||
}
|
||||
|
||||
private fun hasDelegatedSupertypes(classOrObject: KtClassOrObject) = classOrObject.superTypeListEntries.any { it is KtDelegatedSuperTypeEntry }
|
||||
private fun hasDelegatedSupertypes(classOrObject: KtClassOrObject) =
|
||||
classOrObject.superTypeListEntries.any { it is KtDelegatedSuperTypeEntry }
|
||||
|
||||
private fun isDataClassWithGeneratedMembersOverridden(classOrObject: KtClassOrObject): Boolean {
|
||||
return classOrObject.hasModifier(KtTokens.DATA_KEYWORD) &&
|
||||
classOrObject.declarations.filterIsInstance<KtFunction>().any {
|
||||
isGeneratedForDataClass(it.nameAsSafeName)
|
||||
}
|
||||
classOrObject.declarations.filterIsInstance<KtFunction>().any {
|
||||
isGeneratedForDataClass(it.nameAsSafeName)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isGeneratedForDataClass(name: Name): Boolean {
|
||||
return name == DataClassDescriptorResolver.EQUALS_METHOD_NAME ||
|
||||
// known failure is related to equals override, checking for other methods 'just in case'
|
||||
name == DataClassDescriptorResolver.COPY_METHOD_NAME ||
|
||||
name == DataClassDescriptorResolver.HASH_CODE_METHOD_NAME ||
|
||||
name == DataClassDescriptorResolver.TO_STRING_METHOD_NAME ||
|
||||
DataClassDescriptorResolver.isComponentLike(name)
|
||||
// known failure is related to equals override, checking for other methods 'just in case'
|
||||
name == DataClassDescriptorResolver.COPY_METHOD_NAME ||
|
||||
name == DataClassDescriptorResolver.HASH_CODE_METHOD_NAME ||
|
||||
name == DataClassDescriptorResolver.TO_STRING_METHOD_NAME ||
|
||||
DataClassDescriptorResolver.isComponentLike(name)
|
||||
}
|
||||
|
||||
private fun hasMembersOverridingInternalMembers(classOrObject: KtClassOrObject): Boolean {
|
||||
@@ -221,8 +226,8 @@ object IDELightClassContexts {
|
||||
private fun anyInternalMembersWithThisName(name: String, project: Project): Boolean {
|
||||
var result = false
|
||||
StubIndex.getInstance().processElements(
|
||||
KotlinOverridableInternalMembersShortNameIndex.Instance.key, name, project,
|
||||
EverythingGlobalScope(project), KtCallableDeclaration::class.java
|
||||
KotlinOverridableInternalMembersShortNameIndex.Instance.key, name, project,
|
||||
EverythingGlobalScope(project), KtCallableDeclaration::class.java
|
||||
) {
|
||||
result = true
|
||||
false // stop processing at first matching result
|
||||
@@ -284,8 +289,8 @@ object IDELightClassContexts {
|
||||
val container = createContainer("LightClassStub", JvmPlatform) {
|
||||
val jvmTarget = IDELanguageSettingsProvider.getTargetPlatform(moduleInfo) as? JvmTarget
|
||||
configureModule(
|
||||
ModuleContext(moduleDescriptor, project), JvmPlatform,
|
||||
jvmTarget ?: JvmTarget.DEFAULT, trace
|
||||
ModuleContext(moduleDescriptor, project), JvmPlatform,
|
||||
jvmTarget ?: JvmTarget.DEFAULT, trace
|
||||
)
|
||||
|
||||
useInstance(GlobalSearchScope.EMPTY_SCOPE)
|
||||
@@ -321,27 +326,26 @@ object IDELightClassContexts {
|
||||
fun get(name: String): ClassDescriptor? {
|
||||
val annotationFqName = annotationsThatAffectCodegen.firstOrNull { it.shortName().asString() == name } ?: return null
|
||||
return realModule.getPackage(annotationFqName.parent()).memberScope
|
||||
.getContributedClassifier(annotationFqName.shortName(), NoLookupLocation.FROM_IDE) as? ClassDescriptor
|
||||
.getContributedClassifier(annotationFqName.shortName(), NoLookupLocation.FROM_IDE) as? ClassDescriptor
|
||||
}
|
||||
|
||||
// see JvmPlatformAnnotations.kt, JvmFlagAnnotations.kt, also PsiModifier.MODIFIERS
|
||||
private val annotationsThatAffectCodegen = listOf(
|
||||
"JvmField", "JvmOverloads", "JvmName", "JvmStatic",
|
||||
"Synchronized", "Transient", "Volatile", "Strictfp"
|
||||
"JvmField", "JvmOverloads", "JvmName", "JvmStatic",
|
||||
"Synchronized", "Transient", "Volatile", "Strictfp"
|
||||
).map { FqName("kotlin.jvm").child(Name.identifier(it)) } +
|
||||
FqName("kotlin.PublishedApi") +
|
||||
FqName("kotlin.Deprecated") +
|
||||
FqName("kotlin.internal.InlineOnly") +
|
||||
FqName("kotlinx.android.parcel.Parcelize")
|
||||
FqName("kotlin.PublishedApi") +
|
||||
FqName("kotlin.Deprecated") +
|
||||
FqName("kotlin.internal.InlineOnly") +
|
||||
FqName("kotlinx.android.parcel.Parcelize")
|
||||
}
|
||||
|
||||
class AdHocAnnotationResolver(
|
||||
private val codegenAffectingAnnotations: CodegenAffectingAnnotations,
|
||||
private val callResolver: CallResolver,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory,
|
||||
constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||
storageManager: StorageManager
|
||||
private val codegenAffectingAnnotations: CodegenAffectingAnnotations,
|
||||
private val callResolver: CallResolver,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory,constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||
storageManager: StorageManager
|
||||
) : AnnotationResolverImpl(callResolver, constantExpressionEvaluator, storageManager) {
|
||||
|
||||
override fun resolveAnnotationType(scope: LexicalScope, entryElement: KtAnnotationEntry, trace: BindingTrace): KotlinType {
|
||||
@@ -354,20 +358,24 @@ object IDELightClassContexts {
|
||||
return codegenAffectingAnnotations.get(referencedName)
|
||||
}
|
||||
|
||||
override fun resolveAnnotationCall(annotationEntry: KtAnnotationEntry, scope: LexicalScope, trace: BindingTrace): OverloadResolutionResults<FunctionDescriptor> {
|
||||
override fun resolveAnnotationCall(
|
||||
annotationEntry: KtAnnotationEntry,
|
||||
scope: LexicalScope,
|
||||
trace: BindingTrace
|
||||
): OverloadResolutionResults<FunctionDescriptor> {
|
||||
val annotationConstructor = annotationClassByEntry(annotationEntry)?.constructors?.singleOrNull()
|
||||
?: return super.resolveAnnotationCall(annotationEntry, scope, trace)
|
||||
?: return super.resolveAnnotationCall(annotationEntry, scope, trace)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return callResolver.resolveConstructorCall(
|
||||
BasicCallResolutionContext.create(
|
||||
trace, scope, CallMaker.makeCall(null, null, annotationEntry), TypeUtils.NO_EXPECTED_TYPE,
|
||||
DataFlowInfoFactory.EMPTY, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
true, languageVersionSettings,
|
||||
dataFlowValueFactory
|
||||
),
|
||||
annotationEntry.calleeExpression!!.constructorReferenceExpression!!,
|
||||
annotationConstructor.returnType
|
||||
BasicCallResolutionContext.create(
|
||||
trace, scope, CallMaker.makeCall(null, null, annotationEntry), TypeUtils.NO_EXPECTED_TYPE,
|
||||
DataFlowInfoFactory.EMPTY, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
true, languageVersionSettings,
|
||||
dataFlowValueFactory
|
||||
),
|
||||
annotationEntry.calleeExpression!!.constructorReferenceExpression!!,
|
||||
annotationConstructor.returnType
|
||||
) as OverloadResolutionResults<FunctionDescriptor>
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -30,9 +30,9 @@ import org.jetbrains.kotlin.psi.KtSuperTypeListEntry
|
||||
|
||||
class IdeLightClassInheritanceHelper : LightClassInheritanceHelper {
|
||||
override fun isInheritor(
|
||||
lightClass: KtLightClass,
|
||||
baseClass: PsiClass,
|
||||
checkDeep: Boolean
|
||||
lightClass: KtLightClass,
|
||||
baseClass: PsiClass,
|
||||
checkDeep: Boolean
|
||||
): ImpreciseResolveResult {
|
||||
val classOrObject = lightClass.kotlinOrigin ?: return UNSURE
|
||||
val entries = classOrObject.superTypeListEntries
|
||||
|
||||
+13
-10
@@ -36,8 +36,8 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
// Used as a placeholder when actual light class does not exist (expect-classes, for example)
|
||||
// The main purpose is to allow search of inheritors within hierarchies containing such classes
|
||||
class KtFakeLightClass(override val kotlinOrigin: KtClassOrObject) :
|
||||
AbstractLightClass(kotlinOrigin.manager, KotlinLanguage.INSTANCE),
|
||||
KtLightClass {
|
||||
AbstractLightClass(kotlinOrigin.manager, KotlinLanguage.INSTANCE),
|
||||
KtLightClass {
|
||||
private val _delegate by lazy { PsiElementFactory.SERVICE.getInstance(kotlinOrigin.project).createClass("dummy") }
|
||||
private val _containingClass by lazy { kotlinOrigin.containingClassOrObject?.let { KtFakeLightClass(it) } }
|
||||
|
||||
@@ -62,18 +62,21 @@ class KtFakeLightClass(override val kotlinOrigin: KtClassOrObject) :
|
||||
val baseKtClass = (baseClass as? KtLightClass)?.kotlinOrigin ?: return false
|
||||
val baseDescriptor = baseKtClass.resolveToDescriptorIfAny() ?: return false
|
||||
val thisDescriptor = kotlinOrigin.resolveToDescriptorIfAny() ?: return false
|
||||
return if (checkDeep) DescriptorUtils.isSubclass(thisDescriptor, baseDescriptor) else DescriptorUtils.isDirectSubclass(thisDescriptor, baseDescriptor)
|
||||
return if (checkDeep)
|
||||
DescriptorUtils.isSubclass(thisDescriptor, baseDescriptor)
|
||||
else
|
||||
DescriptorUtils.isDirectSubclass(thisDescriptor, baseDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
class KtFakeLightMethod private constructor(
|
||||
val ktDeclaration: KtNamedDeclaration,
|
||||
ktClassOrObject : KtClassOrObject
|
||||
) : LightMethod (
|
||||
ktDeclaration.manager,
|
||||
PsiElementFactory.SERVICE.getInstance(ktDeclaration.project).createMethod("dummy", PsiType.VOID),
|
||||
KtFakeLightClass(ktClassOrObject),
|
||||
KotlinLanguage.INSTANCE
|
||||
val ktDeclaration: KtNamedDeclaration,
|
||||
ktClassOrObject: KtClassOrObject
|
||||
) : LightMethod(
|
||||
ktDeclaration.manager,
|
||||
PsiElementFactory.SERVICE.getInstance(ktDeclaration.project).createMethod("dummy", PsiType.VOID),
|
||||
KtFakeLightClass(ktClassOrObject),
|
||||
KotlinLanguage.INSTANCE
|
||||
), KtLightElement<KtNamedDeclaration, PsiMethod> {
|
||||
override val kotlinOrigin get() = ktDeclaration
|
||||
override val clsDelegate get() = myMethod
|
||||
|
||||
+8
-7
@@ -29,9 +29,9 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
|
||||
class KtLightClassForDecompiledDeclaration(
|
||||
override val clsDelegate: ClsClassImpl,
|
||||
override val kotlinOrigin: KtClassOrObject?,
|
||||
private val file: KtClsFile
|
||||
override val clsDelegate: ClsClassImpl,
|
||||
override val kotlinOrigin: KtClassOrObject?,
|
||||
private val file: KtClsFile
|
||||
) : KtLightClassBase(clsDelegate.manager) {
|
||||
val fqName = kotlinOrigin?.fqName ?: FqName(clsDelegate.qualifiedName.orEmpty())
|
||||
|
||||
@@ -41,7 +41,8 @@ class KtLightClassForDecompiledDeclaration(
|
||||
val nestedClasses = kotlinOrigin?.declarations?.filterIsInstance<KtClassOrObject>() ?: emptyList()
|
||||
return clsDelegate.ownInnerClasses.map { innerClsClass ->
|
||||
KtLightClassForDecompiledDeclaration(innerClsClass as ClsClassImpl,
|
||||
nestedClasses.firstOrNull { innerClsClass.name == it.name }, file)
|
||||
nestedClasses.firstOrNull { innerClsClass.name == it.name }, file
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,11 +59,11 @@ class KtLightClassForDecompiledDeclaration(
|
||||
override fun getParent() = clsDelegate.parent
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is KtLightClassForDecompiledDeclaration &&
|
||||
fqName == other.fqName
|
||||
other is KtLightClassForDecompiledDeclaration &&
|
||||
fqName == other.fqName
|
||||
|
||||
override fun hashCode(): Int =
|
||||
fqName.hashCode()
|
||||
fqName.hashCode()
|
||||
|
||||
override val originKind: LightClassOriginKind
|
||||
get() = LightClassOriginKind.BINARY
|
||||
|
||||
+31
-30
@@ -31,22 +31,23 @@ typealias ExactLightClassContextProvider = () -> LightClassConstructionContext
|
||||
typealias DummyLightClassContextProvider = (() -> LightClassConstructionContext?)?
|
||||
|
||||
sealed class LazyLightClassDataHolder(
|
||||
builder: LightClassBuilder,
|
||||
project: Project,
|
||||
exactContextProvider: ExactLightClassContextProvider,
|
||||
dummyContextProvider: DummyLightClassContextProvider,
|
||||
isLocal: Boolean = false
|
||||
builder: LightClassBuilder,
|
||||
project: Project,
|
||||
exactContextProvider: ExactLightClassContextProvider,
|
||||
dummyContextProvider: DummyLightClassContextProvider,
|
||||
isLocal: Boolean = false
|
||||
) : LightClassDataHolder {
|
||||
|
||||
private val exactResultCachedValue =
|
||||
CachedValuesManager.getManager(project).createCachedValue({
|
||||
CachedValueProvider.Result.create(
|
||||
builder(exactContextProvider()),
|
||||
if (isLocal)
|
||||
PsiModificationTracker.MODIFICATION_COUNT
|
||||
else
|
||||
PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
|
||||
}, false)
|
||||
CachedValueProvider.Result.create(
|
||||
builder(exactContextProvider()),
|
||||
if (isLocal)
|
||||
PsiModificationTracker.MODIFICATION_COUNT
|
||||
else
|
||||
PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
||||
)
|
||||
}, false)
|
||||
|
||||
private val lazyInexactStub by lazyPub {
|
||||
dummyContextProvider?.let { provider -> provider()?.let { context -> builder.invoke(context).stub } }
|
||||
@@ -60,32 +61,32 @@ sealed class LazyLightClassDataHolder(
|
||||
|
||||
// for facade or defaultImpls
|
||||
override fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass): LightClassData =
|
||||
LazyLightClassData { stub ->
|
||||
findDelegate(stub)
|
||||
}
|
||||
LazyLightClassData { stub ->
|
||||
findDelegate(stub)
|
||||
}
|
||||
|
||||
class ForClass(
|
||||
builder: LightClassBuilder, project: Project, isLocal: Boolean,
|
||||
exactContextProvider: ExactLightClassContextProvider, dummyContextProvider: DummyLightClassContextProvider
|
||||
builder: LightClassBuilder, project: Project, isLocal: Boolean,
|
||||
exactContextProvider: ExactLightClassContextProvider, dummyContextProvider: DummyLightClassContextProvider
|
||||
) : LazyLightClassDataHolder(builder, project, exactContextProvider, dummyContextProvider, isLocal), LightClassDataHolder.ForClass {
|
||||
override fun findDataForClassOrObject(classOrObject: KtClassOrObject): LightClassData =
|
||||
LazyLightClassData { stub ->
|
||||
stub.findDelegate(classOrObject)
|
||||
}
|
||||
LazyLightClassData { stub ->
|
||||
stub.findDelegate(classOrObject)
|
||||
}
|
||||
}
|
||||
|
||||
class ForFacade(
|
||||
builder: LightClassBuilder, project: Project,
|
||||
exactContextProvider: ExactLightClassContextProvider, dummyContextProvider: DummyLightClassContextProvider
|
||||
builder: LightClassBuilder, project: Project,
|
||||
exactContextProvider: ExactLightClassContextProvider, dummyContextProvider: DummyLightClassContextProvider
|
||||
) : LazyLightClassDataHolder(builder, project, exactContextProvider, dummyContextProvider), LightClassDataHolder.ForFacade
|
||||
|
||||
class ForScript(
|
||||
builder: LightClassBuilder, project: Project,
|
||||
exactContextProvider: ExactLightClassContextProvider, dummyContextProvider: DummyLightClassContextProvider
|
||||
builder: LightClassBuilder, project: Project,
|
||||
exactContextProvider: ExactLightClassContextProvider, dummyContextProvider: DummyLightClassContextProvider
|
||||
) : LazyLightClassDataHolder(builder, project, exactContextProvider, dummyContextProvider), LightClassDataHolder.ForScript
|
||||
|
||||
private inner class LazyLightClassData(
|
||||
findDelegate: (PsiJavaFileStub) -> PsiClass
|
||||
findDelegate: (PsiJavaFileStub) -> PsiClass
|
||||
) : LightClassData {
|
||||
override val clsDelegate: PsiClass by lazyPub { findDelegate(javaFileStub) }
|
||||
|
||||
@@ -121,7 +122,7 @@ sealed class LazyLightClassDataHolder(
|
||||
Resulting light member is not consistent in this case, so this should happen only for erroneous code
|
||||
*/
|
||||
val exactDelegateMethod = clsDelegate.findMethodsByName(dummyMethod.name, false).firstOrNull(byMemberIndex)
|
||||
?: clsDelegate.methods.firstOrNull(byMemberIndex)
|
||||
?: clsDelegate.methods.firstOrNull(byMemberIndex)
|
||||
exactDelegateMethod.assertMatches(dummyMethod, containingClass)
|
||||
}
|
||||
}
|
||||
@@ -141,8 +142,8 @@ sealed class LazyLightClassDataHolder(
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class LazyLightClassMemberMatchingError(message: String, containingClass: KtLightClass)
|
||||
: KotlinExceptionWithAttachments(message) {
|
||||
private sealed class LazyLightClassMemberMatchingError(message: String, containingClass: KtLightClass) :
|
||||
KotlinExceptionWithAttachments(message) {
|
||||
|
||||
init {
|
||||
containingClass.kotlinOrigin?.hasLightClassMatchingErrors = true
|
||||
@@ -150,11 +151,11 @@ private sealed class LazyLightClassMemberMatchingError(message: String, containi
|
||||
}
|
||||
|
||||
class NoMatch(dummyMember: PsiMember, containingClass: KtLightClass) : LazyLightClassMemberMatchingError(
|
||||
"Couldn't match ${dummyMember.debugName}", containingClass
|
||||
"Couldn't match ${dummyMember.debugName}", containingClass
|
||||
)
|
||||
|
||||
class WrongMatch(realMember: PsiMember, dummyMember: PsiMember, containingClass: KtLightClass) : LazyLightClassMemberMatchingError(
|
||||
"Matched ${dummyMember.debugName} to ${realMember.debugName}", containingClass
|
||||
"Matched ${dummyMember.debugName} to ${realMember.debugName}", containingClass
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+90
-84
@@ -43,35 +43,31 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||
|
||||
private val readOnlyQualifiedNamesToJavaClass = JavaToKotlinClassMap.mutabilityMappings.associateBy {
|
||||
(_, readOnly, _) ->
|
||||
private val readOnlyQualifiedNamesToJavaClass = JavaToKotlinClassMap.mutabilityMappings.associateBy { (_, readOnly, _) ->
|
||||
readOnly.asSingleFqName()
|
||||
}
|
||||
|
||||
private val mutableQualifiedNamesToJavaClass = JavaToKotlinClassMap.mutabilityMappings.associateBy {
|
||||
(_, _, mutable) ->
|
||||
private val mutableQualifiedNamesToJavaClass = JavaToKotlinClassMap.mutabilityMappings.associateBy { (_, _, mutable) ->
|
||||
mutable.asSingleFqName()
|
||||
}
|
||||
|
||||
private val membersWithSpecializedSignature: Set<String> =
|
||||
BuiltinMethodsWithSpecialGenericSignature.ERASED_VALUE_PARAMETERS_SIGNATURES.mapTo(LinkedHashSet()) {
|
||||
val fqNameString = it.substringBefore('(').replace('/', '.')
|
||||
FqName(fqNameString).shortName().asString()
|
||||
}
|
||||
BuiltinMethodsWithSpecialGenericSignature.ERASED_VALUE_PARAMETERS_SIGNATURES.mapTo(LinkedHashSet()) {
|
||||
val fqNameString = it.substringBefore('(').replace('/', '.')
|
||||
FqName(fqNameString).shortName().asString()
|
||||
}
|
||||
|
||||
private val javaGetterNameToKotlinGetterName: Map<String, String> = BuiltinSpecialProperties.PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.map {
|
||||
(propertyFqName, javaGetterShortName) ->
|
||||
Pair(javaGetterShortName.asString(), JvmAbi.getterName(propertyFqName.shortName().asString()))
|
||||
}.toMap()
|
||||
private val javaGetterNameToKotlinGetterName: Map<String, String> =
|
||||
BuiltinSpecialProperties.PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.map { (propertyFqName, javaGetterShortName) ->
|
||||
Pair(javaGetterShortName.asString(), JvmAbi.getterName(propertyFqName.shortName().asString()))
|
||||
}.toMap()
|
||||
|
||||
fun platformMutabilityWrapper(fqName: FqName, findJavaClass: (String) -> PsiClass?): PsiClass? {
|
||||
readOnlyQualifiedNamesToJavaClass[fqName]?.let {
|
||||
(javaClass, kotlinReadOnly) ->
|
||||
readOnlyQualifiedNamesToJavaClass[fqName]?.let { (javaClass, kotlinReadOnly) ->
|
||||
val javaBaseClass = findJavaClass(javaClass.asSingleFqName().asString()) ?: return null
|
||||
return getOrCreateWrapper(javaBaseClass, kotlinReadOnly.asSingleFqName(), isMutable = false)
|
||||
}
|
||||
mutableQualifiedNamesToJavaClass[fqName]?.let {
|
||||
(javaClass, _, kotlinMutable) ->
|
||||
mutableQualifiedNamesToJavaClass[fqName]?.let { (javaClass, _, kotlinMutable) ->
|
||||
val javaBaseClass = findJavaClass(javaClass.asSingleFqName().asString()) ?: return null
|
||||
return getOrCreateWrapper(javaBaseClass, kotlinMutable.asSingleFqName(), isMutable = true)
|
||||
}
|
||||
@@ -80,16 +76,20 @@ fun platformMutabilityWrapper(fqName: FqName, findJavaClass: (String) -> PsiClas
|
||||
|
||||
private fun getOrCreateWrapper(javaBaseClass: PsiClass, kotlinFqName: FqName, isMutable: Boolean): KtLightMutabilityPlatformWrapper {
|
||||
val userDataStorage = if (isMutable) javaBaseClass::mutableWrapper else javaBaseClass::readOnlyWrapper
|
||||
return userDataStorage.get() ?: KtLightMutabilityPlatformWrapper(javaBaseClass, kotlinFqName, isMutable).also { userDataStorage.set(it) }
|
||||
return userDataStorage.get() ?: KtLightMutabilityPlatformWrapper(
|
||||
javaBaseClass,
|
||||
kotlinFqName,
|
||||
isMutable
|
||||
).also { userDataStorage.set(it) }
|
||||
}
|
||||
|
||||
private var PsiClass.readOnlyWrapper: KtLightMutabilityPlatformWrapper? by UserDataProperty(Key.create("READ_ONLY_WRAPPER"))
|
||||
private var PsiClass.mutableWrapper: KtLightMutabilityPlatformWrapper? by UserDataProperty(Key.create("MUTABLE_WRAPPER"))
|
||||
|
||||
class KtLightMutabilityPlatformWrapper(
|
||||
private val javaBaseClass: PsiClass,
|
||||
private val kotlinInterfaceFqName: FqName,
|
||||
private val isMutable: Boolean
|
||||
private val javaBaseClass: PsiClass,
|
||||
private val kotlinInterfaceFqName: FqName,
|
||||
private val isMutable: Boolean
|
||||
) : KtAbstractContainerWrapper(kotlinInterfaceFqName, javaBaseClass), PsiClass {
|
||||
private val _methods by lazyPub { calcMethods() }
|
||||
|
||||
@@ -144,11 +144,11 @@ class KtLightMutabilityPlatformWrapper(
|
||||
|
||||
private fun createRemoveAt(baseMethod: PsiMethod): PsiMethod {
|
||||
return baseMethod.wrap(
|
||||
name = "removeAt",
|
||||
signature = MethodSignature(
|
||||
parameterTypes = listOf(PsiType.INT),
|
||||
returnType = singleTypeParameterAsType()
|
||||
)
|
||||
name = "removeAt",
|
||||
signature = MethodSignature(
|
||||
parameterTypes = listOf(PsiType.INT),
|
||||
returnType = singleTypeParameterAsType()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -156,18 +156,18 @@ class KtLightMutabilityPlatformWrapper(
|
||||
private fun PsiMethod.openBridge() = wrap(makeFinal = false, hasImplementation = true)
|
||||
|
||||
private fun PsiMethod.wrap(
|
||||
makeFinal: Boolean = false,
|
||||
hasImplementation: Boolean = false,
|
||||
name: String = this.name,
|
||||
substituteObjectWith: PsiType? = null,
|
||||
signature: MethodSignature? = null
|
||||
makeFinal: Boolean = false,
|
||||
hasImplementation: Boolean = false,
|
||||
name: String = this.name,
|
||||
substituteObjectWith: PsiType? = null,
|
||||
signature: MethodSignature? = null
|
||||
) = KtLightMethodWrapper(
|
||||
this@KtLightMutabilityPlatformWrapper, this@wrap,
|
||||
isFinal = makeFinal,
|
||||
name = name,
|
||||
substituteObjectWith = substituteObjectWith,
|
||||
providedSignature = signature,
|
||||
hasImplementation = hasImplementation
|
||||
this@KtLightMutabilityPlatformWrapper, this@wrap,
|
||||
isFinal = makeFinal,
|
||||
name = name,
|
||||
substituteObjectWith = substituteObjectWith,
|
||||
providedSignature = signature,
|
||||
hasImplementation = hasImplementation
|
||||
)
|
||||
|
||||
private fun javaUtilMapMethodWithSpecialSignature(method: PsiMethod): KtLightMethodWrapper? {
|
||||
@@ -176,30 +176,30 @@ class KtLightMutabilityPlatformWrapper(
|
||||
|
||||
val signature = when (method.name) {
|
||||
"get" -> MethodSignature(
|
||||
parameterTypes = listOf(k),
|
||||
returnType = v
|
||||
parameterTypes = listOf(k),
|
||||
returnType = v
|
||||
)
|
||||
"getOrDefault" -> MethodSignature(
|
||||
parameterTypes = listOf(k, v),
|
||||
returnType = v
|
||||
parameterTypes = listOf(k, v),
|
||||
returnType = v
|
||||
)
|
||||
"containsKey" -> MethodSignature(
|
||||
parameterTypes = listOf(k),
|
||||
returnType = PsiType.BOOLEAN
|
||||
parameterTypes = listOf(k),
|
||||
returnType = PsiType.BOOLEAN
|
||||
)
|
||||
"containsValue" -> MethodSignature(
|
||||
parameterTypes = listOf(v),
|
||||
returnType = PsiType.BOOLEAN
|
||||
parameterTypes = listOf(v),
|
||||
returnType = PsiType.BOOLEAN
|
||||
)
|
||||
"remove" ->
|
||||
when (method.parameterList.parametersCount) {
|
||||
1 -> MethodSignature(
|
||||
parameterTypes = listOf(k),
|
||||
returnType = v
|
||||
parameterTypes = listOf(k),
|
||||
returnType = v
|
||||
)
|
||||
2 -> MethodSignature(
|
||||
parameterTypes = listOf(k, v),
|
||||
returnType = PsiType.BOOLEAN
|
||||
parameterTypes = listOf(k, v),
|
||||
returnType = PsiType.BOOLEAN
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
@@ -221,7 +221,7 @@ class KtLightMutabilityPlatformWrapper(
|
||||
|
||||
val methodName = Name.identifier(name)
|
||||
return scope.getContributedFunctions(methodName, NoLookupLocation.FROM_IDE).isNotEmpty()
|
||||
|| scope.getContributedVariables(methodName, NoLookupLocation.FROM_IDE).isNotEmpty()
|
||||
|| scope.getContributedVariables(methodName, NoLookupLocation.FROM_IDE).isNotEmpty()
|
||||
}
|
||||
|
||||
override fun getContainingFile() = javaBaseClass.containingFile
|
||||
@@ -230,13 +230,13 @@ class KtLightMutabilityPlatformWrapper(
|
||||
private data class MethodSignature(val parameterTypes: List<PsiType>, val returnType: PsiType)
|
||||
|
||||
private class KtLightMethodWrapper(
|
||||
private val containingClass: KtAbstractContainerWrapper,
|
||||
private val baseMethod: PsiMethod,
|
||||
private val name: String,
|
||||
private val isFinal: Boolean,
|
||||
private val hasImplementation: Boolean,
|
||||
private val substituteObjectWith: PsiType?,
|
||||
private val providedSignature: MethodSignature?
|
||||
private val containingClass: KtAbstractContainerWrapper,
|
||||
private val baseMethod: PsiMethod,
|
||||
private val name: String,
|
||||
private val isFinal: Boolean,
|
||||
private val hasImplementation: Boolean,
|
||||
private val substituteObjectWith: PsiType?,
|
||||
private val providedSignature: MethodSignature?
|
||||
) : PsiMethod, KtLightElementBase(containingClass) {
|
||||
|
||||
init {
|
||||
@@ -249,8 +249,7 @@ private class KtLightMethodWrapper(
|
||||
val substituted = containingClass.substitutor.substitute(psiType)
|
||||
return if (TypeUtils.isJavaLangObject(substituted) && substituteObjectWith != null) {
|
||||
substituteObjectWith
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
substituted
|
||||
}
|
||||
}
|
||||
@@ -260,20 +259,22 @@ private class KtLightMethodWrapper(
|
||||
override val kotlinOrigin get() = null
|
||||
|
||||
override fun hasModifierProperty(name: String) =
|
||||
when (name) {
|
||||
PsiModifier.DEFAULT -> hasImplementation
|
||||
PsiModifier.ABSTRACT -> !hasImplementation
|
||||
PsiModifier.FINAL -> isFinal
|
||||
else -> baseMethod.hasModifierProperty(name)
|
||||
}
|
||||
when (name) {
|
||||
PsiModifier.DEFAULT -> hasImplementation
|
||||
PsiModifier.ABSTRACT -> !hasImplementation
|
||||
PsiModifier.FINAL -> isFinal
|
||||
else -> baseMethod.hasModifierProperty(name)
|
||||
}
|
||||
|
||||
override fun getParameterList(): PsiParameterList {
|
||||
return LightParameterListBuilder(manager, KotlinLanguage.INSTANCE).apply {
|
||||
baseMethod.parameterList.parameters.forEachIndexed { index, paramFromJava ->
|
||||
val type = providedSignature?.parameterTypes?.get(index) ?: substituteType(paramFromJava.type)
|
||||
addParameter(
|
||||
LightParameter(paramFromJava.name ?: "p$index", type,
|
||||
this@KtLightMethodWrapper, KotlinLanguage.INSTANCE, paramFromJava.isVarArgs)
|
||||
LightParameter(
|
||||
paramFromJava.name ?: "p$index", type,
|
||||
this@KtLightMethodWrapper, KotlinLanguage.INSTANCE, paramFromJava.isVarArgs
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -288,8 +289,12 @@ private class KtLightMethodWrapper(
|
||||
override fun findSuperMethods(checkAccess: Boolean) = PsiSuperMethodImplUtil.findSuperMethods(this, checkAccess)
|
||||
override fun findSuperMethods(parentClass: PsiClass) = PsiSuperMethodImplUtil.findSuperMethods(this, parentClass)
|
||||
override fun findSuperMethods() = PsiSuperMethodImplUtil.findSuperMethods(this)
|
||||
override fun findSuperMethodSignaturesIncludingStatic(checkAccess: Boolean) = PsiSuperMethodImplUtil.findSuperMethodSignaturesIncludingStatic(this, checkAccess)
|
||||
@Suppress("OverridingDeprecatedMember") override fun findDeepestSuperMethod() = PsiSuperMethodImplUtil.findDeepestSuperMethod(this)
|
||||
override fun findSuperMethodSignaturesIncludingStatic(checkAccess: Boolean) =
|
||||
PsiSuperMethodImplUtil.findSuperMethodSignaturesIncludingStatic(this, checkAccess)
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
override fun findDeepestSuperMethod() = PsiSuperMethodImplUtil.findDeepestSuperMethod(this)
|
||||
|
||||
override fun findDeepestSuperMethods() = PsiSuperMethodImplUtil.findDeepestSuperMethods(this)
|
||||
override fun getHierarchicalMethodSignature() = PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this)
|
||||
override fun getSignature(substitutor: PsiSubstitutor) = MethodSignatureBackedByPsiMethod.create(this, substitutor)
|
||||
@@ -313,17 +318,16 @@ private class KtLightMethodWrapper(
|
||||
}
|
||||
|
||||
|
||||
abstract class KtAbstractContainerWrapper(internal val fqName: FqName, private val superInterface: PsiClass)
|
||||
: LightElement(superInterface.manager, KotlinLanguage.INSTANCE), PsiExtensibleClass {
|
||||
abstract class KtAbstractContainerWrapper(internal val fqName: FqName, private val superInterface: PsiClass) :
|
||||
LightElement(superInterface.manager, KotlinLanguage.INSTANCE), PsiExtensibleClass {
|
||||
|
||||
private val memberCache = ClassInnerStuffCache(this)
|
||||
|
||||
private val superClassTypeParametersToMyTypeParameters: Map<PsiTypeParameter, PsiTypeParameter>
|
||||
= superInterface.typeParameters
|
||||
.mapIndexed { index, supersParameter ->
|
||||
supersParameter to LightTypeParameterBuilder(supersParameter.name ?: "T$index", this, index)
|
||||
}
|
||||
.toMap()
|
||||
private val superClassTypeParametersToMyTypeParameters: Map<PsiTypeParameter, PsiTypeParameter> = superInterface.typeParameters
|
||||
.mapIndexed { index, supersParameter ->
|
||||
supersParameter to LightTypeParameterBuilder(supersParameter.name ?: "T$index", this, index)
|
||||
}
|
||||
.toMap()
|
||||
|
||||
internal val substitutor = createSubstitutor(superClassTypeParametersToMyTypeParameters.mapValues {
|
||||
it.value.asType()
|
||||
@@ -378,14 +382,16 @@ abstract class KtAbstractContainerWrapper(internal val fqName: FqName, private v
|
||||
override fun getSuperClass() = null
|
||||
override fun findInnerClassByName(name: String?, checkBases: Boolean) = null
|
||||
override fun getExtendsListTypes() = PsiClassType.EMPTY_ARRAY
|
||||
override fun isInheritorDeep(baseClass: PsiClass, classToByPass: PsiClass?) = InheritanceImplUtil.isInheritorDeep(this, baseClass, classToByPass)
|
||||
override fun isInheritorDeep(baseClass: PsiClass, classToByPass: PsiClass?) =
|
||||
InheritanceImplUtil.isInheritorDeep(this, baseClass, classToByPass)
|
||||
|
||||
override fun isAnnotationType() = false
|
||||
override fun findMethodsAndTheirSubstitutorsByName(name: String?, checkBases: Boolean)
|
||||
= PsiClassImplUtil.findMethodsAndTheirSubstitutorsByName(this, name, checkBases)
|
||||
override fun findMethodsAndTheirSubstitutorsByName(name: String?, checkBases: Boolean) =
|
||||
PsiClassImplUtil.findMethodsAndTheirSubstitutorsByName(this, name, checkBases)
|
||||
|
||||
override fun getInnerClasses() = PsiClass.EMPTY_ARRAY
|
||||
override fun findMethodBySignature(patternMethod: PsiMethod, checkBases: Boolean)
|
||||
= PsiClassImplUtil.findMethodBySignature(this, patternMethod, checkBases)
|
||||
override fun findMethodBySignature(patternMethod: PsiMethod, checkBases: Boolean) =
|
||||
PsiClassImplUtil.findMethodBySignature(this, patternMethod, checkBases)
|
||||
|
||||
override fun findFieldByName(name: String?, checkBases: Boolean) = null
|
||||
override fun getAllFields() = PsiClassImplUtil.getAllFields(this)
|
||||
@@ -394,7 +400,7 @@ abstract class KtAbstractContainerWrapper(internal val fqName: FqName, private v
|
||||
override fun getAllMethods() = PsiClassImplUtil.getAllMethods(this)
|
||||
override fun getOwnFields() = emptyList<PsiField>()
|
||||
override fun getAllMethodsAndTheirSubstitutors() =
|
||||
PsiClassImplUtil.getAllWithSubstitutorsByMap<PsiMethod>(this, PsiClassImplUtil.MemberType.METHOD)
|
||||
PsiClassImplUtil.getAllWithSubstitutorsByMap<PsiMethod>(this, PsiClassImplUtil.MemberType.METHOD)
|
||||
|
||||
override fun hasTypeParameters() = true
|
||||
override fun getRBrace() = null
|
||||
@@ -410,8 +416,8 @@ abstract class KtAbstractContainerWrapper(internal val fqName: FqName, private v
|
||||
override fun getConstructors() = PsiMethod.EMPTY_ARRAY
|
||||
override fun isDeprecated() = false
|
||||
override fun setName(name: String) = cannotModify()
|
||||
override fun findMethodsBySignature(patternMethod: PsiMethod, checkBases: Boolean)
|
||||
= PsiClassImplUtil.findMethodsBySignature(this, patternMethod, checkBases)
|
||||
override fun findMethodsBySignature(patternMethod: PsiMethod, checkBases: Boolean) =
|
||||
PsiClassImplUtil.findMethodsBySignature(this, patternMethod, checkBases)
|
||||
}
|
||||
|
||||
private fun PsiTypeParameter.asType() = PsiImmediateClassType(this, PsiSubstitutor.EMPTY)
|
||||
@@ -34,8 +34,7 @@ fun ModuleSourceInfo.getDependentModules(): Set<ModuleSourceInfo> {
|
||||
val dependents = getDependents(module)
|
||||
return if (isTests()) {
|
||||
dependents.mapNotNullTo(HashSet<ModuleSourceInfo>(), Module::testSourceInfo)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
dependents.flatMapTo(HashSet<ModuleSourceInfo>()) { it.correspondingModuleInfos() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,9 +64,9 @@ class IdePackageOracleFactory(val project: Project) : PackageOracleFactory {
|
||||
private val kotlinSourceOracle = KotlinSourceFilesOracle(moduleInfo)
|
||||
|
||||
override fun packageExists(fqName: FqName) =
|
||||
javaPackagesOracle.packageExists(fqName)
|
||||
|| kotlinSourceOracle.packageExists(fqName)
|
||||
|| fqName.isSubpackageOf(ANDROID_SYNTHETIC_PACKAGE_PREFIX)
|
||||
javaPackagesOracle.packageExists(fqName)
|
||||
|| kotlinSourceOracle.packageExists(fqName)
|
||||
|| fqName.isSubpackageOf(ANDROID_SYNTHETIC_PACKAGE_PREFIX)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ fun getResolveScope(file: KtFile): GlobalSearchScope {
|
||||
|
||||
return when (file.getModuleInfo()) {
|
||||
is ModuleSourceInfo -> KotlinSourceFilterScope.projectSourceAndClassFiles(file.resolveScope, file.project)
|
||||
is ScriptModuleInfo -> file.getModuleInfo().dependencies().map { it.contentScope() }.let { GlobalSearchScope.union(it.toTypedArray()) }
|
||||
is ScriptModuleInfo -> file.getModuleInfo().dependencies().map { it.contentScope() }.let { GlobalSearchScope.union(it.toTypedArray()) }
|
||||
else -> GlobalSearchScope.EMPTY_SCOPE
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user