Split LightClassGenerationSupport into separate entities
LightClassGenerationSupport:
Includes utilities related to generating light classes
Primary client of this service are KtLight* implementation classes
KotlinAsJavaSupport:
Provides APIs to transform kotlin code into Psi* entities
Primary client of this service is JavaElementFinder
This commit is contained in:
+40
-29
@@ -20,7 +20,9 @@ import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.asJava.builder.*
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassBuilderResult
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
@@ -30,31 +32,24 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
typealias LightClassBuilder = (LightClassConstructionContext) -> LightClassBuilderResult
|
||||
|
||||
abstract class LightClassGenerationSupport {
|
||||
|
||||
abstract fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass
|
||||
|
||||
abstract fun createDataHolderForFacade(files: Collection<KtFile>, builder: LightClassBuilder): LightClassDataHolder.ForFacade
|
||||
|
||||
abstract fun createDataHolderForScript(script: KtScript, builder: LightClassBuilder): LightClassDataHolder.ForScript
|
||||
|
||||
abstract fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject>
|
||||
|
||||
/*
|
||||
* Finds files whose package declaration is exactly {@code fqName}. For example, if a file declares
|
||||
* package a.b.c
|
||||
* it will not be returned for fqName "a.b"
|
||||
*
|
||||
* If the resulting collection is empty, it means that this package has not other declarations than sub-packages
|
||||
*/
|
||||
abstract fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile>
|
||||
|
||||
abstract class KotlinAsJavaSupport {
|
||||
// Returns only immediately declared classes/objects, package classes are not included (they have no declarations)
|
||||
abstract fun findClassOrObjectDeclarationsInPackage(
|
||||
packageFqName: FqName,
|
||||
searchScope: GlobalSearchScope
|
||||
packageFqName: FqName,
|
||||
searchScope: GlobalSearchScope
|
||||
): Collection<KtClassOrObject>
|
||||
|
||||
/*
|
||||
* Finds files whose package declaration is exactly {@code fqName}. For example, if a file declares
|
||||
* package a.b.c
|
||||
* it will not be returned for fqName "a.b"
|
||||
*
|
||||
* If the resulting collection is empty, it means that this package has not other declarations than sub-packages
|
||||
*/
|
||||
abstract fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile>
|
||||
|
||||
abstract fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject>
|
||||
|
||||
abstract fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean
|
||||
|
||||
abstract fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection<FqName>
|
||||
@@ -63,12 +58,6 @@ abstract class LightClassGenerationSupport {
|
||||
|
||||
abstract fun getLightClassForScript(script: KtScript): KtLightClassForScript?
|
||||
|
||||
abstract fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor?
|
||||
|
||||
abstract fun analyze(element: KtElement): BindingContext
|
||||
|
||||
abstract fun analyzeWithContent(element: KtClassOrObject): BindingContext
|
||||
|
||||
abstract fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
|
||||
abstract fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
@@ -82,7 +71,29 @@ abstract class LightClassGenerationSupport {
|
||||
abstract fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtFile>
|
||||
|
||||
companion object {
|
||||
@JvmStatic fun getInstance(project: Project): LightClassGenerationSupport {
|
||||
@JvmStatic
|
||||
fun getInstance(project: Project): KotlinAsJavaSupport {
|
||||
return ServiceManager.getService(project, KotlinAsJavaSupport::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class LightClassGenerationSupport {
|
||||
abstract fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass
|
||||
|
||||
abstract fun createDataHolderForFacade(files: Collection<KtFile>, builder: LightClassBuilder): LightClassDataHolder.ForFacade
|
||||
|
||||
abstract fun createDataHolderForScript(script: KtScript, builder: LightClassBuilder): LightClassDataHolder.ForScript
|
||||
|
||||
abstract fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor?
|
||||
|
||||
abstract fun analyze(element: KtElement): BindingContext
|
||||
|
||||
abstract fun analyzeWithContent(element: KtClassOrObject): BindingContext
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(project: Project): LightClassGenerationSupport {
|
||||
return ServiceManager.getService(project, LightClassGenerationSupport::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -23,6 +23,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
||||
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
|
||||
@@ -114,7 +115,7 @@ sealed class LightClassDataProviderForFileFacade constructor(
|
||||
facadeFqName: FqName,
|
||||
private val searchScope: GlobalSearchScope
|
||||
) : LightClassDataProviderForFileFacade(project, facadeFqName) {
|
||||
override fun findFiles() = LightClassGenerationSupport.getInstance(project).findFilesForFacade(facadeFqName, searchScope)
|
||||
override fun findFiles() = KotlinAsJavaSupport.getInstance(project).findFilesForFacade(facadeFqName, searchScope)
|
||||
}
|
||||
|
||||
// create delegate by single file
|
||||
|
||||
+19
-16
@@ -29,11 +29,14 @@ import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport;
|
||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNamesUtilKt;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.KtClass;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinFinderMarker;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -58,15 +61,15 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
|
||||
private final Project project;
|
||||
private final PsiManager psiManager;
|
||||
private final LightClassGenerationSupport lightClassGenerationSupport;
|
||||
private final KotlinAsJavaSupport kotlinAsJavaSupport;
|
||||
|
||||
public JavaElementFinder(
|
||||
@NotNull Project project,
|
||||
@NotNull LightClassGenerationSupport lightClassGenerationSupport
|
||||
@NotNull KotlinAsJavaSupport kotlinAsJavaSupport
|
||||
) {
|
||||
this.project = project;
|
||||
this.psiManager = PsiManager.getInstance(project);
|
||||
this.lightClassGenerationSupport = lightClassGenerationSupport;
|
||||
this.kotlinAsJavaSupport = kotlinAsJavaSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,8 +90,8 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
FqName qualifiedName = new FqName(qualifiedNameString);
|
||||
|
||||
findClassesAndObjects(qualifiedName, scope, answer);
|
||||
answer.addAll(lightClassGenerationSupport.getFacadeClasses(qualifiedName, scope));
|
||||
answer.addAll(lightClassGenerationSupport.getKotlinInternalClasses(qualifiedName, scope));
|
||||
answer.addAll(kotlinAsJavaSupport.getFacadeClasses(qualifiedName, scope));
|
||||
answer.addAll(kotlinAsJavaSupport.getKotlinInternalClasses(qualifiedName, scope));
|
||||
|
||||
return sortByClasspath(answer, scope).toArray(new PsiClass[answer.size()]);
|
||||
}
|
||||
@@ -99,7 +102,7 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
findInterfaceDefaultImpls(qualifiedName, scope, answer);
|
||||
|
||||
Collection<KtClassOrObject> classOrObjectDeclarations =
|
||||
lightClassGenerationSupport.findClassOrObjectDeclarations(qualifiedName, scope);
|
||||
kotlinAsJavaSupport.findClassOrObjectDeclarations(qualifiedName, scope);
|
||||
|
||||
for (KtClassOrObject declaration : classOrObjectDeclarations) {
|
||||
if (!(declaration instanceof KtEnumEntry)) {
|
||||
@@ -116,7 +119,7 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
|
||||
if (!qualifiedName.shortName().asString().equals(JvmAbi.DEFAULT_IMPLS_CLASS_NAME)) return;
|
||||
|
||||
for (KtClassOrObject classOrObject : lightClassGenerationSupport.findClassOrObjectDeclarations(qualifiedName.parent(), scope)) {
|
||||
for (KtClassOrObject classOrObject : kotlinAsJavaSupport.findClassOrObjectDeclarations(qualifiedName.parent(), scope)) {
|
||||
//NOTE: can't filter out more interfaces right away because decompiled declarations do not have member bodies
|
||||
if (classOrObject instanceof KtClass && ((KtClass) classOrObject).isInterface()) {
|
||||
PsiClass interfaceClass = toLightClass(classOrObject);
|
||||
@@ -135,10 +138,10 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
FqName packageFQN = new FqName(psiPackage.getQualifiedName());
|
||||
|
||||
Collection<KtClassOrObject> declarations = lightClassGenerationSupport.findClassOrObjectDeclarationsInPackage(packageFQN, scope);
|
||||
Collection<KtClassOrObject> declarations = kotlinAsJavaSupport.findClassOrObjectDeclarationsInPackage(packageFQN, scope);
|
||||
|
||||
Set<String> answer = Sets.newHashSet();
|
||||
answer.addAll(lightClassGenerationSupport.getFacadeNames(packageFQN, scope));
|
||||
answer.addAll(kotlinAsJavaSupport.getFacadeNames(packageFQN, scope));
|
||||
|
||||
for (KtClassOrObject declaration : declarations) {
|
||||
String name = declaration.getName();
|
||||
@@ -160,7 +163,7 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
|
||||
// allScope() because the contract says that the whole project
|
||||
GlobalSearchScope allScope = GlobalSearchScope.allScope(project);
|
||||
if (lightClassGenerationSupport.packageExists(fqName, allScope)) {
|
||||
if (kotlinAsJavaSupport.packageExists(fqName, allScope)) {
|
||||
return new KtLightPackage(psiManager, fqName, allScope);
|
||||
}
|
||||
|
||||
@@ -172,7 +175,7 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
public PsiPackage[] getSubPackages(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
FqName packageFQN = new FqName(psiPackage.getQualifiedName());
|
||||
|
||||
Collection<FqName> subpackages = lightClassGenerationSupport.getSubPackages(packageFQN, scope);
|
||||
Collection<FqName> subpackages = kotlinAsJavaSupport.getSubPackages(packageFQN, scope);
|
||||
|
||||
Collection<PsiPackage> answer = Collections2.transform(subpackages, input -> new KtLightPackage(psiManager, input, scope));
|
||||
|
||||
@@ -185,9 +188,9 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
List<PsiClass> answer = new SmartList<>();
|
||||
FqName packageFQN = new FqName(psiPackage.getQualifiedName());
|
||||
|
||||
answer.addAll(lightClassGenerationSupport.getFacadeClassesInPackage(packageFQN, scope));
|
||||
answer.addAll(kotlinAsJavaSupport.getFacadeClassesInPackage(packageFQN, scope));
|
||||
|
||||
Collection<KtClassOrObject> declarations = lightClassGenerationSupport.findClassOrObjectDeclarationsInPackage(packageFQN, scope);
|
||||
Collection<KtClassOrObject> declarations = kotlinAsJavaSupport.findClassOrObjectDeclarationsInPackage(packageFQN, scope);
|
||||
for (KtClassOrObject declaration : declarations) {
|
||||
PsiClass aClass = toLightClass(declaration);
|
||||
if (aClass != null) {
|
||||
@@ -203,7 +206,7 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
public PsiFile[] getPackageFiles(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
|
||||
FqName packageFQN = new FqName(psiPackage.getQualifiedName());
|
||||
// TODO: this does not take into account JvmPackageName annotation
|
||||
Collection<KtFile> result = lightClassGenerationSupport.findFilesForPackage(packageFQN, scope);
|
||||
Collection<KtFile> result = kotlinAsJavaSupport.findFilesForPackage(packageFQN, scope);
|
||||
return result.toArray(new PsiFile[result.size()]);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.file.PsiPackageImpl;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport;
|
||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
|
||||
public class KtLightPackage extends PsiPackageImpl {
|
||||
@@ -43,6 +43,6 @@ public class KtLightPackage extends PsiPackageImpl {
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return LightClassGenerationSupport.getInstance(getProject()).packageExists(fqName, scope);
|
||||
return KotlinAsJavaSupport.getInstance(getProject()).packageExists(fqName, scope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
||||
|
||||
fun KtClassOrObject.toLightClass(): KtLightClass? = LightClassGenerationSupport.getInstance(project).getLightClass(this)
|
||||
fun KtClassOrObject.toLightClass(): KtLightClass? = KotlinAsJavaSupport.getInstance(project).getLightClass(this)
|
||||
|
||||
fun KtClassOrObject.toLightClassWithBuiltinMapping(): PsiClass? {
|
||||
toLightClass()?.let { return it }
|
||||
@@ -48,12 +48,12 @@ fun KtClassOrObject.toLightClassWithBuiltinMapping(): PsiClass? {
|
||||
}
|
||||
|
||||
fun KtFile.findFacadeClass(): KtLightClass? {
|
||||
return LightClassGenerationSupport.getInstance(project)
|
||||
return KotlinAsJavaSupport.getInstance(project)
|
||||
.getFacadeClassesInPackage(packageFqName, this.useScope as? GlobalSearchScope ?: GlobalSearchScope.projectScope(project))
|
||||
.firstOrNull { it is KtLightClassForFacade && this in it.files } as? KtLightClass
|
||||
}
|
||||
|
||||
fun KtScript.toLightClass(): KtLightClassForScript? = LightClassGenerationSupport.getInstance(project).getLightClassForScript(this)
|
||||
fun KtScript.toLightClass(): KtLightClassForScript? = KotlinAsJavaSupport.getInstance(project).getLightClassForScript(this)
|
||||
|
||||
fun KtElement.toLightElements(): List<PsiNamedElement> =
|
||||
when (this) {
|
||||
|
||||
Reference in New Issue
Block a user