diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java b/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java deleted file mode 100644 index bf0db709429..00000000000 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2010-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.plugin.caches; - -import com.google.common.collect.Sets; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; -import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex; -import com.intellij.psi.search.GlobalSearchScope; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.descriptors.serialization.*; -import org.jetbrains.jet.lang.descriptors.ClassKind; -import org.jetbrains.jet.lang.resolve.java.JavaResolverUtils; -import org.jetbrains.jet.lang.resolve.kotlin.KotlinBinaryClassCache; -import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass; -import org.jetbrains.jet.lang.resolve.name.FqName; -import org.jetbrains.jet.lang.resolve.name.Name; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Set; - -import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_CLASS; -import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_PACKAGE; - -/** - * Number of helper methods for searching kotlin element prototypes in java. Methods use java indices for search. - */ -public class JetFromJavaDescriptorHelper { - - private JetFromJavaDescriptorHelper() { - } - - static Collection getClassesForKotlinPackages(Project project, GlobalSearchScope scope) { - /* Will iterate through short name caches - Kotlin packages from jar a class files will be collected from java cache - Kotlin package classes from sources will be collected with JetShortNamesCache.getClassesByName */ - return getClassesByAnnotation(KOTLIN_PACKAGE.shortName().asString(), project, scope); - } - - /** - * Get names that could have jet descriptor equivalents. It could be inaccurate and return more results than necessary. - */ - @NotNull - static Collection getPossiblePackageDeclarationsNames(Project project, GlobalSearchScope scope) { - Collection result = new ArrayList(); - - for (PsiClass packageClass : getClassesForKotlinPackages(project, scope)) { - for (PsiMethod psiMethod : packageClass.getMethods()) { - if (psiMethod.getModifierList().hasModifierProperty(PsiModifier.STATIC)) { - result.add(psiMethod.getName()); - } - } - } - - return result; - } - - @NotNull - static Collection getCompiledClassesForTopLevelObjects(Project project, GlobalSearchScope scope) { - Set jetObjectClasses = Sets.newHashSet(); - - Collection classesByAnnotation = getClassesByAnnotation(KOTLIN_CLASS.shortName().asString(), project, scope); - - for (PsiClass psiClass : classesByAnnotation) { - ClassKind kind = getCompiledClassKind(psiClass); - if (kind == ClassKind.OBJECT && psiClass.getContainingClass() == null) { - jetObjectClasses.add(psiClass); - } - } - - return jetObjectClasses; - } - - @Nullable - public static ClassKind getCompiledClassKind(@NotNull PsiClass psiClass) { - ClassData classData = getClassData(psiClass); - if (classData == null) return null; - return SerializationPackage.classKind(Flags.CLASS_KIND.get(classData.getClassProto().getFlags())); - } - - - @Nullable - private static ClassData getClassData(@NotNull PsiClass psiClass) { - String[] data = getAnnotationDataForKotlinClass(psiClass); - return data == null ? null : JavaProtoBufUtil.readClassDataFrom(data); - } - - @Nullable - private static PackageData getPackageData(@NotNull PsiClass psiClass) { - String[] data = getAnnotationDataForKotlinClass(psiClass); - return data == null ? null : JavaProtoBufUtil.readPackageDataFrom(data); - } - - @Nullable - private static String[] getAnnotationDataForKotlinClass(@NotNull PsiClass psiClass) { - VirtualFile virtualFile = getVirtualFileForPsiClass(psiClass); - if (virtualFile != null) { - KotlinJvmBinaryClass kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(virtualFile); - if (kotlinClass != null) { - return kotlinClass.getClassHeader().getAnnotationData(); - } - } - return null; - } - - //TODO: common utility - //TODO: doesn't work for inner classes and stuff - @Nullable - private static VirtualFile getVirtualFileForPsiClass(@NotNull PsiClass psiClass) { - PsiFile psiFile = psiClass.getContainingFile(); - return psiFile == null ? null : psiFile.getVirtualFile(); - } - - @Nullable - static FqName getJetTopLevelDeclarationFQN(@NotNull PsiMethod method) { - PsiClass containingClass = method.getContainingClass(); - - if (containingClass != null) { - String qualifiedName = containingClass.getQualifiedName(); - assert qualifiedName != null; - - FqName classFQN = new FqName(qualifiedName); - - if (JavaResolverUtils.isCompiledKotlinPackageClass(containingClass)) { - return classFQN.parent().child(Name.identifier(method.getName())); - } - } - - return null; - } - - private static Collection getClassesByAnnotation( - String annotationName, Project project, GlobalSearchScope scope - ) { - Collection classes = Sets.newHashSet(); - Collection annotations = JavaAnnotationIndex.getInstance().get(annotationName, project, scope); - for (PsiAnnotation annotation : annotations) { - PsiModifierList modifierList = (PsiModifierList) annotation.getParent(); - PsiElement owner = modifierList.getParent(); - if (owner instanceof PsiClass) { - classes.add((PsiClass) owner); - } - } - return classes; - } - - - @NotNull - public static Collection getTopLevelCallableFqNames( - @NotNull Project project, - @NotNull GlobalSearchScope scope, - boolean shouldBeExtension - ) { - Collection result = Sets.newHashSet(); - Collection packageClasses = getClassesByAnnotation(KOTLIN_PACKAGE.shortName().asString(), project, scope); - for (PsiClass psiClass : packageClasses) { - String qualifiedName = psiClass.getQualifiedName(); - if (qualifiedName == null) { - continue; - } - FqName packageFqName = new FqName(qualifiedName).parent(); - PackageData data = getPackageData(psiClass); - if (data == null) { - continue; - } - NameResolver nameResolver = data.getNameResolver(); - for (ProtoBuf.Callable callable : data.getPackageProto().getMemberList()) { - if (callable.hasReceiverType() == shouldBeExtension) { - Name name = nameResolver.getName(callable.getName()); - result.add(packageFqName.child(name)); - } - } - } - return result; - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/caches/KotlinIndicesHelper.kt b/idea/src/org/jetbrains/jet/plugin/caches/KotlinIndicesHelper.kt index 2ee6dfe3b23..64848cce670 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/KotlinIndicesHelper.kt +++ b/idea/src/org/jetbrains/jet/plugin/caches/KotlinIndicesHelper.kt @@ -23,7 +23,6 @@ import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils import org.jetbrains.jet.lang.resolve.name.FqName import org.jetbrains.jet.lang.psi.* import org.jetbrains.jet.lang.resolve.* -import org.jetbrains.jet.lang.resolve.name.Name import org.jetbrains.jet.lang.resolve.scopes.JetScope import com.intellij.openapi.project.Project import java.util.HashSet @@ -37,6 +36,7 @@ import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade import org.jetbrains.jet.plugin.util.substituteExtensionIfCallable import org.jetbrains.jet.plugin.util.CallType import org.jetbrains.jet.plugin.codeInsight.ReferenceVariantsHelper +import org.jetbrains.jet.utils.addToStdlib.singletonOrEmptyList public class KotlinIndicesHelper( private val project: Project, @@ -47,36 +47,32 @@ public class KotlinIndicesHelper( private val visibilityFilter: (DeclarationDescriptor) -> Boolean ) { public fun getTopLevelCallablesByName(name: String, context: JetExpression /*TODO: to be dropped*/): Collection { - val jetScope = bindingContext[BindingContext.RESOLUTION_SCOPE, context] ?: return listOf() + val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, context] ?: return listOf() - val result = HashSet() - - //TODO: this code is temporary and is to be dropped when compiled top level functions are indexed - val identifier = Name.identifier(name) - for (fqName in JetFromJavaDescriptorHelper.getTopLevelCallableFqNames(project, scope, false)) { - if (fqName.lastSegmentIs(identifier)) { - result.addAll(findTopLevelCallables(fqName, context, jetScope)) + val declarations = HashSet() + declarations.addTopLevelNonExtensionCallablesByName(JetFunctionShortNameIndex.getInstance(), name) + declarations.addTopLevelNonExtensionCallablesByName(JetPropertyShortNameIndex.getInstance(), name) + return declarations.flatMap { + if (it.getContainingJetFile().isCompiled()) { + val importDirective = JetPsiFactory(project).createImportDirective(it.getFqName().asString()) + analyzeImportReference(importDirective, resolutionScope, BindingTraceContext(), moduleDescriptor).filterIsInstance() } - } - - result.addTopLevelNonExtensionCallablesByName(JetFunctionShortNameIndex.getInstance(), name) - result.addTopLevelNonExtensionCallablesByName(JetPropertyShortNameIndex.getInstance(), name) - - return result.filter(visibilityFilter) + else { + (resolutionFacade.resolveToDescriptor(it) as? CallableDescriptor).singletonOrEmptyList() + } + }.filter { it.getExtensionReceiverParameter() == null && visibilityFilter(it) } } - private fun MutableSet.addTopLevelNonExtensionCallablesByName( + private fun MutableSet.addTopLevelNonExtensionCallablesByName( index: StringStubIndexExtension, name: String ) { - index.get(name, project, scope) - .filter { it.getParent() is JetFile && it.getReceiverTypeReference() == null } - .mapTo(this) { resolutionFacade.resolveToDescriptor(it) as CallableDescriptor } + index.get(name, project, scope).filterTo(this) { it.getParent() is JetFile && it.getReceiverTypeReference() == null } } public fun getTopLevelCallables(nameFilter: (String) -> Boolean, context: JetExpression /*TODO: to be dropped*/): Collection { val sourceNames = JetTopLevelFunctionFqnNameIndex.getInstance().getAllKeys(project).stream() + JetTopLevelPropertyFqnNameIndex.getInstance().getAllKeys(project).stream() - val allFqNames = sourceNames.map { FqName(it) } + JetFromJavaDescriptorHelper.getTopLevelCallableFqNames(project, scope, false).stream() + val allFqNames = sourceNames.map { FqName(it) } val jetScope = bindingContext[BindingContext.RESOLUTION_SCOPE, context] ?: return listOf() @@ -93,19 +89,17 @@ public class KotlinIndicesHelper( val sourceFunctionNames = functionsIndex.getAllKeys(project).stream().map { FqName(it) } val sourcePropertyNames = propertiesIndex.getAllKeys(project).stream().map { FqName(it) } - val compiledFqNames = JetFromJavaDescriptorHelper.getTopLevelCallableFqNames(project, scope, true).stream() val result = HashSet() result.fqNamesToSuitableExtensions(sourceFunctionNames, nameFilter, functionsIndex, expression, bindingContext, dataFlowInfo) result.fqNamesToSuitableExtensions(sourcePropertyNames, nameFilter, propertiesIndex, expression, bindingContext, dataFlowInfo) - result.fqNamesToSuitableExtensions(compiledFqNames, nameFilter, null, expression, bindingContext, dataFlowInfo) return result } private fun MutableCollection.fqNamesToSuitableExtensions( fqNames: Stream, nameFilter: (String) -> Boolean, - index: StringStubIndexExtension?, + index: StringStubIndexExtension, expression: JetSimpleNameExpression, bindingContext: BindingContext, dataFlowInfo: DataFlowInfo) { @@ -141,7 +135,7 @@ public class KotlinIndicesHelper( * Check that function or property with the given qualified name can be resolved in given scope and called on given receiver */ private fun findSuitableExtensions(callableFQN: FqName, - index: StringStubIndexExtension?, + index: StringStubIndexExtension, receiverValue: ReceiverValue, dataFlowInfo: DataFlowInfo, callType: CallType, @@ -149,18 +143,14 @@ public class KotlinIndicesHelper( module: ModuleDescriptor, bindingContext: BindingContext): Stream { val fqnString = callableFQN.asString() - val descriptors = if (index != null) { - index.get(fqnString, project, scope) - .filter { it.getReceiverTypeReference() != null } - .map { resolutionFacade.resolveToDescriptor(it) as CallableDescriptor } - } - else { + val extensions = index.get(fqnString, project, scope).filter { it.getReceiverTypeReference() != null } + val descriptors = if (extensions.any { it.getContainingJetFile().isCompiled() } ) { val importDirective = JetPsiFactory(project).createImportDirective(fqnString) analyzeImportReference(importDirective, resolutionScope, BindingTraceContext(), module) .filterIsInstance() .filter { it.getExtensionReceiverParameter() != null } } - + else extensions.map { resolutionFacade.resolveToDescriptor(it) as CallableDescriptor } return descriptors.stream() .filter(visibilityFilter) .flatMap { it.substituteExtensionIfCallable(receiverValue, callType, bindingContext, dataFlowInfo).stream() } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt index 34ed40d7af0..506593d7f6d 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt @@ -17,15 +17,10 @@ package org.jetbrains.jet.plugin.completion import com.intellij.codeInsight.completion.* -import com.intellij.psi.PsiClass import org.jetbrains.jet.asJava.KotlinLightClass import org.jetbrains.jet.lang.descriptors.ClassKind import org.jetbrains.jet.lang.psi.JetFile -import org.jetbrains.jet.lang.resolve.java.JavaResolverUtils -import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils -import org.jetbrains.jet.lang.resolve.name.FqName import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns -import org.jetbrains.jet.plugin.caches.JetFromJavaDescriptorHelper import org.jetbrains.jet.plugin.project.ProjectStructureUtil import org.jetbrains.jet.plugin.caches.KotlinIndicesHelper import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor @@ -56,37 +51,19 @@ class AllClassesCompletion(val parameters: CompletionParameters, } } - /** - * Add java elements with performing conversion to kotlin elements if necessary. - */ private fun addAdaptedJavaCompletion(collector: LookupElementsCollector) { AllClassesGetter.processJavaClasses(parameters, prefixMatcher, true, { psiClass -> - if (psiClass!! !is KotlinLightClass) { // Kotlin non-compiled class should have already been added as kotlin element before - if (JavaResolverUtils.isCompiledKotlinClass(psiClass)) { - addLookupElementForCompiledKotlinClass(psiClass, collector) + if (psiClass!! !is KotlinLightClass) { // Kotlin class should have already been added as kotlin element before + val kind = when { + psiClass.isAnnotationType() -> ClassKind.ANNOTATION_CLASS + psiClass.isInterface() -> ClassKind.TRAIT + psiClass.isEnum() -> ClassKind.ENUM_CLASS + else -> ClassKind.CLASS } - else if (!JavaResolverUtils.isCompiledKotlinPackageClass(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(lookupElementFactory.createLookupElementForJavaClass(psiClass)) - } + if (kindFilter(kind)) { + collector.addElementWithAutoInsertionSuppressed(lookupElementFactory.createLookupElementForJavaClass(psiClass)) } } }) } - - private fun addLookupElementForCompiledKotlinClass(aClass: PsiClass, collector: LookupElementsCollector) { - if (kindFilter(JetFromJavaDescriptorHelper.getCompiledClassKind(aClass))) { - val qualifiedName = aClass.getQualifiedName() - if (qualifiedName != null) { - val descriptors = ResolveSessionUtils.getClassDescriptorsByFqName(moduleDescriptor, FqName(qualifiedName)).filter(visibilityFilter) - collector.addDescriptorElements(descriptors, suppressAutoInsertion = true) - } - } - } }