Add AnalysisHandlerExtension extension point for K2MetadataCompiler
AnalysisHandlerExtension allows compiler plugins to: 1. Intercept and override the default analysis. 2. Utilize the compiler infrastructure to do custom analysis. A well know plugin on the JVM platform is KAPT.
This commit is contained in:
committed by
TeamCityServer
parent
e0c28e27d2
commit
4db79285c1
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.cli.metadata
|
package org.jetbrains.kotlin.cli.metadata
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
|
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
@@ -33,7 +34,16 @@ internal fun runCommonAnalysisForSerialization(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return runCommonAnalysis(environment, dependOnBuiltins, dependencyContainer)
|
var analyzer: AnalyzerWithCompilerReport
|
||||||
|
do {
|
||||||
|
analyzer = runCommonAnalysis(environment, dependOnBuiltins, dependencyContainer)
|
||||||
|
val result = analyzer.analysisResult
|
||||||
|
if (result is AnalysisResult.RetryWithAdditionalRoots) {
|
||||||
|
environment.addKotlinSourceRoots(result.additionalKotlinRoots)
|
||||||
|
}
|
||||||
|
} while (result is AnalysisResult.RetryWithAdditionalRoots)
|
||||||
|
|
||||||
|
return if (analyzer.analysisResult.shouldGenerateCode) analyzer else null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runCommonAnalysis(
|
private fun runCommonAnalysis(
|
||||||
|
|||||||
+21
-3
@@ -40,11 +40,13 @@ import org.jetbrains.kotlin.platform.TargetPlatform
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||||
|
import org.jetbrains.kotlin.resolve.extensions.AnalysisHandlerExtension
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragmentProvider
|
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragmentProvider
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
|
import org.jetbrains.kotlin.serialization.deserialization.MetadataPartProvider
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||||
|
|
||||||
class CommonAnalysisParameters(
|
class CommonAnalysisParameters(
|
||||||
val metadataPartProviderFactory: (ModuleContent<*>) -> MetadataPartProvider
|
val metadataPartProviderFactory: (ModuleContent<*>) -> MetadataPartProvider
|
||||||
@@ -148,10 +150,11 @@ class CommonResolverForModuleFactory(
|
|||||||
dependenciesContainer
|
dependenciesContainer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val projectContext = ProjectContext(project, "metadata serializer")
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
val resolver = ResolverForSingleModuleProject<ModuleInfo>(
|
val resolver = ResolverForSingleModuleProject<ModuleInfo>(
|
||||||
"sources for metadata serializer",
|
"sources for metadata serializer",
|
||||||
ProjectContext(project, "metadata serializer"),
|
projectContext,
|
||||||
moduleInfo,
|
moduleInfo,
|
||||||
resolverForModuleFactory,
|
resolverForModuleFactory,
|
||||||
GlobalSearchScope.allScope(project),
|
GlobalSearchScope.allScope(project),
|
||||||
@@ -167,9 +170,24 @@ class CommonResolverForModuleFactory(
|
|||||||
|
|
||||||
val container = resolver.resolverForModule(moduleInfo).componentProvider
|
val container = resolver.resolverForModule(moduleInfo).componentProvider
|
||||||
|
|
||||||
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
val analysisHandlerExtensions = AnalysisHandlerExtension.getInstances(project)
|
||||||
|
val trace = container.get<BindingTrace>()
|
||||||
|
|
||||||
return AnalysisResult.success(container.get<BindingTrace>().bindingContext, moduleDescriptor)
|
// Mimic the behavior in the jvm frontend. The extensions have 2 chances to override the normal analysis:
|
||||||
|
// * If any of the extensions returns a non-null result, it. Otherwise do the normal analysis.
|
||||||
|
// * `analysisCompleted` can be used to override the result, too.
|
||||||
|
var result = analysisHandlerExtensions.firstNotNullResult { extension ->
|
||||||
|
extension.doAnalysis(project, moduleDescriptor, projectContext, files, trace, container)
|
||||||
|
} ?: run {
|
||||||
|
container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
||||||
|
AnalysisResult.success(trace.bindingContext, moduleDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
result = analysisHandlerExtensions.firstNotNullResult { extension ->
|
||||||
|
extension.analysisCompleted(project, moduleDescriptor, trace, files)
|
||||||
|
} ?: result
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user