Remove all usages of JetFromJavaDescriptorHelper
Rewrite some utilities in KotlinIndicesHelper ResolutionFacade#resolveToDescriptor() should be avoided on psi from compiled kotlin for now
This commit is contained in:
-193
@@ -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<PsiClass> 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<String> getPossiblePackageDeclarationsNames(Project project, GlobalSearchScope scope) {
|
||||
Collection<String> result = new ArrayList<String>();
|
||||
|
||||
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<PsiClass> getCompiledClassesForTopLevelObjects(Project project, GlobalSearchScope scope) {
|
||||
Set<PsiClass> jetObjectClasses = Sets.newHashSet();
|
||||
|
||||
Collection<PsiClass> 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<PsiClass> getClassesByAnnotation(
|
||||
String annotationName, Project project, GlobalSearchScope scope
|
||||
) {
|
||||
Collection<PsiClass> classes = Sets.newHashSet();
|
||||
Collection<PsiAnnotation> 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<FqName> getTopLevelCallableFqNames(
|
||||
@NotNull Project project,
|
||||
@NotNull GlobalSearchScope scope,
|
||||
boolean shouldBeExtension
|
||||
) {
|
||||
Collection<FqName> result = Sets.newHashSet();
|
||||
Collection<PsiClass> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<CallableDescriptor> {
|
||||
val jetScope = bindingContext[BindingContext.RESOLUTION_SCOPE, context] ?: return listOf()
|
||||
val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, context] ?: return listOf()
|
||||
|
||||
val result = HashSet<CallableDescriptor>()
|
||||
|
||||
//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<JetNamedDeclaration>()
|
||||
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<CallableDescriptor>()
|
||||
}
|
||||
}
|
||||
|
||||
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<CallableDescriptor>.addTopLevelNonExtensionCallablesByName(
|
||||
private fun MutableSet<JetNamedDeclaration>.addTopLevelNonExtensionCallablesByName(
|
||||
index: StringStubIndexExtension<out JetCallableDeclaration>,
|
||||
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<CallableDescriptor> {
|
||||
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<CallableDescriptor>()
|
||||
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<CallableDescriptor>.fqNamesToSuitableExtensions(
|
||||
fqNames: Stream<FqName>,
|
||||
nameFilter: (String) -> Boolean,
|
||||
index: StringStubIndexExtension<out JetCallableDeclaration>?,
|
||||
index: StringStubIndexExtension<out JetCallableDeclaration>,
|
||||
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<out JetCallableDeclaration>?,
|
||||
index: StringStubIndexExtension<out JetCallableDeclaration>,
|
||||
receiverValue: ReceiverValue,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
callType: CallType,
|
||||
@@ -149,18 +143,14 @@ public class KotlinIndicesHelper(
|
||||
module: ModuleDescriptor,
|
||||
bindingContext: BindingContext): Stream<CallableDescriptor> {
|
||||
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<CallableDescriptor>()
|
||||
.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() }
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user