Allow to avoid declaration body resolution for function and property initializers if the return type is explicitly specified. This significantly reduces the analysis time in kapt3.
This commit is contained in:
+25
-6
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.container.ComponentProvider
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.context.ContextForNewModule
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.context.MutableModuleContext
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -55,7 +56,7 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer
|
||||
import org.jetbrains.kotlin.resolve.TopDownAnalysisMode
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||
@@ -79,13 +80,31 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
project, files, trace, configuration, packagePartProvider, declarationProviderFactory, sourceModuleSearchScope
|
||||
)
|
||||
|
||||
val module = container.get<ModuleDescriptor>()
|
||||
val moduleContext = container.get<ModuleContext>()
|
||||
|
||||
val analysisHandlerExtensions = AnalysisHandlerExtension.getInstances(project)
|
||||
|
||||
fun invokeExtensionsOnAnalysisComplete(): AnalysisResult? {
|
||||
for (extension in analysisHandlerExtensions) {
|
||||
val result = extension.analysisCompleted(project, module, trace, files)
|
||||
if (result != null) return result
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
for (extension in analysisHandlerExtensions) {
|
||||
val result = extension.doAnalysis(project, module, moduleContext, files, trace, container)
|
||||
if (result != null) {
|
||||
invokeExtensionsOnAnalysisComplete()?.let { return it }
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
||||
|
||||
val module = container.get<ModuleDescriptor>()
|
||||
for (extension in AnalysisCompletedHandlerExtension.getInstances(project)) {
|
||||
val result = extension.analysisCompleted(project, module, trace, files)
|
||||
if (result != null) return result
|
||||
}
|
||||
invokeExtensionsOnAnalysisComplete()?.let { return it }
|
||||
|
||||
return AnalysisResult.success(trace.bindingContext, module)
|
||||
}
|
||||
|
||||
+16
-4
@@ -18,20 +18,32 @@ package org.jetbrains.kotlin.resolve.jvm.extensions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.container.ComponentProvider
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
|
||||
interface AnalysisCompletedHandlerExtension {
|
||||
companion object : ProjectExtensionDescriptor<AnalysisCompletedHandlerExtension>(
|
||||
interface AnalysisHandlerExtension {
|
||||
companion object : ProjectExtensionDescriptor<AnalysisHandlerExtension>(
|
||||
"org.jetbrains.kotlin.analyzeCompleteHandlerExtension",
|
||||
AnalysisCompletedHandlerExtension::class.java
|
||||
AnalysisHandlerExtension::class.java
|
||||
)
|
||||
|
||||
fun doAnalysis(
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
projectContext: ProjectContext,
|
||||
files: Collection<KtFile>,
|
||||
bindingTrace: BindingTrace,
|
||||
componentProvider: ComponentProvider
|
||||
): AnalysisResult? = null
|
||||
|
||||
fun analysisCompleted(
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
bindingTrace: BindingTrace,
|
||||
files: Collection<KtFile>): AnalysisResult?
|
||||
files: Collection<KtFile>
|
||||
): AnalysisResult? = null
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.kotlin.resolve.jvm.extensions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.container.ComponentProvider
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProvider
|
||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
|
||||
|
||||
open class PartialAnalysisHandlerExtension : AnalysisHandlerExtension {
|
||||
protected open val analyzePartially: Boolean
|
||||
get() = true
|
||||
|
||||
override fun doAnalysis(
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
projectContext: ProjectContext,
|
||||
files: Collection<KtFile>,
|
||||
bindingTrace: BindingTrace,
|
||||
componentProvider: ComponentProvider
|
||||
): AnalysisResult? {
|
||||
if (!analyzePartially) {
|
||||
return null
|
||||
}
|
||||
|
||||
val resolveSession = componentProvider.get<ResolveSession>()
|
||||
val bodyResolver = componentProvider.get<BodyResolver>()
|
||||
val declarationScopeProvider = componentProvider.get<DeclarationScopeProvider>()
|
||||
|
||||
val topDownAnalysisContext = TopDownAnalysisContext(
|
||||
TopDownAnalysisMode.TopLevelDeclarations, DataFlowInfo.EMPTY, declarationScopeProvider)
|
||||
|
||||
for (file in files) {
|
||||
ForceResolveUtil.forceResolveAllContents(resolveSession.getFileAnnotations(file))
|
||||
}
|
||||
|
||||
doForEachDeclaration(files) { declaration ->
|
||||
val descriptor = resolveSession.resolveToDescriptor(declaration)
|
||||
|
||||
when (descriptor) {
|
||||
is ClassDescriptor -> {
|
||||
ForceResolveUtil.forceResolveAllContents(descriptor)
|
||||
ForceResolveUtil.forceResolveAllContents(descriptor.typeConstructor.supertypes)
|
||||
|
||||
if (declaration is KtClassOrObject && descriptor is ClassDescriptorWithResolutionScopes) {
|
||||
bodyResolver.resolveSuperTypeEntryList(DataFlowInfo.EMPTY,
|
||||
declaration,
|
||||
descriptor,
|
||||
descriptor.unsubstitutedPrimaryConstructor,
|
||||
descriptor.scopeForConstructorHeaderResolution,
|
||||
descriptor.scopeForMemberDeclarationResolution)
|
||||
}
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
if (declaration is KtProperty) {
|
||||
/* TODO Now we analyse body with anonymous object initializers. Check if we can't avoid it
|
||||
* val a: Runnable = object : Runnable { ... } */
|
||||
bodyResolver.resolveProperty(topDownAnalysisContext, declaration, descriptor)
|
||||
}
|
||||
else if (declaration is KtParameter) { // Annotation parameter
|
||||
val ownerElement = declaration.ownerFunction
|
||||
val ownerDescriptor = bindingTrace[BindingContext.VALUE_PARAMETER, declaration]?.containingDeclaration
|
||||
val containingScope = ownerDescriptor?.containingScope
|
||||
|
||||
if (ownerElement is KtPrimaryConstructor && ownerDescriptor is ConstructorDescriptor && containingScope != null) {
|
||||
bodyResolver.resolveConstructorParameterDefaultValues(
|
||||
topDownAnalysisContext.outerDataFlowInfo, bindingTrace, ownerElement, ownerDescriptor, containingScope)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AnalysisResult.Companion.success(bindingTrace.bindingContext, module, true)
|
||||
}
|
||||
|
||||
private val DeclarationDescriptor.containingScope: LexicalScope?
|
||||
get() {
|
||||
val containingDescriptor = containingDeclaration ?: return null
|
||||
return when (containingDescriptor) {
|
||||
is ClassDescriptorWithResolutionScopes -> containingDescriptor.scopeForInitializerResolution
|
||||
is PackageFragmentDescriptor -> LexicalScope.Empty(containingDescriptor.getMemberScope().memberScopeAsImportingScope(), this)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun doForEachDeclaration(declaration: KtDeclaration, f: (KtDeclaration) -> Unit) {
|
||||
if (declaration !is KtAnonymousInitializer) {
|
||||
f(declaration)
|
||||
}
|
||||
|
||||
if (declaration is KtClassOrObject) {
|
||||
declaration.declarations.forEach { doForEachDeclaration(it, f) }
|
||||
}
|
||||
|
||||
if (declaration is KtClass && declaration.isAnnotation()) {
|
||||
declaration.getPrimaryConstructorParameters().forEach { doForEachDeclaration(it, f) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun doForEachDeclaration(files: Collection<KtFile>, f: (KtDeclaration) -> Unit) {
|
||||
for (file in files) {
|
||||
file.declarations.forEach { doForEachDeclaration(it, f) }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user