Optimization to not fetch objects in separate pass

This commit is contained in:
Valentin Kipyatkov
2014-11-03 12:25:37 +03:00
parent 19f9f27675
commit c040c53f51
3 changed files with 49 additions and 32 deletions
@@ -42,6 +42,8 @@ public class KotlinIndicesHelper(private val project: Project,
private val resolveSession: ResolveSessionForBodies, private val resolveSession: ResolveSessionForBodies,
private val scope: GlobalSearchScope, private val scope: GlobalSearchScope,
private val visibilityFilter: (DeclarationDescriptor) -> Boolean) { private val visibilityFilter: (DeclarationDescriptor) -> Boolean) {
private val moduleDescriptor = resolveSession.getModuleDescriptor()
public fun getTopLevelObjects(nameFilter: (String) -> Boolean): Collection<ClassDescriptor> { public fun getTopLevelObjects(nameFilter: (String) -> Boolean): Collection<ClassDescriptor> {
val allObjectNames = JetTopLevelObjectShortNameIndex.getInstance().getAllKeys(project).stream() + val allObjectNames = JetTopLevelObjectShortNameIndex.getInstance().getAllKeys(project).stream() +
JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(project, scope).stream() JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(project, scope).stream()
@@ -57,13 +59,13 @@ public class KotlinIndicesHelper(private val project: Project,
val topObjects = JetTopLevelObjectShortNameIndex.getInstance().get(name, project, scope) val topObjects = JetTopLevelObjectShortNameIndex.getInstance().get(name, project, scope)
for (objectDeclaration in topObjects) { for (objectDeclaration in topObjects) {
val fqName = objectDeclaration.getFqName() ?: error("Local object declaration in JetTopLevelShortObjectNameIndex:${objectDeclaration.getText()}") val fqName = objectDeclaration.getFqName() ?: error("Local object declaration in JetTopLevelShortObjectNameIndex:${objectDeclaration.getText()}")
result.addAll(ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(resolveSession.getModuleDescriptor(), fqName, ResolveSessionUtils.SINGLETON_FILTER)) result.addAll(ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(moduleDescriptor, fqName, ResolveSessionUtils.SINGLETON_FILTER))
} }
for (psiClass in JetFromJavaDescriptorHelper.getCompiledClassesForTopLevelObjects(project, scope)) { for (psiClass in JetFromJavaDescriptorHelper.getCompiledClassesForTopLevelObjects(project, scope)) {
val qualifiedName = psiClass.getQualifiedName() val qualifiedName = psiClass.getQualifiedName()
if (qualifiedName != null) { if (qualifiedName != null) {
result.addAll(ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(resolveSession.getModuleDescriptor(), FqName(qualifiedName), ResolveSessionUtils.SINGLETON_FILTER)) result.addAll(ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(moduleDescriptor, FqName(qualifiedName), ResolveSessionUtils.SINGLETON_FILTER))
} }
} }
@@ -99,7 +101,7 @@ public class KotlinIndicesHelper(private val project: Project,
.toSet() .toSet()
for (affectedPackage in affectedPackages) { for (affectedPackage in affectedPackages) {
val packageDescriptor = resolveSession.getModuleDescriptor().getPackage(affectedPackage) val packageDescriptor = moduleDescriptor.getPackage(affectedPackage)
?: error("There's a function in stub index with invalid package: $affectedPackage") ?: error("There's a function in stub index with invalid package: $affectedPackage")
addAll(packageDescriptor.getMemberScope().getFunctions(identifier)) addAll(packageDescriptor.getMemberScope().getFunctions(identifier))
} }
@@ -115,7 +117,7 @@ public class KotlinIndicesHelper(private val project: Project,
.toSet() .toSet()
for (affectedPackage in affectedPackages) { for (affectedPackage in affectedPackages) {
val packageDescriptor = resolveSession.getModuleDescriptor().getPackage(affectedPackage) val packageDescriptor = moduleDescriptor.getPackage(affectedPackage)
?: error("There's a property in stub index with invalid package: $affectedPackage") ?: error("There's a property in stub index with invalid package: $affectedPackage")
addAll(packageDescriptor.getMemberScope().getProperties(identifier)) addAll(packageDescriptor.getMemberScope().getProperties(identifier))
} }
@@ -153,7 +155,7 @@ public class KotlinIndicesHelper(private val project: Project,
val receiverValue = ExpressionReceiver(receiverExpression, expressionType) val receiverValue = ExpressionReceiver(receiverExpression, expressionType)
return matchingFqNames.flatMap { return matchingFqNames.flatMap {
findSuitableExtensions(it, receiverValue, dataFlowInfo, isInfixCall, resolutionScope, resolveSession.getModuleDescriptor(), bindingContext) findSuitableExtensions(it, receiverValue, dataFlowInfo, isInfixCall, resolutionScope, moduleDescriptor, bindingContext)
} }
} }
else { else {
@@ -162,7 +164,7 @@ public class KotlinIndicesHelper(private val project: Project,
val result = HashSet<CallableDescriptor>() val result = HashSet<CallableDescriptor>()
for (receiver in resolutionScope.getImplicitReceiversHierarchy()) { for (receiver in resolutionScope.getImplicitReceiversHierarchy()) {
matchingFqNames.flatMapTo(result) { matchingFqNames.flatMapTo(result) {
findSuitableExtensions(it, receiver.getValue(), dataFlowInfo, false, resolutionScope, resolveSession.getModuleDescriptor(), bindingContext) findSuitableExtensions(it, receiver.getValue(), dataFlowInfo, false, resolutionScope, moduleDescriptor, bindingContext)
} }
} }
return result return result
@@ -190,29 +192,30 @@ public class KotlinIndicesHelper(private val project: Project,
ExpressionTypingUtils.checkIsExtensionCallable(receiverValue, it, isInfixCall, bindingContext, dataFlowInfo) } ExpressionTypingUtils.checkIsExtensionCallable(receiverValue, it, isInfixCall, bindingContext, dataFlowInfo) }
} }
public fun getClassDescriptors(nameFilter: (String) -> Boolean): Collection<ClassDescriptor> { public fun getClassDescriptors(nameFilter: (String) -> Boolean, kindFilter: (ClassKind) -> Boolean): Collection<ClassDescriptor> {
return JetFullClassNameIndex.getInstance().getAllKeys(project).stream() return JetFullClassNameIndex.getInstance().getAllKeys(project).stream()
.map { FqName(it) } .map { FqName(it) }
.filter { nameFilter(it.shortName().asString()) } .filter { nameFilter(it.shortName().asString()) }
.toList() .toList()
.flatMap { getClassDescriptorsByFQName(it) } .flatMap { getClassDescriptorsByFQName(it, kindFilter) }
} }
private fun getClassDescriptorsByFQName(classFQName: FqName): Collection<ClassDescriptor> { private fun getClassDescriptorsByFQName(classFQName: FqName, kindFilter: (ClassKind) -> Boolean): Collection<ClassDescriptor> {
val jetClassOrObjects = JetFullClassNameIndex.getInstance().get(classFQName.asString(), project, scope) val declarations = JetFullClassNameIndex.getInstance()[classFQName.asString(), project, scope]
if (jetClassOrObjects.isEmpty()) { if (declarations.isEmpty()) {
// This fqn is absent in caches, dead or not in scope // This fqn is absent in caches, dead or not in scope
return listOf() return listOf()
} }
// Note: Can't search with psi element as analyzer could be built over temp files // Note: Can't search with psi element as analyzer could be built over temp files
return ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession.getModuleDescriptor(), classFQName).filter(visibilityFilter) return ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(moduleDescriptor, classFQName) { kindFilter(it.getKind()) }
.filter(visibilityFilter)
} }
private fun findTopLevelCallables(fqName: FqName, context: JetExpression, jetScope: JetScope): Collection<CallableDescriptor> { private fun findTopLevelCallables(fqName: FqName, context: JetExpression, jetScope: JetScope): Collection<CallableDescriptor> {
val importDirective = JetPsiFactory(context.getProject()).createImportDirective(ImportPath(fqName, false)) val importDirective = JetPsiFactory(context.getProject()).createImportDirective(ImportPath(fqName, false))
val allDescriptors = analyzeImportReference(importDirective, jetScope, BindingTraceContext(), resolveSession.getModuleDescriptor()) val allDescriptors = analyzeImportReference(importDirective, jetScope, BindingTraceContext(), moduleDescriptor)
return allDescriptors.filterIsInstance(javaClass<CallableDescriptor>()).filter { it.getExtensionReceiverParameter() == null } return allDescriptors.filterIsInstance(javaClass<CallableDescriptor>()).filter { it.getExtensionReceiverParameter() == null }
} }
@@ -31,18 +31,20 @@ import org.jetbrains.jet.plugin.project.ResolveSessionForBodies
import org.jetbrains.jet.plugin.caches.KotlinIndicesHelper import org.jetbrains.jet.plugin.caches.KotlinIndicesHelper
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
class TypesCompletion(val parameters: CompletionParameters, class AllClassesCompletion(val parameters: CompletionParameters,
val resolveSession: ResolveSessionForBodies, val resolveSession: ResolveSessionForBodies,
val prefixMatcher: PrefixMatcher, val prefixMatcher: PrefixMatcher,
val visibilityFilter: (DeclarationDescriptor) -> Boolean) { val kindFilter: (ClassKind) -> Boolean,
fun addAllTypes(result: LookupElementsCollector) { val visibilityFilter: (DeclarationDescriptor) -> Boolean) {
result.addDescriptorElements(KotlinBuiltIns.getInstance().getNonPhysicalClasses().filter { prefixMatcher.prefixMatches(it.getName().asString()) }, fun collect(result: LookupElementsCollector) {
suppressAutoInsertion = true) val builtIns = KotlinBuiltIns.getInstance().getNonPhysicalClasses().filter { kindFilter(it.getKind()) && prefixMatcher.prefixMatches(it.getName().asString()) }
result.addDescriptorElements(builtIns, suppressAutoInsertion = true)
val file = parameters.getOriginalFile() val file = parameters.getOriginalFile()
val project = file.getProject() val project = file.getProject()
val searchScope = file.getResolveScope() val searchScope = file.getResolveScope()
result.addDescriptorElements(KotlinIndicesHelper(project, resolveSession, searchScope, visibilityFilter).getClassDescriptors { prefixMatcher.prefixMatches(it) }, val helper = KotlinIndicesHelper(project, resolveSession, searchScope, visibilityFilter)
result.addDescriptorElements(helper.getClassDescriptors({ prefixMatcher.prefixMatches(it) }, kindFilter),
suppressAutoInsertion = true) suppressAutoInsertion = true)
if (!ProjectStructureUtil.isJsKotlinModule(file as JetFile)) { if (!ProjectStructureUtil.isJsKotlinModule(file as JetFile)) {
@@ -60,14 +62,22 @@ class TypesCompletion(val parameters: CompletionParameters,
addLookupElementForCompiledKotlinClass(psiClass, collector) addLookupElementForCompiledKotlinClass(psiClass, collector)
} }
else if (!JavaResolverUtils.isCompiledKotlinPackageClass(psiClass)) { else if (!JavaResolverUtils.isCompiledKotlinPackageClass(psiClass)) {
collector.addElementWithAutoInsertionSuppressed(KotlinLookupElementFactory.createLookupElementForJavaClass(psiClass)) val kind = when {
psiClass.isAnnotationType() -> ClassKind.ANNOTATION_CLASS
psiClass.isInterface() -> ClassKind.TRAIT
psiClass.isEnum() -> ClassKind.ENUM_CLASS
else -> ClassKind.CLASS
}
if (kindFilter(kind)) {
collector.addElementWithAutoInsertionSuppressed(KotlinLookupElementFactory.createLookupElementForJavaClass(psiClass))
}
} }
} }
}) })
} }
private fun addLookupElementForCompiledKotlinClass(aClass: PsiClass, collector: LookupElementsCollector) { private fun addLookupElementForCompiledKotlinClass(aClass: PsiClass, collector: LookupElementsCollector) {
if (JetFromJavaDescriptorHelper.getCompiledClassKind(aClass) != ClassKind.CLASS_OBJECT) { if (kindFilter(JetFromJavaDescriptorHelper.getCompiledClassKind(aClass))) {
val qualifiedName = aClass.getQualifiedName() val qualifiedName = aClass.getQualifiedName()
if (qualifiedName != null) { if (qualifiedName != null) {
val descriptors = ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession.getModuleDescriptor(), FqName(qualifiedName)).filter(visibilityFilter) val descriptors = ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession.getModuleDescriptor(), FqName(qualifiedName)).filter(visibilityFilter)
@@ -110,17 +110,20 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
return configuration.completeNonImportedDeclarations || prefixMatcher.getPrefix().length >= 3 return configuration.completeNonImportedDeclarations || prefixMatcher.getPrefix().length >= 3
} }
protected fun getKotlinTopLevelDeclarations(): Collection<DeclarationDescriptor> { protected fun getKotlinTopLevelCallables(): Collection<DeclarationDescriptor> {
val filter = { (name: String) -> prefixMatcher.prefixMatches(name) } return indicesHelper.getTopLevelCallables({ prefixMatcher.prefixMatches(it) }, jetReference!!.expression)
return indicesHelper.getTopLevelCallables(filter, jetReference!!.expression) + indicesHelper.getTopLevelObjects(filter) }
protected fun getKotlinTopLevelObjects(): Collection<DeclarationDescriptor> {
return indicesHelper.getTopLevelObjects({ prefixMatcher.prefixMatches(it) })
} }
protected fun getKotlinExtensions(): Collection<CallableDescriptor> { protected fun getKotlinExtensions(): Collection<CallableDescriptor> {
return indicesHelper.getCallableExtensions({ prefixMatcher.prefixMatches(it) }, jetReference!!.expression) return indicesHelper.getCallableExtensions({ prefixMatcher.prefixMatches(it) }, jetReference!!.expression)
} }
protected fun addAllTypes() { protected fun addAllClasses(kindFilter: (ClassKind) -> Boolean) {
TypesCompletion(parameters, resolveSession, prefixMatcher, { isVisibleDescriptor(it) }).addAllTypes(collector) AllClassesCompletion(parameters, resolveSession, prefixMatcher, kindFilter, { isVisibleDescriptor(it) }).collect(collector)
} }
} }
@@ -138,7 +141,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
if (completeReference) { if (completeReference) {
if (shouldRunOnlyTypeCompletion()) { if (shouldRunOnlyTypeCompletion()) {
if (configuration.completeNonImportedDeclarations) { if (configuration.completeNonImportedDeclarations) {
addAllTypes() addAllClasses { !it.isSingleton() }
} }
else { else {
addReferenceVariants(JetScope.TYPE or JetScope.PACKAGE) addReferenceVariants(JetScope.TYPE or JetScope.PACKAGE)
@@ -164,8 +167,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
private fun addNonImported() { private fun addNonImported() {
if (shouldRunTopLevelCompletion()) { if (shouldRunTopLevelCompletion()) {
addAllTypes() addAllClasses { it != ClassKind.ENUM_ENTRY }
collector.addDescriptorElements(getKotlinTopLevelDeclarations(), suppressAutoInsertion = true) collector.addDescriptorElements(getKotlinTopLevelCallables(), suppressAutoInsertion = true)
} }
if (shouldRunExtensionsCompletion()) { if (shouldRunExtensionsCompletion()) {
@@ -223,7 +226,8 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
private fun processNonImported(processor: (DeclarationDescriptor) -> Unit) { private fun processNonImported(processor: (DeclarationDescriptor) -> Unit) {
if (shouldRunTopLevelCompletion()) { if (shouldRunTopLevelCompletion()) {
getKotlinTopLevelDeclarations().forEach(processor) getKotlinTopLevelCallables().forEach(processor)
getKotlinTopLevelObjects().forEach(processor) //TODO: shouldn't it work via inheritors search?
} }
if (shouldRunExtensionsCompletion()) { if (shouldRunExtensionsCompletion()) {