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