Cache the result of hasTopLevelCallables() for a KtFile
#KT-19885 Fixed
This commit is contained in:
+2
-11
@@ -20,11 +20,10 @@ import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.util.*
|
||||
|
||||
object PackagePartClassUtils {
|
||||
@@ -52,15 +51,7 @@ object PackagePartClassUtils {
|
||||
}
|
||||
|
||||
@JvmStatic fun getFilesWithCallables(files: Collection<KtFile>): List<KtFile> =
|
||||
files.filter { fileHasTopLevelCallables(it) }
|
||||
|
||||
@JvmStatic fun fileHasTopLevelCallables(file: KtFile): Boolean =
|
||||
file.declarations.any {
|
||||
(it is KtProperty ||
|
||||
it is KtNamedFunction ||
|
||||
it is KtScript ||
|
||||
it is KtTypeAlias) && !it.hasModifier(KtTokens.HEADER_KEYWORD)
|
||||
}
|
||||
files.filter { it.hasTopLevelCallables() }
|
||||
|
||||
@JvmStatic fun getFilePartShortName(fileName: String): String =
|
||||
NameUtils.getPackagePartClassNamePrefix(FileUtil.getNameWithoutExtension(fileName)) + PART_CLASS_NAME_SUFFIX
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||
@@ -43,8 +44,12 @@ open class KtFile(viewProvider: FileViewProvider, val isCompiled: Boolean) :
|
||||
PsiNamedElement,
|
||||
PsiModifiableCodeBlock {
|
||||
|
||||
@Volatile
|
||||
private var isScript: Boolean? = null
|
||||
|
||||
@Volatile
|
||||
private var hasTopLeveCallables: Boolean? = null
|
||||
|
||||
val importList: KtImportList?
|
||||
get() = findChildByTypeOrClass(KtStubElementTypes.IMPORT_LIST, KtImportList::class.java)
|
||||
|
||||
@@ -153,10 +158,25 @@ open class KtFile(viewProvider: FileViewProvider, val isCompiled: Boolean) :
|
||||
override fun clearCaches() {
|
||||
super.clearCaches()
|
||||
isScript = null
|
||||
hasTopLeveCallables = null
|
||||
}
|
||||
|
||||
fun isScript(): Boolean = stub?.isScript() ?: isScriptByTree
|
||||
|
||||
fun hasTopLevelCallables(): Boolean {
|
||||
hasTopLeveCallables?.let { return it }
|
||||
|
||||
val result = declarations.any {
|
||||
(it is KtProperty ||
|
||||
it is KtNamedFunction ||
|
||||
it is KtScript ||
|
||||
it is KtTypeAlias) && !it.hasModifier(KtTokens.HEADER_KEYWORD)
|
||||
}
|
||||
|
||||
hasTopLeveCallables = result
|
||||
return result
|
||||
}
|
||||
|
||||
override fun accept(visitor: PsiElementVisitor) {
|
||||
if (visitor is KtVisitor<*, *>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
||||
+1
-2
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils.fileHasTopLevelCallables
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -190,7 +189,7 @@ class KtLightClassForFacade private constructor(
|
||||
|
||||
override fun getQualifiedName() = facadeClassFqName.asString()
|
||||
|
||||
override fun isValid() = files.all { it.isValid && fileHasTopLevelCallables(it) && facadeClassFqName == it.javaFileFacadeFqName }
|
||||
override fun isValid() = files.all { it.isValid && it.hasTopLevelCallables() && facadeClassFqName == it.javaFileFacadeFqName }
|
||||
|
||||
override fun copy() = KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files)
|
||||
|
||||
|
||||
+6
-4
@@ -27,7 +27,10 @@ import org.jetbrains.kotlin.asJava.LightClassBuilder
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||
import org.jetbrains.kotlin.asJava.classes.*
|
||||
import org.jetbrains.kotlin.asJava.classes.FakeLightClassForFileOfPackage
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
@@ -39,7 +42,6 @@ import org.jetbrains.kotlin.idea.stubindex.*
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope.Companion.sourceAndClassFiles
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
@@ -330,13 +332,13 @@ class KtFileClassProviderImpl(val lightClassGenerationSupport: LightClassGenerat
|
||||
val fileClassFqName = file.javaFileFacadeFqName
|
||||
|
||||
val facadeClasses = when {
|
||||
file.analysisContext != null && PackagePartClassUtils.fileHasTopLevelCallables(file) ->
|
||||
file.analysisContext != null && file.hasTopLevelCallables() ->
|
||||
listOf(KtLightClassForFacade.createForSyntheticFile(PsiManager.getInstance(file.project), fileClassFqName, file))
|
||||
|
||||
jvmClassInfo.withJvmMultifileClass ->
|
||||
lightClassGenerationSupport.getFacadeClasses(fileClassFqName, moduleInfo.contentScope())
|
||||
|
||||
PackagePartClassUtils.fileHasTopLevelCallables(file) ->
|
||||
file.hasTopLevelCallables() ->
|
||||
(lightClassGenerationSupport as IDELightClassGenerationSupport).createLightClassForFileFacade(
|
||||
fileClassFqName, listOf(file), moduleInfo)
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
@@ -256,7 +255,7 @@ public class IdeStubIndexService extends StubIndexService {
|
||||
public KotlinFileStub createFileStub(@NotNull KtFile file) {
|
||||
StringRef packageFqName = StringRef.fromString(file.getPackageFqNameByTree().asString());
|
||||
boolean isScript = file.isScriptByTree();
|
||||
if (PackagePartClassUtils.fileHasTopLevelCallables(file)) {
|
||||
if (file.hasTopLevelCallables()) {
|
||||
JvmFileClassInfo fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file);
|
||||
StringRef facadeSimpleName = StringRef.fromString(fileClassInfo.getFacadeClassFqName().shortName().asString());
|
||||
StringRef partSimpleName = StringRef.fromString(fileClassInfo.getFileClassFqName().shortName().asString());
|
||||
|
||||
Reference in New Issue
Block a user