AA: do not use full decompilation for built-ins
This is the major performance bottleneck for AA/UAST artifacts rollout to Android Lint. KT stubs are good/fast enough.
This commit is contained in:
committed by
Ilya Kirillov
parent
669afdd463
commit
2da4693cc0
+38
-14
@@ -6,20 +6,22 @@
|
|||||||
package org.jetbrains.kotlin.analysis.providers.impl
|
package org.jetbrains.kotlin.analysis.providers.impl
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
|
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import com.intellij.psi.stubs.StubElement
|
||||||
import com.intellij.util.indexing.FileContent
|
import com.intellij.util.indexing.FileContent
|
||||||
import com.intellij.util.indexing.FileContentImpl
|
import com.intellij.util.indexing.FileContentImpl
|
||||||
import com.intellij.util.io.URLUtil
|
import com.intellij.util.io.URLUtil
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler
|
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinDecompiledFileViewProvider
|
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.file.KtDecompiledFile
|
|
||||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory
|
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory
|
||||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.name.*
|
import org.jetbrains.kotlin.name.*
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.stubs.impl.*
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||||
|
|
||||||
public class KotlinStaticDeclarationProvider internal constructor(
|
public class KotlinStaticDeclarationProvider internal constructor(
|
||||||
@@ -107,7 +109,7 @@ public class KotlinStaticDeclarationProviderFactory(
|
|||||||
private val psiManager = PsiManager.getInstance(project)
|
private val psiManager = PsiManager.getInstance(project)
|
||||||
private val builtInDecompiler = KotlinBuiltInDecompiler()
|
private val builtInDecompiler = KotlinBuiltInDecompiler()
|
||||||
|
|
||||||
private fun loadBuiltIns(): Collection<KtDecompiledFile> {
|
private fun loadBuiltIns(): Collection<KotlinFileStubImpl> {
|
||||||
val classLoader = this::class.java.classLoader
|
val classLoader = this::class.java.classLoader
|
||||||
return buildList {
|
return buildList {
|
||||||
StandardClassIds.builtInsPackages.forEach { builtInPackageFqName ->
|
StandardClassIds.builtInsPackages.forEach { builtInPackageFqName ->
|
||||||
@@ -121,7 +123,7 @@ public class KotlinStaticDeclarationProviderFactory(
|
|||||||
val pathToQuery = jarPath + URLUtil.JAR_SEPARATOR + builtInFile
|
val pathToQuery = jarPath + URLUtil.JAR_SEPARATOR + builtInFile
|
||||||
jarFileSystem.findFileByPath(pathToQuery)?.let { vf ->
|
jarFileSystem.findFileByPath(pathToQuery)?.let { vf ->
|
||||||
val fileContent = FileContentImpl.createByFile(vf, project)
|
val fileContent = FileContentImpl.createByFile(vf, project)
|
||||||
createKtFileStub(fileContent)?.let { file -> add(file) }
|
createKtFileStub(psiManager, builtInDecompiler, fileContent)?.let { file -> add(file) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,18 +132,25 @@ public class KotlinStaticDeclarationProviderFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createKtFileStub(
|
private fun createKtFileStub(
|
||||||
|
psiManager: PsiManager,
|
||||||
|
builtInDecompiler: KotlinBuiltInDecompiler,
|
||||||
fileContent: FileContent,
|
fileContent: FileContent,
|
||||||
): KtDecompiledFile? {
|
): KotlinFileStubImpl? {
|
||||||
val fileViewProvider =
|
val ktFileStub = builtInDecompiler.stubBuilder.buildFileStub(fileContent) as? KotlinFileStubImpl ?: return null
|
||||||
builtInDecompiler.createFileViewProvider(fileContent.file, psiManager, physical = true) as? KotlinDecompiledFileViewProvider
|
val fakeFile = object : KtFile(KtClassFileViewProvider(psiManager, fileContent.file), isCompiled = true) {
|
||||||
?: return null
|
override fun getStub() = ktFileStub
|
||||||
return builtInDecompiler.readFile(fileContent.content, fileContent.file)?.let { fileWithMetadata ->
|
|
||||||
KtDecompiledFile(fileViewProvider) {
|
override fun isPhysical() = false
|
||||||
builtInDecompiler.buildDecompiledText(fileWithMetadata)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ktFileStub.psi = fakeFile
|
||||||
|
return ktFileStub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class KtClassFileViewProvider(
|
||||||
|
psiManager: PsiManager,
|
||||||
|
virtualFile: VirtualFile,
|
||||||
|
) : SingleRootFileViewProvider(psiManager, virtualFile, true, KotlinLanguage.INSTANCE)
|
||||||
|
|
||||||
private inner class KtDeclarationRecorder : KtVisitorVoid() {
|
private inner class KtDeclarationRecorder : KtVisitorVoid() {
|
||||||
|
|
||||||
override fun visitElement(element: PsiElement) {
|
override fun visitElement(element: PsiElement) {
|
||||||
@@ -217,8 +226,23 @@ public class KotlinStaticDeclarationProviderFactory(
|
|||||||
val recorder = KtDeclarationRecorder()
|
val recorder = KtDeclarationRecorder()
|
||||||
|
|
||||||
// Indexing built-ins
|
// Indexing built-ins
|
||||||
loadBuiltIns().forEach {
|
fun indexStub(stub: StubElement<*>) {
|
||||||
it.accept(recorder)
|
when (stub) {
|
||||||
|
is KotlinClassStubImpl -> {
|
||||||
|
addToClassMap(stub.psi)
|
||||||
|
// member functions and properties
|
||||||
|
stub.childrenStubs.forEach(::indexStub)
|
||||||
|
}
|
||||||
|
is KotlinTypeAliasStubImpl -> addToTypeAliasMap(stub.psi)
|
||||||
|
is KotlinFunctionStubImpl -> addToFunctionMap(stub.psi)
|
||||||
|
is KotlinPropertyStubImpl -> addToPropertyMap(stub.psi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadBuiltIns().forEach { ktFileStub ->
|
||||||
|
addToFacadeFileMap(ktFileStub.psi)
|
||||||
|
// top-level functions and properties, built-in classes
|
||||||
|
ktFileStub.childrenStubs.forEach(::indexStub)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indexing user source files
|
// Indexing user source files
|
||||||
|
|||||||
+15
@@ -9,9 +9,24 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
import com.intellij.psi.PsiParameter
|
import com.intellij.psi.PsiParameter
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
|
|
||||||
object TestPsiElementRenderer {
|
object TestPsiElementRenderer {
|
||||||
fun render(psiElement: PsiElement): String = when (psiElement) {
|
fun render(psiElement: PsiElement): String = when (psiElement) {
|
||||||
|
is KtNamedFunction -> buildString {
|
||||||
|
append("KtNamedFunction:")
|
||||||
|
append(psiElement.name)
|
||||||
|
append("(")
|
||||||
|
psiElement.valueParameters.joinTo(this) { render(it) }
|
||||||
|
append(")")
|
||||||
|
}
|
||||||
|
is KtParameter -> buildString {
|
||||||
|
if (psiElement.isVarArg) {
|
||||||
|
append("vararg ")
|
||||||
|
}
|
||||||
|
append(psiElement.name)
|
||||||
|
}
|
||||||
is KtElement -> psiElement.text
|
is KtElement -> psiElement.text
|
||||||
is PsiMethod -> buildString {
|
is PsiMethod -> buildString {
|
||||||
append("PsiMethod:")
|
append("PsiMethod:")
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
Resolved to:
|
Resolved to:
|
||||||
public abstract fun add(element: T): kotlin.Unit
|
KtNamedFunction:add(element)
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
Resolved to:
|
Resolved to:
|
||||||
@kotlin.SinceKotlin @kotlin.internal.PlatformDependent public open fun getOrDefault(key: K, defaultValue: V): V { /* compiled code */ }
|
KtNamedFunction:getOrDefault(key, defaultValue)
|
||||||
Reference in New Issue
Block a user