Reformat caches package

This commit is contained in:
Nikolay Krasko
2018-02-16 19:14:37 +03:00
parent 77b146a51a
commit 47f4c79204
28 changed files with 675 additions and 624 deletions
@@ -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> {
@@ -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,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
@@ -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>()
}
@@ -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()
}
@@ -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
@@ -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)
@@ -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
}
}
@@ -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
}
@@ -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
}
}
@@ -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)
@@ -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>
)
@@ -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" }
@@ -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)
@@ -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)
}
}
@@ -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)
}
@@ -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>
}
}
@@ -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
@@ -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
@@ -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,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
)
}
@@ -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
}
}